Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: BSD-3-Clause |
2 | | /* |
3 | | * Copyright (C) 2004 6WIND |
4 | | * <Vincent.Jardin@6WIND.com> |
5 | | * All rights reserved. |
6 | | * |
7 | | * This MD5 code is Big endian and Little Endian compatible. |
8 | | */ |
9 | | |
10 | | /* |
11 | | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
12 | | * All rights reserved. |
13 | | */ |
14 | | |
15 | | #include <zebra.h> |
16 | | #include "md5.h" |
17 | | |
18 | 0 | #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s)))) |
19 | | |
20 | 0 | #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) |
21 | 0 | #define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z))) |
22 | 0 | #define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) |
23 | 0 | #define I(X, Y, Z) ((Y) ^ ((X) | (~Z))) |
24 | | |
25 | | #define ROUND1(a, b, c, d, k, s, i) \ |
26 | 0 | { \ |
27 | 0 | (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ |
28 | 0 | (a) = SHIFT((a), (s)); \ |
29 | 0 | (a) = (b) + (a); \ |
30 | 0 | } |
31 | | |
32 | | #define ROUND2(a, b, c, d, k, s, i) \ |
33 | 0 | { \ |
34 | 0 | (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ |
35 | 0 | (a) = SHIFT((a), (s)); \ |
36 | 0 | (a) = (b) + (a); \ |
37 | 0 | } |
38 | | |
39 | | #define ROUND3(a, b, c, d, k, s, i) \ |
40 | 0 | { \ |
41 | 0 | (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ |
42 | 0 | (a) = SHIFT((a), (s)); \ |
43 | 0 | (a) = (b) + (a); \ |
44 | 0 | } |
45 | | |
46 | | #define ROUND4(a, b, c, d, k, s, i) \ |
47 | 0 | { \ |
48 | 0 | (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ |
49 | 0 | (a) = SHIFT((a), (s)); \ |
50 | 0 | (a) = (b) + (a); \ |
51 | 0 | } |
52 | | |
53 | | #define Sa 7 |
54 | | #define Sb 12 |
55 | | #define Sc 17 |
56 | | #define Sd 22 |
57 | | |
58 | | #define Se 5 |
59 | | #define Sf 9 |
60 | | #define Sg 14 |
61 | | #define Sh 20 |
62 | | |
63 | | #define Si 4 |
64 | | #define Sj 11 |
65 | | #define Sk 16 |
66 | | #define Sl 23 |
67 | | |
68 | | #define Sm 6 |
69 | | #define Sn 10 |
70 | | #define So 15 |
71 | | #define Sp 21 |
72 | | |
73 | 0 | #define MD5_A0 0x67452301 |
74 | 0 | #define MD5_B0 0xefcdab89 |
75 | 0 | #define MD5_C0 0x98badcfe |
76 | 0 | #define MD5_D0 0x10325476 |
77 | | |
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, |
83 | | |
84 | | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, |
85 | | 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, |
86 | | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, |
87 | | |
88 | | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, |
89 | | 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, |
90 | | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, |
91 | | |
92 | | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, |
93 | | 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, |
94 | | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, |
95 | | }; |
96 | | |
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, |
101 | | }; |
102 | | |
103 | | static void md5_calc(const uint8_t *, md5_ctxt *); |
104 | | |
105 | | void md5_init(md5_ctxt *ctxt) |
106 | 0 | { |
107 | 0 | ctxt->md5_n = 0; |
108 | 0 | ctxt->md5_i = 0; |
109 | 0 | ctxt->md5_sta = MD5_A0; |
110 | 0 | ctxt->md5_stb = MD5_B0; |
111 | 0 | ctxt->md5_stc = MD5_C0; |
112 | 0 | ctxt->md5_std = MD5_D0; |
113 | 0 | memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); |
114 | 0 | } |
115 | | |
116 | | void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len) |
117 | 0 | { |
118 | 0 | uint gap, i; |
119 | 0 | const uint8_t *input = vinput; |
120 | |
|
121 | 0 | ctxt->md5_n += len * 8; /* byte to bit */ |
122 | 0 | gap = MD5_BUFLEN - ctxt->md5_i; |
123 | |
|
124 | 0 | if (len >= gap) { |
125 | 0 | memcpy(ctxt->md5_buf + ctxt->md5_i, input, gap); |
126 | 0 | md5_calc(ctxt->md5_buf, ctxt); |
127 | |
|
128 | 0 | for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) { |
129 | 0 | md5_calc((input + i), ctxt); |
130 | 0 | } |
131 | |
|
132 | 0 | ctxt->md5_i = len - i; |
133 | 0 | memcpy(ctxt->md5_buf, (input + i), ctxt->md5_i); |
134 | 0 | } else { |
135 | 0 | memcpy(ctxt->md5_buf + ctxt->md5_i, input, len); |
136 | 0 | ctxt->md5_i += len; |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | | void md5_pad(md5_ctxt *ctxt) |
141 | 0 | { |
142 | 0 | uint gap; |
143 | | |
144 | | /* Don't count up padding. Keep md5_n. */ |
145 | 0 | gap = MD5_BUFLEN - ctxt->md5_i; |
146 | 0 | if (gap > 8) { |
147 | 0 | memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat, |
148 | 0 | gap - sizeof(ctxt->md5_n)); |
149 | 0 | } else { |
150 | | /* including gap == 8 */ |
151 | 0 | memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); |
152 | 0 | md5_calc(ctxt->md5_buf, ctxt); |
153 | 0 | memcpy(ctxt->md5_buf, md5_paddat + gap, |
154 | 0 | MD5_BUFLEN - sizeof(ctxt->md5_n)); |
155 | 0 | } |
156 | | |
157 | | /* 8 byte word */ |
158 | 0 | if (BYTE_ORDER == LITTLE_ENDIAN) |
159 | 0 | memcpy(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); |
160 | 0 | else { |
161 | 0 | ctxt->md5_buf[56] = ctxt->md5_n8[7]; |
162 | 0 | ctxt->md5_buf[57] = ctxt->md5_n8[6]; |
163 | 0 | ctxt->md5_buf[58] = ctxt->md5_n8[5]; |
164 | 0 | ctxt->md5_buf[59] = ctxt->md5_n8[4]; |
165 | 0 | ctxt->md5_buf[60] = ctxt->md5_n8[3]; |
166 | 0 | ctxt->md5_buf[61] = ctxt->md5_n8[2]; |
167 | 0 | ctxt->md5_buf[62] = ctxt->md5_n8[1]; |
168 | 0 | ctxt->md5_buf[63] = ctxt->md5_n8[0]; |
169 | 0 | } |
170 | 0 | md5_calc(ctxt->md5_buf, ctxt); |
171 | 0 | } |
172 | | |
173 | | void md5_result(uint8_t *digest, md5_ctxt *ctxt) |
174 | 0 | { |
175 | | /* 4 byte words */ |
176 | 0 | if (BYTE_ORDER == LITTLE_ENDIAN) |
177 | 0 | memcpy(digest, &ctxt->md5_st8[0], 16); |
178 | 0 | else if (BYTE_ORDER == BIG_ENDIAN) { |
179 | 0 | digest[0] = ctxt->md5_st8[3]; |
180 | 0 | digest[1] = ctxt->md5_st8[2]; |
181 | 0 | digest[2] = ctxt->md5_st8[1]; |
182 | 0 | digest[3] = ctxt->md5_st8[0]; |
183 | 0 | digest[4] = ctxt->md5_st8[7]; |
184 | 0 | digest[5] = ctxt->md5_st8[6]; |
185 | 0 | digest[6] = ctxt->md5_st8[5]; |
186 | 0 | digest[7] = ctxt->md5_st8[4]; |
187 | 0 | digest[8] = ctxt->md5_st8[11]; |
188 | 0 | digest[9] = ctxt->md5_st8[10]; |
189 | 0 | digest[10] = ctxt->md5_st8[9]; |
190 | 0 | digest[11] = ctxt->md5_st8[8]; |
191 | 0 | digest[12] = ctxt->md5_st8[15]; |
192 | 0 | digest[13] = ctxt->md5_st8[14]; |
193 | 0 | digest[14] = ctxt->md5_st8[13]; |
194 | 0 | digest[15] = ctxt->md5_st8[12]; |
195 | 0 | } |
196 | 0 | } |
197 | | |
198 | | static void md5_calc(const uint8_t *b64, md5_ctxt *ctxt) |
199 | 0 | { |
200 | 0 | uint32_t A = ctxt->md5_sta; |
201 | 0 | uint32_t B = ctxt->md5_stb; |
202 | 0 | uint32_t C = ctxt->md5_stc; |
203 | 0 | uint32_t D = ctxt->md5_std; |
204 | 0 | #if (BYTE_ORDER == LITTLE_ENDIAN) |
205 | 0 | const uint32_t *X = (const uint32_t *)b64; |
206 | | #elif (BYTE_ORDER == BIG_ENDIAN) |
207 | | uint32_t X[16]; |
208 | | |
209 | | if (BYTE_ORDER == BIG_ENDIAN) { |
210 | | /* 4 byte words */ |
211 | | /* what a brute force but fast! */ |
212 | | uint8_t *y = (uint8_t *)X; |
213 | | y[0] = b64[3]; |
214 | | y[1] = b64[2]; |
215 | | y[2] = b64[1]; |
216 | | y[3] = b64[0]; |
217 | | y[4] = b64[7]; |
218 | | y[5] = b64[6]; |
219 | | y[6] = b64[5]; |
220 | | y[7] = b64[4]; |
221 | | y[8] = b64[11]; |
222 | | y[9] = b64[10]; |
223 | | y[10] = b64[9]; |
224 | | y[11] = b64[8]; |
225 | | y[12] = b64[15]; |
226 | | y[13] = b64[14]; |
227 | | y[14] = b64[13]; |
228 | | y[15] = b64[12]; |
229 | | y[16] = b64[19]; |
230 | | y[17] = b64[18]; |
231 | | y[18] = b64[17]; |
232 | | y[19] = b64[16]; |
233 | | y[20] = b64[23]; |
234 | | y[21] = b64[22]; |
235 | | y[22] = b64[21]; |
236 | | y[23] = b64[20]; |
237 | | y[24] = b64[27]; |
238 | | y[25] = b64[26]; |
239 | | y[26] = b64[25]; |
240 | | y[27] = b64[24]; |
241 | | y[28] = b64[31]; |
242 | | y[29] = b64[30]; |
243 | | y[30] = b64[29]; |
244 | | y[31] = b64[28]; |
245 | | y[32] = b64[35]; |
246 | | y[33] = b64[34]; |
247 | | y[34] = b64[33]; |
248 | | y[35] = b64[32]; |
249 | | y[36] = b64[39]; |
250 | | y[37] = b64[38]; |
251 | | y[38] = b64[37]; |
252 | | y[39] = b64[36]; |
253 | | y[40] = b64[43]; |
254 | | y[41] = b64[42]; |
255 | | y[42] = b64[41]; |
256 | | y[43] = b64[40]; |
257 | | y[44] = b64[47]; |
258 | | y[45] = b64[46]; |
259 | | y[46] = b64[45]; |
260 | | y[47] = b64[44]; |
261 | | y[48] = b64[51]; |
262 | | y[49] = b64[50]; |
263 | | y[50] = b64[49]; |
264 | | y[51] = b64[48]; |
265 | | y[52] = b64[55]; |
266 | | y[53] = b64[54]; |
267 | | y[54] = b64[53]; |
268 | | y[55] = b64[52]; |
269 | | y[56] = b64[59]; |
270 | | y[57] = b64[58]; |
271 | | y[58] = b64[57]; |
272 | | y[59] = b64[56]; |
273 | | y[60] = b64[63]; |
274 | | y[61] = b64[62]; |
275 | | y[62] = b64[61]; |
276 | | y[63] = b64[60]; |
277 | | } |
278 | | #endif |
279 | |
|
280 | 0 | ROUND1(A, B, C, D, 0, Sa, 1); |
281 | 0 | ROUND1(D, A, B, C, 1, Sb, 2); |
282 | 0 | ROUND1(C, D, A, B, 2, Sc, 3); |
283 | 0 | ROUND1(B, C, D, A, 3, Sd, 4); |
284 | 0 | ROUND1(A, B, C, D, 4, Sa, 5); |
285 | 0 | ROUND1(D, A, B, C, 5, Sb, 6); |
286 | 0 | ROUND1(C, D, A, B, 6, Sc, 7); |
287 | 0 | ROUND1(B, C, D, A, 7, Sd, 8); |
288 | 0 | ROUND1(A, B, C, D, 8, Sa, 9); |
289 | 0 | ROUND1(D, A, B, C, 9, Sb, 10); |
290 | 0 | ROUND1(C, D, A, B, 10, Sc, 11); |
291 | 0 | ROUND1(B, C, D, A, 11, Sd, 12); |
292 | 0 | ROUND1(A, B, C, D, 12, Sa, 13); |
293 | 0 | ROUND1(D, A, B, C, 13, Sb, 14); |
294 | 0 | ROUND1(C, D, A, B, 14, Sc, 15); |
295 | 0 | ROUND1(B, C, D, A, 15, Sd, 16); |
296 | |
|
297 | 0 | ROUND2(A, B, C, D, 1, Se, 17); |
298 | 0 | ROUND2(D, A, B, C, 6, Sf, 18); |
299 | 0 | ROUND2(C, D, A, B, 11, Sg, 19); |
300 | 0 | ROUND2(B, C, D, A, 0, Sh, 20); |
301 | 0 | ROUND2(A, B, C, D, 5, Se, 21); |
302 | 0 | ROUND2(D, A, B, C, 10, Sf, 22); |
303 | 0 | ROUND2(C, D, A, B, 15, Sg, 23); |
304 | 0 | ROUND2(B, C, D, A, 4, Sh, 24); |
305 | 0 | ROUND2(A, B, C, D, 9, Se, 25); |
306 | 0 | ROUND2(D, A, B, C, 14, Sf, 26); |
307 | 0 | ROUND2(C, D, A, B, 3, Sg, 27); |
308 | 0 | ROUND2(B, C, D, A, 8, Sh, 28); |
309 | 0 | ROUND2(A, B, C, D, 13, Se, 29); |
310 | 0 | ROUND2(D, A, B, C, 2, Sf, 30); |
311 | 0 | ROUND2(C, D, A, B, 7, Sg, 31); |
312 | 0 | ROUND2(B, C, D, A, 12, Sh, 32); |
313 | |
|
314 | 0 | ROUND3(A, B, C, D, 5, Si, 33); |
315 | 0 | ROUND3(D, A, B, C, 8, Sj, 34); |
316 | 0 | ROUND3(C, D, A, B, 11, Sk, 35); |
317 | 0 | ROUND3(B, C, D, A, 14, Sl, 36); |
318 | 0 | ROUND3(A, B, C, D, 1, Si, 37); |
319 | 0 | ROUND3(D, A, B, C, 4, Sj, 38); |
320 | 0 | ROUND3(C, D, A, B, 7, Sk, 39); |
321 | 0 | ROUND3(B, C, D, A, 10, Sl, 40); |
322 | 0 | ROUND3(A, B, C, D, 13, Si, 41); |
323 | 0 | ROUND3(D, A, B, C, 0, Sj, 42); |
324 | 0 | ROUND3(C, D, A, B, 3, Sk, 43); |
325 | 0 | ROUND3(B, C, D, A, 6, Sl, 44); |
326 | 0 | ROUND3(A, B, C, D, 9, Si, 45); |
327 | 0 | ROUND3(D, A, B, C, 12, Sj, 46); |
328 | 0 | ROUND3(C, D, A, B, 15, Sk, 47); |
329 | 0 | ROUND3(B, C, D, A, 2, Sl, 48); |
330 | |
|
331 | 0 | ROUND4(A, B, C, D, 0, Sm, 49); |
332 | 0 | ROUND4(D, A, B, C, 7, Sn, 50); |
333 | 0 | ROUND4(C, D, A, B, 14, So, 51); |
334 | 0 | ROUND4(B, C, D, A, 5, Sp, 52); |
335 | 0 | ROUND4(A, B, C, D, 12, Sm, 53); |
336 | 0 | ROUND4(D, A, B, C, 3, Sn, 54); |
337 | 0 | ROUND4(C, D, A, B, 10, So, 55); |
338 | 0 | ROUND4(B, C, D, A, 1, Sp, 56); |
339 | 0 | ROUND4(A, B, C, D, 8, Sm, 57); |
340 | 0 | ROUND4(D, A, B, C, 15, Sn, 58); |
341 | 0 | ROUND4(C, D, A, B, 6, So, 59); |
342 | 0 | ROUND4(B, C, D, A, 13, Sp, 60); |
343 | 0 | ROUND4(A, B, C, D, 4, Sm, 61); |
344 | 0 | ROUND4(D, A, B, C, 11, Sn, 62); |
345 | 0 | ROUND4(C, D, A, B, 2, So, 63); |
346 | 0 | ROUND4(B, C, D, A, 9, Sp, 64); |
347 | |
|
348 | 0 | ctxt->md5_sta += A; |
349 | 0 | ctxt->md5_stb += B; |
350 | 0 | ctxt->md5_stc += C; |
351 | 0 | ctxt->md5_std += D; |
352 | 0 | } |
353 | | |
354 | | /* From RFC 2104 */ |
355 | | void hmac_md5(unsigned char *text, int text_len, unsigned char *key, |
356 | | int key_len, uint8_t *digest) |
357 | 0 | { |
358 | 0 | MD5_CTX context; |
359 | 0 | unsigned char k_ipad[65]; /* inner padding - |
360 | | * key XORd with ipad |
361 | | */ |
362 | 0 | unsigned char k_opad[65]; /* outer padding - |
363 | | * key XORd with opad |
364 | | */ |
365 | 0 | unsigned char tk[16]; |
366 | 0 | int i; |
367 | | /* if key is longer than 64 bytes reset it to key=MD5(key) */ |
368 | 0 | if (key_len > 64) { |
369 | |
|
370 | 0 | MD5_CTX tctx; |
371 | |
|
372 | 0 | MD5Init(&tctx); |
373 | 0 | MD5Update(&tctx, key, key_len); |
374 | 0 | MD5Final(tk, &tctx); |
375 | |
|
376 | 0 | key = tk; |
377 | 0 | key_len = 16; |
378 | 0 | } |
379 | | |
380 | | /* |
381 | | * the HMAC_MD5 transform looks like: |
382 | | * |
383 | | * MD5(K XOR opad, MD5(K XOR ipad, text)) |
384 | | * |
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 |
389 | | */ |
390 | | |
391 | | /* start out by storing key in pads */ |
392 | 0 | bzero(k_ipad, sizeof(k_ipad)); |
393 | 0 | bzero(k_opad, sizeof(k_opad)); |
394 | 0 | bcopy(key, k_ipad, key_len); |
395 | 0 | bcopy(key, k_opad, key_len); |
396 | | |
397 | | /* XOR key with ipad and opad values */ |
398 | 0 | for (i = 0; i < 64; i++) { |
399 | 0 | k_ipad[i] ^= 0x36; |
400 | 0 | k_opad[i] ^= 0x5c; |
401 | 0 | } |
402 | | /* |
403 | | * perform inner MD5 |
404 | | */ |
405 | 0 | MD5Init(&context); /* init context for 1st |
406 | | * pass */ |
407 | 0 | MD5Update(&context, k_ipad, 64); /* start with inner pad */ |
408 | 0 | MD5Update(&context, text, text_len); /* then text of datagram */ |
409 | 0 | MD5Final(digest, &context); /* finish up 1st pass */ |
410 | | /* |
411 | | * perform outer MD5 |
412 | | */ |
413 | 0 | MD5Init(&context); /* init context for 2nd |
414 | | * pass */ |
415 | 0 | MD5Update(&context, k_opad, 64); /* start with outer pad */ |
416 | 0 | MD5Update(&context, digest, 16); /* then results of 1st |
417 | | * hash */ |
418 | 0 | MD5Final(digest, &context); /* finish up 2nd pass */ |
419 | 0 | explicit_bzero(&context, sizeof(context)); |
420 | 0 | } |