]> git.proxmox.com Git - mirror_frr.git/blame - lib/md5.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / md5.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: BSD-3-Clause
c1a03d47 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.
c1a03d47 13 */
14
34204aac 15#include <zebra.h>
c1a03d47 16#include "md5.h"
17
18#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
19
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)))
24
d62a17ae 25#define ROUND1(a, b, c, d, k, s, i) \
26 { \
27 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
28 (a) = SHIFT((a), (s)); \
29 (a) = (b) + (a); \
30 }
718e3744 31
d62a17ae 32#define ROUND2(a, b, c, d, k, s, i) \
33 { \
34 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
35 (a) = SHIFT((a), (s)); \
36 (a) = (b) + (a); \
37 }
718e3744 38
d62a17ae 39#define ROUND3(a, b, c, d, k, s, i) \
40 { \
41 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
42 (a) = SHIFT((a), (s)); \
43 (a) = (b) + (a); \
44 }
718e3744 45
d62a17ae 46#define ROUND4(a, b, c, d, k, s, i) \
47 { \
48 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
49 (a) = SHIFT((a), (s)); \
50 (a) = (b) + (a); \
51 }
718e3744 52
c1a03d47 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#define MD5_A0 0x67452301
74#define MD5_B0 0xefcdab89
75#define MD5_C0 0x98badcfe
76#define MD5_D0 0x10325476
77
78/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
34204aac 79static const uint32_t T[65] = {
d62a17ae 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,
c1a03d47 95};
96
34204aac 97static const uint8_t md5_paddat[MD5_BUFLEN] = {
d62a17ae 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,
c1a03d47 101};
102
d62a17ae 103static void md5_calc(const uint8_t *, md5_ctxt *);
c1a03d47 104
34204aac 105void md5_init(md5_ctxt *ctxt)
718e3744 106{
c1a03d47 107 ctxt->md5_n = 0;
108 ctxt->md5_i = 0;
109 ctxt->md5_sta = MD5_A0;
110 ctxt->md5_stb = MD5_B0;
111 ctxt->md5_stc = MD5_C0;
112 ctxt->md5_std = MD5_D0;
d62a17ae 113 memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf));
718e3744 114}
115
7d0b0c4b 116void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len)
718e3744 117{
34204aac 118 uint gap, i;
eac314c7 119 const uint8_t *input = vinput;
c1a03d47 120
121 ctxt->md5_n += len * 8; /* byte to bit */
122 gap = MD5_BUFLEN - ctxt->md5_i;
123
124 if (len >= gap) {
d62a17ae 125 memcpy(ctxt->md5_buf + ctxt->md5_i, input, gap);
c1a03d47 126 md5_calc(ctxt->md5_buf, ctxt);
127
128 for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
34204aac 129 md5_calc((input + i), ctxt);
c1a03d47 130 }
d62a17ae 131
c1a03d47 132 ctxt->md5_i = len - i;
d62a17ae 133 memcpy(ctxt->md5_buf, (input + i), ctxt->md5_i);
c1a03d47 134 } else {
d62a17ae 135 memcpy(ctxt->md5_buf + ctxt->md5_i, input, len);
c1a03d47 136 ctxt->md5_i += len;
718e3744 137 }
718e3744 138}
139
34204aac 140void md5_pad(md5_ctxt *ctxt)
718e3744 141{
34204aac 142 uint gap;
c1a03d47 143
d62a17ae 144 /* Don't count up padding. Keep md5_n. */
c1a03d47 145 gap = MD5_BUFLEN - ctxt->md5_i;
146 if (gap > 8) {
d62a17ae 147 memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat,
148 gap - sizeof(ctxt->md5_n));
c1a03d47 149 } else {
150 /* including gap == 8 */
d62a17ae 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));
c1a03d47 155 }
718e3744 156
d62a17ae 157 /* 8 byte word */
34204aac 158 if (BYTE_ORDER == LITTLE_ENDIAN)
d62a17ae 159 memcpy(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8);
160 else {
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];
169 }
c1a03d47 170 md5_calc(ctxt->md5_buf, ctxt);
718e3744 171}
172
34204aac 173void md5_result(uint8_t *digest, md5_ctxt *ctxt)
718e3744 174{
c1a03d47 175 /* 4 byte words */
34204aac 176 if (BYTE_ORDER == LITTLE_ENDIAN)
d62a17ae 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];
195 }
718e3744 196}
197
d62a17ae 198static void md5_calc(const uint8_t *b64, md5_ctxt *ctxt)
718e3744 199{
34204aac 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)
207 uint32_t X[16];
3949a60c 208
d62a17ae 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 }
3949a60c 278#endif
c1a03d47 279
d62a17ae 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);
296
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);
313
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);
330
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);
c1a03d47 347
348 ctxt->md5_sta += A;
349 ctxt->md5_stb += B;
350 ctxt->md5_stc += C;
351 ctxt->md5_std += D;
352}
e6b03b77
FR
353
354/* From RFC 2104 */
4d762f26
RK
355void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
356 int key_len, uint8_t *digest)
e6b03b77 357{
d62a17ae 358 MD5_CTX context;
359 unsigned char k_ipad[65]; /* inner padding -
9d303b37
DL
360 * key XORd with ipad
361 */
d62a17ae 362 unsigned char k_opad[65]; /* outer padding -
9d303b37
DL
363 * key XORd with opad
364 */
d62a17ae 365 unsigned char tk[16];
366 int i;
367 /* if key is longer than 64 bytes reset it to key=MD5(key) */
368 if (key_len > 64) {
369
370 MD5_CTX tctx;
371
372 MD5Init(&tctx);
373 MD5Update(&tctx, key, key_len);
374 MD5Final(tk, &tctx);
375
376 key = tk;
377 key_len = 16;
378 }
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 */
0d6f7fd6
DA
392 bzero(k_ipad, sizeof(k_ipad));
393 bzero(k_opad, sizeof(k_opad));
d62a17ae 394 bcopy(key, k_ipad, key_len);
395 bcopy(key, k_opad, key_len);
396
397 /* XOR key with ipad and opad values */
398 for (i = 0; i < 64; i++) {
399 k_ipad[i] ^= 0x36;
400 k_opad[i] ^= 0x5c;
401 }
402 /*
403 * perform inner MD5
404 */
405 MD5Init(&context); /* init context for 1st
406 * pass */
407 MD5Update(&context, k_ipad, 64); /* start with inner pad */
408 MD5Update(&context, text, text_len); /* then text of datagram */
c4efd0f4 409 MD5Final(digest, &context); /* finish up 1st pass */
d62a17ae 410 /*
411 * perform outer MD5
412 */
413 MD5Init(&context); /* init context for 2nd
414 * pass */
415 MD5Update(&context, k_opad, 64); /* start with outer pad */
416 MD5Update(&context, digest, 16); /* then results of 1st
417 * hash */
c4efd0f4 418 MD5Final(digest, &context); /* finish up 2nd pass */
04b4b595 419 explicit_bzero(&context, sizeof(context));
e6b03b77 420}