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