(root)/
glibc-2.38/
crypt/
md5.c
       1  /* Functions to compute MD5 message digest of files or memory blocks.
       2     according to the definition of MD5 in RFC 1321 from April 1992.
       3     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
      21  
      22  #ifdef HAVE_CONFIG_H
      23  # include <config.h>
      24  #endif
      25  
      26  #include <sys/types.h>
      27  
      28  #if STDC_HEADERS || defined _LIBC
      29  # include <stdlib.h>
      30  # include <string.h>
      31  #else
      32  # ifndef HAVE_MEMCPY
      33  #  define memcpy(d, s, n) (bcopy ((s), (d), (n)), (d))
      34  # endif
      35  #endif
      36  
      37  #include "md5.h"
      38  
      39  #ifdef _LIBC
      40  # include <endian.h>
      41  # if __BYTE_ORDER == __BIG_ENDIAN
      42  #  define WORDS_BIGENDIAN 1
      43  # endif
      44  /* We need to keep the namespace clean so define the MD5 function
      45     protected using leading __ .  */
      46  # define md5_init_ctx __md5_init_ctx
      47  # define md5_process_bytes __md5_process_bytes
      48  # define md5_finish_ctx __md5_finish_ctx
      49  # define md5_read_ctx __md5_read_ctx
      50  # define md5_stream __md5_stream
      51  # define md5_buffer __md5_buffer
      52  #endif
      53  
      54  #ifdef WORDS_BIGENDIAN
      55  # define SWAP(n)							\
      56      (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
      57  #else
      58  # define SWAP(n) (n)
      59  #endif
      60  
      61  
      62  /* This array contains the bytes used to pad the buffer to the next
      63     64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
      64  static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
      65  
      66  
      67  /* Initialize structure containing state of computation.
      68     (RFC 1321, 3.3: Step 3)  */
      69  void
      70  md5_init_ctx (struct md5_ctx *ctx)
      71  {
      72    ctx->A = 0x67452301;
      73    ctx->B = 0xefcdab89;
      74    ctx->C = 0x98badcfe;
      75    ctx->D = 0x10325476;
      76  
      77    ctx->total[0] = ctx->total[1] = 0;
      78    ctx->buflen = 0;
      79  }
      80  
      81  /* Put result from CTX in first 16 bytes following RESBUF.  The result
      82     must be in little endian byte order.
      83  
      84     IMPORTANT: On some systems it is required that RESBUF is correctly
      85     aligned for a 32 bits value.  */
      86  void *
      87  md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
      88  {
      89    ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
      90    ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
      91    ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
      92    ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
      93  
      94    return resbuf;
      95  }
      96  
      97  /* Process the remaining bytes in the internal buffer and the usual
      98     prolog according to the standard and write the result to RESBUF.
      99  
     100     IMPORTANT: On some systems it is required that RESBUF is correctly
     101     aligned for a 32 bits value.  */
     102  void *
     103  md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
     104  {
     105    /* Take yet unprocessed bytes into account.  */
     106    md5_uint32 bytes = ctx->buflen;
     107    size_t pad;
     108  
     109    /* Now count remaining bytes.  */
     110    ctx->total[0] += bytes;
     111    if (ctx->total[0] < bytes)
     112      ++ctx->total[1];
     113  
     114    pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
     115    memcpy (&ctx->buffer[bytes], fillbuf, pad);
     116  
     117    /* Put the 64-bit file length in *bits* at the end of the buffer.  */
     118    ctx->buffer32[(bytes + pad) / 4] = SWAP (ctx->total[0] << 3);
     119    ctx->buffer32[(bytes + pad + 4) / 4] = SWAP ((ctx->total[1] << 3)
     120  					       | (ctx->total[0] >> 29));
     121  
     122    /* Process last bytes.  */
     123    __md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
     124  
     125    return md5_read_ctx (ctx, resbuf);
     126  }
     127  
     128  /* Compute MD5 message digest for bytes read from STREAM.  The
     129     resulting message digest number will be written into the 16 bytes
     130     beginning at RESBLOCK.  */
     131  int
     132  md5_stream (FILE *stream, void *resblock)
     133  {
     134    /* Important: BLOCKSIZE must be a multiple of 64.  */
     135  #define BLOCKSIZE 4096
     136    struct md5_ctx ctx;
     137    char buffer[BLOCKSIZE + 72];
     138    size_t sum;
     139  
     140    /* Initialize the computation context.  */
     141    md5_init_ctx (&ctx);
     142  
     143    /* Iterate over full file contents.  */
     144    while (1)
     145      {
     146        /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
     147  	 computation function processes the whole buffer so that with the
     148  	 next round of the loop another block can be read.  */
     149        size_t n;
     150        sum = 0;
     151  
     152        /* Read block.  Take care for partial reads.  */
     153        do
     154  	{
     155  	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
     156  
     157  	  sum += n;
     158  	}
     159        while (sum < BLOCKSIZE && n != 0);
     160        if (n == 0 && ferror (stream))
     161  	return 1;
     162  
     163        /* If end of file is reached, end the loop.  */
     164        if (n == 0)
     165  	break;
     166  
     167        /* Process buffer with BLOCKSIZE bytes.  Note that
     168  			BLOCKSIZE % 64 == 0
     169         */
     170        __md5_process_block (buffer, BLOCKSIZE, &ctx);
     171      }
     172  
     173    /* Add the last bytes if necessary.  */
     174    if (sum > 0)
     175      md5_process_bytes (buffer, sum, &ctx);
     176  
     177    /* Construct result in desired memory.  */
     178    md5_finish_ctx (&ctx, resblock);
     179    return 0;
     180  }
     181  
     182  /* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
     183     result is always in little endian byte order, so that a byte-wise
     184     output yields to the wanted ASCII representation of the message
     185     digest.  */
     186  void *
     187  md5_buffer (const char *buffer, size_t len, void *resblock)
     188  {
     189    struct md5_ctx ctx;
     190  
     191    /* Initialize the computation context.  */
     192    md5_init_ctx (&ctx);
     193  
     194    /* Process whole buffer but last len % 64 bytes.  */
     195    md5_process_bytes (buffer, len, &ctx);
     196  
     197    /* Put result in desired memory area.  */
     198    return md5_finish_ctx (&ctx, resblock);
     199  }
     200  
     201  
     202  void
     203  md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
     204  {
     205    /* When we already have some bits in our internal buffer concatenate
     206       both inputs first.  */
     207    if (ctx->buflen != 0)
     208      {
     209        size_t left_over = ctx->buflen;
     210        size_t add = 128 - left_over > len ? len : 128 - left_over;
     211  
     212        memcpy (&ctx->buffer[left_over], buffer, add);
     213        ctx->buflen += add;
     214  
     215        if (ctx->buflen > 64)
     216  	{
     217  	  __md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
     218  
     219  	  ctx->buflen &= 63;
     220  	  /* The regions in the following copy operation cannot overlap.  */
     221  	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
     222  		  ctx->buflen);
     223  	}
     224  
     225        buffer = (const char *) buffer + add;
     226        len -= add;
     227      }
     228  
     229    /* Process available complete blocks.  */
     230    if (len >= 64)
     231      {
     232        while (len > 64)
     233  	{
     234  	  __md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
     235  	  buffer = (const char *) buffer + 64;
     236  	  len -= 64;
     237  	}
     238      }
     239  
     240    /* Move remaining bytes in internal buffer.  */
     241    if (len > 0)
     242      {
     243        size_t left_over = ctx->buflen;
     244  
     245        memcpy (&ctx->buffer[left_over], buffer, len);
     246        left_over += len;
     247        if (left_over >= 64)
     248  	{
     249  	  __md5_process_block (ctx->buffer, 64, ctx);
     250  	  left_over -= 64;
     251  	  memcpy (ctx->buffer, &ctx->buffer[64], left_over);
     252  	}
     253        ctx->buflen = left_over;
     254      }
     255  }
     256  
     257  #include <md5-block.c>