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