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 $ */
3: /* $Id: md5.c,v 1.1.1.2 2012/10/09 09:22:28 misho Exp $ */
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:
42: #include <zebra.h>
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:
52: #define ROUND1(a, b, c, d, k, s, i) { \
53: (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
54: (a) = SHIFT((a), (s)); \
55: (a) = (b) + (a); \
56: }
57:
58: #define ROUND2(a, b, c, d, k, s, i) { \
59: (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
60: (a) = SHIFT((a), (s)); \
61: (a) = (b) + (a); \
62: }
63:
64: #define ROUND3(a, b, c, d, k, s, i) { \
65: (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
66: (a) = SHIFT((a), (s)); \
67: (a) = (b) + (a); \
68: }
69:
70: #define ROUND4(a, b, c, d, k, s, i) { \
71: (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
72: (a) = SHIFT((a), (s)); \
73: (a) = (b) + (a); \
74: }
75:
76: #define Sa 7
77: #define Sb 12
78: #define Sc 17
79: #define Sd 22
80:
81: #define Se 5
82: #define Sf 9
83: #define Sg 14
84: #define Sh 20
85:
86: #define Si 4
87: #define Sj 11
88: #define Sk 16
89: #define Sl 23
90:
91: #define Sm 6
92: #define Sn 10
93: #define So 15
94: #define Sp 21
95:
96: #define MD5_A0 0x67452301
97: #define MD5_B0 0xefcdab89
98: #define MD5_C0 0x98badcfe
99: #define MD5_D0 0x10325476
100:
101: /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
102: static const uint32_t T[65] = {
103: 0,
104: 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
105: 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
106: 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
107: 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
108:
109: 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
110: 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
111: 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
112: 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
113:
114: 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
115: 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
116: 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
117: 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
118:
119: 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
120: 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
121: 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
122: 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
123: };
124:
125: static const uint8_t md5_paddat[MD5_BUFLEN] = {
126: 0x80, 0, 0, 0, 0, 0, 0, 0,
127: 0, 0, 0, 0, 0, 0, 0, 0,
128: 0, 0, 0, 0, 0, 0, 0, 0,
129: 0, 0, 0, 0, 0, 0, 0, 0,
130: 0, 0, 0, 0, 0, 0, 0, 0,
131: 0, 0, 0, 0, 0, 0, 0, 0,
132: 0, 0, 0, 0, 0, 0, 0, 0,
133: 0, 0, 0, 0, 0, 0, 0, 0,
134: };
135:
136: static void md5_calc (const uint8_t *, md5_ctxt *);
137:
138: void md5_init(md5_ctxt *ctxt)
139: {
140: ctxt->md5_n = 0;
141: ctxt->md5_i = 0;
142: ctxt->md5_sta = MD5_A0;
143: ctxt->md5_stb = MD5_B0;
144: ctxt->md5_stc = MD5_C0;
145: ctxt->md5_std = MD5_D0;
146: memset (ctxt->md5_buf, 0, sizeof(ctxt->md5_buf));
147: }
148:
149: void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len)
150: {
151: uint gap, i;
152: const uint8_t *input = vinput;
153:
154: ctxt->md5_n += len * 8; /* byte to bit */
155: gap = MD5_BUFLEN - ctxt->md5_i;
156:
157: if (len >= gap) {
158: memcpy (ctxt->md5_buf + ctxt->md5_i, input, gap);
159: md5_calc(ctxt->md5_buf, ctxt);
160:
161: for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
162: md5_calc((input + i), ctxt);
163: }
164:
165: ctxt->md5_i = len - i;
166: memcpy (ctxt->md5_buf, (input + i), ctxt->md5_i);
167: } else {
168: memcpy (ctxt->md5_buf + ctxt->md5_i, input, len);
169: ctxt->md5_i += len;
170: }
171: }
172:
173: void md5_pad(md5_ctxt *ctxt)
174: {
175: uint gap;
176:
177: /* Don't count up padding. Keep md5_n. */
178: gap = MD5_BUFLEN - ctxt->md5_i;
179: if (gap > 8) {
180: memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat,
181: gap - sizeof(ctxt->md5_n));
182: } else {
183: /* including gap == 8 */
184: memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap);
185: md5_calc (ctxt->md5_buf, ctxt);
186: memcpy (ctxt->md5_buf, md5_paddat + gap,
187: MD5_BUFLEN - sizeof(ctxt->md5_n));
188: }
189:
190: /* 8 byte word */
191: if (BYTE_ORDER == LITTLE_ENDIAN)
192: memcpy (&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8);
193: else
194: {
195: ctxt->md5_buf[56] = ctxt->md5_n8[7];
196: ctxt->md5_buf[57] = ctxt->md5_n8[6];
197: ctxt->md5_buf[58] = ctxt->md5_n8[5];
198: ctxt->md5_buf[59] = ctxt->md5_n8[4];
199: ctxt->md5_buf[60] = ctxt->md5_n8[3];
200: ctxt->md5_buf[61] = ctxt->md5_n8[2];
201: ctxt->md5_buf[62] = ctxt->md5_n8[1];
202: ctxt->md5_buf[63] = ctxt->md5_n8[0];
203: }
204: md5_calc(ctxt->md5_buf, ctxt);
205: }
206:
207: void md5_result(uint8_t *digest, md5_ctxt *ctxt)
208: {
209: /* 4 byte words */
210: if (BYTE_ORDER == LITTLE_ENDIAN)
211: memcpy (digest, &ctxt->md5_st8[0], 16);
212: else if (BYTE_ORDER == BIG_ENDIAN)
213: {
214: digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
215: digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
216: digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
217: digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
218: digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
219: digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
220: digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
221: digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
222: }
223: }
224:
225: static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt)
226: {
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];
235:
236: if (BYTE_ORDER == BIG_ENDIAN)
237: {
238: /* 4 byte words */
239: /* what a brute force but fast! */
240: uint8_t *y = (uint8_t *)X;
241: y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
242: y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
243: y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
244: y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
245: y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
246: y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
247: y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
248: y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
249: y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
250: y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
251: y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
252: y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
253: y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
254: y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
255: y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
256: y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
257: }
258: #endif
259:
260: ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2);
261: ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4);
262: ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6);
263: ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8);
264: ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10);
265: ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
266: ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
267: ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
268:
269: ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18);
270: ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20);
271: ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
272: ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24);
273: ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
274: ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28);
275: ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30);
276: ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
277:
278: ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34);
279: ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
280: ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38);
281: ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
282: ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42);
283: ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44);
284: ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
285: ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48);
286:
287: ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50);
288: ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52);
289: ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54);
290: ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56);
291: ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);
292: ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);
293: ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);
294: ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64);
295:
296: ctxt->md5_sta += A;
297: ctxt->md5_stb += B;
298: ctxt->md5_stc += C;
299: ctxt->md5_std += D;
300: }
301:
302: /* From RFC 2104 */
303: void
304: hmac_md5(text, text_len, key, key_len, digest)
305: unsigned char* text; /* pointer to data stream */
306: int text_len; /* length of data stream */
307: unsigned char* key; /* pointer to authentication key */
308: int key_len; /* length of authentication key */
309: caddr_t digest; /* caller digest to be filled in */
310:
311: {
312: MD5_CTX context;
313: unsigned char k_ipad[65]; /* inner padding -
314: * key XORd with ipad
315: */
316: unsigned char k_opad[65]; /* outer padding -
317: * key XORd with opad
318: */
319: unsigned char tk[16];
320: int i;
321: /* if key is longer than 64 bytes reset it to key=MD5(key) */
322: if (key_len > 64) {
323:
324: MD5_CTX tctx;
325:
326: MD5Init(&tctx);
327: MD5Update(&tctx, key, key_len);
328: MD5Final(tk, &tctx);
329:
330: key = tk;
331: key_len = 16;
332: }
333:
334: /*
335: * the HMAC_MD5 transform looks like:
336: *
337: * MD5(K XOR opad, MD5(K XOR ipad, text))
338: *
339: * where K is an n byte key
340: * ipad is the byte 0x36 repeated 64 times
341: * opad is the byte 0x5c repeated 64 times
342: * and text is the data being protected
343: */
344:
345: /* start out by storing key in pads */
346: bzero( k_ipad, sizeof k_ipad);
347: bzero( k_opad, sizeof k_opad);
348: bcopy( key, k_ipad, key_len);
349: bcopy( key, k_opad, key_len);
350:
351: /* XOR key with ipad and opad values */
352: for (i=0; i<64; i++) {
353: k_ipad[i] ^= 0x36;
354: k_opad[i] ^= 0x5c;
355: }
356: /*
357: * perform inner MD5
358: */
359: MD5Init(&context); /* init context for 1st
360: * pass */
361: MD5Update(&context, k_ipad, 64); /* start with inner pad */
362: MD5Update(&context, text, text_len); /* then text of datagram */
363: MD5Final(digest, &context); /* finish up 1st pass */
364: /*
365: * perform outer MD5
366: */
367: MD5Init(&context); /* init context for 2nd
368: * pass */
369: MD5Update(&context, k_opad, 64); /* start with outer pad */
370: MD5Update(&context, digest, 16); /* then results of 1st
371: * hash */
372: MD5Final(digest, &context); /* finish up 2nd pass */
373: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>