177298Sobrien/* md5.c - Functions to compute MD5 message digest of files or memory blocks
277298Sobrien   according to the definition of MD5 in RFC 1321 from April 1992.
377298Sobrien   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
477298Sobrien
577298Sobrien   NOTE: This source is derived from an old version taken from the GNU C
677298Sobrien   Library (glibc).
777298Sobrien
877298Sobrien   This program is free software; you can redistribute it and/or modify it
977298Sobrien   under the terms of the GNU General Public License as published by the
1077298Sobrien   Free Software Foundation; either version 2, or (at your option) any
1177298Sobrien   later version.
1277298Sobrien
1377298Sobrien   This program is distributed in the hope that it will be useful,
1477298Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1577298Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1677298Sobrien   GNU General Public License for more details.
1777298Sobrien
1877298Sobrien   You should have received a copy of the GNU General Public License
1977298Sobrien   along with this program; if not, write to the Free Software Foundation,
20218822Sdim   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2177298Sobrien
2277298Sobrien/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
2377298Sobrien
2477298Sobrien#ifdef HAVE_CONFIG_H
2577298Sobrien# include <config.h>
2677298Sobrien#endif
2777298Sobrien
2877298Sobrien#include <sys/types.h>
2977298Sobrien
3077298Sobrien#if STDC_HEADERS || defined _LIBC
3177298Sobrien# include <stdlib.h>
3277298Sobrien# include <string.h>
3377298Sobrien#else
3477298Sobrien# ifndef HAVE_MEMCPY
3577298Sobrien#  define memcpy(d, s, n) bcopy ((s), (d), (n))
3677298Sobrien# endif
3777298Sobrien#endif
3877298Sobrien
3977298Sobrien#include "ansidecl.h"
4077298Sobrien#include "md5.h"
4177298Sobrien
4277298Sobrien#ifdef _LIBC
4377298Sobrien# include <endian.h>
4477298Sobrien# if __BYTE_ORDER == __BIG_ENDIAN
4577298Sobrien#  define WORDS_BIGENDIAN 1
4677298Sobrien# endif
4777298Sobrien#endif
4877298Sobrien
4977298Sobrien#ifdef WORDS_BIGENDIAN
5077298Sobrien# define SWAP(n)							\
5177298Sobrien    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
5277298Sobrien#else
5377298Sobrien# define SWAP(n) (n)
5477298Sobrien#endif
5577298Sobrien
5677298Sobrien
5777298Sobrien/* This array contains the bytes used to pad the buffer to the next
5877298Sobrien   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
5977298Sobrienstatic const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
6077298Sobrien
6177298Sobrien
6277298Sobrien/* Initialize structure containing state of computation.
6377298Sobrien   (RFC 1321, 3.3: Step 3)  */
6477298Sobrienvoid
65218822Sdimmd5_init_ctx (struct md5_ctx *ctx)
6677298Sobrien{
6789857Sobrien  ctx->A = (md5_uint32) 0x67452301;
6889857Sobrien  ctx->B = (md5_uint32) 0xefcdab89;
6989857Sobrien  ctx->C = (md5_uint32) 0x98badcfe;
7089857Sobrien  ctx->D = (md5_uint32) 0x10325476;
7177298Sobrien
7277298Sobrien  ctx->total[0] = ctx->total[1] = 0;
7377298Sobrien  ctx->buflen = 0;
7477298Sobrien}
7577298Sobrien
7677298Sobrien/* Put result from CTX in first 16 bytes following RESBUF.  The result
7777298Sobrien   must be in little endian byte order.
7877298Sobrien
7977298Sobrien   IMPORTANT: On some systems it is required that RESBUF is correctly
8077298Sobrien   aligned for a 32 bits value.  */
8177298Sobrienvoid *
82218822Sdimmd5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
8377298Sobrien{
8477298Sobrien  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
8577298Sobrien  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
8677298Sobrien  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
8777298Sobrien  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
8877298Sobrien
8977298Sobrien  return resbuf;
9077298Sobrien}
9177298Sobrien
9277298Sobrien/* Process the remaining bytes in the internal buffer and the usual
9377298Sobrien   prolog according to the standard and write the result to RESBUF.
9477298Sobrien
9577298Sobrien   IMPORTANT: On some systems it is required that RESBUF is correctly
9677298Sobrien   aligned for a 32 bits value.  */
9777298Sobrienvoid *
98218822Sdimmd5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
9977298Sobrien{
10077298Sobrien  /* Take yet unprocessed bytes into account.  */
10177298Sobrien  md5_uint32 bytes = ctx->buflen;
10277298Sobrien  size_t pad;
10377298Sobrien
10477298Sobrien  /* Now count remaining bytes.  */
10577298Sobrien  ctx->total[0] += bytes;
10677298Sobrien  if (ctx->total[0] < bytes)
10777298Sobrien    ++ctx->total[1];
10877298Sobrien
10977298Sobrien  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
11077298Sobrien  memcpy (&ctx->buffer[bytes], fillbuf, pad);
11177298Sobrien
11277298Sobrien  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
11377298Sobrien  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
11477298Sobrien  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
11577298Sobrien							(ctx->total[0] >> 29));
11677298Sobrien
11777298Sobrien  /* Process last bytes.  */
11877298Sobrien  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
11977298Sobrien
12077298Sobrien  return md5_read_ctx (ctx, resbuf);
12177298Sobrien}
12277298Sobrien
12377298Sobrien/* Compute MD5 message digest for bytes read from STREAM.  The
12477298Sobrien   resulting message digest number will be written into the 16 bytes
12577298Sobrien   beginning at RESBLOCK.  */
12677298Sobrienint
127218822Sdimmd5_stream (FILE *stream, void *resblock)
12877298Sobrien{
12977298Sobrien  /* Important: BLOCKSIZE must be a multiple of 64.  */
13077298Sobrien#define BLOCKSIZE 4096
13177298Sobrien  struct md5_ctx ctx;
13277298Sobrien  char buffer[BLOCKSIZE + 72];
13377298Sobrien  size_t sum;
13477298Sobrien
13577298Sobrien  /* Initialize the computation context.  */
13677298Sobrien  md5_init_ctx (&ctx);
13777298Sobrien
13877298Sobrien  /* Iterate over full file contents.  */
13977298Sobrien  while (1)
14077298Sobrien    {
14177298Sobrien      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
14277298Sobrien	 computation function processes the whole buffer so that with the
14377298Sobrien	 next round of the loop another block can be read.  */
14477298Sobrien      size_t n;
14577298Sobrien      sum = 0;
14677298Sobrien
14777298Sobrien      /* Read block.  Take care for partial reads.  */
14877298Sobrien      do
14977298Sobrien	{
15077298Sobrien	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
15177298Sobrien
15277298Sobrien	  sum += n;
15377298Sobrien	}
15477298Sobrien      while (sum < BLOCKSIZE && n != 0);
15577298Sobrien      if (n == 0 && ferror (stream))
15677298Sobrien        return 1;
15777298Sobrien
15877298Sobrien      /* If end of file is reached, end the loop.  */
15977298Sobrien      if (n == 0)
16077298Sobrien	break;
16177298Sobrien
16277298Sobrien      /* Process buffer with BLOCKSIZE bytes.  Note that
16377298Sobrien			BLOCKSIZE % 64 == 0
16477298Sobrien       */
16577298Sobrien      md5_process_block (buffer, BLOCKSIZE, &ctx);
16677298Sobrien    }
16777298Sobrien
16877298Sobrien  /* Add the last bytes if necessary.  */
16977298Sobrien  if (sum > 0)
17077298Sobrien    md5_process_bytes (buffer, sum, &ctx);
17177298Sobrien
17277298Sobrien  /* Construct result in desired memory.  */
17377298Sobrien  md5_finish_ctx (&ctx, resblock);
17477298Sobrien  return 0;
17577298Sobrien}
17677298Sobrien
17777298Sobrien/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
17877298Sobrien   result is always in little endian byte order, so that a byte-wise
17977298Sobrien   output yields to the wanted ASCII representation of the message
18077298Sobrien   digest.  */
18177298Sobrienvoid *
182218822Sdimmd5_buffer (const char *buffer, size_t len, void *resblock)
18377298Sobrien{
18477298Sobrien  struct md5_ctx ctx;
18577298Sobrien
18677298Sobrien  /* Initialize the computation context.  */
18777298Sobrien  md5_init_ctx (&ctx);
18877298Sobrien
18977298Sobrien  /* Process whole buffer but last len % 64 bytes.  */
19077298Sobrien  md5_process_bytes (buffer, len, &ctx);
19177298Sobrien
19277298Sobrien  /* Put result in desired memory area.  */
19377298Sobrien  return md5_finish_ctx (&ctx, resblock);
19477298Sobrien}
19577298Sobrien
19677298Sobrien
19777298Sobrienvoid
198218822Sdimmd5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
19977298Sobrien{
20077298Sobrien  /* When we already have some bits in our internal buffer concatenate
20177298Sobrien     both inputs first.  */
20277298Sobrien  if (ctx->buflen != 0)
20377298Sobrien    {
20477298Sobrien      size_t left_over = ctx->buflen;
20577298Sobrien      size_t add = 128 - left_over > len ? len : 128 - left_over;
20677298Sobrien
20777298Sobrien      memcpy (&ctx->buffer[left_over], buffer, add);
20877298Sobrien      ctx->buflen += add;
20977298Sobrien
21077298Sobrien      if (left_over + add > 64)
21177298Sobrien	{
21277298Sobrien	  md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
21377298Sobrien	  /* The regions in the following copy operation cannot overlap.  */
21477298Sobrien	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
21577298Sobrien		  (left_over + add) & 63);
21677298Sobrien	  ctx->buflen = (left_over + add) & 63;
21777298Sobrien	}
21877298Sobrien
219130561Sobrien      buffer = (const void *) ((const char *) buffer + add);
22077298Sobrien      len -= add;
22177298Sobrien    }
22277298Sobrien
22377298Sobrien  /* Process available complete blocks.  */
22477298Sobrien  if (len > 64)
22577298Sobrien    {
226218822Sdim#if !_STRING_ARCH_unaligned
227218822Sdim/* To check alignment gcc has an appropriate operator.  Other
228218822Sdim   compilers don't.  */
229218822Sdim# if __GNUC__ >= 2
230218822Sdim#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
231218822Sdim# else
232218822Sdim#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
233218822Sdim# endif
234218822Sdim      if (UNALIGNED_P (buffer))
235218822Sdim        while (len > 64)
236218822Sdim          {
237218822Sdim            md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
238218822Sdim            buffer = (const char *) buffer + 64;
239218822Sdim            len -= 64;
240218822Sdim          }
241218822Sdim      else
242218822Sdim#endif
24377298Sobrien      md5_process_block (buffer, len & ~63, ctx);
244130561Sobrien      buffer = (const void *) ((const char *) buffer + (len & ~63));
24577298Sobrien      len &= 63;
24677298Sobrien    }
24777298Sobrien
24877298Sobrien  /* Move remaining bytes in internal buffer.  */
24977298Sobrien  if (len > 0)
25077298Sobrien    {
25177298Sobrien      memcpy (ctx->buffer, buffer, len);
25277298Sobrien      ctx->buflen = len;
25377298Sobrien    }
25477298Sobrien}
25577298Sobrien
25677298Sobrien
25777298Sobrien/* These are the four functions used in the four steps of the MD5 algorithm
25877298Sobrien   and defined in the RFC 1321.  The first function is a little bit optimized
25977298Sobrien   (as found in Colin Plumbs public domain implementation).  */
26077298Sobrien/* #define FF(b, c, d) ((b & c) | (~b & d)) */
26177298Sobrien#define FF(b, c, d) (d ^ (b & (c ^ d)))
26277298Sobrien#define FG(b, c, d) FF (d, b, c)
26377298Sobrien#define FH(b, c, d) (b ^ c ^ d)
26477298Sobrien#define FI(b, c, d) (c ^ (b | ~d))
26577298Sobrien
26677298Sobrien/* Process LEN bytes of BUFFER, accumulating context into CTX.
26777298Sobrien   It is assumed that LEN % 64 == 0.  */
26877298Sobrien
26977298Sobrienvoid
270218822Sdimmd5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
27177298Sobrien{
27277298Sobrien  md5_uint32 correct_words[16];
273130561Sobrien  const md5_uint32 *words = (const md5_uint32 *) buffer;
27477298Sobrien  size_t nwords = len / sizeof (md5_uint32);
27577298Sobrien  const md5_uint32 *endp = words + nwords;
27677298Sobrien  md5_uint32 A = ctx->A;
27777298Sobrien  md5_uint32 B = ctx->B;
27877298Sobrien  md5_uint32 C = ctx->C;
27977298Sobrien  md5_uint32 D = ctx->D;
28077298Sobrien
28177298Sobrien  /* First increment the byte count.  RFC 1321 specifies the possible
28277298Sobrien     length of the file up to 2^64 bits.  Here we only compute the
28377298Sobrien     number of bytes.  Do a double word increment.  */
28477298Sobrien  ctx->total[0] += len;
28577298Sobrien  if (ctx->total[0] < len)
28677298Sobrien    ++ctx->total[1];
28777298Sobrien
28877298Sobrien  /* Process all bytes in the buffer with 64 bytes in each round of
28977298Sobrien     the loop.  */
29077298Sobrien  while (words < endp)
29177298Sobrien    {
29277298Sobrien      md5_uint32 *cwp = correct_words;
29377298Sobrien      md5_uint32 A_save = A;
29477298Sobrien      md5_uint32 B_save = B;
29577298Sobrien      md5_uint32 C_save = C;
29677298Sobrien      md5_uint32 D_save = D;
29777298Sobrien
29877298Sobrien      /* First round: using the given function, the context and a constant
29977298Sobrien	 the next context is computed.  Because the algorithms processing
30077298Sobrien	 unit is a 32-bit word and it is determined to work on words in
30177298Sobrien	 little endian byte order we perhaps have to change the byte order
30277298Sobrien	 before the computation.  To reduce the work for the next steps
30377298Sobrien	 we store the swapped words in the array CORRECT_WORDS.  */
30477298Sobrien
30577298Sobrien#define OP(a, b, c, d, s, T)						\
30677298Sobrien      do								\
30777298Sobrien        {								\
30877298Sobrien	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
30977298Sobrien	  ++words;							\
31077298Sobrien	  CYCLIC (a, s);						\
31177298Sobrien	  a += b;							\
31277298Sobrien        }								\
31377298Sobrien      while (0)
31477298Sobrien
31577298Sobrien      /* It is unfortunate that C does not provide an operator for
31677298Sobrien	 cyclic rotation.  Hope the C compiler is smart enough.  */
31777298Sobrien#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
31877298Sobrien
31977298Sobrien      /* Before we start, one word to the strange constants.
32077298Sobrien	 They are defined in RFC 1321 as
32177298Sobrien
32277298Sobrien	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
32377298Sobrien       */
32477298Sobrien
32577298Sobrien      /* Round 1.  */
32689857Sobrien      OP (A, B, C, D,  7, (md5_uint32) 0xd76aa478);
32789857Sobrien      OP (D, A, B, C, 12, (md5_uint32) 0xe8c7b756);
32889857Sobrien      OP (C, D, A, B, 17, (md5_uint32) 0x242070db);
32989857Sobrien      OP (B, C, D, A, 22, (md5_uint32) 0xc1bdceee);
33089857Sobrien      OP (A, B, C, D,  7, (md5_uint32) 0xf57c0faf);
33189857Sobrien      OP (D, A, B, C, 12, (md5_uint32) 0x4787c62a);
33289857Sobrien      OP (C, D, A, B, 17, (md5_uint32) 0xa8304613);
33389857Sobrien      OP (B, C, D, A, 22, (md5_uint32) 0xfd469501);
33489857Sobrien      OP (A, B, C, D,  7, (md5_uint32) 0x698098d8);
33589857Sobrien      OP (D, A, B, C, 12, (md5_uint32) 0x8b44f7af);
33689857Sobrien      OP (C, D, A, B, 17, (md5_uint32) 0xffff5bb1);
33789857Sobrien      OP (B, C, D, A, 22, (md5_uint32) 0x895cd7be);
33889857Sobrien      OP (A, B, C, D,  7, (md5_uint32) 0x6b901122);
33989857Sobrien      OP (D, A, B, C, 12, (md5_uint32) 0xfd987193);
34089857Sobrien      OP (C, D, A, B, 17, (md5_uint32) 0xa679438e);
34189857Sobrien      OP (B, C, D, A, 22, (md5_uint32) 0x49b40821);
34277298Sobrien
34377298Sobrien      /* For the second to fourth round we have the possibly swapped words
34477298Sobrien	 in CORRECT_WORDS.  Redefine the macro to take an additional first
34577298Sobrien	 argument specifying the function to use.  */
34677298Sobrien#undef OP
347130561Sobrien#define OP(a, b, c, d, k, s, T)						\
34877298Sobrien      do 								\
34977298Sobrien	{								\
350130561Sobrien	  a += FX (b, c, d) + correct_words[k] + T;			\
35177298Sobrien	  CYCLIC (a, s);						\
35277298Sobrien	  a += b;							\
35377298Sobrien	}								\
35477298Sobrien      while (0)
35577298Sobrien
356130561Sobrien#define FX(b, c, d) FG (b, c, d)
357130561Sobrien
35877298Sobrien      /* Round 2.  */
359130561Sobrien      OP (A, B, C, D,  1,  5, (md5_uint32) 0xf61e2562);
360130561Sobrien      OP (D, A, B, C,  6,  9, (md5_uint32) 0xc040b340);
361130561Sobrien      OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
362130561Sobrien      OP (B, C, D, A,  0, 20, (md5_uint32) 0xe9b6c7aa);
363130561Sobrien      OP (A, B, C, D,  5,  5, (md5_uint32) 0xd62f105d);
364130561Sobrien      OP (D, A, B, C, 10,  9, (md5_uint32) 0x02441453);
365130561Sobrien      OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
366130561Sobrien      OP (B, C, D, A,  4, 20, (md5_uint32) 0xe7d3fbc8);
367130561Sobrien      OP (A, B, C, D,  9,  5, (md5_uint32) 0x21e1cde6);
368130561Sobrien      OP (D, A, B, C, 14,  9, (md5_uint32) 0xc33707d6);
369130561Sobrien      OP (C, D, A, B,  3, 14, (md5_uint32) 0xf4d50d87);
370130561Sobrien      OP (B, C, D, A,  8, 20, (md5_uint32) 0x455a14ed);
371130561Sobrien      OP (A, B, C, D, 13,  5, (md5_uint32) 0xa9e3e905);
372130561Sobrien      OP (D, A, B, C,  2,  9, (md5_uint32) 0xfcefa3f8);
373130561Sobrien      OP (C, D, A, B,  7, 14, (md5_uint32) 0x676f02d9);
374130561Sobrien      OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
37577298Sobrien
376130561Sobrien#undef FX
377130561Sobrien#define FX(b, c, d) FH (b, c, d)
378130561Sobrien
37977298Sobrien      /* Round 3.  */
380130561Sobrien      OP (A, B, C, D,  5,  4, (md5_uint32) 0xfffa3942);
381130561Sobrien      OP (D, A, B, C,  8, 11, (md5_uint32) 0x8771f681);
382130561Sobrien      OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
383130561Sobrien      OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
384130561Sobrien      OP (A, B, C, D,  1,  4, (md5_uint32) 0xa4beea44);
385130561Sobrien      OP (D, A, B, C,  4, 11, (md5_uint32) 0x4bdecfa9);
386130561Sobrien      OP (C, D, A, B,  7, 16, (md5_uint32) 0xf6bb4b60);
387130561Sobrien      OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
388130561Sobrien      OP (A, B, C, D, 13,  4, (md5_uint32) 0x289b7ec6);
389130561Sobrien      OP (D, A, B, C,  0, 11, (md5_uint32) 0xeaa127fa);
390130561Sobrien      OP (C, D, A, B,  3, 16, (md5_uint32) 0xd4ef3085);
391130561Sobrien      OP (B, C, D, A,  6, 23, (md5_uint32) 0x04881d05);
392130561Sobrien      OP (A, B, C, D,  9,  4, (md5_uint32) 0xd9d4d039);
393130561Sobrien      OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
394130561Sobrien      OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
395130561Sobrien      OP (B, C, D, A,  2, 23, (md5_uint32) 0xc4ac5665);
39677298Sobrien
397130561Sobrien#undef FX
398130561Sobrien#define FX(b, c, d) FI (b, c, d)
399130561Sobrien
40077298Sobrien      /* Round 4.  */
401130561Sobrien      OP (A, B, C, D,  0,  6, (md5_uint32) 0xf4292244);
402130561Sobrien      OP (D, A, B, C,  7, 10, (md5_uint32) 0x432aff97);
403130561Sobrien      OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
404130561Sobrien      OP (B, C, D, A,  5, 21, (md5_uint32) 0xfc93a039);
405130561Sobrien      OP (A, B, C, D, 12,  6, (md5_uint32) 0x655b59c3);
406130561Sobrien      OP (D, A, B, C,  3, 10, (md5_uint32) 0x8f0ccc92);
407130561Sobrien      OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
408130561Sobrien      OP (B, C, D, A,  1, 21, (md5_uint32) 0x85845dd1);
409130561Sobrien      OP (A, B, C, D,  8,  6, (md5_uint32) 0x6fa87e4f);
410130561Sobrien      OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
411130561Sobrien      OP (C, D, A, B,  6, 15, (md5_uint32) 0xa3014314);
412130561Sobrien      OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
413130561Sobrien      OP (A, B, C, D,  4,  6, (md5_uint32) 0xf7537e82);
414130561Sobrien      OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
415130561Sobrien      OP (C, D, A, B,  2, 15, (md5_uint32) 0x2ad7d2bb);
416130561Sobrien      OP (B, C, D, A,  9, 21, (md5_uint32) 0xeb86d391);
41777298Sobrien
41877298Sobrien      /* Add the starting values of the context.  */
41977298Sobrien      A += A_save;
42077298Sobrien      B += B_save;
42177298Sobrien      C += C_save;
42277298Sobrien      D += D_save;
42377298Sobrien    }
42477298Sobrien
42577298Sobrien  /* Put checksum in context given as argument.  */
42677298Sobrien  ctx->A = A;
42777298Sobrien  ctx->B = B;
42877298Sobrien  ctx->C = C;
42977298Sobrien  ctx->D = D;
43077298Sobrien}
431