125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Functions to compute MD5 message digest of files or memory blocks.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   according to the definition of MD5 in RFC 1321 from April 1992.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 1995-2011 Red Hat, Inc.
403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 1995.
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of either
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU Lesser General Public License as published by the Free
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 3 of the License, or (at
1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or
1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU General Public License as published by the Free
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 2 of the License, or (at
1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or both in parallel, as here.
2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received copies of the GNU General Public License and
2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the GNU Lesser General Public License along with this program.  If
2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   not, see <http://www.gnu.org/licenses/>.  */
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/types.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "md5.h"
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "system.h"
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define SWAP(n) LE32 (n)
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This array contains the bytes used to pad the buffer to the next
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
4625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Initialize structure containing state of computation.
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   (RFC 1321, 3.3: Step 3)  */
5125b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
5225b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_init_ctx (ctx)
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     struct md5_ctx *ctx;
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->A = 0x67452301;
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->B = 0xefcdab89;
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->C = 0x98badcfe;
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->D = 0x10325476;
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->total[0] = ctx->total[1] = 0;
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->buflen = 0;
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Put result from CTX in first 16 bytes following RESBUF.  The result
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   must be in little endian byte order.
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   IMPORTANT: On some systems it is required that RESBUF is correctly
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   aligned for a 32 bits value.  */
6925b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid *
7025b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_read_ctx (ctx, resbuf)
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     const struct md5_ctx *ctx;
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     void *resbuf;
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return resbuf;
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
8325b3c049e70834cf33790a28643ab058b507b35cBen Chengle64_copy (char *dest, uint64_t x)
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < 8; ++i)
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dest[i] = (uint8_t) x;
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      x >>= 8;
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process the remaining bytes in the internal buffer and the usual
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   prolog according to the standard and write the result to RESBUF.
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   IMPORTANT: On some systems it is required that RESBUF is correctly
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   aligned for a 32 bits value.  */
9725b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid *
9825b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_finish_ctx (ctx, resbuf)
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     struct md5_ctx *ctx;
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     void *resbuf;
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Take yet unprocessed bytes into account.  */
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 bytes = ctx->buflen;
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t pad;
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now count remaining bytes.  */
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->total[0] += bytes;
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx->total[0] < bytes)
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++ctx->total[1];
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (&ctx->buffer[bytes], fillbuf, pad);
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const uint64_t bit_length = ((ctx->total[0] << 3)
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       + ((uint64_t) ((ctx->total[1] << 3) |
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      (ctx->total[0] >> 29)) << 32));
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  le64_copy (&ctx->buffer[bytes + pad], bit_length);
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process last bytes.  */
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return md5_read_ctx (ctx, resbuf);
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef NEED_MD5_STREAM
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Compute MD5 message digest for bytes read from STREAM.  The
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   resulting message digest number will be written into the 16 bytes
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   beginning at RESBLOCK.  */
13125b3c049e70834cf33790a28643ab058b507b35cBen Chengint
13225b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_stream (stream, resblock)
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     FILE *stream;
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     void *resblock;
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Important: BLOCKSIZE must be a multiple of 64.  */
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define BLOCKSIZE 4096
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct md5_ctx ctx;
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char buffer[BLOCKSIZE + 72];
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t sum;
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the computation context.  */
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_init_ctx (&ctx);
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over full file contents.  */
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (1)
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 computation function processes the whole buffer so that with the
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 next round of the loop another block can be read.  */
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t n;
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sum = 0;
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Read block.  Take care for partial reads.  */
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  sum += n;
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (sum < BLOCKSIZE && n != 0);
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (n == 0 && ferror (stream))
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng        return 1;
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If end of file is reached, end the loop.  */
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (n == 0)
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Process buffer with BLOCKSIZE bytes.  Note that
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			BLOCKSIZE % 64 == 0
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng       */
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_process_block (buffer, BLOCKSIZE, &ctx);
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add the last bytes if necessary.  */
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (sum > 0)
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    md5_process_bytes (buffer, sum, &ctx);
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Construct result in desired memory.  */
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_finish_ctx (&ctx, resblock);
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef NEED_MD5_BUFFER
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   result is always in little endian byte order, so that a byte-wise
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   output yields to the wanted ASCII representation of the message
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   digest.  */
19125b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid *
19225b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_buffer (buffer, len, resblock)
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     const char *buffer;
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t len;
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     void *resblock;
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct md5_ctx ctx;
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the computation context.  */
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_init_ctx (&ctx);
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process whole buffer but last len % 64 bytes.  */
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_process_bytes (buffer, len, &ctx);
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Put result in desired memory area.  */
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return md5_finish_ctx (&ctx, resblock);
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21125b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
21225b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_process_bytes (buffer, len, ctx)
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     const void *buffer;
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t len;
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     struct md5_ctx *ctx;
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* When we already have some bits in our internal buffer concatenate
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     both inputs first.  */
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx->buflen != 0)
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t left_over = ctx->buflen;
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t add = 128 - left_over > len ? len : 128 - left_over;
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&ctx->buffer[left_over], buffer, add);
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ctx->buflen += add;
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ctx->buflen > 64)
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ctx->buflen &= 63;
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The regions in the following copy operation cannot overlap.  */
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ctx->buflen);
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      buffer = (const char *) buffer + add;
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      len -= add;
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process available complete blocks.  */
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (len >= 64)
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if !_STRING_ARCH_unaligned
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* To check alignment gcc has an appropriate operator.  Other
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   compilers don't.  */
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# if __GNUC__ >= 2
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# else
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# endif
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (UNALIGNED_P (buffer))
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	while (len > 64)
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    buffer = (const char *) buffer + 64;
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    len -= 64;
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  md5_process_block (buffer, len & ~63, ctx);
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  buffer = (const char *) buffer + (len & ~63);
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  len &= 63;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Move remaining bytes in internal buffer.  */
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (len > 0)
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t left_over = ctx->buflen;
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&ctx->buffer[left_over], buffer, len);
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      left_over += len;
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (left_over >= 64)
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  md5_process_block (ctx->buffer, 64, ctx);
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  left_over -= 64;
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (ctx->buffer, &ctx->buffer[64], left_over);
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ctx->buflen = left_over;
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* These are the four functions used in the four steps of the MD5 algorithm
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   and defined in the RFC 1321.  The first function is a little bit optimized
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   (as found in Colin Plumbs public domain implementation).  */
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* #define FF(b, c, d) ((b & c) | (~b & d)) */
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FF(b, c, d) (d ^ (b & (c ^ d)))
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FG(b, c, d) FF (d, b, c)
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FH(b, c, d) (b ^ c ^ d)
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FI(b, c, d) (c ^ (b | ~d))
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process LEN bytes of BUFFER, accumulating context into CTX.
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   It is assumed that LEN % 64 == 0.  */
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
29925b3c049e70834cf33790a28643ab058b507b35cBen Chengmd5_process_block (buffer, len, ctx)
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     const void *buffer;
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     size_t len;
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     struct md5_ctx *ctx;
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 correct_words[16];
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const md5_uint32 *words = buffer;
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nwords = len / sizeof (md5_uint32);
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const md5_uint32 *endp = words + nwords;
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 A = ctx->A;
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 B = ctx->B;
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 C = ctx->C;
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  md5_uint32 D = ctx->D;
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* First increment the byte count.  RFC 1321 specifies the possible
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     length of the file up to 2^64 bits.  Here we only compute the
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     number of bytes.  Do a double word increment.  */
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->total[0] += len;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx->total[0] < len)
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++ctx->total[1];
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process all bytes in the buffer with 64 bytes in each round of
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the loop.  */
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (words < endp)
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_uint32 *cwp = correct_words;
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_uint32 A_save = A;
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_uint32 B_save = B;
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_uint32 C_save = C;
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      md5_uint32 D_save = D;
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* First round: using the given function, the context and a constant
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 the next context is computed.  Because the algorithms processing
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 unit is a 32-bit word and it is determined to work on words in
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 little endian byte order we perhaps have to change the byte order
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 before the computation.  To reduce the work for the next steps
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 we store the swapped words in the array CORRECT_WORDS.  */
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OP(a, b, c, d, s, T)						\
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do								\
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng        {								\
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++words;							\
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CYCLIC (a, s);						\
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  a += b;							\
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng        }								\
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (0)
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* It is unfortunate that C does not provide an operator for
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 cyclic rotation.  Hope the C compiler is smart enough.  */
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Before we start, one word to the strange constants.
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 They are defined in RFC 1321 as
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng       */
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Round 1.  */
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (A, B, C, D,  7, 0xd76aa478);
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (D, A, B, C, 12, 0xe8c7b756);
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (C, D, A, B, 17, 0x242070db);
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (B, C, D, A, 22, 0xc1bdceee);
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (A, B, C, D,  7, 0xf57c0faf);
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (D, A, B, C, 12, 0x4787c62a);
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (C, D, A, B, 17, 0xa8304613);
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (B, C, D, A, 22, 0xfd469501);
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (A, B, C, D,  7, 0x698098d8);
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (D, A, B, C, 12, 0x8b44f7af);
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (C, D, A, B, 17, 0xffff5bb1);
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (B, C, D, A, 22, 0x895cd7be);
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (A, B, C, D,  7, 0x6b901122);
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (D, A, B, C, 12, 0xfd987193);
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (C, D, A, B, 17, 0xa679438e);
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (B, C, D, A, 22, 0x49b40821);
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* For the second to fourth round we have the possibly swapped words
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 in CORRECT_WORDS.  Redefine the macro to take an additional first
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 argument specifying the function to use.  */
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef OP
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define OP(f, a, b, c, d, k, s, T)					\
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do 								\
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{								\
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  a += f (b, c, d) + correct_words[k] + T;			\
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CYCLIC (a, s);						\
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  a += b;							\
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}								\
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (0)
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Round 2.  */
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, D, A, B, C, 10,  9, 0x02441453);
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Round 3.  */
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Round 4.  */
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Add the starting values of the context.  */
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      A += A_save;
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      B += B_save;
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      C += C_save;
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      D += D_save;
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Put checksum in context given as argument.  */
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->A = A;
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->B = B;
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->C = C;
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ctx->D = D;
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
455