libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

md5_int.c (21936B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2022-2024 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd 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   GNU libmicrohttpd 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   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/mhd2/md5_int.c
     41  * @brief  Calculation of MD5 digest as defined in RFC 1321
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #include "mhd_sys_options.h"
     46 
     47 #include "sys_bool_type.h"
     48 
     49 #include <string.h>
     50 #include "mhd_bithelpers.h"
     51 #include "mhd_align.h"
     52 #include "mhd_assert.h"
     53 
     54 #include "md5_int.h"
     55 
     56 MHD_INTERNAL void MHD_FN_PAR_NONNULL_ALL_
     57 mhd_MD5_init (struct mhd_Md5CtxInt *ctx)
     58 {
     59   /* Initial hash values, see RFC 1321, Clause 3.3 (step 3). */
     60   /* Note: values specified in RFC by bytes and should be loaded in
     61            little-endian mode, therefore hash values here are initialised with
     62            original bytes used in little-endian order. */
     63   ctx->H[0] = UINT32_C (0x67452301);
     64   ctx->H[1] = UINT32_C (0xefcdab89);
     65   ctx->H[2] = UINT32_C (0x98badcfe);
     66   ctx->H[3] = UINT32_C (0x10325476);
     67 
     68   /* Initialise the number of bytes. */
     69   ctx->count = 0;
     70 }
     71 
     72 
     73 mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
     74 
     75 /**
     76  * Base of MD5 transformation.
     77  * Gets full 64 bytes block of data and updates hash values;
     78  * @param H     hash values
     79  * @param M     the data buffer with #mhd_MD5_BLOCK_SIZE bytes block
     80  */
     81 static MHD_FN_PAR_NONNULL_ALL_ void
     82 md5_transform (uint32_t H[mhd_MD5_HASH_SIZE_WORDS],
     83                const void *restrict M)
     84 {
     85   /* Working variables,
     86      See RFC 1321, Clause 3.4 (step 4). */
     87   uint32_t A = H[0];
     88   uint32_t B = H[1];
     89   uint32_t C = H[2];
     90   uint32_t D = H[3];
     91 
     92   /* The data buffer. See RFC 1321, Clause 3.4 (step 4). */
     93   uint32_t X[16];
     94 
     95 #ifndef mhd_GET_32BIT_LE_UNALIGNED
     96   if (0 != (((uintptr_t) M) % mhd_UINT32_ALIGN))
     97   { /* The input data is unaligned. */
     98     /* Copy the unaligned input data to the aligned buffer. */
     99     memcpy (X, M, sizeof(X));
    100     /* The X[] buffer itself will be used as the source of the data,
    101      * but the data will be reloaded in correct bytes order on
    102      * the next steps. */
    103     M = (const void *) X;
    104   }
    105 #endif /* mhd_GET_32BIT_LE_UNALIGNED */
    106 
    107   /* Four auxiliary functions, see RFC 1321, Clause 3.4 (step 4). */
    108   /* Some optimisations used. */
    109 /* #define F_FUNC(x,y,z) (((x)&(y)) | ((~(x))&(z))) */ /* Original version */
    110 #define F_FUNC(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
    111 /* #define G_FUNC_1(x,y,z) (((x)&(z)) | ((y)&(~(z)))) */ /* Original version */
    112 /* #define G_FUNC_2(x,y,z) UINT32_C(0) */ /* Original version */
    113 #ifndef MHD_FAVOR_SMALL_CODE
    114 #  define G_FUNC_1(x,y,z) ((~(z)) & (y))
    115 #  define G_FUNC_2(x,y,z) ((z) & (x))
    116 #else  /* MHD_FAVOR_SMALL_CODE */
    117 #  define G_FUNC_1(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
    118 #  define G_FUNC_2(x,y,z) UINT32_C (0)
    119 #endif /* MHD_FAVOR_SMALL_CODE */
    120 #define H_FUNC(x,y,z) ((x) ^ (y) ^ (z)) /* Original version */
    121 /* #define I_FUNC(x,y,z) ((y) ^ ((x) | (~(z)))) */ /* Original version */
    122 #define I_FUNC(x,y,z) (((~(z)) | (x)) ^ (y))
    123 
    124   /* One step of round 1 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
    125      The original function was modified to use X[k] and T[i] as
    126      direct inputs. */
    127 #define MD5STEP_R1(va,vb,vc,vd,vX,vs,vT) do {          \
    128           (va) += (vX) + (vT);                               \
    129           (va) += F_FUNC ((vb),(vc),(vd));                    \
    130           (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0)
    131 
    132   /* Get value of X(k) from input data buffer.
    133      See RFC 1321 Clause 3.4 (step 4). */
    134 #define GET_X_FROM_DATA(buf,t) \
    135         mhd_GET_32BIT_LE (((const uint32_t*) (buf)) + (t))
    136 
    137   /* One step of round 2 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
    138      The original function was modified to use X[k] and T[i] as
    139      direct inputs. */
    140 #define MD5STEP_R2(va,vb,vc,vd,vX,vs,vT) do {         \
    141           (va) += (vX) + (vT);                              \
    142           (va) += G_FUNC_1 ((vb),(vc),(vd));                 \
    143           (va) += G_FUNC_2 ((vb),(vc),(vd));                 \
    144           (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0)
    145 
    146   /* One step of round 3 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
    147      The original function was modified to use X[k] and T[i] as
    148      direct inputs. */
    149 #define MD5STEP_R3(va,vb,vc,vd,vX,vs,vT) do {         \
    150           (va) += (vX) + (vT);                              \
    151           (va) += H_FUNC ((vb),(vc),(vd));                   \
    152           (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0)
    153 
    154   /* One step of round 4 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
    155      The original function was modified to use X[k] and T[i] as
    156      direct inputs. */
    157 #define MD5STEP_R4(va,vb,vc,vd,vX,vs,vT) do {         \
    158           (va) += (vX) + (vT);                              \
    159           (va) += I_FUNC ((vb),(vc),(vd));                   \
    160           (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0)
    161 
    162 #if ! defined(MHD_FAVOR_SMALL_CODE)
    163 
    164   /* Round 1. */
    165 
    166 #if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
    167   if ((const void *) X == M)
    168   {
    169     /* The input data is already in the data buffer X[] in correct bytes
    170        order. */
    171     MD5STEP_R1 (A, B, C, D, X[0],  7,  UINT32_C (0xd76aa478));
    172     MD5STEP_R1 (D, A, B, C, X[1],  12, UINT32_C (0xe8c7b756));
    173     MD5STEP_R1 (C, D, A, B, X[2],  17, UINT32_C (0x242070db));
    174     MD5STEP_R1 (B, C, D, A, X[3],  22, UINT32_C (0xc1bdceee));
    175 
    176     MD5STEP_R1 (A, B, C, D, X[4],  7,  UINT32_C (0xf57c0faf));
    177     MD5STEP_R1 (D, A, B, C, X[5],  12, UINT32_C (0x4787c62a));
    178     MD5STEP_R1 (C, D, A, B, X[6],  17, UINT32_C (0xa8304613));
    179     MD5STEP_R1 (B, C, D, A, X[7],  22, UINT32_C (0xfd469501));
    180 
    181     MD5STEP_R1 (A, B, C, D, X[8],  7,  UINT32_C (0x698098d8));
    182     MD5STEP_R1 (D, A, B, C, X[9],  12, UINT32_C (0x8b44f7af));
    183     MD5STEP_R1 (C, D, A, B, X[10], 17, UINT32_C (0xffff5bb1));
    184     MD5STEP_R1 (B, C, D, A, X[11], 22, UINT32_C (0x895cd7be));
    185 
    186     MD5STEP_R1 (A, B, C, D, X[12], 7,  UINT32_C (0x6b901122));
    187     MD5STEP_R1 (D, A, B, C, X[13], 12, UINT32_C (0xfd987193));
    188     MD5STEP_R1 (C, D, A, B, X[14], 17, UINT32_C (0xa679438e));
    189     MD5STEP_R1 (B, C, D, A, X[15], 22, UINT32_C (0x49b40821));
    190   }
    191   else /* Combined with the next 'if' */
    192 #endif /* mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN */
    193   if (1)
    194   {
    195     /* The input data is loaded in correct (little-endian) format before
    196        calculations on each step. */
    197     MD5STEP_R1 (A, B, C, D, X[0]  = GET_X_FROM_DATA (M, 0),  7, \
    198                 UINT32_C (0xd76aa478));
    199     MD5STEP_R1 (D, A, B, C, X[1]  = GET_X_FROM_DATA (M, 1),  12, \
    200                 UINT32_C (0xe8c7b756));
    201     MD5STEP_R1 (C, D, A, B, X[2]  = GET_X_FROM_DATA (M, 2),  17, \
    202                 UINT32_C (0x242070db));
    203     MD5STEP_R1 (B, C, D, A, X[3]  = GET_X_FROM_DATA (M, 3),  22, \
    204                 UINT32_C (0xc1bdceee));
    205 
    206     MD5STEP_R1 (A, B, C, D, X[4]  = GET_X_FROM_DATA (M, 4),  7, \
    207                 UINT32_C (0xf57c0faf));
    208     MD5STEP_R1 (D, A, B, C, X[5]  = GET_X_FROM_DATA (M, 5),  12, \
    209                 UINT32_C (0x4787c62a));
    210     MD5STEP_R1 (C, D, A, B, X[6]  = GET_X_FROM_DATA (M, 6),  17, \
    211                 UINT32_C (0xa8304613));
    212     MD5STEP_R1 (B, C, D, A, X[7]  = GET_X_FROM_DATA (M, 7),  22, \
    213                 UINT32_C (0xfd469501));
    214 
    215     MD5STEP_R1 (A, B, C, D, X[8]  = GET_X_FROM_DATA (M, 8),  7, \
    216                 UINT32_C (0x698098d8));
    217     MD5STEP_R1 (D, A, B, C, X[9]  = GET_X_FROM_DATA (M, 9),  12, \
    218                 UINT32_C (0x8b44f7af));
    219     MD5STEP_R1 (C, D, A, B, X[10] = GET_X_FROM_DATA (M, 10), 17, \
    220                 UINT32_C (0xffff5bb1));
    221     MD5STEP_R1 (B, C, D, A, X[11] = GET_X_FROM_DATA (M, 11), 22, \
    222                 UINT32_C (0x895cd7be));
    223 
    224     MD5STEP_R1 (A, B, C, D, X[12] = GET_X_FROM_DATA (M, 12), 7, \
    225                 UINT32_C (0x6b901122));
    226     MD5STEP_R1 (D, A, B, C, X[13] = GET_X_FROM_DATA (M, 13), 12, \
    227                 UINT32_C (0xfd987193));
    228     MD5STEP_R1 (C, D, A, B, X[14] = GET_X_FROM_DATA (M, 14), 17, \
    229                 UINT32_C (0xa679438e));
    230     MD5STEP_R1 (B, C, D, A, X[15] = GET_X_FROM_DATA (M, 15), 22, \
    231                 UINT32_C (0x49b40821));
    232   }
    233 
    234   /* Round 2. */
    235 
    236   MD5STEP_R2 (A, B, C, D, X[1], 5, UINT32_C (0xf61e2562));
    237   MD5STEP_R2 (D, A, B, C, X[6], 9, UINT32_C (0xc040b340));
    238   MD5STEP_R2 (C, D, A, B, X[11], 14, UINT32_C (0x265e5a51));
    239   MD5STEP_R2 (B, C, D, A, X[0], 20, UINT32_C (0xe9b6c7aa));
    240 
    241   MD5STEP_R2 (A, B, C, D, X[5], 5, UINT32_C (0xd62f105d));
    242   MD5STEP_R2 (D, A, B, C, X[10], 9, UINT32_C (0x02441453));
    243   MD5STEP_R2 (C, D, A, B, X[15], 14, UINT32_C (0xd8a1e681));
    244   MD5STEP_R2 (B, C, D, A, X[4], 20, UINT32_C (0xe7d3fbc8));
    245 
    246   MD5STEP_R2 (A, B, C, D, X[9], 5, UINT32_C (0x21e1cde6));
    247   MD5STEP_R2 (D, A, B, C, X[14], 9, UINT32_C (0xc33707d6));
    248   MD5STEP_R2 (C, D, A, B, X[3], 14, UINT32_C (0xf4d50d87));
    249   MD5STEP_R2 (B, C, D, A, X[8], 20, UINT32_C (0x455a14ed));
    250 
    251   MD5STEP_R2 (A, B, C, D, X[13], 5, UINT32_C (0xa9e3e905));
    252   MD5STEP_R2 (D, A, B, C, X[2], 9, UINT32_C (0xfcefa3f8));
    253   MD5STEP_R2 (C, D, A, B, X[7], 14, UINT32_C (0x676f02d9));
    254   MD5STEP_R2 (B, C, D, A, X[12], 20, UINT32_C (0x8d2a4c8a));
    255 
    256   /* Round 3. */
    257 
    258   MD5STEP_R3 (A, B, C, D, X[5], 4, UINT32_C (0xfffa3942));
    259   MD5STEP_R3 (D, A, B, C, X[8], 11, UINT32_C (0x8771f681));
    260   MD5STEP_R3 (C, D, A, B, X[11], 16, UINT32_C (0x6d9d6122));
    261   MD5STEP_R3 (B, C, D, A, X[14], 23, UINT32_C (0xfde5380c));
    262 
    263   MD5STEP_R3 (A, B, C, D, X[1], 4, UINT32_C (0xa4beea44));
    264   MD5STEP_R3 (D, A, B, C, X[4], 11, UINT32_C (0x4bdecfa9));
    265   MD5STEP_R3 (C, D, A, B, X[7], 16, UINT32_C (0xf6bb4b60));
    266   MD5STEP_R3 (B, C, D, A, X[10], 23, UINT32_C (0xbebfbc70));
    267 
    268   MD5STEP_R3 (A, B, C, D, X[13], 4, UINT32_C (0x289b7ec6));
    269   MD5STEP_R3 (D, A, B, C, X[0], 11, UINT32_C (0xeaa127fa));
    270   MD5STEP_R3 (C, D, A, B, X[3], 16, UINT32_C (0xd4ef3085));
    271   MD5STEP_R3 (B, C, D, A, X[6], 23, UINT32_C (0x04881d05));
    272 
    273   MD5STEP_R3 (A, B, C, D, X[9], 4, UINT32_C (0xd9d4d039));
    274   MD5STEP_R3 (D, A, B, C, X[12], 11, UINT32_C (0xe6db99e5));
    275   MD5STEP_R3 (C, D, A, B, X[15], 16, UINT32_C (0x1fa27cf8));
    276   MD5STEP_R3 (B, C, D, A, X[2], 23, UINT32_C (0xc4ac5665));
    277 
    278   /* Round 4. */
    279 
    280   MD5STEP_R4 (A, B, C, D, X[0], 6, UINT32_C (0xf4292244));
    281   MD5STEP_R4 (D, A, B, C, X[7], 10, UINT32_C (0x432aff97));
    282   MD5STEP_R4 (C, D, A, B, X[14], 15, UINT32_C (0xab9423a7));
    283   MD5STEP_R4 (B, C, D, A, X[5], 21, UINT32_C (0xfc93a039));
    284 
    285   MD5STEP_R4 (A, B, C, D, X[12], 6, UINT32_C (0x655b59c3));
    286   MD5STEP_R4 (D, A, B, C, X[3], 10, UINT32_C (0x8f0ccc92));
    287   MD5STEP_R4 (C, D, A, B, X[10], 15, UINT32_C (0xffeff47d));
    288   MD5STEP_R4 (B, C, D, A, X[1], 21, UINT32_C (0x85845dd1));
    289 
    290   MD5STEP_R4 (A, B, C, D, X[8], 6, UINT32_C (0x6fa87e4f));
    291   MD5STEP_R4 (D, A, B, C, X[15], 10, UINT32_C (0xfe2ce6e0));
    292   MD5STEP_R4 (C, D, A, B, X[6], 15, UINT32_C (0xa3014314));
    293   MD5STEP_R4 (B, C, D, A, X[13], 21, UINT32_C (0x4e0811a1));
    294 
    295   MD5STEP_R4 (A, B, C, D, X[4], 6, UINT32_C (0xf7537e82));
    296   MD5STEP_R4 (D, A, B, C, X[11], 10, UINT32_C (0xbd3af235));
    297   MD5STEP_R4 (C, D, A, B, X[2], 15, UINT32_C (0x2ad7d2bb));
    298   MD5STEP_R4 (B, C, D, A, X[9], 21, UINT32_C (0xeb86d391));
    299 #else  /* MHD_FAVOR_SMALL_CODE */
    300   if (1)
    301   {
    302     static const uint32_t T[64] =
    303     { UINT32_C (0xd76aa478), UINT32_C (0xe8c7b756), UINT32_C (0x242070db),
    304       UINT32_C (0xc1bdceee), UINT32_C (0xf57c0faf), UINT32_C (0x4787c62a),
    305       UINT32_C (0xa8304613), UINT32_C (0xfd469501), UINT32_C (0x698098d8),
    306       UINT32_C (0x8b44f7af), UINT32_C (0xffff5bb1), UINT32_C (0x895cd7be),
    307       UINT32_C (0x6b901122), UINT32_C (0xfd987193), UINT32_C (0xa679438e),
    308       UINT32_C (0x49b40821), UINT32_C (0xf61e2562), UINT32_C (0xc040b340),
    309       UINT32_C (0x265e5a51), UINT32_C (0xe9b6c7aa), UINT32_C (0xd62f105d),
    310       UINT32_C (0x02441453), UINT32_C (0xd8a1e681), UINT32_C (0xe7d3fbc8),
    311       UINT32_C (0x21e1cde6), UINT32_C (0xc33707d6), UINT32_C (0xf4d50d87),
    312       UINT32_C (0x455a14ed), UINT32_C (0xa9e3e905), UINT32_C (0xfcefa3f8),
    313       UINT32_C (0x676f02d9), UINT32_C (0x8d2a4c8a), UINT32_C (0xfffa3942),
    314       UINT32_C (0x8771f681), UINT32_C (0x6d9d6122), UINT32_C (0xfde5380c),
    315       UINT32_C (0xa4beea44), UINT32_C (0x4bdecfa9), UINT32_C (0xf6bb4b60),
    316       UINT32_C (0xbebfbc70), UINT32_C (0x289b7ec6), UINT32_C (0xeaa127fa),
    317       UINT32_C (0xd4ef3085), UINT32_C (0x04881d05), UINT32_C (0xd9d4d039),
    318       UINT32_C (0xe6db99e5), UINT32_C (0x1fa27cf8), UINT32_C (0xc4ac5665),
    319       UINT32_C (0xf4292244), UINT32_C (0x432aff97), UINT32_C (0xab9423a7),
    320       UINT32_C (0xfc93a039), UINT32_C (0x655b59c3), UINT32_C (0x8f0ccc92),
    321       UINT32_C (0xffeff47d), UINT32_C (0x85845dd1), UINT32_C (0x6fa87e4f),
    322       UINT32_C (0xfe2ce6e0), UINT32_C (0xa3014314), UINT32_C (0x4e0811a1),
    323       UINT32_C (0xf7537e82), UINT32_C (0xbd3af235), UINT32_C (0x2ad7d2bb),
    324       UINT32_C (0xeb86d391) };
    325     unsigned int i; /**< Zero-based index */
    326 
    327     /* Round 1. */
    328 
    329     i = 0;
    330     do
    331     {
    332       /* The input data is loaded in correct (little-endian) format before
    333          calculations on each step. */
    334       MD5STEP_R1 (A, B, C, D, X[i]  = GET_X_FROM_DATA (M, i),  7,  T[i]);
    335       ++i;
    336       MD5STEP_R1 (D, A, B, C, X[i]  = GET_X_FROM_DATA (M, i),  12, T[i]);
    337       ++i;
    338       MD5STEP_R1 (C, D, A, B, X[i]  = GET_X_FROM_DATA (M, i),  17, T[i]);
    339       ++i;
    340       MD5STEP_R1 (B, C, D, A, X[i]  = GET_X_FROM_DATA (M, i),  22, T[i]);
    341       ++i;
    342     } while (i < 16);
    343 
    344     /* Round 2. */
    345 
    346     do
    347     {
    348       const unsigned int idx_add = i;
    349       MD5STEP_R2 (A, B, C, D, X[(1U  + idx_add) & 15U], 5,  T[i]);
    350       ++i;
    351       MD5STEP_R2 (D, A, B, C, X[(6U  + idx_add) & 15U], 9,  T[i]);
    352       ++i;
    353       MD5STEP_R2 (C, D, A, B, X[(11U + idx_add) & 15U], 14, T[i]);
    354       ++i;
    355       MD5STEP_R2 (B, C, D, A, X[(0U  + idx_add) & 15U], 20, T[i]);
    356       ++i;
    357     } while (i < 32);
    358 
    359     /* Round 3. */
    360 
    361     do
    362     {
    363       const unsigned int idx_add = i;
    364       MD5STEP_R3 (A, B, C, D, X[(5U  + 64U - idx_add) & 15U], 4,  T[i]);
    365       ++i;
    366       MD5STEP_R3 (D, A, B, C, X[(8U  + 64U - idx_add) & 15U], 11, T[i]);
    367       ++i;
    368       MD5STEP_R3 (C, D, A, B, X[(11U + 64U - idx_add) & 15U], 16, T[i]);
    369       ++i;
    370       MD5STEP_R3 (B, C, D, A, X[(14U + 64U - idx_add) & 15U], 23, T[i]);
    371       ++i;
    372     } while (i < 48);
    373 
    374     /* Round 4. */
    375 
    376     do
    377     {
    378       const unsigned int idx_add = i;
    379       MD5STEP_R4 (A, B, C, D, X[(0U  + 64U - idx_add) & 15U], 6,  T[i]);
    380       ++i;
    381       MD5STEP_R4 (D, A, B, C, X[(7U  + 64U - idx_add) & 15U], 10, T[i]);
    382       ++i;
    383       MD5STEP_R4 (C, D, A, B, X[(14U + 64U - idx_add) & 15U], 15, T[i]);
    384       ++i;
    385       MD5STEP_R4 (B, C, D, A, X[(5U  + 64U - idx_add) & 15U], 21, T[i]);
    386       ++i;
    387     } while (i < 64);
    388   }
    389 #endif /* MHD_FAVOR_SMALL_CODE */
    390 
    391   /* Finally increment and store working variables.
    392      See RFC 1321, end of Clause 3.4 (step 4). */
    393 
    394   H[0] += A;
    395   H[1] += B;
    396   H[2] += C;
    397   H[3] += D;
    398 }
    399 
    400 
    401 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    402 MHD_FN_PAR_IN_SIZE_ (3, 2) void
    403 mhd_MD5_update (struct mhd_Md5CtxInt *restrict ctx,
    404                 size_t size,
    405                 const uint8_t *restrict data)
    406 {
    407   unsigned int bytes_have; /**< Number of bytes in the context buffer */
    408 
    409   mhd_assert (0 != size);
    410 
    411   /* Note: (count & (mhd_MD5_BLOCK_SIZE-1))
    412            equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */
    413   bytes_have = (unsigned int) (ctx->count & (mhd_MD5_BLOCK_SIZE - 1));
    414   ctx->count += size;
    415 
    416   if (0 != bytes_have)
    417   {
    418     unsigned int bytes_left = mhd_MD5_BLOCK_SIZE - bytes_have;
    419     if (size >= bytes_left)
    420     {     /* Combine new data with data in the buffer and
    421              process the full block. */
    422       memcpy (((uint8_t *) ctx->buffer) + bytes_have,
    423               data,
    424               bytes_left);
    425       data += bytes_left;
    426       size -= bytes_left;
    427       md5_transform (ctx->H, ctx->buffer);
    428       bytes_have = 0;
    429     }
    430   }
    431 
    432   while (mhd_MD5_BLOCK_SIZE <= size)
    433   {   /* Process any full blocks of new data directly,
    434          without copying to the buffer. */
    435     md5_transform (ctx->H, data);
    436     data += mhd_MD5_BLOCK_SIZE;
    437     size -= mhd_MD5_BLOCK_SIZE;
    438   }
    439 
    440   if (0 != size)
    441   {   /* Copy incomplete block of new data (if any)
    442          to the buffer. */
    443     memcpy (((uint8_t *) ctx->buffer) + bytes_have, data, size);
    444   }
    445 }
    446 
    447 
    448 /**
    449  * Size of "length" insertion in bits.
    450  * See RFC 1321, end of Clause 3.2 (step 2).
    451  */
    452 #define MD5_SIZE_OF_LEN_ADD_BITS 64
    453 
    454 /**
    455  * Size of "length" insertion in bytes.
    456  */
    457 #define MD5_SIZE_OF_LEN_ADD (MD5_SIZE_OF_LEN_ADD_BITS / 8)
    458 
    459 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    460 MHD_FN_PAR_OUT_ (2) void
    461 mhd_MD5_finish (struct mhd_Md5CtxInt *restrict ctx,
    462                 uint8_t digest[mhd_MD5_DIGEST_SIZE])
    463 {
    464   uint64_t num_bits;   /**< Number of processed bits */
    465   unsigned int bytes_have; /**< Number of bytes in the context buffer */
    466 
    467   /* Memorise the number of processed bits.
    468      The padding and other data added here during the postprocessing must
    469      not change the amount of hashed data. */
    470   num_bits = ctx->count << 3;
    471 
    472   /* Note: (count & (mhd_MD5_BLOCK_SIZE-1))
    473            equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */
    474   bytes_have = (unsigned int) (ctx->count & (mhd_MD5_BLOCK_SIZE - 1));
    475 
    476   /* Input data must be padded with a single bit "1", then with zeros and
    477      the finally the length of data in bits must be added as the final bytes
    478      of the last block.
    479      See RFC 1321, Clauses 3.1 and 3.2 (steps 1 and 2). */
    480   /* Data is always processed in form of bytes (not by individual bits),
    481      therefore position of the first padding bit in byte is always
    482      predefined (0x80). */
    483   /* Buffer always have space for one byte at least (as full buffers are
    484      processed immediately). */
    485   ((uint8_t *) ctx->buffer)[bytes_have++] = 0x80;
    486 
    487   if (mhd_MD5_BLOCK_SIZE - bytes_have < MD5_SIZE_OF_LEN_ADD)
    488   {   /* No space in the current block to put the total length of message.
    489          Pad the current block with zeros and process it. */
    490     if (bytes_have < mhd_MD5_BLOCK_SIZE)
    491       memset (((uint8_t *) ctx->buffer) + bytes_have, 0,
    492               mhd_MD5_BLOCK_SIZE - bytes_have);
    493     /* Process the full block. */
    494     md5_transform (ctx->H, ctx->buffer);
    495     /* Start the new block. */
    496     bytes_have = 0;
    497   }
    498 
    499   /* Pad the rest of the buffer with zeros. */
    500   memset (((uint8_t *) ctx->buffer) + bytes_have, 0,
    501           mhd_MD5_BLOCK_SIZE - MD5_SIZE_OF_LEN_ADD - bytes_have);
    502   /* Put the number of bits in processed data as little-endian value.
    503      See RFC 1321, clauses 2 and 3.2 (step 2). */
    504   mhd_PUT_64BIT_LE_UNALIGN (ctx->buffer + mhd_MD5_BLOCK_SIZE_WORDS - 2,
    505                             num_bits);
    506   /* Process the full final block. */
    507   md5_transform (ctx->H, ctx->buffer);
    508 
    509   /* Put in LE mode the hash as the final digest.
    510      See RFC 1321, clauses 2 and 3.5 (step 5). */
    511   if (1)
    512   {
    513     bool use_tmp_buf_to_align_result;
    514 
    515 #if defined(mhd_PUT_32BIT_LE_UNALIGNED)
    516     use_tmp_buf_to_align_result = false;
    517 #elif defined (MHD_FAVOR_SMALL_CODE)
    518     use_tmp_buf_to_align_result = true; /* smaller code: eliminated branch below */
    519 #else
    520     use_tmp_buf_to_align_result =
    521       (0 != ((uintptr_t) digest) % mhd_UINT32_ALIGN);
    522 #endif
    523     if (use_tmp_buf_to_align_result)
    524     {
    525       /* If storing of the final result requires aligned address and
    526          the destination address is not aligned or compact code is used,
    527          store the final digest in aligned temporary buffer first, then
    528          copy it to the destination. */
    529       uint32_t alig_dgst[mhd_MD5_DIGEST_SIZE_WORDS];
    530       mhd_PUT_32BIT_LE (alig_dgst + 0, ctx->H[0]);
    531       mhd_PUT_32BIT_LE (alig_dgst + 1, ctx->H[1]);
    532       mhd_PUT_32BIT_LE (alig_dgst + 2, ctx->H[2]);
    533       mhd_PUT_32BIT_LE (alig_dgst + 3, ctx->H[3]);
    534       /* Copy result to the unaligned destination address. */
    535       memcpy (digest, alig_dgst, mhd_MD5_DIGEST_SIZE);
    536     }
    537     else
    538     {
    539       /* Use cast to (void*) here to mute compiler alignment warnings.
    540        * Compilers are not smart enough to see that alignment has been checked. */
    541       mhd_PUT_32BIT_LE ((void *) (digest + 0 * mhd_MD5_BYTES_IN_WORD), \
    542                         ctx->H[0]);
    543       mhd_PUT_32BIT_LE ((void *) (digest + 1 * mhd_MD5_BYTES_IN_WORD), \
    544                         ctx->H[1]);
    545       mhd_PUT_32BIT_LE ((void *) (digest + 2 * mhd_MD5_BYTES_IN_WORD), \
    546                         ctx->H[2]);
    547       mhd_PUT_32BIT_LE ((void *) (digest + 3 * mhd_MD5_BYTES_IN_WORD), \
    548                         ctx->H[3]);
    549     }
    550   }
    551 
    552   /* Erase potentially sensitive data. */
    553   memset (ctx, 0, sizeof(struct mhd_Md5CtxInt));
    554 }
    555 
    556 
    557 mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE