blob: e994085c86739e79ce7cb7df1abdcfbbb5e1f17b [file] [log] [blame]
vincentc1a03d42005-09-28 15:47:44 +00001/* $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 $ */
paul34204aa2005-11-03 09:00:23 +00003/* $Id: md5.c,v 1.4 2005/11/03 09:00:23 paul Exp $ */
paul718e3742002-12-13 20:15:29 +00004
vincentc1a03d42005-09-28 15:47:44 +00005/*
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 */
paul718e3742002-12-13 20:15:29 +000012
vincentc1a03d42005-09-28 15:47:44 +000013/*
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 */
paul718e3742002-12-13 20:15:29 +000041
paul34204aa2005-11-03 09:00:23 +000042#include <zebra.h>
vincentc1a03d42005-09-28 15:47:44 +000043#include "md5.h"
paul718e3742002-12-13 20:15:29 +000044
vincentc1a03d42005-09-28 15:47:44 +000045#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
paul718e3742002-12-13 20:15:29 +000046
vincentc1a03d42005-09-28 15:47:44 +000047#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)))
paul718e3742002-12-13 20:15:29 +000051
vincentc1a03d42005-09-28 15:47:44 +000052#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); \
paul718e3742002-12-13 20:15:29 +000056}
57
vincentc1a03d42005-09-28 15:47:44 +000058#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); \
paul718e3742002-12-13 20:15:29 +000062}
63
vincentc1a03d42005-09-28 15:47:44 +000064#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); \
paul718e3742002-12-13 20:15:29 +000068}
69
vincentc1a03d42005-09-28 15:47:44 +000070#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. */
paul34204aa2005-11-03 09:00:23 +0000102static const uint32_t T[65] = {
vincentc1a03d42005-09-28 15:47:44 +0000103 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
paul34204aa2005-11-03 09:00:23 +0000125static const uint8_t md5_paddat[MD5_BUFLEN] = {
vincentc1a03d42005-09-28 15:47:44 +0000126 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
paul34204aa2005-11-03 09:00:23 +0000136static void md5_calc (const uint8_t *, md5_ctxt *);
vincentc1a03d42005-09-28 15:47:44 +0000137
paul34204aa2005-11-03 09:00:23 +0000138void md5_init(md5_ctxt *ctxt)
paul718e3742002-12-13 20:15:29 +0000139{
vincentc1a03d42005-09-28 15:47:44 +0000140 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;
paul34204aa2005-11-03 09:00:23 +0000146 memset (ctxt->md5_buf, 0, sizeof(ctxt->md5_buf));
vincentc1a03d42005-09-28 15:47:44 +0000147}
paul718e3742002-12-13 20:15:29 +0000148
paul34204aa2005-11-03 09:00:23 +0000149void md5_loop(md5_ctxt *ctxt, const uint8_t *input, uint len)
vincentc1a03d42005-09-28 15:47:44 +0000150{
paul34204aa2005-11-03 09:00:23 +0000151 uint gap, i;
paul718e3742002-12-13 20:15:29 +0000152
vincentc1a03d42005-09-28 15:47:44 +0000153 ctxt->md5_n += len * 8; /* byte to bit */
154 gap = MD5_BUFLEN - ctxt->md5_i;
paul718e3742002-12-13 20:15:29 +0000155
vincentc1a03d42005-09-28 15:47:44 +0000156 if (len >= gap) {
paul34204aa2005-11-03 09:00:23 +0000157 memcpy (ctxt->md5_buf + ctxt->md5_i, input, gap);
vincentc1a03d42005-09-28 15:47:44 +0000158 md5_calc(ctxt->md5_buf, ctxt);
paul718e3742002-12-13 20:15:29 +0000159
vincentc1a03d42005-09-28 15:47:44 +0000160 for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
paul34204aa2005-11-03 09:00:23 +0000161 md5_calc((input + i), ctxt);
vincentc1a03d42005-09-28 15:47:44 +0000162 }
163
164 ctxt->md5_i = len - i;
paul34204aa2005-11-03 09:00:23 +0000165 memcpy (ctxt->md5_buf, (input + i), ctxt->md5_i);
vincentc1a03d42005-09-28 15:47:44 +0000166 } else {
paul34204aa2005-11-03 09:00:23 +0000167 memcpy (ctxt->md5_buf + ctxt->md5_i, input, len);
vincentc1a03d42005-09-28 15:47:44 +0000168 ctxt->md5_i += len;
paul718e3742002-12-13 20:15:29 +0000169 }
paul718e3742002-12-13 20:15:29 +0000170}
171
paul34204aa2005-11-03 09:00:23 +0000172void md5_pad(md5_ctxt *ctxt)
paul718e3742002-12-13 20:15:29 +0000173{
paul34204aa2005-11-03 09:00:23 +0000174 uint gap;
paul718e3742002-12-13 20:15:29 +0000175
vincentc1a03d42005-09-28 15:47:44 +0000176 /* Don't count up padding. Keep md5_n. */
177 gap = MD5_BUFLEN - ctxt->md5_i;
178 if (gap > 8) {
paul34204aa2005-11-03 09:00:23 +0000179 memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat,
180 gap - sizeof(ctxt->md5_n));
vincentc1a03d42005-09-28 15:47:44 +0000181 } else {
182 /* including gap == 8 */
paul34204aa2005-11-03 09:00:23 +0000183 memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap);
184 md5_calc (ctxt->md5_buf, ctxt);
185 memcpy (ctxt->md5_buf, md5_paddat + gap,
186 MD5_BUFLEN - sizeof(ctxt->md5_n));
paul718e3742002-12-13 20:15:29 +0000187 }
188
vincentc1a03d42005-09-28 15:47:44 +0000189 /* 8 byte word */
paul34204aa2005-11-03 09:00:23 +0000190 if (BYTE_ORDER == LITTLE_ENDIAN)
191 memcpy (&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8);
192 else
193 {
194 ctxt->md5_buf[56] = ctxt->md5_n8[7];
195 ctxt->md5_buf[57] = ctxt->md5_n8[6];
196 ctxt->md5_buf[58] = ctxt->md5_n8[5];
197 ctxt->md5_buf[59] = ctxt->md5_n8[4];
198 ctxt->md5_buf[60] = ctxt->md5_n8[3];
199 ctxt->md5_buf[61] = ctxt->md5_n8[2];
200 ctxt->md5_buf[62] = ctxt->md5_n8[1];
201 ctxt->md5_buf[63] = ctxt->md5_n8[0];
202 }
vincentc1a03d42005-09-28 15:47:44 +0000203 md5_calc(ctxt->md5_buf, ctxt);
204}
205
paul34204aa2005-11-03 09:00:23 +0000206void md5_result(uint8_t *digest, md5_ctxt *ctxt)
vincentc1a03d42005-09-28 15:47:44 +0000207{
208 /* 4 byte words */
paul34204aa2005-11-03 09:00:23 +0000209 if (BYTE_ORDER == LITTLE_ENDIAN)
210 memcpy (digest, &ctxt->md5_st8[0], 16);
211 else if (BYTE_ORDER == BIG_ENDIAN)
212 {
213 digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
214 digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
215 digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
216 digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
217 digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
218 digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
219 digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
220 digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
221 }
vincentc1a03d42005-09-28 15:47:44 +0000222}
223
paul34204aa2005-11-03 09:00:23 +0000224static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt)
vincentc1a03d42005-09-28 15:47:44 +0000225{
paul34204aa2005-11-03 09:00:23 +0000226 uint32_t A = ctxt->md5_sta;
227 uint32_t B = ctxt->md5_stb;
228 uint32_t C = ctxt->md5_stc;
229 uint32_t D = ctxt->md5_std;
230#if (BYTE_ORDER == LITTLE_ENDIAN)
231 const uint32_t *X = (const uint32_t *)b64;
232#elif (BYTE_ORDER == BIG_ENDIAN)
233 uint32_t X[16];
vincentc1a03d42005-09-28 15:47:44 +0000234#endif
paul34204aa2005-11-03 09:00:23 +0000235 if (BYTE_ORDER == BIG_ENDIAN)
236 {
237 /* 4 byte words */
238 /* what a brute force but fast! */
239 uint8_t *y = (uint8_t *)X;
240 y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
241 y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
242 y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
243 y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
244 y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
245 y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
246 y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
247 y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
248 y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
249 y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
250 y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
251 y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
252 y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
253 y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
254 y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
255 y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
256 }
vincentc1a03d42005-09-28 15:47:44 +0000257
258 ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2);
259 ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4);
260 ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6);
261 ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8);
262 ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10);
263 ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
264 ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
265 ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
266
267 ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18);
268 ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20);
269 ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
270 ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24);
271 ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
272 ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28);
273 ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30);
274 ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
275
276 ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34);
277 ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
278 ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38);
279 ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
280 ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42);
281 ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44);
282 ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
283 ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48);
284
285 ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50);
286 ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52);
287 ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54);
288 ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56);
289 ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);
290 ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);
291 ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);
292 ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64);
293
294 ctxt->md5_sta += A;
295 ctxt->md5_stb += B;
296 ctxt->md5_stc += C;
297 ctxt->md5_std += D;
298}