The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/** A local MD5 implementation
2 *
3 * @note license is LGPL, but largely derived from a public domain source.
4 *
5 * @file src/lib/util/md5.c
6 */
7RCSID("$Id: c8885e9123963185b38c4218a569cc87ac59231e $")
8
9#include <freeradius-devel/util/debug.h>
10#include <freeradius-devel/util/strerror.h>
11#include <freeradius-devel/util/atexit.h>
12
13/*
14 * FORCE MD5 TO USE OUR MD5 HEADER FILE!
15 * If we don't do this, it might pick up the systems broken MD5.
16 */
17#include <freeradius-devel/util/md5.h>
18
19/** The thread local free list
20 *
21 * Any entries remaining in the list will be freed when the thread is joined
22 */
23#define ARRAY_SIZE (8)
24typedef struct {
25 bool used;
28static _Thread_local fr_md5_free_list_t *md5_array;
29
30static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx);
31static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src);
32#ifdef HAVE_OPENSSL_EVP_H
33static fr_md5_ctx_t *fr_md5_local_ctx_init(void);
34#else
36#endif
37static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx);
38static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen);
40
44#ifdef HAVE_OPENSSL_EVP_H
45 .alloc = fr_md5_local_ctx_init,
46#else
48#endif
50 .update = fr_md5_local_update,
51 .final = fr_md5_local_final
52};
54
55/*
56 * If we have OpenSSL's EVP API available, then build wrapper functions.
57 *
58 * We always need to build the local MD5 functions as OpenSSL could
59 * be operating in FIPS mode where MD5 digest functions are unavailable.
60 */
61#ifdef HAVE_OPENSSL_EVP_H
62# include <freeradius-devel/tls/openssl_user_macros.h>
63# include <openssl/evp.h>
64# include <openssl/crypto.h>
65# include <openssl/err.h>
66# include <openssl/provider.h>
67
68/** @copydoc fr_md5_ctx_reset
69 *
70 */
71static void fr_md5_openssl_ctx_reset(fr_md5_ctx_t *ctx)
72{
73 EVP_MD_CTX *md_ctx = ctx;
74
75 EVP_MD_CTX_reset(md_ctx);
76 (void)EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL);
77}
78
79/** @copydoc fr_md5_ctx_copy
80 *
81 */
82static void fr_md5_openssl_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
83{
84 EVP_MD_CTX_copy_ex(dst, src);
85}
86
87/** @copydoc fr_md5_ctx_alloc
88 *
89 */
90static fr_md5_ctx_t *fr_md5_openssl_ctx_alloc(void)
91{
92 EVP_MD_CTX *md_ctx;
93
94 md_ctx = EVP_MD_CTX_new();
95 if (unlikely(!md_ctx)) return NULL;
96
97 if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL) != 1) {
98 char buffer[256];
99
100 ERR_error_string_n(ERR_get_error(), buffer, sizeof(buffer));
101 fr_strerror_printf("Failed initialising MD5 ctx: %s", buffer);
102 EVP_MD_CTX_free(md_ctx);
103
104 return NULL;
105 }
106
107 return md_ctx;
108}
109
110/** @copydoc fr_md5_ctx_free
111 *
112 */
113static void fr_md5_openssl_ctx_free(fr_md5_ctx_t **ctx)
114{
115 EVP_MD_CTX_free(*ctx);
116 *ctx = NULL;
117}
118
119/** @copydoc fr_md5_update
120 *
121 */
122static void fr_md5_openssl_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
123{
124 EVP_DigestUpdate(ctx, in, inlen);
125}
126
127/** @copydoc fr_md5_final
128 *
129 */
130static void fr_md5_openssl_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
131{
132 unsigned int len;
133
134 EVP_DigestFinal(ctx, out, &len);
135
136 if (!fr_cond_assert(len == MD5_DIGEST_LENGTH)) return;
137}
138
139static fr_md5_funcs_t md5_openssl_funcs = {
140 .reset = fr_md5_openssl_ctx_reset,
141 .copy = fr_md5_openssl_ctx_copy,
142 .alloc = fr_md5_openssl_ctx_alloc,
143 .free = fr_md5_openssl_ctx_free,
144 .update = fr_md5_openssl_update,
145 .final = fr_md5_openssl_final
146};
147#endif
148
149# define MD5_BLOCK_LENGTH 64
150typedef struct {
151 uint32_t state[4]; //!< State.
152 uint32_t count[2]; //!< Number of bits, mod 2^64.
153 uint8_t buffer[MD5_BLOCK_LENGTH]; //!< Input buffer.
155
156/*
157 * This code implements the MD5 message-digest algorithm.
158 * The algorithm is due to Ron Rivest. This code was
159 * written by Colin Plumb in 1993, no copyright is claimed.
160 * This code is in the public domain; do with it what you wish.
161 *
162 * Equivalent code is available from RSA Data Security, Inc.
163 * This code has been tested against that, and is equivalent,
164 * except that you don't need to include two pages of legalese
165 * with every copy.
166 *
167 * To compute the message digest of a chunk of bytes, declare an
168 * MD5Context structure, pass it to fr_md5_init, call fr_md5_update as
169 * needed on buffers full of bytes, and then call fr_md5_final, which
170 * will fill a supplied 16-byte array with the digest.
171 */
172#define PUT_64BIT_LE(cp, value) do {\
173 (cp)[7] = (value)[1] >> 24;\
174 (cp)[6] = (value)[1] >> 16;\
175 (cp)[5] = (value)[1] >> 8;\
176 (cp)[4] = (value)[1];\
177 (cp)[3] = (value)[0] >> 24;\
178 (cp)[2] = (value)[0] >> 16;\
179 (cp)[1] = (value)[0] >> 8;\
180 (cp)[0] = (value)[0];\
181} while (0)
182
183#define PUT_32BIT_LE(cp, value) do {\
184 (cp)[3] = (value) >> 24;\
185 (cp)[2] = (value) >> 16;\
186 (cp)[1] = (value) >> 8;\
187 (cp)[0] = (value);\
188} while (0)
189
191 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
194};
195
196
197/* The four core functions - MD5_F1 is optimized somewhat */
198#define MD5_F1(x, y, z) (z ^ (x & (y ^ z)))
199#define MD5_F2(x, y, z) MD5_F1(z, x, y)
200#define MD5_F3(x, y, z) (x ^ y ^ z)
201#define MD5_F4(x, y, z) (y ^ (x | ~z))
202
203/* This is the central step in the MD5 algorithm. */
204#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
205
206/** The core of the MD5 algorithm
207 *
208 * This alters an existing MD5 hash to reflect the addition of 16
209 * longwords of new data. fr_md5_update blocks the data and converts bytes
210 * into longwords for this routine.
211 *
212 * @param[in] state 16 bytes of data to feed into the hashing function.
213 * @param[in,out] block MD5 digest block to update.
214 */
215static void fr_md5_local_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
216{
217 uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
218
219 for (a = 0; a < (MD5_BLOCK_LENGTH / 4); a++) {
220 size_t idx = a * 4;
221
222 in[a] = (uint32_t)(
223 (uint32_t)(block[idx + 0]) |
224 (uint32_t)(block[idx + 1]) << 8 |
225 (uint32_t)(block[idx + 2]) << 16 |
226 (uint32_t)(block[idx + 3]) << 24);
227 }
228
229 a = state[0];
230 b = state[1];
231 c = state[2];
232 d = state[3];
233
234 MD5STEP(MD5_F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
235 MD5STEP(MD5_F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
236 MD5STEP(MD5_F1, c, d, a, b, in[ 2] + 0x242070db, 17);
237 MD5STEP(MD5_F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
238 MD5STEP(MD5_F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
239 MD5STEP(MD5_F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
240 MD5STEP(MD5_F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
241 MD5STEP(MD5_F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
242 MD5STEP(MD5_F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
243 MD5STEP(MD5_F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
244 MD5STEP(MD5_F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
245 MD5STEP(MD5_F1, b, c, d, a, in[11] + 0x895cd7be, 22);
246 MD5STEP(MD5_F1, a, b, c, d, in[12] + 0x6b901122, 7);
247 MD5STEP(MD5_F1, d, a, b, c, in[13] + 0xfd987193, 12);
248 MD5STEP(MD5_F1, c, d, a, b, in[14] + 0xa679438e, 17);
249 MD5STEP(MD5_F1, b, c, d, a, in[15] + 0x49b40821, 22);
250
251 MD5STEP(MD5_F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
252 MD5STEP(MD5_F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
253 MD5STEP(MD5_F2, c, d, a, b, in[11] + 0x265e5a51, 14);
254 MD5STEP(MD5_F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
255 MD5STEP(MD5_F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
256 MD5STEP(MD5_F2, d, a, b, c, in[10] + 0x02441453, 9);
257 MD5STEP(MD5_F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
258 MD5STEP(MD5_F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
259 MD5STEP(MD5_F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
260 MD5STEP(MD5_F2, d, a, b, c, in[14] + 0xc33707d6, 9);
261 MD5STEP(MD5_F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
262 MD5STEP(MD5_F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
263 MD5STEP(MD5_F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
264 MD5STEP(MD5_F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
265 MD5STEP(MD5_F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
266 MD5STEP(MD5_F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
267
268 MD5STEP(MD5_F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
269 MD5STEP(MD5_F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
270 MD5STEP(MD5_F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
271 MD5STEP(MD5_F3, b, c, d, a, in[14] + 0xfde5380c, 23);
272 MD5STEP(MD5_F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
273 MD5STEP(MD5_F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
274 MD5STEP(MD5_F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
275 MD5STEP(MD5_F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
276 MD5STEP(MD5_F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
277 MD5STEP(MD5_F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
278 MD5STEP(MD5_F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
279 MD5STEP(MD5_F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
280 MD5STEP(MD5_F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
281 MD5STEP(MD5_F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
282 MD5STEP(MD5_F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
283 MD5STEP(MD5_F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
284
285 MD5STEP(MD5_F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
286 MD5STEP(MD5_F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
287 MD5STEP(MD5_F4, c, d, a, b, in[14] + 0xab9423a7, 15);
288 MD5STEP(MD5_F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
289 MD5STEP(MD5_F4, a, b, c, d, in[12] + 0x655b59c3, 6);
290 MD5STEP(MD5_F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
291 MD5STEP(MD5_F4, c, d, a, b, in[10] + 0xffeff47d, 15);
292 MD5STEP(MD5_F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
293 MD5STEP(MD5_F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6);
294 MD5STEP(MD5_F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
295 MD5STEP(MD5_F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
296 MD5STEP(MD5_F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
297 MD5STEP(MD5_F4, a, b, c, d, in[4 ] + 0xf7537e82, 6);
298 MD5STEP(MD5_F4, d, a, b, c, in[11] + 0xbd3af235, 10);
299 MD5STEP(MD5_F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
300 MD5STEP(MD5_F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
301
302 state[0] += a;
303 state[1] += b;
304 state[2] += c;
305 state[3] += d;
306}
307
308/** @copydoc fr_md5_ctx_reset
309 *
310 */
312{
313 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
314
315 ctx_local->count[0] = 0;
316 ctx_local->count[1] = 0;
317 ctx_local->state[0] = 0x67452301;
318 ctx_local->state[1] = 0xefcdab89;
319 ctx_local->state[2] = 0x98badcfe;
320 ctx_local->state[3] = 0x10325476;
321 memset(ctx_local->buffer, 0, sizeof(ctx_local->buffer));
322}
323
324/** @copydoc fr_md5_ctx_copy
325 *
326 */
328{
330 fr_md5_ctx_local_t *ctx_local_dst = talloc_get_type_abort(dst, fr_md5_ctx_local_t);
331
332 memcpy(ctx_local_dst, ctx_local_src, sizeof(*ctx_local_dst));
333}
334
335/** @copydoc fr_md5_ctx_alloc
336 *
337 */
339{
340 fr_md5_ctx_local_t *ctx_local;
341
342 ctx_local = talloc(NULL, fr_md5_ctx_local_t);
343 if (unlikely(!ctx_local)) return NULL;
344 fr_md5_local_ctx_reset(ctx_local);
345
346 return ctx_local;
347}
348
349#ifdef HAVE_OPENSSL_EVP_H
350/** Initialize whether or not we use the local allocator, or the OpenSSL one.
351 *
352 */
353static fr_md5_ctx_t *fr_md5_local_ctx_init(void)
354{
355 /*
356 * If we are in FIPS mode, then use the local allocator.
357 */
358 if (!EVP_default_properties_is_fips_enabled(NULL)) {
359 /*
360 * OpenSSL isn't in FIPS mode. Swap out the functions
361 * pointers for the OpenSSL versions.
362 *
363 * We do this by swapping out a pointer to a structure
364 * containing the functions, as this prevents possible
365 * skew where some threads see a mixture of functions.
366 */
367 fr_md5_funcs = &md5_openssl_funcs;
368 } else {
369 md5_local_funcs.alloc = fr_md5_local_ctx_alloc; /* Don't call this (init) function again */
370 }
371
372 return fr_md5_ctx_alloc();
373}
374#endif
375
376/** @copydoc fr_md5_ctx_free
377 *
378 */
380{
381 talloc_free(*ctx);
382 *ctx = NULL;
383}
384
385static const uint8_t *zero = (uint8_t[]){ 0x00 };
386
387/** @copydoc fr_md5_update
388 *
389 */
390static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
391{
392 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
393
394 size_t have, need;
395
396 /*
397 * Needed so we can calculate the zero
398 * length md5 hash correctly.
399 * ubsan doesn't like arithmetic on
400 * NULL pointers.
401 */
402 if (!in) {
403 in = zero;
404 inlen = 0;
405 }
406
407 /* Check how many bytes we already have and how many more we need. */
408 have = (size_t)((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
409 need = MD5_BLOCK_LENGTH - have;
410
411 /* Update bitcount */
412/* ctx_local->count += (uint64_t)inlen << 3;*/
413 if ((ctx_local->count[0] += ((uint32_t)inlen << 3)) < (uint32_t)inlen) {
414 /* Overflowed ctx_local->count[0] */
415 ctx_local->count[1]++;
416 }
417 ctx_local->count[1] += ((uint32_t)inlen >> 29);
418
419 if (inlen >= need) {
420 if (have != 0) {
421 memcpy(ctx_local->buffer + have, in, need);
422 fr_md5_local_transform(ctx_local->state, ctx_local->buffer);
423 in += need;
424 inlen -= need;
425 have = 0;
426 }
427
428 /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
429 while (inlen >= MD5_BLOCK_LENGTH) {
430 fr_md5_local_transform(ctx_local->state, in);
433 }
434 }
435
436 /* Handle any remaining bytes of data. */
437 memcpy(ctx_local->buffer + have, in, inlen);
438}
439
440/** @copydoc fr_md5_final
441 *
442 */
444{
445 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
446 uint8_t count[8];
447 size_t padlen;
448 int i;
449
450 /* Convert count to 8 bytes in little endian order. */
451 PUT_64BIT_LE(count, ctx_local->count);
452
453 /* Pad out to 56 mod 64. */
454 padlen = MD5_BLOCK_LENGTH -
455 ((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
456 if (padlen < 1 + 8)
457 padlen += MD5_BLOCK_LENGTH;
458 fr_md5_update(ctx_local, PADDING, padlen - 8); /* padlen - 8 <= 64 */
459 fr_md5_update(ctx_local, count, 8);
460
461 for (i = 0; i < 4; i++)
462 PUT_32BIT_LE(out + i * 4, ctx_local->state[i]);
463
464 memset(ctx_local, 0, sizeof(*ctx_local)); /* in case it's sensitive */
465}
466
467/** Calculate the MD5 hash of the contents of a buffer
468 *
469 * @param[out] out Where to write the MD5 digest. Must be a minimum of MD5_DIGEST_LENGTH.
470 * @param[in] in Data to hash.
471 * @param[in] inlen Length of the data.
472 */
474{
475 fr_md5_ctx_t *ctx;
476
478 fr_md5_update(ctx, in, inlen);
479 fr_md5_final(out, ctx);
481}
482
483static int _md5_ctx_free_on_exit(void *arg)
484{
485 int i;
486 fr_md5_free_list_t *free_list = arg;
487
488 for (i = 0; i < ARRAY_SIZE; i++) {
489 if (free_list[i].used) continue;
490
491 fr_md5_ctx_free(&free_list[i].md_ctx);
492 }
493 return talloc_free(free_list);
494}
495
496/** @copydoc fr_md5_ctx_alloc
497 *
498 */
500{
501 int i;
502 fr_md5_ctx_t *md_ctx;
503 fr_md5_free_list_t *free_list;
504
505 if (unlikely(!md5_array)) {
506 free_list = talloc_zero_array(NULL, fr_md5_free_list_t, ARRAY_SIZE);
507 if (unlikely(!free_list)) {
508 oom:
509 fr_strerror_const("Out of Memory");
510 return NULL;
511 }
512
514
515 /*
516 * Initialize all MD5 contexts
517 */
518 for (i = 0; i < ARRAY_SIZE; i++) {
519 md_ctx = fr_md5_ctx_alloc();
520 if (unlikely(md_ctx == NULL)) goto oom;
521
522 free_list[i].md_ctx = md_ctx;
523 }
524 } else {
525 free_list = md5_array;
526 }
527
528 for (i = 0; i < ARRAY_SIZE; i++) {
529 if (free_list[i].used) continue;
530
531 free_list[i].used = true;
532 return free_list[i].md_ctx;
533 }
534
535 /*
536 * No more free contexts, just allocate a new one.
537 */
538 return fr_md5_ctx_alloc();
539}
540
541/** @copydoc fr_md5_ctx_free
542 *
543 */
545{
546 int i;
547 fr_md5_free_list_t *free_list = md5_array;
548
549 if (free_list) {
550 for (i = 0; i < ARRAY_SIZE; i++) {
551 if (free_list[i].md_ctx == *ctx) {
552 free_list[i].used = false;
553 fr_md5_ctx_reset(*ctx);
554 *ctx = NULL;
555 return;
556 }
557 }
558 }
559
560 fr_md5_ctx_free(*ctx);
561 *ctx = NULL;
562}
static int const char char buffer[256]
Definition acutest.h:576
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:221
#define RCSID(id)
Definition build.h:485
#define unlikely(_x)
Definition build.h:383
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
static fr_slen_t in
Definition dict.h:849
talloc_free(reap)
#define MD5_F3(x, y, z)
Definition md5.c:200
#define MD5STEP(f, w, x, y, z, data, s)
Definition md5.c:204
#define MD5_F1(x, y, z)
Definition md5.c:198
fr_md5_ctx_t * md_ctx
Definition md5.c:26
uint32_t state[4]
State.
Definition md5.c:151
static void fr_md5_local_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
The core of the MD5 algorithm.
Definition md5.c:215
#define MD5_F4(x, y, z)
Definition md5.c:201
uint32_t count[2]
Number of bits, mod 2^64.
Definition md5.c:152
static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
Copy the contents of a ctx.
Definition md5.c:327
static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
Ingest plaintext into the digest.
Definition md5.c:390
static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx)
Reset the ctx to allow reuse.
Definition md5.c:311
#define MD5_BLOCK_LENGTH
Definition md5.c:149
#define ARRAY_SIZE
The thread local free list.
Definition md5.c:23
#define PUT_64BIT_LE(cp, value)
Definition md5.c:172
static _Thread_local fr_md5_free_list_t * md5_array
Definition md5.c:28
#define MD5_F2(x, y, z)
Definition md5.c:199
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD5 hash of the contents of a buffer.
Definition md5.c:473
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Free function for MD5 digest ctx.
Definition md5.c:544
static fr_md5_ctx_t * fr_md5_local_ctx_alloc(void)
Allocation function for MD5 digest context.
Definition md5.c:338
static int _md5_ctx_free_on_exit(void *arg)
Definition md5.c:483
static const uint8_t PADDING[MD5_BLOCK_LENGTH]
Definition md5.c:190
fr_md5_funcs_t const * fr_md5_funcs
Swap a single pointer, so all functions get swapped as an atomic operation.
Definition md5.c:53
static fr_md5_funcs_t md5_local_funcs
Definition md5.c:41
static void fr_md5_local_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
Finalise the ctx, producing the digest.
Definition md5.c:443
static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx)
Free function for MD5 digest ctx.
Definition md5.c:379
uint8_t buffer[MD5_BLOCK_LENGTH]
Input buffer.
Definition md5.c:153
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Allocation function for MD5 digest context.
Definition md5.c:499
#define PUT_32BIT_LE(cp, value)
Definition md5.c:183
static const uint8_t * zero
Definition md5.c:385
fr_md5_ctx_reset_t reset
Definition md5.h:40
#define fr_md5_final(_out, _ctx)
Finalise the ctx, producing the digest.
Definition md5.h:93
#define fr_md5_ctx_alloc()
Allocation function for MD5 digest context.
Definition md5.h:71
#define fr_md5_ctx_reset(_ctx)
Reset the ctx to allow reuse.
Definition md5.h:56
void fr_md5_ctx_t
Definition md5.h:28
fr_md5_ctx_alloc_t alloc
Definition md5.h:42
#define fr_md5_update(_ctx, _in, _inlen)
Ingest plaintext into the digest.
Definition md5.h:86
#define fr_md5_ctx_free(_ctx)
Free function for MD5 digest ctx.
Definition md5.h:78
#define MD5_DIGEST_LENGTH
unsigned int uint32_t
unsigned char uint8_t
unsigned long int size_t
static size_t used
return count
Definition module.c:155
#define talloc_get_type_abort_const
Definition talloc.h:287
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1023
static size_t char ** out
Definition value.h:1023