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