mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

src/mn-md5.c (11232B) - raw

      1 /*
      2  * MD5 message digest implementation, taken from glibc and edited for
      3  * style.
      4  *
      5  * The GNU C Library,
      6  * Copyright (C) 1995,1996,1997,1999,2000,2001,2005
      7  * Free Software Foundation, Inc.
      8  *
      9  * Mail Notification
     10  * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
     11  *
     12  * This program is free software; you can redistribute it and/or modify
     13  * it under the terms of the GNU General Public License as published by
     14  * the Free Software Foundation; either version 3 of the License, or
     15  * (at your option) any later version.
     16  *
     17  * This program is distributed in the hope that it will be useful,
     18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20  * GNU General Public License for more details.
     21  *
     22  * You should have received a copy of the GNU General Public License along
     23  * with this program; if not, write to the Free Software Foundation, Inc.,
     24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     25  */
     26 
     27 #include <sys/types.h>
     28 #include <string.h>
     29 #include "mn-md5.h"
     30 
     31 #ifdef WORDS_BIGENDIAN
     32 # define SWAP(n)							\
     33     (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
     34 #else
     35 # define SWAP(n) (n)
     36 #endif
     37 
     38 #define HEXCHARS "0123456789abcdef"
     39 
     40 /* This array contains the bytes used to pad the buffer to the next
     41    64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
     42 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
     43 
     44 
     45 /* Initialize structure containing state of computation.
     46    (RFC 1321, 3.3: Step 3)  */
     47 void
     48 mn_md5_init_ctx (MNMD5Context *ctx)
     49 {
     50   ctx->A = 0x67452301;
     51   ctx->B = 0xefcdab89;
     52   ctx->C = 0x98badcfe;
     53   ctx->D = 0x10325476;
     54 
     55   ctx->total[0] = ctx->total[1] = 0;
     56   ctx->buflen = 0;
     57 }
     58 
     59 /* Put result from CTX in first 16 bytes following RESBUF.  The result
     60    must be in little endian byte order.
     61 
     62    IMPORTANT: On some systems it is required that RESBUF is correctly
     63    aligned for a 32 bits value.  */
     64 void *
     65 mn_md5_read_ctx (MNMD5Context *ctx, void *resbuf)
     66 {
     67   ((uint32_t *) resbuf)[0] = SWAP (ctx->A);
     68   ((uint32_t *) resbuf)[1] = SWAP (ctx->B);
     69   ((uint32_t *) resbuf)[2] = SWAP (ctx->C);
     70   ((uint32_t *) resbuf)[3] = SWAP (ctx->D);
     71 
     72   return resbuf;
     73 }
     74 
     75 /* Process the remaining bytes in the internal buffer and the usual
     76    prolog according to the standard and write the result to RESBUF.
     77 
     78    IMPORTANT: On some systems it is required that RESBUF is correctly
     79    aligned for a 32 bits value.  */
     80 void *
     81 mn_md5_finish_ctx (MNMD5Context *ctx, unsigned char resbuf[16])
     82 {
     83   /* Take yet unprocessed bytes into account.  */
     84   uint32_t bytes = ctx->buflen;
     85   size_t pad;
     86 
     87   /* Now count remaining bytes.  */
     88   ctx->total[0] += bytes;
     89   if (ctx->total[0] < bytes)
     90     ++ctx->total[1];
     91 
     92   pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
     93   memcpy (&ctx->buffer[bytes], fillbuf, pad);
     94 
     95   /* Put the 64-bit file length in *bits* at the end of the buffer.  */
     96   *(uint32_t *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
     97   *(uint32_t *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
     98 							(ctx->total[0] >> 29));
     99 
    100   /* Process last bytes.  */
    101   mn_md5_process_block (ctx, ctx->buffer, bytes + pad + 8);
    102 
    103   return mn_md5_read_ctx (ctx, resbuf);
    104 }
    105 
    106 void
    107 mn_md5_to_hex (const unsigned char resbuf[16], char hexbuf[33])
    108 {
    109   int i;
    110 
    111   for (i = 0; i < 16; i++)
    112     {
    113       hexbuf[i * 2] = HEXCHARS[resbuf[i] >> 4];
    114       hexbuf[i * 2 + 1] = HEXCHARS[resbuf[i] & 0xf];
    115     }
    116 
    117   hexbuf[32] = 0;
    118 }
    119 
    120 void
    121 mn_md5_process_bytes (MNMD5Context *ctx, const void *buffer, size_t len)
    122 {
    123   /* When we already have some bits in our internal buffer concatenate
    124      both inputs first.  */
    125   if (ctx->buflen != 0)
    126     {
    127       size_t left_over = ctx->buflen;
    128       size_t add = 128 - left_over > len ? len : 128 - left_over;
    129 
    130       memcpy (&ctx->buffer[left_over], buffer, add);
    131       ctx->buflen += add;
    132 
    133       if (ctx->buflen > 64)
    134 	{
    135 	  mn_md5_process_block (ctx, ctx->buffer, ctx->buflen & ~63);
    136 
    137 	  ctx->buflen &= 63;
    138 	  /* The regions in the following copy operation cannot overlap.  */
    139 	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
    140 		  ctx->buflen);
    141 	}
    142 
    143       buffer = (const char *) buffer + add;
    144       len -= add;
    145     }
    146 
    147   /* Process available complete blocks.  */
    148   if (len >= 64)
    149     {
    150 #ifndef STRING_ARCH_UNALIGNED
    151 /* To check alignment gcc has an appropriate operator.  Other
    152    compilers don't.  */
    153 # if __GNUC__ >= 2
    154 #  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
    155 # else
    156 #  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0)
    157 # endif
    158       if (UNALIGNED_P (buffer))
    159 	while (len > 64)
    160 	  {
    161 	    mn_md5_process_block (ctx, memcpy (ctx->buffer, buffer, 64), 64);
    162 	    buffer = (const char *) buffer + 64;
    163 	    len -= 64;
    164 	  }
    165       else
    166 #endif
    167 	{
    168 	  mn_md5_process_block (ctx, buffer, len & ~63);
    169 	  buffer = (const char *) buffer + (len & ~63);
    170 	  len &= 63;
    171 	}
    172     }
    173 
    174   /* Move remaining bytes in internal buffer.  */
    175   if (len > 0)
    176     {
    177       size_t left_over = ctx->buflen;
    178 
    179       memcpy (&ctx->buffer[left_over], buffer, len);
    180       left_over += len;
    181       if (left_over >= 64)
    182 	{
    183 	  mn_md5_process_block (ctx, ctx->buffer, 64);
    184 	  left_over -= 64;
    185 	  memcpy (ctx->buffer, &ctx->buffer[64], left_over);
    186 	}
    187       ctx->buflen = left_over;
    188     }
    189 }
    190 
    191 
    192 /* These are the four functions used in the four steps of the MD5 algorithm
    193    and defined in the RFC 1321.  The first function is a little bit optimized
    194    (as found in Colin Plumbs public domain implementation).  */
    195 /* #define FF(b, c, d) ((b & c) | (~b & d)) */
    196 #define FF(b, c, d) (d ^ (b & (c ^ d)))
    197 #define FG(b, c, d) FF (d, b, c)
    198 #define FH(b, c, d) (b ^ c ^ d)
    199 #define FI(b, c, d) (c ^ (b | ~d))
    200 
    201 /* Process LEN bytes of BUFFER, accumulating context into CTX.
    202    It is assumed that LEN % 64 == 0.  */
    203 
    204 void
    205 mn_md5_process_block (MNMD5Context *ctx, const void *buffer, size_t len)
    206 {
    207   uint32_t correct_words[16];
    208   const uint32_t *words = buffer;
    209   size_t nwords = len / sizeof (uint32_t);
    210   const uint32_t *endp = words + nwords;
    211   uint32_t A = ctx->A;
    212   uint32_t B = ctx->B;
    213   uint32_t C = ctx->C;
    214   uint32_t D = ctx->D;
    215 
    216   /* First increment the byte count.  RFC 1321 specifies the possible
    217      length of the file up to 2^64 bits.  Here we only compute the
    218      number of bytes.  Do a double word increment.  */
    219   ctx->total[0] += len;
    220   if (ctx->total[0] < len)
    221     ++ctx->total[1];
    222 
    223   /* Process all bytes in the buffer with 64 bytes in each round of
    224      the loop.  */
    225   while (words < endp)
    226     {
    227       uint32_t *cwp = correct_words;
    228       uint32_t A_save = A;
    229       uint32_t B_save = B;
    230       uint32_t C_save = C;
    231       uint32_t D_save = D;
    232 
    233       /* First round: using the given function, the context and a constant
    234 	 the next context is computed.  Because the algorithms processing
    235 	 unit is a 32-bit word and it is determined to work on words in
    236 	 little endian byte order we perhaps have to change the byte order
    237 	 before the computation.  To reduce the work for the next steps
    238 	 we store the swapped words in the array CORRECT_WORDS.  */
    239 
    240 #define OP(a, b, c, d, s, T)						\
    241       do								\
    242         {								\
    243 	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
    244 	  ++words;							\
    245 	  CYCLIC (a, s);						\
    246 	  a += b;							\
    247         }								\
    248       while (0)
    249 
    250       /* It is unfortunate that C does not provide an operator for
    251 	 cyclic rotation.  Hope the C compiler is smart enough.  */
    252 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
    253 
    254       /* Before we start, one word to the strange constants.
    255 	 They are defined in RFC 1321 as
    256 
    257 	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
    258        */
    259 
    260       /* Round 1.  */
    261       OP (A, B, C, D,  7, 0xd76aa478);
    262       OP (D, A, B, C, 12, 0xe8c7b756);
    263       OP (C, D, A, B, 17, 0x242070db);
    264       OP (B, C, D, A, 22, 0xc1bdceee);
    265       OP (A, B, C, D,  7, 0xf57c0faf);
    266       OP (D, A, B, C, 12, 0x4787c62a);
    267       OP (C, D, A, B, 17, 0xa8304613);
    268       OP (B, C, D, A, 22, 0xfd469501);
    269       OP (A, B, C, D,  7, 0x698098d8);
    270       OP (D, A, B, C, 12, 0x8b44f7af);
    271       OP (C, D, A, B, 17, 0xffff5bb1);
    272       OP (B, C, D, A, 22, 0x895cd7be);
    273       OP (A, B, C, D,  7, 0x6b901122);
    274       OP (D, A, B, C, 12, 0xfd987193);
    275       OP (C, D, A, B, 17, 0xa679438e);
    276       OP (B, C, D, A, 22, 0x49b40821);
    277 
    278       /* For the second to fourth round we have the possibly swapped words
    279 	 in CORRECT_WORDS.  Redefine the macro to take an additional first
    280 	 argument specifying the function to use.  */
    281 #undef OP
    282 #define OP(f, a, b, c, d, k, s, T)					\
    283       do 								\
    284 	{								\
    285 	  a += f (b, c, d) + correct_words[k] + T;			\
    286 	  CYCLIC (a, s);						\
    287 	  a += b;							\
    288 	}								\
    289       while (0)
    290 
    291       /* Round 2.  */
    292       OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
    293       OP (FG, D, A, B, C,  6,  9, 0xc040b340);
    294       OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
    295       OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
    296       OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
    297       OP (FG, D, A, B, C, 10,  9, 0x02441453);
    298       OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
    299       OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
    300       OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
    301       OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
    302       OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
    303       OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
    304       OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
    305       OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
    306       OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
    307       OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
    308 
    309       /* Round 3.  */
    310       OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
    311       OP (FH, D, A, B, C,  8, 11, 0x8771f681);
    312       OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
    313       OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
    314       OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
    315       OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
    316       OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
    317       OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
    318       OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
    319       OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
    320       OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
    321       OP (FH, B, C, D, A,  6, 23, 0x04881d05);
    322       OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
    323       OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
    324       OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
    325       OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
    326 
    327       /* Round 4.  */
    328       OP (FI, A, B, C, D,  0,  6, 0xf4292244);
    329       OP (FI, D, A, B, C,  7, 10, 0x432aff97);
    330       OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
    331       OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
    332       OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
    333       OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
    334       OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
    335       OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
    336       OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
    337       OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
    338       OP (FI, C, D, A, B,  6, 15, 0xa3014314);
    339       OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
    340       OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
    341       OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
    342       OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
    343       OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
    344 
    345       /* Add the starting values of the context.  */
    346       A += A_save;
    347       B += B_save;
    348       C += C_save;
    349       D += D_save;
    350     }
    351 
    352   /* Put checksum in context given as argument.  */
    353   ctx->A = A;
    354   ctx->B = B;
    355   ctx->C = C;
    356   ctx->D = D;
    357 }