blob: 9ac1efc708d280c177931c4ad69e14748b4af327 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
15/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */
16
17/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
18rights reserved.
19
20License to copy and use this software is granted provided that it
21is identified as the "RSA Data Security, Inc. MD5 Message-Digest
22Algorithm" in all material mentioning or referencing this software
23or this function.
24
25License is also granted to make and use derivative works provided
26that such works are identified as "derived from the RSA Data
27Security, Inc. MD5 Message-Digest Algorithm" in all material
28mentioning or referencing the derived work.
29
30RSA Data Security, Inc. makes no representations concerning either
31the merchantability of this software or the suitability of this
32software for any particular purpose. It is provided "as is"
33without express or implied warranty of any kind.
34
35These notices must be retained in any copies of any part of this
36documentation and/or software.
37 */
38
Dave Barachc3799992016-08-15 11:12:27 -040039#include <vppinfra/string.h> /* for memset */
Ed Warnickecb9cada2015-12-08 15:45:58 -070040#include <vppinfra/byte_order.h>
41#include <vppinfra/md5.h>
42
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))
48
49/* ROTATE_LEFT rotates x left n bits. */
50#define ROTATE_LEFT(x,n) \
51 (((x) << (n)) | ((x) >> (32 - (n))))
52
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) \
56do { \
57 a += F (b, c, d) + x + ac; \
58 a = ROTATE_LEFT (a, s); \
59 a += b; \
60} while (0)
61
62#define GG(a,b,c,d,x,s,ac) \
63do { \
64 a += G (b, c, d) + x + ac; \
65 a = ROTATE_LEFT (a, s); \
66 a += b; \
67} while (0)
68
69#define HH(a,b,c,d,x,s,ac) \
70do { \
71 a += H (b, c, d) + x + ac; \
72 a = ROTATE_LEFT (a, s); \
73 a += b; \
74} while (0)
75
76#define II(a,b,c,d,x,s,ac) \
77do { \
78 a += I (b, c, d) + x + ac; \
79 a = ROTATE_LEFT (a, s); \
80 a += b; \
81} while (0)
82
83#undef _
84
85/* MD5 basic transformation. Transforms state based on block. */
Dave Barachc3799992016-08-15 11:12:27 -040086static void
87md5_transform (md5_context_t * m, u32 * data, u32 * result, int zero_buffer)
Ed Warnickecb9cada2015-12-08 15:45:58 -070088{
89 u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3];
Dave Barachc3799992016-08-15 11:12:27 -040090 u32 *x = data;
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
92/* Constants for MD5Transform routine. */
93#define S11 7
94#define S12 12
95#define S13 17
96#define S14 22
97#define S21 5
98#define S22 9
99#define S23 14
100#define S24 20
101#define S31 4
102#define S32 11
103#define S33 16
104#define S34 23
105#define S41 6
106#define S42 10
107#define S43 15
108#define S44 21
109
110 /* Round 1 */
Dave Barachc3799992016-08-15 11:12:27 -0400111 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 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127
128 /* Round 2 */
Dave Barachc3799992016-08-15 11:12:27 -0400129 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 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700145
146 /* Round 3 */
Dave Barachc3799992016-08-15 11:12:27 -0400147 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 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163
164 /* Round 4 */
Dave Barachc3799992016-08-15 11:12:27 -0400165 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 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181
182 a += m->state[0];
183 b += m->state[1];
184 c += m->state[2];
185 d += m->state[3];
186
187 if (result)
188 {
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);
193 }
194 else
195 {
196 m->state[0] = a;
197 m->state[1] = b;
198 m->state[2] = c;
199 m->state[3] = d;
200 }
201
202 /* Zero sensitive information. */
203 if (result)
204 memset (m, ~0, sizeof (m[0]));
205 else if (zero_buffer)
206 memset (m->input_buffer.b8, 0, sizeof (m->input_buffer));
207}
208
209/* MD5 initialization. Begins an MD5 operation, writing a new context. */
Dave Barachc3799992016-08-15 11:12:27 -0400210void
211md5_init (md5_context_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700212{
213 memset (c, 0, sizeof (c[0]));
214
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;
220}
221
Dave Barachc3799992016-08-15 11:12:27 -0400222always_inline void __attribute__ ((unused))
223md5_fill_buffer_aligned (md5_context_t * c, u32 * d32)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700224{
225 int i;
226 for (i = 0; i < ARRAY_LEN (c->input_buffer.b32); i++)
227 c->input_buffer.b32[i] = d32[i];
228}
229
230/* MD5 block update operation. Continues an MD5 message-digest
231 operation, processing another message block, and updating the
232 context.
233 */
Dave Barachc3799992016-08-15 11:12:27 -0400234void
235md5_add (md5_context_t * c, void *data, int data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236{
237 u32 data_bytes_left;
Dave Barachc3799992016-08-15 11:12:27 -0400238 void *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239
240 if (data_bytes == 0)
241 return;
242
243 d = data;
244 data_bytes_left = data_bytes;
245
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))
249 {
250 int is_last_iteration;
251 /* Fast aligned version. */
Dave Barachc3799992016-08-15 11:12:27 -0400252 do
253 {
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 */
257 is_last_iteration);
258 d += sizeof (c->input_buffer);
259 }
260 while (!is_last_iteration);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 }
262
263 /* Slow unaligned version. */
264 {
265 int bi;
Dave Barachc3799992016-08-15 11:12:27 -0400266 u8 *d8 = d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267
268 bi = (c->n_bits / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
269
270 while (data_bytes_left > 0)
271 {
272 c->input_buffer.b8[bi] = d8[0];
273 data_bytes_left -= 1;
274 d8++;
275 bi++;
276 if (bi == ARRAY_LEN (c->input_buffer.b8))
277 {
278 bi = 0;
279 md5_transform (c, c->input_buffer.b32,
280 /* result */ 0,
281 /* zero_buffer */ 1);
282 }
283 }
284 }
285
286 c->n_bits += data_bytes * BITS (u8);
287}
288
Dave Barachc3799992016-08-15 11:12:27 -0400289void
290md5_finish (md5_context_t * c, u8 * digest)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291{
292 u64 n_bits_save;
293 int bi, n_pad;
294 static u8 padding[sizeof (c->input_buffer)] = { 0x80, 0, };
295
296 n_bits_save = c->n_bits;
297 bi = (n_bits_save / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
298
299 n_pad = sizeof (c->input_buffer) - (bi + sizeof (u64));
300 if (n_pad <= 0)
301 n_pad += sizeof (c->input_buffer);
302 md5_add (c, padding, n_pad);
303
304 c->input_buffer.b64[ARRAY_LEN (c->input_buffer.b64) - 1]
305 = clib_host_to_little_u64 (n_bits_save);
306
Dave Barachc3799992016-08-15 11:12:27 -0400307 md5_transform (c, c->input_buffer.b32, (u32 *) digest,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308 /* zero_buffer */ 1);
309}
Dave Barachc3799992016-08-15 11:12:27 -0400310
311/*
312 * fd.io coding-style-patch-verification: ON
313 *
314 * Local Variables:
315 * eval: (c-set-style "gnu")
316 * End:
317 */