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. */
87 md5_transform (md5_context_t * m, u32 * data, u32 * result, int zero_buffer)
89 u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3];
92 /* Constants for MD5Transform routine. */
111 FF (a, b, c, d, clib_host_to_little_u32 (x[0]), S11, 0xd76aa478); /* 1 */
112 FF (d, a, b, c, clib_host_to_little_u32 (x[1]), S12, 0xe8c7b756); /* 2 */
113 FF (c, d, a, b, clib_host_to_little_u32 (x[2]), S13, 0x242070db); /* 3 */
114 FF (b, c, d, a, clib_host_to_little_u32 (x[3]), S14, 0xc1bdceee); /* 4 */
115 FF (a, b, c, d, clib_host_to_little_u32 (x[4]), S11, 0xf57c0faf); /* 5 */
116 FF (d, a, b, c, clib_host_to_little_u32 (x[5]), S12, 0x4787c62a); /* 6 */
117 FF (c, d, a, b, clib_host_to_little_u32 (x[6]), S13, 0xa8304613); /* 7 */
118 FF (b, c, d, a, clib_host_to_little_u32 (x[7]), S14, 0xfd469501); /* 8 */
119 FF (a, b, c, d, clib_host_to_little_u32 (x[8]), S11, 0x698098d8); /* 9 */
120 FF (d, a, b, c, clib_host_to_little_u32 (x[9]), S12, 0x8b44f7af); /* 10 */
121 FF (c, d, a, b, clib_host_to_little_u32 (x[10]), S13, 0xffff5bb1); /* 11 */
122 FF (b, c, d, a, clib_host_to_little_u32 (x[11]), S14, 0x895cd7be); /* 12 */
123 FF (a, b, c, d, clib_host_to_little_u32 (x[12]), S11, 0x6b901122); /* 13 */
124 FF (d, a, b, c, clib_host_to_little_u32 (x[13]), S12, 0xfd987193); /* 14 */
125 FF (c, d, a, b, clib_host_to_little_u32 (x[14]), S13, 0xa679438e); /* 15 */
126 FF (b, c, d, a, clib_host_to_little_u32 (x[15]), S14, 0x49b40821); /* 16 */
129 GG (a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
130 GG (d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
131 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
132 GG (b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
133 GG (a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
134 GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
135 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
136 GG (b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
137 GG (a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
138 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
139 GG (c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
140 GG (b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
141 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
142 GG (d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
143 GG (c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
144 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
147 HH (a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
148 HH (d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
149 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
150 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
151 HH (a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
152 HH (d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
153 HH (c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
154 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
155 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
156 HH (d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
157 HH (c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
158 HH (b, c, d, a, x[6], S34, 0x04881d05); /* 44 */
159 HH (a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
160 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
161 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
162 HH (b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
165 II (a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
166 II (d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
167 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
168 II (b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
169 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
170 II (d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
171 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
172 II (b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
173 II (a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
174 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
175 II (c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
176 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
177 II (a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
178 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
179 II (c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
180 II (b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
189 result[0] = clib_host_to_little_u32 (a);
190 result[1] = clib_host_to_little_u32 (b);
191 result[2] = clib_host_to_little_u32 (c);
192 result[3] = clib_host_to_little_u32 (d);
202 /* Zero sensitive information. */
204 memset (m, ~0, sizeof (m[0]));
205 else if (zero_buffer)
206 memset (m->input_buffer.b8, 0, sizeof (m->input_buffer));
209 /* MD5 initialization. Begins an MD5 operation, writing a new context. */
211 md5_init (md5_context_t * c)
213 memset (c, 0, sizeof (c[0]));
215 /* Load magic initialization constants. */
216 c->state[0] = 0x67452301;
217 c->state[1] = 0xefcdab89;
218 c->state[2] = 0x98badcfe;
219 c->state[3] = 0x10325476;
222 always_inline void __attribute__ ((unused))
223 md5_fill_buffer_aligned (md5_context_t * c, u32 * d32)
226 for (i = 0; i < ARRAY_LEN (c->input_buffer.b32); i++)
227 c->input_buffer.b32[i] = d32[i];
230 /* MD5 block update operation. Continues an MD5 message-digest
231 operation, processing another message block, and updating the
235 md5_add (md5_context_t * c, void *data, int data_bytes)
244 data_bytes_left = data_bytes;
246 if ((pointer_to_uword (d) % sizeof (u32)) == 0
247 && (c->n_bits % BITS (c->input_buffer)) == 0
248 && data_bytes >= sizeof (c->input_buffer))
250 int is_last_iteration;
251 /* 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 */
258 d += sizeof (c->input_buffer);
260 while (!is_last_iteration);
263 /* Slow unaligned version. */
268 bi = (c->n_bits / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
270 while (data_bytes_left > 0)
272 c->input_buffer.b8[bi] = d8[0];
273 data_bytes_left -= 1;
276 if (bi == ARRAY_LEN (c->input_buffer.b8))
279 md5_transform (c, c->input_buffer.b32,
281 /* zero_buffer */ 1);
286 c->n_bits += data_bytes * BITS (u8);
290 md5_finish (md5_context_t * c, u8 * digest)
294 static u8 padding[sizeof (c->input_buffer)] = { 0x80, 0, };
296 n_bits_save = c->n_bits;
297 bi = (n_bits_save / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
299 n_pad = sizeof (c->input_buffer) - (bi + sizeof (u64));
301 n_pad += sizeof (c->input_buffer);
302 md5_add (c, padding, n_pad);
304 c->input_buffer.b64[ARRAY_LEN (c->input_buffer.b64) - 1]
305 = clib_host_to_little_u64 (n_bits_save);
307 md5_transform (c, c->input_buffer.b32, (u32 *) digest,
308 /* zero_buffer */ 1);
312 * fd.io coding-style-patch-verification: ON
315 * eval: (c-set-style "gnu")