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