7RCSID(
"$Id: 774f74e3d49871113aa756137cf339b959d75be2 $")
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>
32#ifdef HAVE_OPENSSL_EVP_H
44#ifdef HAVE_OPENSSL_EVP_H
45 .alloc = fr_md4_local_ctx_init,
61#ifdef HAVE_OPENSSL_EVP_H
62# include <freeradius-devel/tls/openssl_user_macros.h>
63# include <openssl/evp.h>
64# include <openssl/crypto.h>
65# include <openssl/err.h>
66# include <openssl/provider.h>
73 EVP_MD_CTX *md_ctx = ctx;
75 EVP_MD_CTX_reset(md_ctx);
76 EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL);
84 EVP_MD_CTX_copy_ex(dst, src);
94 md_ctx = EVP_MD_CTX_new();
97 if (EVP_DigestInit_ex(md_ctx, EVP_md4(), NULL) != 1) {
100 ERR_error_string_n(ERR_get_error(),
buffer,
sizeof(
buffer));
102 EVP_MD_CTX_free(md_ctx);
115 EVP_MD_CTX_free(*ctx);
124 EVP_DigestUpdate(ctx,
in,
inlen);
134 EVP_DigestFinal(ctx,
out, &len);
140 .
reset = fr_md4_openssl_ctx_reset,
141 .copy = fr_md4_openssl_ctx_copy,
142 .alloc = fr_md4_openssl_ctx_alloc,
143 .free = fr_md4_openssl_ctx_free,
144 .update = fr_md4_openssl_update,
145 .final = fr_md4_openssl_final
166#ifndef WORDS_BIGENDIAN
167# define htole32_4(buf)
168# define htole32_14(buf)
169# define htole32_16(buf)
174 (((((uint32_t)x) & 0xff000000) >> 24) |\
175 ((((uint32_t)x) & 0x00ff0000) >> 8) |\
176 ((((uint32_t)x) & 0x0000ff00) << 8) |\
177 ((((uint32_t)x) & 0x000000ff) << 24))
179# define htole32_4(buf) do {\
180 (buf)[0] = htole32((buf)[0]);\
181 (buf)[1] = htole32((buf)[1]);\
182 (buf)[2] = htole32((buf)[2]);\
183 (buf)[3] = htole32((buf)[3]);\
186# define htole32_14(buf) do {\
187 (buf)[0] = htole32((buf)[0]);\
188 (buf)[1] = htole32((buf)[1]);\
189 (buf)[2] = htole32((buf)[2]);\
190 (buf)[3] = htole32((buf)[3]);\
191 (buf)[4] = htole32((buf)[4]);\
192 (buf)[5] = htole32((buf)[5]);\
193 (buf)[6] = htole32((buf)[6]);\
194 (buf)[7] = htole32((buf)[7]);\
195 (buf)[8] = htole32((buf)[8]);\
196 (buf)[9] = htole32((buf)[9]);\
197 (buf)[10] = htole32((buf)[10]);\
198 (buf)[11] = htole32((buf)[11]);\
199 (buf)[12] = htole32((buf)[12]);\
200 (buf)[13] = htole32((buf)[13]);\
203# define htole32_16(buf) do {\
204 (buf)[0] = htole32((buf)[0]);\
205 (buf)[1] = htole32((buf)[1]);\
206 (buf)[2] = htole32((buf)[2]);\
207 (buf)[3] = htole32((buf)[3]);\
208 (buf)[4] = htole32((buf)[4]);\
209 (buf)[5] = htole32((buf)[5]);\
210 (buf)[6] = htole32((buf)[6]);\
211 (buf)[7] = htole32((buf)[7]);\
212 (buf)[8] = htole32((buf)[8]);\
213 (buf)[9] = htole32((buf)[9]);\
214 (buf)[10] = htole32((buf)[10]);\
215 (buf)[11] = htole32((buf)[11]);\
216 (buf)[12] = htole32((buf)[12]);\
217 (buf)[13] = htole32((buf)[13]);\
218 (buf)[14] = htole32((buf)[14]);\
219 (buf)[15] = htole32((buf)[15]);\
223#define MD4_BLOCK_LENGTH 64
226#define MD4_F1(x, y, z) (z ^ (x & (y ^ z)))
227#define MD4_F2(x, y, z) ((x & y) | (x & z) | (y & z))
228#define MD4_F3(x, y, z) (x ^ y ^ z)
231#define MD4STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s))
322 ctx_local->
count[0] = 0;
323 ctx_local->
count[1] = 0;
324 ctx_local->
state[0] = 0x67452301;
325 ctx_local->
state[1] = 0xefcdab89;
326 ctx_local->
state[2] = 0x98badcfe;
327 ctx_local->
state[3] = 0x10325476;
338 memcpy(ctx_local_dst, ctx_local_src,
sizeof(*ctx_local_dst));
349 if (
unlikely(!ctx_local))
return NULL;
355#ifdef HAVE_OPENSSL_EVP_H
364 if (!EVP_default_properties_is_fips_enabled(NULL)) {
419 ctx_local->
count[1]++;
425 unsigned char *p = (
unsigned char *)ctx_local->
buffer +
count;
482 memset(ctx_local->
buffer, 0, 56);
485 memset(p, 0,
count - 8);
496 memset(ctx_local, 0,
sizeof(*ctx_local));
531 if (free_list[i].
used)
continue;
562 if (
unlikely(md_ctx == NULL))
goto oom;
564 free_list[i].
md_ctx = md_ctx;
571 if (free_list[i].
used)
continue;
573 free_list[i].
used =
true;
574 return free_list[i].
md_ctx;
593 if (free_list[i].md_ctx == *ctx) {
594 free_list[i].
used =
false;
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.
fr_md4_ctx_alloc_t fr_md4_ctx_alloc
#define MD4STEP(f, w, x, y, z, data, s)
fr_md4_update_t fr_md4_update
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_reset_t fr_md4_ctx_reset
fr_md4_ctx_copy_t fr_md4_ctx_copy
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.
fr_md4_final_t fr_md4_final
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.
fr_md4_ctx_free_t fr_md4_ctx_free
static void fr_md4_local_ctx_reset(fr_md4_ctx_t *ctx)
Reset the ctx to allow reuse.
static const uint8_t * zero
void(* fr_md4_final_t)(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx)
fr_md4_ctx_t *(* fr_md4_ctx_alloc_t)(void)
void(* fr_md4_ctx_free_t)(fr_md4_ctx_t **ctx)
void(* fr_md4_ctx_copy_t)(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src)
#define MD4_DIGEST_LENGTH
void(* fr_md4_ctx_reset_t)(fr_md4_ctx_t *ctx)
void(* fr_md4_update_t)(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen)
#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