]>
git.proxmox.com Git - mirror_frr.git/blob - lib/md5.c
1 // SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (C) 2004 6WIND
4 * <Vincent.Jardin@6WIND.com>
7 * This MD5 code is Big endian and Little Endian compatible.
11 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
12 * All rights reserved.
18 #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
20 #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
21 #define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
22 #define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
23 #define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
25 #define ROUND1(a, b, c, d, k, s, i) \
27 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
28 (a) = SHIFT((a), (s)); \
32 #define ROUND2(a, b, c, d, k, s, i) \
34 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
35 (a) = SHIFT((a), (s)); \
39 #define ROUND3(a, b, c, d, k, s, i) \
41 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
42 (a) = SHIFT((a), (s)); \
46 #define ROUND4(a, b, c, d, k, s, i) \
48 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
49 (a) = SHIFT((a), (s)); \
73 #define MD5_A0 0x67452301
74 #define MD5_B0 0xefcdab89
75 #define MD5_C0 0x98badcfe
76 #define MD5_D0 0x10325476
78 /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
79 static const uint32_t T
[65] = {
80 0, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
81 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
82 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
84 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453,
85 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
86 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
88 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9,
89 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
90 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
92 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
93 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
94 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
97 static const uint8_t md5_paddat
[MD5_BUFLEN
] = {
98 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 static void md5_calc(const uint8_t *, md5_ctxt
*);
105 void md5_init(md5_ctxt
*ctxt
)
109 ctxt
->md5_sta
= MD5_A0
;
110 ctxt
->md5_stb
= MD5_B0
;
111 ctxt
->md5_stc
= MD5_C0
;
112 ctxt
->md5_std
= MD5_D0
;
113 memset(ctxt
->md5_buf
, 0, sizeof(ctxt
->md5_buf
));
116 void md5_loop(md5_ctxt
*ctxt
, const void *vinput
, uint len
)
119 const uint8_t *input
= vinput
;
121 ctxt
->md5_n
+= len
* 8; /* byte to bit */
122 gap
= MD5_BUFLEN
- ctxt
->md5_i
;
125 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, input
, gap
);
126 md5_calc(ctxt
->md5_buf
, ctxt
);
128 for (i
= gap
; i
+ MD5_BUFLEN
<= len
; i
+= MD5_BUFLEN
) {
129 md5_calc((input
+ i
), ctxt
);
132 ctxt
->md5_i
= len
- i
;
133 memcpy(ctxt
->md5_buf
, (input
+ i
), ctxt
->md5_i
);
135 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, input
, len
);
140 void md5_pad(md5_ctxt
*ctxt
)
144 /* Don't count up padding. Keep md5_n. */
145 gap
= MD5_BUFLEN
- ctxt
->md5_i
;
147 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, md5_paddat
,
148 gap
- sizeof(ctxt
->md5_n
));
150 /* including gap == 8 */
151 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, md5_paddat
, gap
);
152 md5_calc(ctxt
->md5_buf
, ctxt
);
153 memcpy(ctxt
->md5_buf
, md5_paddat
+ gap
,
154 MD5_BUFLEN
- sizeof(ctxt
->md5_n
));
158 if (BYTE_ORDER
== LITTLE_ENDIAN
)
159 memcpy(&ctxt
->md5_buf
[56], &ctxt
->md5_n8
[0], 8);
161 ctxt
->md5_buf
[56] = ctxt
->md5_n8
[7];
162 ctxt
->md5_buf
[57] = ctxt
->md5_n8
[6];
163 ctxt
->md5_buf
[58] = ctxt
->md5_n8
[5];
164 ctxt
->md5_buf
[59] = ctxt
->md5_n8
[4];
165 ctxt
->md5_buf
[60] = ctxt
->md5_n8
[3];
166 ctxt
->md5_buf
[61] = ctxt
->md5_n8
[2];
167 ctxt
->md5_buf
[62] = ctxt
->md5_n8
[1];
168 ctxt
->md5_buf
[63] = ctxt
->md5_n8
[0];
170 md5_calc(ctxt
->md5_buf
, ctxt
);
173 void md5_result(uint8_t *digest
, md5_ctxt
*ctxt
)
176 if (BYTE_ORDER
== LITTLE_ENDIAN
)
177 memcpy(digest
, &ctxt
->md5_st8
[0], 16);
178 else if (BYTE_ORDER
== BIG_ENDIAN
) {
179 digest
[0] = ctxt
->md5_st8
[3];
180 digest
[1] = ctxt
->md5_st8
[2];
181 digest
[2] = ctxt
->md5_st8
[1];
182 digest
[3] = ctxt
->md5_st8
[0];
183 digest
[4] = ctxt
->md5_st8
[7];
184 digest
[5] = ctxt
->md5_st8
[6];
185 digest
[6] = ctxt
->md5_st8
[5];
186 digest
[7] = ctxt
->md5_st8
[4];
187 digest
[8] = ctxt
->md5_st8
[11];
188 digest
[9] = ctxt
->md5_st8
[10];
189 digest
[10] = ctxt
->md5_st8
[9];
190 digest
[11] = ctxt
->md5_st8
[8];
191 digest
[12] = ctxt
->md5_st8
[15];
192 digest
[13] = ctxt
->md5_st8
[14];
193 digest
[14] = ctxt
->md5_st8
[13];
194 digest
[15] = ctxt
->md5_st8
[12];
198 static void md5_calc(const uint8_t *b64
, md5_ctxt
*ctxt
)
200 uint32_t A
= ctxt
->md5_sta
;
201 uint32_t B
= ctxt
->md5_stb
;
202 uint32_t C
= ctxt
->md5_stc
;
203 uint32_t D
= ctxt
->md5_std
;
204 #if (BYTE_ORDER == LITTLE_ENDIAN)
205 const uint32_t *X
= (const uint32_t *)b64
;
206 #elif (BYTE_ORDER == BIG_ENDIAN)
209 if (BYTE_ORDER
== BIG_ENDIAN
) {
211 /* what a brute force but fast! */
212 uint8_t *y
= (uint8_t *)X
;
280 ROUND1(A
, B
, C
, D
, 0, Sa
, 1);
281 ROUND1(D
, A
, B
, C
, 1, Sb
, 2);
282 ROUND1(C
, D
, A
, B
, 2, Sc
, 3);
283 ROUND1(B
, C
, D
, A
, 3, Sd
, 4);
284 ROUND1(A
, B
, C
, D
, 4, Sa
, 5);
285 ROUND1(D
, A
, B
, C
, 5, Sb
, 6);
286 ROUND1(C
, D
, A
, B
, 6, Sc
, 7);
287 ROUND1(B
, C
, D
, A
, 7, Sd
, 8);
288 ROUND1(A
, B
, C
, D
, 8, Sa
, 9);
289 ROUND1(D
, A
, B
, C
, 9, Sb
, 10);
290 ROUND1(C
, D
, A
, B
, 10, Sc
, 11);
291 ROUND1(B
, C
, D
, A
, 11, Sd
, 12);
292 ROUND1(A
, B
, C
, D
, 12, Sa
, 13);
293 ROUND1(D
, A
, B
, C
, 13, Sb
, 14);
294 ROUND1(C
, D
, A
, B
, 14, Sc
, 15);
295 ROUND1(B
, C
, D
, A
, 15, Sd
, 16);
297 ROUND2(A
, B
, C
, D
, 1, Se
, 17);
298 ROUND2(D
, A
, B
, C
, 6, Sf
, 18);
299 ROUND2(C
, D
, A
, B
, 11, Sg
, 19);
300 ROUND2(B
, C
, D
, A
, 0, Sh
, 20);
301 ROUND2(A
, B
, C
, D
, 5, Se
, 21);
302 ROUND2(D
, A
, B
, C
, 10, Sf
, 22);
303 ROUND2(C
, D
, A
, B
, 15, Sg
, 23);
304 ROUND2(B
, C
, D
, A
, 4, Sh
, 24);
305 ROUND2(A
, B
, C
, D
, 9, Se
, 25);
306 ROUND2(D
, A
, B
, C
, 14, Sf
, 26);
307 ROUND2(C
, D
, A
, B
, 3, Sg
, 27);
308 ROUND2(B
, C
, D
, A
, 8, Sh
, 28);
309 ROUND2(A
, B
, C
, D
, 13, Se
, 29);
310 ROUND2(D
, A
, B
, C
, 2, Sf
, 30);
311 ROUND2(C
, D
, A
, B
, 7, Sg
, 31);
312 ROUND2(B
, C
, D
, A
, 12, Sh
, 32);
314 ROUND3(A
, B
, C
, D
, 5, Si
, 33);
315 ROUND3(D
, A
, B
, C
, 8, Sj
, 34);
316 ROUND3(C
, D
, A
, B
, 11, Sk
, 35);
317 ROUND3(B
, C
, D
, A
, 14, Sl
, 36);
318 ROUND3(A
, B
, C
, D
, 1, Si
, 37);
319 ROUND3(D
, A
, B
, C
, 4, Sj
, 38);
320 ROUND3(C
, D
, A
, B
, 7, Sk
, 39);
321 ROUND3(B
, C
, D
, A
, 10, Sl
, 40);
322 ROUND3(A
, B
, C
, D
, 13, Si
, 41);
323 ROUND3(D
, A
, B
, C
, 0, Sj
, 42);
324 ROUND3(C
, D
, A
, B
, 3, Sk
, 43);
325 ROUND3(B
, C
, D
, A
, 6, Sl
, 44);
326 ROUND3(A
, B
, C
, D
, 9, Si
, 45);
327 ROUND3(D
, A
, B
, C
, 12, Sj
, 46);
328 ROUND3(C
, D
, A
, B
, 15, Sk
, 47);
329 ROUND3(B
, C
, D
, A
, 2, Sl
, 48);
331 ROUND4(A
, B
, C
, D
, 0, Sm
, 49);
332 ROUND4(D
, A
, B
, C
, 7, Sn
, 50);
333 ROUND4(C
, D
, A
, B
, 14, So
, 51);
334 ROUND4(B
, C
, D
, A
, 5, Sp
, 52);
335 ROUND4(A
, B
, C
, D
, 12, Sm
, 53);
336 ROUND4(D
, A
, B
, C
, 3, Sn
, 54);
337 ROUND4(C
, D
, A
, B
, 10, So
, 55);
338 ROUND4(B
, C
, D
, A
, 1, Sp
, 56);
339 ROUND4(A
, B
, C
, D
, 8, Sm
, 57);
340 ROUND4(D
, A
, B
, C
, 15, Sn
, 58);
341 ROUND4(C
, D
, A
, B
, 6, So
, 59);
342 ROUND4(B
, C
, D
, A
, 13, Sp
, 60);
343 ROUND4(A
, B
, C
, D
, 4, Sm
, 61);
344 ROUND4(D
, A
, B
, C
, 11, Sn
, 62);
345 ROUND4(C
, D
, A
, B
, 2, So
, 63);
346 ROUND4(B
, C
, D
, A
, 9, Sp
, 64);
355 void hmac_md5(unsigned char *text
, int text_len
, unsigned char *key
,
356 int key_len
, uint8_t *digest
)
359 unsigned char k_ipad
[65]; /* inner padding -
362 unsigned char k_opad
[65]; /* outer padding -
365 unsigned char tk
[16];
367 /* if key is longer than 64 bytes reset it to key=MD5(key) */
373 MD5Update(&tctx
, key
, key_len
);
381 * the HMAC_MD5 transform looks like:
383 * MD5(K XOR opad, MD5(K XOR ipad, text))
385 * where K is an n byte key
386 * ipad is the byte 0x36 repeated 64 times
387 * opad is the byte 0x5c repeated 64 times
388 * and text is the data being protected
391 /* start out by storing key in pads */
392 bzero(k_ipad
, sizeof(k_ipad
));
393 bzero(k_opad
, sizeof(k_opad
));
394 bcopy(key
, k_ipad
, key_len
);
395 bcopy(key
, k_opad
, key_len
);
397 /* XOR key with ipad and opad values */
398 for (i
= 0; i
< 64; i
++) {
405 MD5Init(&context
); /* init context for 1st
407 MD5Update(&context
, k_ipad
, 64); /* start with inner pad */
408 MD5Update(&context
, text
, text_len
); /* then text of datagram */
409 MD5Final(digest
, &context
); /* finish up 1st pass */
413 MD5Init(&context
); /* init context for 2nd
415 MD5Update(&context
, k_opad
, 64); /* start with outer pad */
416 MD5Update(&context
, digest
, 16); /* then results of 1st
418 MD5Final(digest
, &context
); /* finish up 2nd pass */
419 explicit_bzero(&context
, sizeof(context
));