libmicrohttpd2

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

md5_builtin.c (22329B)


      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-2026 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_builtin.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_builtin.h"
     55 
     56 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
     57 mhd_MD5_blti_init (struct mhd_Md5CtxBlti *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_ MHD_FN_PAR_INOUT_ (1)
    402 MHD_FN_PAR_IN_SIZE_ (3, 2) void
    403 mhd_MD5_blti_update (struct mhd_Md5CtxBlti *restrict ctx,
    404                      size_t size,
    405                      const void *restrict data)
    406 {
    407   unsigned int bytes_have; /**< Number of bytes in the context buffer */
    408   const uint8_t *unpr_d;
    409 
    410   unpr_d = (const uint8_t *)data;
    411 
    412 #ifndef MHD_UNIT_TESTING
    413   /* The function works fine with empty data, but it is expected
    414      that MHD calls it only with real data to process. */
    415   mhd_assert ((0 != size)
    416               && "A safeguard against an accidental call with missing data");
    417 #endif
    418 
    419   /* Note: (count & (mhd_MD5_BLOCK_SIZE-1))
    420            equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */
    421   bytes_have = (unsigned int)(ctx->count & (mhd_MD5_BLOCK_SIZE - 1));
    422   ctx->count += size;
    423 
    424   if (0 != bytes_have)
    425   {
    426     unsigned int bytes_left = mhd_MD5_BLOCK_SIZE - bytes_have;
    427     if (size >= bytes_left)
    428     {     /* Combine new data with data in the buffer and
    429              process the full block. */
    430       memcpy (((uint8_t *)ctx->buffer) + bytes_have,
    431               unpr_d,
    432               bytes_left);
    433       unpr_d += bytes_left;
    434       size -= bytes_left;
    435       md5_transform (ctx->H, ctx->buffer);
    436       bytes_have = 0;
    437     }
    438   }
    439 
    440   while (mhd_MD5_BLOCK_SIZE <= size)
    441   {   /* Process any full blocks of new data directly,
    442          without copying to the buffer. */
    443     md5_transform (ctx->H, unpr_d);
    444     unpr_d += mhd_MD5_BLOCK_SIZE;
    445     size -= mhd_MD5_BLOCK_SIZE;
    446   }
    447 
    448   if (0 != size)
    449   {   /* Copy incomplete block of new data (if any)
    450          to the buffer. */
    451     memcpy (((uint8_t *)ctx->buffer) + bytes_have, unpr_d, size);
    452   }
    453 }
    454 
    455 
    456 /**
    457  * Size of "length" insertion in bits.
    458  * See RFC 1321, end of Clause 3.2 (step 2).
    459  */
    460 #define MD5_SIZE_OF_LEN_ADD_BITS 64
    461 
    462 /**
    463  * Size of "length" insertion in bytes.
    464  */
    465 #define MD5_SIZE_OF_LEN_ADD (MD5_SIZE_OF_LEN_ADD_BITS / 8)
    466 
    467 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
    468 MHD_FN_PAR_OUT_ (2) void
    469 mhd_MD5_blti_finish (
    470   struct mhd_Md5CtxBlti *restrict ctx,
    471   uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_MD5_DIGEST_SIZE)])
    472 {
    473   uint64_t num_bits;   /**< Number of processed bits */
    474   unsigned int bytes_have; /**< Number of bytes in the context buffer */
    475 
    476   /* Memorise the number of processed bits.
    477      The padding and other data added here during the postprocessing must
    478      not change the amount of hashed data. */
    479   num_bits = ctx->count << 3;
    480 
    481   /* Note: (count & (mhd_MD5_BLOCK_SIZE-1))
    482            equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */
    483   bytes_have = (unsigned int)(ctx->count & (mhd_MD5_BLOCK_SIZE - 1));
    484 
    485   /* Input data must be padded with a single bit "1", then with zeros and
    486      the finally the length of data in bits must be added as the final bytes
    487      of the last block.
    488      See RFC 1321, Clauses 3.1 and 3.2 (steps 1 and 2). */
    489   /* Data is always processed in form of bytes (not by individual bits),
    490      therefore position of the first padding bit in byte is always
    491      predefined (0x80). */
    492   /* Buffer always have space for one byte at least (as full buffers are
    493      processed immediately). */
    494   ((uint8_t *)ctx->buffer)[bytes_have++] = 0x80;
    495 
    496   if (mhd_MD5_BLOCK_SIZE - bytes_have < MD5_SIZE_OF_LEN_ADD)
    497   {   /* No space in the current block to put the total length of message.
    498          Pad the current block with zeros and process it. */
    499     if (bytes_have < mhd_MD5_BLOCK_SIZE)
    500       memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
    501               mhd_MD5_BLOCK_SIZE - bytes_have);
    502     /* Process the full block. */
    503     md5_transform (ctx->H, ctx->buffer);
    504     /* Start the new block. */
    505     bytes_have = 0;
    506   }
    507 
    508   /* Pad the rest of the buffer with zeros. */
    509   memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
    510           mhd_MD5_BLOCK_SIZE - MD5_SIZE_OF_LEN_ADD - bytes_have);
    511   /* Put the number of bits in processed data as little-endian value.
    512      See RFC 1321, clauses 2 and 3.2 (step 2). */
    513   mhd_PUT_64BIT_LE_UNALIGN (ctx->buffer + mhd_MD5_BLOCK_SIZE_WORDS - 2,
    514                             num_bits);
    515   /* Process the full final block. */
    516   md5_transform (ctx->H, ctx->buffer);
    517 
    518   /* Put in LE mode the hash as the final digest.
    519      See RFC 1321, clauses 2 and 3.5 (step 5). */
    520   if (1)
    521   {
    522     bool use_tmp_buf_to_align_result;
    523 
    524 #if defined(mhd_PUT_32BIT_LE_UNALIGNED)
    525     use_tmp_buf_to_align_result = false;
    526 #elif defined(MHD_FAVOR_SMALL_CODE)
    527     use_tmp_buf_to_align_result = true; /* smaller code: eliminated branch below */
    528 #else
    529     use_tmp_buf_to_align_result =
    530       (0 != ((uintptr_t)digest) % mhd_UINT32_ALIGN);
    531 #endif
    532     if (use_tmp_buf_to_align_result)
    533     {
    534       /* If storing of the final result requires aligned address and
    535          the destination address is not aligned or compact code is used,
    536          store the final digest in aligned temporary buffer first, then
    537          copy it to the destination. */
    538       uint32_t alig_dgst[mhd_MD5_DIGEST_SIZE_WORDS];
    539       mhd_PUT_32BIT_LE (alig_dgst + 0, ctx->H[0]);
    540       mhd_PUT_32BIT_LE (alig_dgst + 1, ctx->H[1]);
    541       mhd_PUT_32BIT_LE (alig_dgst + 2, ctx->H[2]);
    542       mhd_PUT_32BIT_LE (alig_dgst + 3, ctx->H[3]);
    543       /* Copy result to the unaligned destination address. */
    544       memcpy (digest, alig_dgst, mhd_MD5_DIGEST_SIZE);
    545     }
    546     else
    547     {
    548       /* Use cast to (void*) here to mute compiler alignment warnings.
    549        * Compilers are not smart enough to see that alignment has been checked. */
    550       mhd_PUT_32BIT_LE ((void *)(digest + 0 * mhd_MD5_BYTES_IN_WORD), \
    551                         ctx->H[0]);
    552       mhd_PUT_32BIT_LE ((void *)(digest + 1 * mhd_MD5_BYTES_IN_WORD), \
    553                         ctx->H[1]);
    554       mhd_PUT_32BIT_LE ((void *)(digest + 2 * mhd_MD5_BYTES_IN_WORD), \
    555                         ctx->H[2]);
    556       mhd_PUT_32BIT_LE ((void *)(digest + 3 * mhd_MD5_BYTES_IN_WORD), \
    557                         ctx->H[3]);
    558     }
    559   }
    560 
    561   /* Erase potentially sensitive data. */
    562   memset (ctx, 0, sizeof(struct mhd_Md5CtxBlti));
    563 }
    564 
    565 
    566 mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE