Blame crypt/md5-block.c

Packit 6c4009
/* These are the four functions used in the four steps of the MD5 algorithm
Packit 6c4009
   and defined in the RFC 1321.  The first function is a little bit optimized
Packit 6c4009
   (as found in Colin Plumbs public domain implementation).  */
Packit 6c4009
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
Packit 6c4009
#define FF(b, c, d) (d ^ (b & (c ^ d)))
Packit 6c4009
#define FG(b, c, d) FF (d, b, c)
Packit 6c4009
#define FH(b, c, d) (b ^ c ^ d)
Packit 6c4009
#define FI(b, c, d) (c ^ (b | ~d))
Packit 6c4009
Packit 6c4009
/* Process LEN bytes of BUFFER, accumulating context into CTX.
Packit 6c4009
   It is assumed that LEN % 64 == 0.  */
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
__md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
Packit 6c4009
{
Packit 6c4009
  md5_uint32 correct_words[16];
Packit 6c4009
  const md5_uint32 *words = buffer;
Packit 6c4009
  size_t nwords = len / sizeof (md5_uint32);
Packit 6c4009
  const md5_uint32 *endp = words + nwords;
Packit 6c4009
  md5_uint32 A = ctx->A;
Packit 6c4009
  md5_uint32 B = ctx->B;
Packit 6c4009
  md5_uint32 C = ctx->C;
Packit 6c4009
  md5_uint32 D = ctx->D;
Packit 6c4009
  md5_uint32 lolen = len;
Packit 6c4009
Packit 6c4009
  /* First increment the byte count.  RFC 1321 specifies the possible
Packit 6c4009
     length of the file up to 2^64 bits.  Here we only compute the
Packit 6c4009
     number of bytes.  Do a double word increment.  */
Packit 6c4009
  ctx->total[0] += lolen;
Packit 6c4009
  ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen);
Packit 6c4009
Packit 6c4009
  /* Process all bytes in the buffer with 64 bytes in each round of
Packit 6c4009
     the loop.  */
Packit 6c4009
  while (words < endp)
Packit 6c4009
    {
Packit 6c4009
      md5_uint32 *cwp = correct_words;
Packit 6c4009
      md5_uint32 A_save = A;
Packit 6c4009
      md5_uint32 B_save = B;
Packit 6c4009
      md5_uint32 C_save = C;
Packit 6c4009
      md5_uint32 D_save = D;
Packit 6c4009
Packit 6c4009
      /* First round: using the given function, the context and a constant
Packit 6c4009
	 the next context is computed.  Because the algorithms processing
Packit 6c4009
	 unit is a 32-bit word and it is determined to work on words in
Packit 6c4009
	 little endian byte order we perhaps have to change the byte order
Packit 6c4009
	 before the computation.  To reduce the work for the next steps
Packit 6c4009
	 we store the swapped words in the array CORRECT_WORDS.  */
Packit 6c4009
Packit 6c4009
#define OP(a, b, c, d, s, T)						\
Packit 6c4009
      do								\
Packit 6c4009
	{								\
Packit 6c4009
	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
Packit 6c4009
	  ++words;							\
Packit 6c4009
	  CYCLIC (a, s);						\
Packit 6c4009
	  a += b;							\
Packit 6c4009
	}								\
Packit 6c4009
      while (0)
Packit 6c4009
Packit 6c4009
      /* It is unfortunate that C does not provide an operator for
Packit 6c4009
	 cyclic rotation.  Hope the C compiler is smart enough.  */
Packit 6c4009
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
Packit 6c4009
Packit 6c4009
      /* Before we start, one word to the strange constants.
Packit 6c4009
	 They are defined in RFC 1321 as
Packit 6c4009
Packit 6c4009
	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
Packit 6c4009
       */
Packit 6c4009
Packit 6c4009
      /* Round 1.  */
Packit 6c4009
      OP (A, B, C, D,  7, 0xd76aa478);
Packit 6c4009
      OP (D, A, B, C, 12, 0xe8c7b756);
Packit 6c4009
      OP (C, D, A, B, 17, 0x242070db);
Packit 6c4009
      OP (B, C, D, A, 22, 0xc1bdceee);
Packit 6c4009
      OP (A, B, C, D,  7, 0xf57c0faf);
Packit 6c4009
      OP (D, A, B, C, 12, 0x4787c62a);
Packit 6c4009
      OP (C, D, A, B, 17, 0xa8304613);
Packit 6c4009
      OP (B, C, D, A, 22, 0xfd469501);
Packit 6c4009
      OP (A, B, C, D,  7, 0x698098d8);
Packit 6c4009
      OP (D, A, B, C, 12, 0x8b44f7af);
Packit 6c4009
      OP (C, D, A, B, 17, 0xffff5bb1);
Packit 6c4009
      OP (B, C, D, A, 22, 0x895cd7be);
Packit 6c4009
      OP (A, B, C, D,  7, 0x6b901122);
Packit 6c4009
      OP (D, A, B, C, 12, 0xfd987193);
Packit 6c4009
      OP (C, D, A, B, 17, 0xa679438e);
Packit 6c4009
      OP (B, C, D, A, 22, 0x49b40821);
Packit 6c4009
Packit 6c4009
      /* For the second to fourth round we have the possibly swapped words
Packit 6c4009
	 in CORRECT_WORDS.  Redefine the macro to take an additional first
Packit 6c4009
	 argument specifying the function to use.  */
Packit 6c4009
#undef OP
Packit 6c4009
#define OP(f, a, b, c, d, k, s, T)					\
Packit 6c4009
      do 								\
Packit 6c4009
	{								\
Packit 6c4009
	  a += f (b, c, d) + correct_words[k] + T;			\
Packit 6c4009
	  CYCLIC (a, s);						\
Packit 6c4009
	  a += b;							\
Packit 6c4009
	}								\
Packit 6c4009
      while (0)
Packit 6c4009
Packit 6c4009
      /* Round 2.  */
Packit 6c4009
      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
Packit 6c4009
      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
Packit 6c4009
      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
Packit 6c4009
      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
Packit 6c4009
      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
Packit 6c4009
      OP (FG, D, A, B, C, 10,  9, 0x02441453);
Packit 6c4009
      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
Packit 6c4009
      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
Packit 6c4009
      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
Packit 6c4009
      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
Packit 6c4009
      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
Packit 6c4009
      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
Packit 6c4009
      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
Packit 6c4009
      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
Packit 6c4009
      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
Packit 6c4009
      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
Packit 6c4009
Packit 6c4009
      /* Round 3.  */
Packit 6c4009
      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
Packit 6c4009
      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
Packit 6c4009
      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
Packit 6c4009
      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
Packit 6c4009
      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
Packit 6c4009
      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
Packit 6c4009
      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
Packit 6c4009
      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
Packit 6c4009
      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
Packit 6c4009
      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
Packit 6c4009
      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
Packit 6c4009
      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
Packit 6c4009
      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
Packit 6c4009
      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
Packit 6c4009
      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
Packit 6c4009
      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
Packit 6c4009
Packit 6c4009
      /* Round 4.  */
Packit 6c4009
      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
Packit 6c4009
      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
Packit 6c4009
      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
Packit 6c4009
      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
Packit 6c4009
      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
Packit 6c4009
      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
Packit 6c4009
      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
Packit 6c4009
      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
Packit 6c4009
      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
Packit 6c4009
      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
Packit 6c4009
      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
Packit 6c4009
      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
Packit 6c4009
      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
Packit 6c4009
      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
Packit 6c4009
      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
Packit 6c4009
      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
Packit 6c4009
Packit 6c4009
      /* Add the starting values of the context.  */
Packit 6c4009
      A += A_save;
Packit 6c4009
      B += B_save;
Packit 6c4009
      C += C_save;
Packit 6c4009
      D += D_save;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Put checksum in context given as argument.  */
Packit 6c4009
  ctx->A = A;
Packit 6c4009
  ctx->B = B;
Packit 6c4009
  ctx->C = C;
Packit 6c4009
  ctx->D = D;
Packit 6c4009
}