]> git.proxmox.com Git - mirror_frr.git/blame - lib/md5.c
*: reindent
[mirror_frr.git] / lib / md5.c
CommitLineData
c1a03d47 1/* $USAGI: md5.c,v 1.2 2000/11/02 11:59:24 yoshfuji Exp $ */
2/* $KAME: md5.c,v 1.2 2000/05/27 07:07:48 jinmei Exp $ */
eac314c7 3/* $Id: md5.c,v 1.6 2006/01/17 23:39:04 vincent Exp $ */
c1a03d47 4
5/*
6 * Copyright (C) 2004 6WIND
7 * <Vincent.Jardin@6WIND.com>
8 * All rights reserved.
9 *
10 * This MD5 code is Big endian and Little Endian compatible.
11 */
12
13/*
14 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the project nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 */
41
34204aac 42#include <zebra.h>
c1a03d47 43#include "md5.h"
44
45#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
46
47#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
48#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
49#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
50#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
51
d62a17ae 52#define ROUND1(a, b, c, d, k, s, i) \
53 { \
54 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
55 (a) = SHIFT((a), (s)); \
56 (a) = (b) + (a); \
57 }
718e3744 58
d62a17ae 59#define ROUND2(a, b, c, d, k, s, i) \
60 { \
61 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
62 (a) = SHIFT((a), (s)); \
63 (a) = (b) + (a); \
64 }
718e3744 65
d62a17ae 66#define ROUND3(a, b, c, d, k, s, i) \
67 { \
68 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
69 (a) = SHIFT((a), (s)); \
70 (a) = (b) + (a); \
71 }
718e3744 72
d62a17ae 73#define ROUND4(a, b, c, d, k, s, i) \
74 { \
75 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
76 (a) = SHIFT((a), (s)); \
77 (a) = (b) + (a); \
78 }
718e3744 79
c1a03d47 80#define Sa 7
81#define Sb 12
82#define Sc 17
83#define Sd 22
84
85#define Se 5
86#define Sf 9
87#define Sg 14
88#define Sh 20
89
90#define Si 4
91#define Sj 11
92#define Sk 16
93#define Sl 23
94
95#define Sm 6
96#define Sn 10
97#define So 15
98#define Sp 21
99
100#define MD5_A0 0x67452301
101#define MD5_B0 0xefcdab89
102#define MD5_C0 0x98badcfe
103#define MD5_D0 0x10325476
104
105/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
34204aac 106static const uint32_t T[65] = {
d62a17ae 107 0, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
108 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
109 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
110
111 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453,
112 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
113 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
114
115 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9,
116 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
117 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
118
119 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
120 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
121 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
c1a03d47 122};
123
34204aac 124static const uint8_t md5_paddat[MD5_BUFLEN] = {
d62a17ae 125 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
c1a03d47 128};
129
d62a17ae 130static void md5_calc(const uint8_t *, md5_ctxt *);
c1a03d47 131
34204aac 132void md5_init(md5_ctxt *ctxt)
718e3744 133{
c1a03d47 134 ctxt->md5_n = 0;
135 ctxt->md5_i = 0;
136 ctxt->md5_sta = MD5_A0;
137 ctxt->md5_stb = MD5_B0;
138 ctxt->md5_stc = MD5_C0;
139 ctxt->md5_std = MD5_D0;
d62a17ae 140 memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf));
718e3744 141}
142
7d0b0c4b 143void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len)
718e3744 144{
34204aac 145 uint gap, i;
eac314c7 146 const uint8_t *input = vinput;
c1a03d47 147
148 ctxt->md5_n += len * 8; /* byte to bit */
149 gap = MD5_BUFLEN - ctxt->md5_i;
150
151 if (len >= gap) {
d62a17ae 152 memcpy(ctxt->md5_buf + ctxt->md5_i, input, gap);
c1a03d47 153 md5_calc(ctxt->md5_buf, ctxt);
154
155 for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
34204aac 156 md5_calc((input + i), ctxt);
c1a03d47 157 }
d62a17ae 158
c1a03d47 159 ctxt->md5_i = len - i;
d62a17ae 160 memcpy(ctxt->md5_buf, (input + i), ctxt->md5_i);
c1a03d47 161 } else {
d62a17ae 162 memcpy(ctxt->md5_buf + ctxt->md5_i, input, len);
c1a03d47 163 ctxt->md5_i += len;
718e3744 164 }
718e3744 165}
166
34204aac 167void md5_pad(md5_ctxt *ctxt)
718e3744 168{
34204aac 169 uint gap;
c1a03d47 170
d62a17ae 171 /* Don't count up padding. Keep md5_n. */
c1a03d47 172 gap = MD5_BUFLEN - ctxt->md5_i;
173 if (gap > 8) {
d62a17ae 174 memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat,
175 gap - sizeof(ctxt->md5_n));
c1a03d47 176 } else {
177 /* including gap == 8 */
d62a17ae 178 memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap);
179 md5_calc(ctxt->md5_buf, ctxt);
180 memcpy(ctxt->md5_buf, md5_paddat + gap,
181 MD5_BUFLEN - sizeof(ctxt->md5_n));
c1a03d47 182 }
718e3744 183
d62a17ae 184 /* 8 byte word */
34204aac 185 if (BYTE_ORDER == LITTLE_ENDIAN)
d62a17ae 186 memcpy(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8);
187 else {
188 ctxt->md5_buf[56] = ctxt->md5_n8[7];
189 ctxt->md5_buf[57] = ctxt->md5_n8[6];
190 ctxt->md5_buf[58] = ctxt->md5_n8[5];
191 ctxt->md5_buf[59] = ctxt->md5_n8[4];
192 ctxt->md5_buf[60] = ctxt->md5_n8[3];
193 ctxt->md5_buf[61] = ctxt->md5_n8[2];
194 ctxt->md5_buf[62] = ctxt->md5_n8[1];
195 ctxt->md5_buf[63] = ctxt->md5_n8[0];
196 }
c1a03d47 197 md5_calc(ctxt->md5_buf, ctxt);
718e3744 198}
199
34204aac 200void md5_result(uint8_t *digest, md5_ctxt *ctxt)
718e3744 201{
c1a03d47 202 /* 4 byte words */
34204aac 203 if (BYTE_ORDER == LITTLE_ENDIAN)
d62a17ae 204 memcpy(digest, &ctxt->md5_st8[0], 16);
205 else if (BYTE_ORDER == BIG_ENDIAN) {
206 digest[0] = ctxt->md5_st8[3];
207 digest[1] = ctxt->md5_st8[2];
208 digest[2] = ctxt->md5_st8[1];
209 digest[3] = ctxt->md5_st8[0];
210 digest[4] = ctxt->md5_st8[7];
211 digest[5] = ctxt->md5_st8[6];
212 digest[6] = ctxt->md5_st8[5];
213 digest[7] = ctxt->md5_st8[4];
214 digest[8] = ctxt->md5_st8[11];
215 digest[9] = ctxt->md5_st8[10];
216 digest[10] = ctxt->md5_st8[9];
217 digest[11] = ctxt->md5_st8[8];
218 digest[12] = ctxt->md5_st8[15];
219 digest[13] = ctxt->md5_st8[14];
220 digest[14] = ctxt->md5_st8[13];
221 digest[15] = ctxt->md5_st8[12];
222 }
718e3744 223}
224
d62a17ae 225static void md5_calc(const uint8_t *b64, md5_ctxt *ctxt)
718e3744 226{
34204aac 227 uint32_t A = ctxt->md5_sta;
228 uint32_t B = ctxt->md5_stb;
229 uint32_t C = ctxt->md5_stc;
230 uint32_t D = ctxt->md5_std;
231#if (BYTE_ORDER == LITTLE_ENDIAN)
232 const uint32_t *X = (const uint32_t *)b64;
233#elif (BYTE_ORDER == BIG_ENDIAN)
234 uint32_t X[16];
3949a60c 235
d62a17ae 236 if (BYTE_ORDER == BIG_ENDIAN) {
237 /* 4 byte words */
238 /* what a brute force but fast! */
239 uint8_t *y = (uint8_t *)X;
240 y[0] = b64[3];
241 y[1] = b64[2];
242 y[2] = b64[1];
243 y[3] = b64[0];
244 y[4] = b64[7];
245 y[5] = b64[6];
246 y[6] = b64[5];
247 y[7] = b64[4];
248 y[8] = b64[11];
249 y[9] = b64[10];
250 y[10] = b64[9];
251 y[11] = b64[8];
252 y[12] = b64[15];
253 y[13] = b64[14];
254 y[14] = b64[13];
255 y[15] = b64[12];
256 y[16] = b64[19];
257 y[17] = b64[18];
258 y[18] = b64[17];
259 y[19] = b64[16];
260 y[20] = b64[23];
261 y[21] = b64[22];
262 y[22] = b64[21];
263 y[23] = b64[20];
264 y[24] = b64[27];
265 y[25] = b64[26];
266 y[26] = b64[25];
267 y[27] = b64[24];
268 y[28] = b64[31];
269 y[29] = b64[30];
270 y[30] = b64[29];
271 y[31] = b64[28];
272 y[32] = b64[35];
273 y[33] = b64[34];
274 y[34] = b64[33];
275 y[35] = b64[32];
276 y[36] = b64[39];
277 y[37] = b64[38];
278 y[38] = b64[37];
279 y[39] = b64[36];
280 y[40] = b64[43];
281 y[41] = b64[42];
282 y[42] = b64[41];
283 y[43] = b64[40];
284 y[44] = b64[47];
285 y[45] = b64[46];
286 y[46] = b64[45];
287 y[47] = b64[44];
288 y[48] = b64[51];
289 y[49] = b64[50];
290 y[50] = b64[49];
291 y[51] = b64[48];
292 y[52] = b64[55];
293 y[53] = b64[54];
294 y[54] = b64[53];
295 y[55] = b64[52];
296 y[56] = b64[59];
297 y[57] = b64[58];
298 y[58] = b64[57];
299 y[59] = b64[56];
300 y[60] = b64[63];
301 y[61] = b64[62];
302 y[62] = b64[61];
303 y[63] = b64[60];
304 }
3949a60c 305#endif
c1a03d47 306
d62a17ae 307 ROUND1(A, B, C, D, 0, Sa, 1);
308 ROUND1(D, A, B, C, 1, Sb, 2);
309 ROUND1(C, D, A, B, 2, Sc, 3);
310 ROUND1(B, C, D, A, 3, Sd, 4);
311 ROUND1(A, B, C, D, 4, Sa, 5);
312 ROUND1(D, A, B, C, 5, Sb, 6);
313 ROUND1(C, D, A, B, 6, Sc, 7);
314 ROUND1(B, C, D, A, 7, Sd, 8);
315 ROUND1(A, B, C, D, 8, Sa, 9);
316 ROUND1(D, A, B, C, 9, Sb, 10);
317 ROUND1(C, D, A, B, 10, Sc, 11);
318 ROUND1(B, C, D, A, 11, Sd, 12);
319 ROUND1(A, B, C, D, 12, Sa, 13);
320 ROUND1(D, A, B, C, 13, Sb, 14);
321 ROUND1(C, D, A, B, 14, Sc, 15);
322 ROUND1(B, C, D, A, 15, Sd, 16);
323
324 ROUND2(A, B, C, D, 1, Se, 17);
325 ROUND2(D, A, B, C, 6, Sf, 18);
326 ROUND2(C, D, A, B, 11, Sg, 19);
327 ROUND2(B, C, D, A, 0, Sh, 20);
328 ROUND2(A, B, C, D, 5, Se, 21);
329 ROUND2(D, A, B, C, 10, Sf, 22);
330 ROUND2(C, D, A, B, 15, Sg, 23);
331 ROUND2(B, C, D, A, 4, Sh, 24);
332 ROUND2(A, B, C, D, 9, Se, 25);
333 ROUND2(D, A, B, C, 14, Sf, 26);
334 ROUND2(C, D, A, B, 3, Sg, 27);
335 ROUND2(B, C, D, A, 8, Sh, 28);
336 ROUND2(A, B, C, D, 13, Se, 29);
337 ROUND2(D, A, B, C, 2, Sf, 30);
338 ROUND2(C, D, A, B, 7, Sg, 31);
339 ROUND2(B, C, D, A, 12, Sh, 32);
340
341 ROUND3(A, B, C, D, 5, Si, 33);
342 ROUND3(D, A, B, C, 8, Sj, 34);
343 ROUND3(C, D, A, B, 11, Sk, 35);
344 ROUND3(B, C, D, A, 14, Sl, 36);
345 ROUND3(A, B, C, D, 1, Si, 37);
346 ROUND3(D, A, B, C, 4, Sj, 38);
347 ROUND3(C, D, A, B, 7, Sk, 39);
348 ROUND3(B, C, D, A, 10, Sl, 40);
349 ROUND3(A, B, C, D, 13, Si, 41);
350 ROUND3(D, A, B, C, 0, Sj, 42);
351 ROUND3(C, D, A, B, 3, Sk, 43);
352 ROUND3(B, C, D, A, 6, Sl, 44);
353 ROUND3(A, B, C, D, 9, Si, 45);
354 ROUND3(D, A, B, C, 12, Sj, 46);
355 ROUND3(C, D, A, B, 15, Sk, 47);
356 ROUND3(B, C, D, A, 2, Sl, 48);
357
358 ROUND4(A, B, C, D, 0, Sm, 49);
359 ROUND4(D, A, B, C, 7, Sn, 50);
360 ROUND4(C, D, A, B, 14, So, 51);
361 ROUND4(B, C, D, A, 5, Sp, 52);
362 ROUND4(A, B, C, D, 12, Sm, 53);
363 ROUND4(D, A, B, C, 3, Sn, 54);
364 ROUND4(C, D, A, B, 10, So, 55);
365 ROUND4(B, C, D, A, 1, Sp, 56);
366 ROUND4(A, B, C, D, 8, Sm, 57);
367 ROUND4(D, A, B, C, 15, Sn, 58);
368 ROUND4(C, D, A, B, 6, So, 59);
369 ROUND4(B, C, D, A, 13, Sp, 60);
370 ROUND4(A, B, C, D, 4, Sm, 61);
371 ROUND4(D, A, B, C, 11, Sn, 62);
372 ROUND4(C, D, A, B, 2, So, 63);
373 ROUND4(B, C, D, A, 9, Sp, 64);
c1a03d47 374
375 ctxt->md5_sta += A;
376 ctxt->md5_stb += B;
377 ctxt->md5_stc += C;
378 ctxt->md5_std += D;
379}
e6b03b77
FR
380
381/* From RFC 2104 */
d62a17ae 382void hmac_md5(text, text_len, key, key_len,
383 digest) unsigned char *text; /* pointer to data stream */
384int text_len; /* length of data stream */
385unsigned char *key; /* pointer to authentication key */
386int key_len; /* length of authentication key */
387uint8_t *digest; /* caller digest to be filled in */
e6b03b77
FR
388
389{
d62a17ae 390 MD5_CTX context;
391 unsigned char k_ipad[65]; /* inner padding -
392 * key XORd with ipad
393 */
394 unsigned char k_opad[65]; /* outer padding -
395 * key XORd with opad
396 */
397 unsigned char tk[16];
398 int i;
399 /* if key is longer than 64 bytes reset it to key=MD5(key) */
400 if (key_len > 64) {
401
402 MD5_CTX tctx;
403
404 MD5Init(&tctx);
405 MD5Update(&tctx, key, key_len);
406 MD5Final(tk, &tctx);
407
408 key = tk;
409 key_len = 16;
410 }
411
412 /*
413 * the HMAC_MD5 transform looks like:
414 *
415 * MD5(K XOR opad, MD5(K XOR ipad, text))
416 *
417 * where K is an n byte key
418 * ipad is the byte 0x36 repeated 64 times
419 * opad is the byte 0x5c repeated 64 times
420 * and text is the data being protected
421 */
422
423 /* start out by storing key in pads */
424 bzero(k_ipad, sizeof k_ipad);
425 bzero(k_opad, sizeof k_opad);
426 bcopy(key, k_ipad, key_len);
427 bcopy(key, k_opad, key_len);
428
429 /* XOR key with ipad and opad values */
430 for (i = 0; i < 64; i++) {
431 k_ipad[i] ^= 0x36;
432 k_opad[i] ^= 0x5c;
433 }
434 /*
435 * perform inner MD5
436 */
437 MD5Init(&context); /* init context for 1st
438 * pass */
439 MD5Update(&context, k_ipad, 64); /* start with inner pad */
440 MD5Update(&context, text, text_len); /* then text of datagram */
441 MD5Final((uint8_t *)digest, &context); /* finish up 1st pass */
442 /*
443 * perform outer MD5
444 */
445 MD5Init(&context); /* init context for 2nd
446 * pass */
447 MD5Update(&context, k_opad, 64); /* start with outer pad */
448 MD5Update(&context, digest, 16); /* then results of 1st
449 * hash */
450 MD5Final((uint8_t *)digest, &context); /* finish up 2nd pass */
e6b03b77 451}