]>
git.proxmox.com Git - mirror_frr.git/blob - lib/md5.c
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.6 2006/01/17 23:39:04 vincent Exp $ */
6 * Copyright (C) 2004 6WIND
7 * <Vincent.Jardin@6WIND.com>
10 * This MD5 code is Big endian and Little Endian compatible.
14 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
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.
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
45 #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
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)))
52 #define ROUND1(a, b, c, d, k, s, i) \
54 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
55 (a) = SHIFT((a), (s)); \
59 #define ROUND2(a, b, c, d, k, s, i) \
61 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
62 (a) = SHIFT((a), (s)); \
66 #define ROUND3(a, b, c, d, k, s, i) \
68 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
69 (a) = SHIFT((a), (s)); \
73 #define ROUND4(a, b, c, d, k, s, i) \
75 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
76 (a) = SHIFT((a), (s)); \
100 #define MD5_A0 0x67452301
101 #define MD5_B0 0xefcdab89
102 #define MD5_C0 0x98badcfe
103 #define MD5_D0 0x10325476
105 /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
106 static const uint32_t T
[65] = {
107 0, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
108 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
109 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
111 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453,
112 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
113 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
115 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9,
116 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
117 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
119 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
120 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
121 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
124 static const uint8_t md5_paddat
[MD5_BUFLEN
] = {
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,
130 static void md5_calc(const uint8_t *, md5_ctxt
*);
132 void md5_init(md5_ctxt
*ctxt
)
136 ctxt
->md5_sta
= MD5_A0
;
137 ctxt
->md5_stb
= MD5_B0
;
138 ctxt
->md5_stc
= MD5_C0
;
139 ctxt
->md5_std
= MD5_D0
;
140 memset(ctxt
->md5_buf
, 0, sizeof(ctxt
->md5_buf
));
143 void md5_loop(md5_ctxt
*ctxt
, const void *vinput
, uint len
)
146 const uint8_t *input
= vinput
;
148 ctxt
->md5_n
+= len
* 8; /* byte to bit */
149 gap
= MD5_BUFLEN
- ctxt
->md5_i
;
152 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, input
, gap
);
153 md5_calc(ctxt
->md5_buf
, ctxt
);
155 for (i
= gap
; i
+ MD5_BUFLEN
<= len
; i
+= MD5_BUFLEN
) {
156 md5_calc((input
+ i
), ctxt
);
159 ctxt
->md5_i
= len
- i
;
160 memcpy(ctxt
->md5_buf
, (input
+ i
), ctxt
->md5_i
);
162 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, input
, len
);
167 void md5_pad(md5_ctxt
*ctxt
)
171 /* Don't count up padding. Keep md5_n. */
172 gap
= MD5_BUFLEN
- ctxt
->md5_i
;
174 memcpy(ctxt
->md5_buf
+ ctxt
->md5_i
, md5_paddat
,
175 gap
- sizeof(ctxt
->md5_n
));
177 /* including gap == 8 */
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
));
185 if (BYTE_ORDER
== LITTLE_ENDIAN
)
186 memcpy(&ctxt
->md5_buf
[56], &ctxt
->md5_n8
[0], 8);
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];
197 md5_calc(ctxt
->md5_buf
, ctxt
);
200 void md5_result(uint8_t *digest
, md5_ctxt
*ctxt
)
203 if (BYTE_ORDER
== LITTLE_ENDIAN
)
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];
225 static void md5_calc(const uint8_t *b64
, md5_ctxt
*ctxt
)
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)
236 if (BYTE_ORDER
== BIG_ENDIAN
) {
238 /* what a brute force but fast! */
239 uint8_t *y
= (uint8_t *)X
;
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);
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);
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);
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);
382 void hmac_md5(text
, text_len
, key
, key_len
,
383 digest
) unsigned char *text
; /* pointer to data stream */
384 int text_len
; /* length of data stream */
385 unsigned char *key
; /* pointer to authentication key */
386 int key_len
; /* length of authentication key */
387 uint8_t *digest
; /* caller digest to be filled in */
391 unsigned char k_ipad
[65]; /* inner padding -
394 unsigned char k_opad
[65]; /* outer padding -
397 unsigned char tk
[16];
399 /* if key is longer than 64 bytes reset it to key=MD5(key) */
405 MD5Update(&tctx
, key
, key_len
);
413 * the HMAC_MD5 transform looks like:
415 * MD5(K XOR opad, MD5(K XOR ipad, text))
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
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
);
429 /* XOR key with ipad and opad values */
430 for (i
= 0; i
< 64; i
++) {
437 MD5Init(&context
); /* init context for 1st
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 */
445 MD5Init(&context
); /* init context for 2nd
447 MD5Update(&context
, k_opad
, 64); /* start with outer pad */
448 MD5Update(&context
, digest
, 16); /* then results of 1st
450 MD5Final((uint8_t *)digest
, &context
); /* finish up 2nd pass */