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