7RCSID(
"$Id: 041a5475b03843098de143e61cca8af5b7bab0e0 $")
9#include <freeradius-devel/util/debug.h>
10#include <freeradius-devel/util/strerror.h>
11#include <freeradius-devel/util/atexit.h>
17#include <freeradius-devel/util/md4.h>
53#ifdef HAVE_OPENSSL_EVP_H
54# include <freeradius-devel/tls/openssl_user_macros.h>
55# include <openssl/evp.h>
56# include <openssl/crypto.h>
57# include <openssl/err.h>
58# include <openssl/provider.h>
65 EVP_MD_CTX *md_ctx = ctx;
67 EVP_MD_CTX_reset(md_ctx);
68 EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL);
76 EVP_MD_CTX_copy_ex(dst, src);
86 md_ctx = EVP_MD_CTX_new();
89 if (EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL) != 1) {
92 ERR_error_string_n(ERR_get_error(),
buffer,
sizeof(
buffer));
94 EVP_MD_CTX_free(md_ctx);
107 EVP_MD_CTX_free(*ctx);
116 EVP_DigestUpdate(ctx,
in,
inlen);
126 EVP_DigestFinal(ctx,
out, &len);
132 .
reset = fr_md4_openssl_ctx_reset,
133 .copy = fr_md4_openssl_ctx_copy,
134 .alloc = fr_md4_openssl_ctx_alloc,
135 .free = fr_md4_openssl_ctx_free,
136 .update = fr_md4_openssl_update,
137 .final = fr_md4_openssl_final
158#ifndef WORDS_BIGENDIAN
159# define htole32_4(buf)
160# define htole32_14(buf)
161# define htole32_16(buf)
166 (((((uint32_t)x) & 0xff000000) >> 24) |\
167 ((((uint32_t)x) & 0x00ff0000) >> 8) |\
168 ((((uint32_t)x) & 0x0000ff00) << 8) |\
169 ((((uint32_t)x) & 0x000000ff) << 24))
171# define htole32_4(buf) do {\
172 (buf)[0] = htole32((buf)[0]);\
173 (buf)[1] = htole32((buf)[1]);\
174 (buf)[2] = htole32((buf)[2]);\
175 (buf)[3] = htole32((buf)[3]);\
178# define htole32_14(buf) do {\
179 (buf)[0] = htole32((buf)[0]);\
180 (buf)[1] = htole32((buf)[1]);\
181 (buf)[2] = htole32((buf)[2]);\
182 (buf)[3] = htole32((buf)[3]);\
183 (buf)[4] = htole32((buf)[4]);\
184 (buf)[5] = htole32((buf)[5]);\
185 (buf)[6] = htole32((buf)[6]);\
186 (buf)[7] = htole32((buf)[7]);\
187 (buf)[8] = htole32((buf)[8]);\
188 (buf)[9] = htole32((buf)[9]);\
189 (buf)[10] = htole32((buf)[10]);\
190 (buf)[11] = htole32((buf)[11]);\
191 (buf)[12] = htole32((buf)[12]);\
192 (buf)[13] = htole32((buf)[13]);\
195# define htole32_16(buf) do {\
196 (buf)[0] = htole32((buf)[0]);\
197 (buf)[1] = htole32((buf)[1]);\
198 (buf)[2] = htole32((buf)[2]);\
199 (buf)[3] = htole32((buf)[3]);\
200 (buf)[4] = htole32((buf)[4]);\
201 (buf)[5] = htole32((buf)[5]);\
202 (buf)[6] = htole32((buf)[6]);\
203 (buf)[7] = htole32((buf)[7]);\
204 (buf)[8] = htole32((buf)[8]);\
205 (buf)[9] = htole32((buf)[9]);\
206 (buf)[10] = htole32((buf)[10]);\
207 (buf)[11] = htole32((buf)[11]);\
208 (buf)[12] = htole32((buf)[12]);\
209 (buf)[13] = htole32((buf)[13]);\
210 (buf)[14] = htole32((buf)[14]);\
211 (buf)[15] = htole32((buf)[15]);\
215#define MD4_BLOCK_LENGTH 64
218#define MD4_F1(x, y, z) (z ^ (x & (y ^ z)))
219#define MD4_F2(x, y, z) ((x & y) | (x & z) | (y & z))
220#define MD4_F3(x, y, z) (x ^ y ^ z)
223#define MD4STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s))
314 ctx_local->
count[0] = 0;
315 ctx_local->
count[1] = 0;
316 ctx_local->
state[0] = 0x67452301;
317 ctx_local->
state[1] = 0xefcdab89;
318 ctx_local->
state[2] = 0x98badcfe;
319 ctx_local->
state[3] = 0x10325476;
330 memcpy(ctx_local_dst, ctx_local_src,
sizeof(*ctx_local_dst));
341 if (
unlikely(!ctx_local))
return NULL;
385 ctx_local->
count[1]++;
391 unsigned char *p = (
unsigned char *)ctx_local->
buffer +
count;
448 memset(ctx_local->
buffer, 0, 56);
451 memset(p, 0,
count - 8);
462 memset(ctx_local, 0,
sizeof(*ctx_local));
487 if (free_list[i].
used)
continue;
518 if (
unlikely(md_ctx == NULL))
goto oom;
520 free_list[i].
md_ctx = md_ctx;
527 if (free_list[i].
used)
continue;
529 free_list[i].
used =
true;
530 return free_list[i].
md_ctx;
549 if (free_list[i].md_ctx == *ctx) {
550 free_list[i].
used =
false;
562#ifdef HAVE_OPENSSL_EVP_H
563void fr_md4_openssl_init(
void)
569 if (!EVP_default_properties_is_fips_enabled(NULL))
return;
582void fr_md4_openssl_free(
void)
static int const char char buffer[256]
#define fr_atexit_thread_local(_name, _free, _uctx)
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
uint8_t buffer[MD4_BLOCK_LENGTH]
Input buffer.
static int _md4_ctx_free_on_exit(void *arg)
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.
#define MD4STEP(f, w, x, y, z, data, s)
static void fr_md4_local_ctx_free(fr_md4_ctx_t **ctx)
Free function for MD4 digest ctx.
#define ARRAY_SIZE
The thread local free list.
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.
static fr_md4_ctx_t * fr_md4_local_ctx_alloc(void)
Allocation function for MD4 digest context.
fr_md4_ctx_t * fr_md4_ctx_alloc_from_list(void)
Allocation function for MD4 digest context.
uint32_t count[2]
Number of bits, mod 2^64.
static void fr_md4_local_update(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
Ingest plaintext into the digest.
static _Thread_local fr_md4_free_list_t * md4_array
static void fr_md4_local_ctx_copy(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
Copy the contents of a ctx.
static void fr_md4_local_final(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx)
Finalise the ctx, producing the digest.
static fr_md4_funcs_t md4_local_funcs
void fr_md4_ctx_free_from_list(fr_md4_ctx_t **ctx)
Free function for MD4 digest ctx.
fr_md4_funcs_t const * fr_md4_funcs
Swap a single pointer, so all functions get swapped as an atomic operation.
static void fr_md4_local_ctx_reset(fr_md4_ctx_t *ctx)
Reset the ctx to allow reuse.
static const uint8_t * zero
#define fr_md4_ctx_reset(_ctx)
Reset the ctx to allow reuse.
#define fr_md4_ctx_alloc()
Allocation function for MD4 digest context.
#define fr_md4_final(_out, _ctx)
Finalise the ctx, producing the digest.
#define MD4_DIGEST_LENGTH
#define fr_md4_ctx_free(_ctx)
Free function for MD4 digest ctx.
#define fr_md4_update(_ctx, _in, _inlen)
Ingest plaintext into the digest.
#define talloc_get_type_abort_const
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out