2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */
17 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
20 License to copy and use this software is granted provided that it
21 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
22 Algorithm" in all material mentioning or referencing this software
25 License is also granted to make and use derivative works provided
26 that such works are identified as "derived from the RSA Data
27 Security, Inc. MD5 Message-Digest Algorithm" in all material
28 mentioning or referencing the derived work.
30 RSA Data Security, Inc. makes no representations concerning either
31 the merchantability of this software or the suitability of this
32 software for any particular purpose. It is provided "as is"
33 without express or implied warranty of any kind.
35 These notices must be retained in any copies of any part of this
36 documentation and/or software.
39 #include <vppinfra/string.h> /* for memset */
40 #include <vppinfra/byte_order.h>
41 #include <vppinfra/md5.h>
43 /* F, G, H and I are basic MD5 functions. */
44 #define F(b, c, d) (d ^ (b & (c ^ d)))
45 #define G(b, c, d) F (d, b, c)
46 #define H(b, c, d) (b ^ c ^ d)
47 #define I(b, c, d) (c ^ (b | ~d))
49 /* ROTATE_LEFT rotates x left n bits. */
50 #define ROTATE_LEFT(x,n) \
51 (((x) << (n)) | ((x) >> (32 - (n))))
53 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
54 Rotation is separate from addition to prevent recomputation. */
55 #define FF(a,b,c,d,x,s,ac) \
57 a += F (b, c, d) + x + ac; \
58 a = ROTATE_LEFT (a, s); \
62 #define GG(a,b,c,d,x,s,ac) \
64 a += G (b, c, d) + x + ac; \
65 a = ROTATE_LEFT (a, s); \
69 #define HH(a,b,c,d,x,s,ac) \
71 a += H (b, c, d) + x + ac; \
72 a = ROTATE_LEFT (a, s); \
76 #define II(a,b,c,d,x,s,ac) \
78 a += I (b, c, d) + x + ac; \
79 a = ROTATE_LEFT (a, s); \
85 /* MD5 basic transformation. Transforms state based on block. */
86 static void md5_transform (md5_context_t * m,
91 u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3];
94 /* Constants for MD5Transform routine. */
113 FF (a, b, c, d, clib_host_to_little_u32 (x[ 0]), S11, 0xd76aa478); /* 1 */
114 FF (d, a, b, c, clib_host_to_little_u32 (x[ 1]), S12, 0xe8c7b756); /* 2 */
115 FF (c, d, a, b, clib_host_to_little_u32 (x[ 2]), S13, 0x242070db); /* 3 */
116 FF (b, c, d, a, clib_host_to_little_u32 (x[ 3]), S14, 0xc1bdceee); /* 4 */
117 FF (a, b, c, d, clib_host_to_little_u32 (x[ 4]), S11, 0xf57c0faf); /* 5 */
118 FF (d, a, b, c, clib_host_to_little_u32 (x[ 5]), S12, 0x4787c62a); /* 6 */
119 FF (c, d, a, b, clib_host_to_little_u32 (x[ 6]), S13, 0xa8304613); /* 7 */
120 FF (b, c, d, a, clib_host_to_little_u32 (x[ 7]), S14, 0xfd469501); /* 8 */
121 FF (a, b, c, d, clib_host_to_little_u32 (x[ 8]), S11, 0x698098d8); /* 9 */
122 FF (d, a, b, c, clib_host_to_little_u32 (x[ 9]), S12, 0x8b44f7af); /* 10 */
123 FF (c, d, a, b, clib_host_to_little_u32 (x[10]), S13, 0xffff5bb1); /* 11 */
124 FF (b, c, d, a, clib_host_to_little_u32 (x[11]), S14, 0x895cd7be); /* 12 */
125 FF (a, b, c, d, clib_host_to_little_u32 (x[12]), S11, 0x6b901122); /* 13 */
126 FF (d, a, b, c, clib_host_to_little_u32 (x[13]), S12, 0xfd987193); /* 14 */
127 FF (c, d, a, b, clib_host_to_little_u32 (x[14]), S13, 0xa679438e); /* 15 */
128 FF (b, c, d, a, clib_host_to_little_u32 (x[15]), S14, 0x49b40821); /* 16 */
131 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
132 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
133 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
134 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
135 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
136 GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
137 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
138 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
139 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
140 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
141 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
142 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
143 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
144 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
145 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
146 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
149 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
150 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
151 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
152 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
153 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
154 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
155 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
156 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
157 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
158 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
159 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
160 HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
161 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
162 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
163 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
164 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
167 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
168 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
169 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
170 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
171 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
172 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
173 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
174 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
175 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
176 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
177 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
178 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
179 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
180 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
181 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
182 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
191 result[0] = clib_host_to_little_u32 (a);
192 result[1] = clib_host_to_little_u32 (b);
193 result[2] = clib_host_to_little_u32 (c);
194 result[3] = clib_host_to_little_u32 (d);
204 /* Zero sensitive information. */
206 memset (m, ~0, sizeof (m[0]));
207 else if (zero_buffer)
208 memset (m->input_buffer.b8, 0, sizeof (m->input_buffer));
211 /* MD5 initialization. Begins an MD5 operation, writing a new context. */
212 void md5_init (md5_context_t * c)
214 memset (c, 0, sizeof (c[0]));
216 /* Load magic initialization constants. */
217 c->state[0] = 0x67452301;
218 c->state[1] = 0xefcdab89;
219 c->state[2] = 0x98badcfe;
220 c->state[3] = 0x10325476;
223 always_inline void __attribute__((unused))
224 md5_fill_buffer_aligned (md5_context_t * c,
228 for (i = 0; i < ARRAY_LEN (c->input_buffer.b32); i++)
229 c->input_buffer.b32[i] = d32[i];
232 /* MD5 block update operation. Continues an MD5 message-digest
233 operation, processing another message block, and updating the
236 void md5_add (md5_context_t * c, void * data, int data_bytes)
245 data_bytes_left = data_bytes;
247 if ((pointer_to_uword (d) % sizeof (u32)) == 0
248 && (c->n_bits % BITS (c->input_buffer)) == 0
249 && data_bytes >= sizeof (c->input_buffer))
251 int is_last_iteration;
252 /* Fast aligned version. */
254 data_bytes_left -= sizeof (c->input_buffer);
255 is_last_iteration = data_bytes_left < sizeof (c->input_buffer);
256 md5_transform (c, d, /* result */ 0, /* zero_buffer */ is_last_iteration);
257 d += sizeof (c->input_buffer);
258 } while (! is_last_iteration);
261 /* Slow unaligned version. */
266 bi = (c->n_bits / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
268 while (data_bytes_left > 0)
270 c->input_buffer.b8[bi] = d8[0];
271 data_bytes_left -= 1;
274 if (bi == ARRAY_LEN (c->input_buffer.b8))
277 md5_transform (c, c->input_buffer.b32,
279 /* zero_buffer */ 1);
284 c->n_bits += data_bytes * BITS (u8);
287 void md5_finish (md5_context_t * c, u8 * digest)
291 static u8 padding[sizeof (c->input_buffer)] = { 0x80, 0, };
293 n_bits_save = c->n_bits;
294 bi = (n_bits_save / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
296 n_pad = sizeof (c->input_buffer) - (bi + sizeof (u64));
298 n_pad += sizeof (c->input_buffer);
299 md5_add (c, padding, n_pad);
301 c->input_buffer.b64[ARRAY_LEN (c->input_buffer.b64) - 1]
302 = clib_host_to_little_u64 (n_bits_save);
304 md5_transform (c, c->input_buffer.b32,
306 /* zero_buffer */ 1);