The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
7 RCSID("$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)
24 typedef struct {
25  bool used;
28 static _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 
43 static int have_openssl_md5 = -1;
44 
45 /** @copydoc fr_md5_ctx_reset
46  *
47  */
48 static 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  */
59 static 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  */
67 static 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  */
90 static 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  */
99 static 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  */
107 static 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
118 typedef 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  */
183 static 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  */
295 static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
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 
353 static const uint8_t *zero = (uint8_t[]){ 0x00 };
354 
355 /** @copydoc fr_md5_update
356  *
357  */
358 static 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);
399  in += MD5_BLOCK_LENGTH;
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  */
451 void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
452 {
453  fr_md5_ctx_t *ctx;
454 
456  fr_md5_update(ctx, in, inlen);
457  fr_md5_final(out, ctx);
459 }
460 
461 static 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:574
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition: atexit.h:221
#define RCSID(id)
Definition: build.h:481
#define unlikely(_x)
Definition: build.h:379
#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:821
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
static fr_md5_ctx_t * fr_md5_local_ctx_alloc(void)
Definition: md5.c:306
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
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Definition: md5.c:477
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
#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
fr_md5_ctx_t *(* fr_md5_ctx_alloc_t)(void)
Allocation function for MD5 digest context.
Definition: md5.h:53
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
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
Definition: merged_model.c:248
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
unsigned long int size_t
Definition: merged_model.c:25
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