The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
md4.c
Go to the documentation of this file.
1 /** A local MD4 implementation
2  *
3  * @note license is LGPL, but largely derived from a public domain source.
4  *
5  * @file src/lib/util/md4.c
6  */
7 RCSID("$Id: 8f0f3e17b6b6689d24065998753e49f332e45cc5 $")
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 MD4 TO USE OUR MD4 HEADER FILE!
15  * If we don't do this, it might pick up the systems broken MD4.
16  */
17 #include <freeradius-devel/util/md4.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_md4_free_list_t *md4_array;
29 /*
30  * If we have OpenSSL's EVP API available, then build wrapper functions.
31  *
32  * We always need to build the local MD4 functions as OpenSSL could
33  * be operating in FIPS mode where MD4 digest functions are unavailable.
34  */
35 #ifdef HAVE_OPENSSL_EVP_H
36 # include <freeradius-devel/tls/openssl_user_macros.h>
37 # include <openssl/evp.h>
38 # include <openssl/crypto.h>
39 # include <openssl/err.h>
40 # include <openssl/provider.h>
41 
42 static int have_openssl_md4 = -1;
43 
44 /** @copydoc fr_md4_ctx_reset
45  *
46  */
47 static void fr_md4_openssl_ctx_reset(fr_md4_ctx_t *ctx)
48 {
49  EVP_MD_CTX *md_ctx = ctx;
50 
51  EVP_MD_CTX_reset(md_ctx);
52  EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL);
53 }
54 
55 /** @copydoc fr_md4_ctx_copy
56  *
57  */
58 static void fr_md4_openssl_ctx_copy(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
59 {
60  EVP_MD_CTX_copy_ex(dst, src);
61 }
62 
63 /** @copydoc fr_md4_ctx_alloc
64  *
65  */
66 static fr_md4_ctx_t *fr_md4_openssl_ctx_alloc(void)
67 {
68  EVP_MD_CTX *md_ctx;
69 
70  md_ctx = EVP_MD_CTX_new();
71  if (unlikely(!md_ctx)) return NULL;
72 
73  if (EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL) != 1) {
74  char buffer[256];
75 
76  ERR_error_string_n(ERR_get_error(), buffer, sizeof(buffer));
77  fr_strerror_printf("Failed initialising md4 ctx: %s", buffer);
78  EVP_MD_CTX_free(md_ctx);
79 
80  return NULL;
81  }
82 
83  return md_ctx;
84 }
85 
86 /** @copydoc fr_md4_ctx_free
87  *
88  */
89 static void fr_md4_openssl_ctx_free(fr_md4_ctx_t **ctx)
90 {
91  EVP_MD_CTX_free(*ctx);
92  *ctx = NULL;
93 }
94 
95 /** @copydoc fr_md4_update
96  *
97  */
98 static void fr_md4_openssl_update(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
99 {
100  EVP_DigestUpdate(ctx, in, inlen);
101 }
102 
103 /** @copydoc fr_md4_final
104  *
105  */
106 static void fr_md4_openssl_final(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx)
107 {
108  unsigned int len;
109 
110  EVP_DigestFinal(ctx, out, &len);
111 
112  if (!fr_cond_assert(len == MD4_DIGEST_LENGTH)) return;
113 }
114 #endif
115 
116 /*
117  * This code implements the MD4 message-digest algorithm.
118  * The algorithm is due to Ron Rivest. This code was
119  * written by Colin Plumb in 1993, no copyright is claimed.
120  * This code is in the public domain; do with it what you wish.
121  * Todd C. Miller modified the md4 code to do MD4 based on RFC 1186.
122  *
123  * Equivalent code is available from RSA Data Security, Inc.
124  * This code has been tested against that, and is equivalent,
125  * except that you don't need to include two pages of legalese
126  * with every copy.
127  *
128  * To compute the message digest of a chunk of bytes, declare an
129  * MD4Context structure, pass it to fr_md4_init, call fr_md4_update as
130  * needed on buffers full of bytes, and then call fr_md4_final, which
131  * will fill a supplied 16-byte array with the digest.
132  */
133 #ifndef WORDS_BIGENDIAN
134 # define htole32_4(buf) /* Nothing */
135 # define htole32_14(buf) /* Nothing */
136 # define htole32_16(buf) /* Nothing */
137 #else
138 /* Sometimes defined by endian.h */
139 # ifndef htole32
140 # define htole32(x)\
141  (((((uint32_t)x) & 0xff000000) >> 24) |\
142  ((((uint32_t)x) & 0x00ff0000) >> 8) |\
143  ((((uint32_t)x) & 0x0000ff00) << 8) |\
144  ((((uint32_t)x) & 0x000000ff) << 24))
145 # endif
146 # define htole32_4(buf) do {\
147  (buf)[0] = htole32((buf)[0]);\
148  (buf)[1] = htole32((buf)[1]);\
149  (buf)[2] = htole32((buf)[2]);\
150  (buf)[3] = htole32((buf)[3]);\
151 } while (0)
152 
153 # define htole32_14(buf) do {\
154  (buf)[0] = htole32((buf)[0]);\
155  (buf)[1] = htole32((buf)[1]);\
156  (buf)[2] = htole32((buf)[2]);\
157  (buf)[3] = htole32((buf)[3]);\
158  (buf)[4] = htole32((buf)[4]);\
159  (buf)[5] = htole32((buf)[5]);\
160  (buf)[6] = htole32((buf)[6]);\
161  (buf)[7] = htole32((buf)[7]);\
162  (buf)[8] = htole32((buf)[8]);\
163  (buf)[9] = htole32((buf)[9]);\
164  (buf)[10] = htole32((buf)[10]);\
165  (buf)[11] = htole32((buf)[11]);\
166  (buf)[12] = htole32((buf)[12]);\
167  (buf)[13] = htole32((buf)[13]);\
168 } while (0)
169 
170 # define htole32_16(buf) do {\
171  (buf)[0] = htole32((buf)[0]);\
172  (buf)[1] = htole32((buf)[1]);\
173  (buf)[2] = htole32((buf)[2]);\
174  (buf)[3] = htole32((buf)[3]);\
175  (buf)[4] = htole32((buf)[4]);\
176  (buf)[5] = htole32((buf)[5]);\
177  (buf)[6] = htole32((buf)[6]);\
178  (buf)[7] = htole32((buf)[7]);\
179  (buf)[8] = htole32((buf)[8]);\
180  (buf)[9] = htole32((buf)[9]);\
181  (buf)[10] = htole32((buf)[10]);\
182  (buf)[11] = htole32((buf)[11]);\
183  (buf)[12] = htole32((buf)[12]);\
184  (buf)[13] = htole32((buf)[13]);\
185  (buf)[14] = htole32((buf)[14]);\
186  (buf)[15] = htole32((buf)[15]);\
187 } while (0)
188 #endif
189 
190 #define MD4_BLOCK_LENGTH 64
191 
192 /* The three core functions - F1 is optimized somewhat */
193 #define MD4_F1(x, y, z) (z ^ (x & (y ^ z)))
194 #define MD4_F2(x, y, z) ((x & y) | (x & z) | (y & z))
195 #define MD4_F3(x, y, z) (x ^ y ^ z)
196 
197 /* This is the central step in the MD4 algorithm. */
198 #define MD4STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s))
199 
200 /** The core of the MD4 algorithm
201  *
202  * This alters an existing MD4 hash to reflect the addition of 16
203  * longwords of new data. fr_md4_update blocks the data and converts bytes
204  * into longwords for this routine.
205  *
206  * @param[in] state 16 bytes of data to feed into the hashing function.
207  * @param[in,out] block MD4 digest block to update.
208  */
209 static void fr_md4_local_transform(uint32_t state[static 4], uint8_t const block[static MD4_BLOCK_LENGTH])
210 {
211  uint32_t a, b, c, d;
212  uint32_t const *in = (uint32_t const *)block;
213 
214  a = state[0];
215  b = state[1];
216  c = state[2];
217  d = state[3];
218 
219  MD4STEP(MD4_F1, a, b, c, d, in[ 0], 3);
220  MD4STEP(MD4_F1, d, a, b, c, in[ 1], 7);
221  MD4STEP(MD4_F1, c, d, a, b, in[ 2], 11);
222  MD4STEP(MD4_F1, b, c, d, a, in[ 3], 19);
223  MD4STEP(MD4_F1, a, b, c, d, in[ 4], 3);
224  MD4STEP(MD4_F1, d, a, b, c, in[ 5], 7);
225  MD4STEP(MD4_F1, c, d, a, b, in[ 6], 11);
226  MD4STEP(MD4_F1, b, c, d, a, in[ 7], 19);
227  MD4STEP(MD4_F1, a, b, c, d, in[ 8], 3);
228  MD4STEP(MD4_F1, d, a, b, c, in[ 9], 7);
229  MD4STEP(MD4_F1, c, d, a, b, in[10], 11);
230  MD4STEP(MD4_F1, b, c, d, a, in[11], 19);
231  MD4STEP(MD4_F1, a, b, c, d, in[12], 3);
232  MD4STEP(MD4_F1, d, a, b, c, in[13], 7);
233  MD4STEP(MD4_F1, c, d, a, b, in[14], 11);
234  MD4STEP(MD4_F1, b, c, d, a, in[15], 19);
235 
236  MD4STEP(MD4_F2, a, b, c, d, in[ 0] + 0x5a827999, 3);
237  MD4STEP(MD4_F2, d, a, b, c, in[ 4] + 0x5a827999, 5);
238  MD4STEP(MD4_F2, c, d, a, b, in[ 8] + 0x5a827999, 9);
239  MD4STEP(MD4_F2, b, c, d, a, in[12] + 0x5a827999, 13);
240  MD4STEP(MD4_F2, a, b, c, d, in[ 1] + 0x5a827999, 3);
241  MD4STEP(MD4_F2, d, a, b, c, in[ 5] + 0x5a827999, 5);
242  MD4STEP(MD4_F2, c, d, a, b, in[ 9] + 0x5a827999, 9);
243  MD4STEP(MD4_F2, b, c, d, a, in[13] + 0x5a827999, 13);
244  MD4STEP(MD4_F2, a, b, c, d, in[ 2] + 0x5a827999, 3);
245  MD4STEP(MD4_F2, d, a, b, c, in[ 6] + 0x5a827999, 5);
246  MD4STEP(MD4_F2, c, d, a, b, in[10] + 0x5a827999, 9);
247  MD4STEP(MD4_F2, b, c, d, a, in[14] + 0x5a827999, 13);
248  MD4STEP(MD4_F2, a, b, c, d, in[ 3] + 0x5a827999, 3);
249  MD4STEP(MD4_F2, d, a, b, c, in[ 7] + 0x5a827999, 5);
250  MD4STEP(MD4_F2, c, d, a, b, in[11] + 0x5a827999, 9);
251  MD4STEP(MD4_F2, b, c, d, a, in[15] + 0x5a827999, 13);
252 
253  MD4STEP(MD4_F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3);
254  MD4STEP(MD4_F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9);
255  MD4STEP(MD4_F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
256  MD4STEP(MD4_F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
257  MD4STEP(MD4_F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3);
258  MD4STEP(MD4_F3, d, a, b, c, in[10] + 0x6ed9eba1, 9);
259  MD4STEP(MD4_F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
260  MD4STEP(MD4_F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
261  MD4STEP(MD4_F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3);
262  MD4STEP(MD4_F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9);
263  MD4STEP(MD4_F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
264  MD4STEP(MD4_F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
265  MD4STEP(MD4_F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3);
266  MD4STEP(MD4_F3, d, a, b, c, in[11] + 0x6ed9eba1, 9);
267  MD4STEP(MD4_F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
268  MD4STEP(MD4_F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
269 
270  state[0] += a;
271  state[1] += b;
272  state[2] += c;
273  state[3] += d;
274 }
275 
276 typedef struct {
277  uint32_t state[4]; //!< State.
278  uint32_t count[2]; //!< Number of bits, mod 2^64.
279  uint8_t buffer[MD4_BLOCK_LENGTH]; //!< Input buffer.
281 
282 /** @copydoc fr_md4_ctx_reset
283  *
284  */
286 {
287  fr_md4_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md4_ctx_local_t);
288 
289  ctx_local->count[0] = 0;
290  ctx_local->count[1] = 0;
291  ctx_local->state[0] = 0x67452301;
292  ctx_local->state[1] = 0xefcdab89;
293  ctx_local->state[2] = 0x98badcfe;
294  ctx_local->state[3] = 0x10325476;
295 }
296 
297 /** @copydoc fr_md4_ctx_copy
298  *
299  */
300 static void fr_md4_local_ctx_copy(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
301 {
303  fr_md4_ctx_local_t *ctx_local_dst = talloc_get_type_abort(dst, fr_md4_ctx_local_t);
304 
305  memcpy(ctx_local_dst, ctx_local_src, sizeof(*ctx_local_dst));
306 }
307 
308 /** @copydoc fr_md4_ctx_alloc
309  *
310  */
312 {
313  fr_md4_ctx_local_t *ctx_local;
314 
315 #ifdef HAVE_OPENSSL_EVP_H
316  if (unlikely(have_openssl_md4 == -1)) {
317  /*
318  * If we're not in FIPS mode, then swap out the
319  * md4 functions, and call the OpenSSL init
320  * function.
321  */
322  if (!EVP_default_properties_is_fips_enabled(NULL)) {
323  have_openssl_md4 = 1;
324 
325  /*
326  * Swap out the functions pointers
327  * for the OpenSSL versions.
328  */
329  fr_md4_ctx_reset = fr_md4_openssl_ctx_reset;
330  fr_md4_ctx_copy = fr_md4_openssl_ctx_copy;
331  fr_md4_ctx_alloc = fr_md4_openssl_ctx_alloc;
332  fr_md4_ctx_free = fr_md4_openssl_ctx_free;
333  fr_md4_update = fr_md4_openssl_update;
334  fr_md4_final = fr_md4_openssl_final;
335 
336  return fr_md4_ctx_alloc();
337  }
338 
339  have_openssl_md4 = 0;
340  }
341 #endif
342  ctx_local = talloc(NULL, fr_md4_ctx_local_t);
343  if (unlikely(!ctx_local)) return NULL;
344  fr_md4_local_ctx_reset(ctx_local);
345 
346  return ctx_local;
347 }
348 
349 /** @copydoc fr_md4_ctx_free
350  *
351  */
353 {
354  talloc_free(*ctx);
355  *ctx = NULL;
356 }
357 
358 static const uint8_t *zero = (uint8_t[]){ 0x00 };
359 
360 /** @copydoc fr_md4_update
361  *
362  */
363 static void fr_md4_local_update(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
364 {
365  uint32_t count;
366  fr_md4_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md4_ctx_local_t);
367 
368  /*
369  * Needed so we can calculate the zero
370  * length md4 hash correctly.
371  * ubsan doesn't like arithmetic on
372  * NULL pointers.
373  */
374  if (!in) {
375  in = zero;
376  inlen = 0;
377  }
378 
379  /* Bytes already stored in ctx_local->buffer */
380  count = (uint32_t)((ctx_local->count[0] >> 3) & 0x3f);
381 
382  /* Update bitcount */
383 /* ctx_local->count += (uint64_t)inlen << 3;*/
384  if ((ctx_local->count[0] += ((uint32_t)inlen << 3)) < (uint32_t)inlen) {
385  /* Overflowed ctx_local->count[0] */
386  ctx_local->count[1]++;
387  }
388  ctx_local->count[1] += ((uint32_t)inlen >> 29);
389 
390  /* Handle any leading odd-sized chunks */
391  if (count) {
392  unsigned char *p = (unsigned char *)ctx_local->buffer + count;
393 
395  if (inlen < count) {
396  memcpy(p, in, inlen);
397  return;
398  }
399  memcpy(p, in, count);
400  htole32_16((uint32_t *)ctx_local->buffer);
401  fr_md4_local_transform(ctx_local->state, ctx_local->buffer);
402  in += count;
403  inlen -= count;
404  }
405 
406  /* Process data in MD4_BLOCK_LENGTH-byte chunks */
407  while (inlen >= MD4_BLOCK_LENGTH) {
408  memcpy(ctx_local->buffer, in, MD4_BLOCK_LENGTH);
409  htole32_16((uint32_t *)ctx_local->buffer);
410  fr_md4_local_transform(ctx_local->state, ctx_local->buffer);
411  in += MD4_BLOCK_LENGTH;
413  }
414 
415  /* Handle any remaining bytes of data. */
416  memcpy(ctx_local->buffer, in, inlen);
417 }
418 
419 /** @copydoc fr_md4_final
420  *
421  */
423 {
424  uint32_t count;
425  unsigned char *p;
426  fr_md4_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md4_ctx_local_t);
427 
428  /* number of bytes mod 64 */
429  count = (uint32_t)(ctx_local->count[0] >> 3) & 0x3f;
430 
431  /*
432  * Set the first char of padding to 0x80.
433  * This is safe since there is always at least one byte free.
434  */
435  p = ctx_local->buffer + count;
436  *p++ = 0x80;
437 
438  /* Bytes of padding needed to make 64 bytes */
439  count = 64 - 1 - count;
440 
441  /* Pad out to 56 mod 64 */
442  if (count < 8) {
443  /* Two lots of padding: Pad the first block to 64 bytes */
444  memset(p, 0, count);
445  htole32_16((uint32_t *)ctx_local->buffer);
446  fr_md4_local_transform(ctx_local->state, ctx_local->buffer);
447 
448  /* Now fill the next block with 56 bytes */
449  memset(ctx_local->buffer, 0, 56);
450  } else {
451  /* Pad block to 56 bytes */
452  memset(p, 0, count - 8);
453  }
454  htole32_14((uint32_t *)ctx_local->buffer);
455 
456  /* Append bit count and transform */
457  ((uint32_t *)ctx_local->buffer)[14] = ctx_local->count[0];
458  ((uint32_t *)ctx_local->buffer)[15] = ctx_local->count[1];
459 
460  fr_md4_local_transform(ctx_local->state, ctx_local->buffer);
461  htole32_4(ctx_local->state);
462  memcpy(out, ctx_local->state, MD4_DIGEST_LENGTH);
463  memset(ctx_local, 0, sizeof(*ctx_local)); /* in case it's sensitive */
464 }
465 
466 /*
467  * Digest function pointers
468  */
475 
476 /** Calculate the MD4 hash of the contents of a buffer
477  *
478  * @param[out] out Where to write the MD4 digest. Must be a minimum of MD4_DIGEST_LENGTH.
479  * @param[in] in Data to hash.
480  * @param[in] inlen Length of the data.
481  */
482 void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
483 {
484  fr_md4_ctx_t *ctx;
485 
487  fr_md4_update(ctx, in, inlen);
488  fr_md4_final(out, ctx);
490 }
491 
492 static int _md4_ctx_free_on_exit(void *arg)
493 {
494  int i;
495  fr_md4_free_list_t *free_list = arg;
496 
497  for (i = 0; i < ARRAY_SIZE; i++) {
498  if (free_list[i].used) continue;
499 
500  fr_md4_ctx_free(&free_list[i].md_ctx);
501  }
502  return talloc_free(free_list);
503 }
504 
505 /** @copydoc fr_md4_ctx_alloc
506  *
507  */
509 {
510  int i;
511  fr_md4_ctx_t *md_ctx;
512  fr_md4_free_list_t *free_list;
513 
514  if (unlikely(!md4_array)) {
515  free_list = talloc_zero_array(NULL, fr_md4_free_list_t, ARRAY_SIZE);
516  if (unlikely(!free_list)) {
517  oom:
518  fr_strerror_const("Out of Memory");
519  return NULL;
520  }
521 
523 
524  /*
525  * Initialize all md4 contexts
526  */
527  for (i = 0; i < ARRAY_SIZE; i++) {
528  md_ctx = fr_md4_ctx_alloc();
529  if (unlikely(md_ctx == NULL)) goto oom;
530 
531  free_list[i].md_ctx = md_ctx;
532  }
533  } else {
534  free_list = md4_array;
535  }
536 
537  for (i = 0; i < ARRAY_SIZE; i++) {
538  if (free_list[i].used) continue;
539 
540  free_list[i].used = true;
541  return free_list[i].md_ctx;
542  }
543 
544  /*
545  * No more free contexts, just allocate a new one.
546  */
547  return fr_md4_ctx_alloc();
548 }
549 
550 /** @copydoc fr_md4_ctx_free
551  *
552  */
554 {
555  int i;
556  fr_md4_free_list_t *free_list = md4_array;
557 
558  if (free_list) {
559  for (i = 0; i < ARRAY_SIZE; i++) {
560  if (free_list[i].md_ctx == *ctx) {
561  free_list[i].used = false;
562  fr_md4_ctx_reset(*ctx);
563  *ctx = NULL;
564  return;
565  }
566  }
567  }
568 
569  fr_md4_ctx_free(*ctx);
570  *ctx = NULL;
571 }
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
if(rcode > 0)
Definition: fd_read.h:9
talloc_free(reap)
uint8_t buffer[MD4_BLOCK_LENGTH]
Input buffer.
Definition: md4.c:279
static int _md4_ctx_free_on_exit(void *arg)
Definition: md4.c:492
static void fr_md4_local_transform(uint32_t state[static 4], uint8_t const block[static MD4_BLOCK_LENGTH])
The core of the MD4 algorithm.
Definition: md4.c:209
#define MD4_F1(x, y, z)
Definition: md4.c:193
uint32_t state[4]
State.
Definition: md4.c:277
fr_md4_ctx_alloc_t fr_md4_ctx_alloc
Definition: md4.c:471
#define MD4STEP(f, w, x, y, z, data, s)
Definition: md4.c:198
#define htole32_16(buf)
Definition: md4.c:136
#define htole32_4(buf)
Definition: md4.c:134
#define MD4_F3(x, y, z)
Definition: md4.c:195
fr_md4_update_t fr_md4_update
Definition: md4.c:473
static void fr_md4_local_ctx_free(fr_md4_ctx_t **ctx)
Definition: md4.c:352
#define ARRAY_SIZE
The thread local free list.
Definition: md4.c:23
void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
Definition: md4.c:482
fr_md4_ctx_reset_t fr_md4_ctx_reset
Definition: md4.c:469
fr_md4_ctx_copy_t fr_md4_ctx_copy
Definition: md4.c:470
uint32_t count[2]
Number of bits, mod 2^64.
Definition: md4.c:278
static void fr_md4_local_update(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
Definition: md4.c:363
fr_md4_final_t fr_md4_final
Definition: md4.c:474
#define htole32_14(buf)
Definition: md4.c:135
static fr_md4_ctx_t * fr_md4_local_ctx_alloc(void)
Definition: md4.c:311
fr_md4_ctx_t * fr_md4_ctx_alloc_from_list(void)
Definition: md4.c:508
#define MD4_F2(x, y, z)
Definition: md4.c:194
static _Thread_local fr_md4_free_list_t * md4_array
Definition: md4.c:28
static void fr_md4_local_ctx_copy(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
Definition: md4.c:300
static void fr_md4_local_final(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx)
Definition: md4.c:422
fr_md4_ctx_t * md_ctx
Definition: md4.c:26
void fr_md4_ctx_free_from_list(fr_md4_ctx_t **ctx)
Definition: md4.c:553
#define MD4_BLOCK_LENGTH
Definition: md4.c:190
fr_md4_ctx_free_t fr_md4_ctx_free
Definition: md4.c:472
static void fr_md4_local_ctx_reset(fr_md4_ctx_t *ctx)
Definition: md4.c:285
static const uint8_t * zero
Definition: md4.c:358
fr_md4_ctx_t *(* fr_md4_ctx_alloc_t)(void)
Allocation function for MD4 digest context.
Definition: md4.h:53
void(* fr_md4_final_t)(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx)
Finalise the ctx, producing the digest.
Definition: md4.h:79
void(* fr_md4_ctx_free_t)(fr_md4_ctx_t **ctx)
Free function for MD4 digest ctx.
Definition: md4.h:61
void(* fr_md4_ctx_copy_t)(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
Copy the contents of a ctx.
Definition: md4.h:44
#define MD4_DIGEST_LENGTH
Definition: md4.h:25
void(* fr_md4_ctx_reset_t)(fr_md4_ctx_t *ctx)
Reset the ctx to allow reuse.
Definition: md4.h:36
void fr_md4_ctx_t
Definition: md4.h:28
void(* fr_md4_update_t)(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
Ingest plaintext into the digest.
Definition: md4.h:71
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
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