FD.io VPP  v16.06
Vector Packet Processing
md5.c
Go to the documentation of this file.
1 /*
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
18 rights reserved.
19 
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
23 or this function.
24 
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.
29 
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.
34 
35 These notices must be retained in any copies of any part of this
36 documentation and/or software.
37  */
38 
39 #include <vppinfra/string.h> /* for memset */
40 #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) \
56 do { \
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) \
63 do { \
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) \
70 do { \
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) \
77 do { \
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. */
86 static void md5_transform (md5_context_t * m,
87  u32 * data,
88  u32 * result,
89  int zero_buffer)
90 {
91  u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3];
92  u32 * x = data;
93 
94 /* Constants for MD5Transform routine. */
95 #define S11 7
96 #define S12 12
97 #define S13 17
98 #define S14 22
99 #define S21 5
100 #define S22 9
101 #define S23 14
102 #define S24 20
103 #define S31 4
104 #define S32 11
105 #define S33 16
106 #define S34 23
107 #define S41 6
108 #define S42 10
109 #define S43 15
110 #define S44 21
111 
112  /* Round 1 */
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 */
129 
130  /* Round 2 */
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 */
147 
148  /* Round 3 */
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 */
165 
166  /* Round 4 */
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 */
183 
184  a += m->state[0];
185  b += m->state[1];
186  c += m->state[2];
187  d += m->state[3];
188 
189  if (result)
190  {
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);
195  }
196  else
197  {
198  m->state[0] = a;
199  m->state[1] = b;
200  m->state[2] = c;
201  m->state[3] = d;
202  }
203 
204  /* Zero sensitive information. */
205  if (result)
206  memset (m, ~0, sizeof (m[0]));
207  else if (zero_buffer)
208  memset (m->input_buffer.b8, 0, sizeof (m->input_buffer));
209 }
210 
211 /* MD5 initialization. Begins an MD5 operation, writing a new context. */
213 {
214  memset (c, 0, sizeof (c[0]));
215 
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;
221 }
222 
223 always_inline void __attribute__((unused))
225  u32 * d32)
226 {
227  int i;
228  for (i = 0; i < ARRAY_LEN (c->input_buffer.b32); i++)
229  c->input_buffer.b32[i] = d32[i];
230 }
231 
232 /* MD5 block update operation. Continues an MD5 message-digest
233  operation, processing another message block, and updating the
234  context.
235  */
236 void md5_add (md5_context_t * c, void * data, int data_bytes)
237 {
238  u32 data_bytes_left;
239  void * d;
240 
241  if (data_bytes == 0)
242  return;
243 
244  d = data;
245  data_bytes_left = data_bytes;
246 
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))
250  {
251  int is_last_iteration;
252  /* Fast aligned version. */
253  do {
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);
259  }
260 
261  /* Slow unaligned version. */
262  {
263  int bi;
264  u8 * d8 = d;
265 
266  bi = (c->n_bits / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
267 
268  while (data_bytes_left > 0)
269  {
270  c->input_buffer.b8[bi] = d8[0];
271  data_bytes_left -= 1;
272  d8++;
273  bi++;
274  if (bi == ARRAY_LEN (c->input_buffer.b8))
275  {
276  bi = 0;
278  /* result */ 0,
279  /* zero_buffer */ 1);
280  }
281  }
282  }
283 
284  c->n_bits += data_bytes * BITS (u8);
285 }
286 
287 void md5_finish (md5_context_t * c, u8 * digest)
288 {
289  u64 n_bits_save;
290  int bi, n_pad;
291  static u8 padding[sizeof (c->input_buffer)] = { 0x80, 0, };
292 
293  n_bits_save = c->n_bits;
294  bi = (n_bits_save / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8);
295 
296  n_pad = sizeof (c->input_buffer) - (bi + sizeof (u64));
297  if (n_pad <= 0)
298  n_pad += sizeof (c->input_buffer);
299  md5_add (c, padding, n_pad);
300 
302  = clib_host_to_little_u64 (n_bits_save);
303 
305  (u32 *) digest,
306  /* zero_buffer */ 1);
307 }
void md5_finish(md5_context_t *c, u8 *digest)
Definition: md5.c:287
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
u8 b8[16 *4]
Definition: md5.h:37
a
Definition: bitmap.h:393
#define S44
#define S43
u32 state[4]
Definition: md5.h:32
#define S32
void md5_init(md5_context_t *c)
Definition: md5.c:212
#define GG(a, b, c, d, x, s, ac)
Definition: md5.c:62
#define S31
#define always_inline
Definition: clib.h:84
#define II(a, b, c, d, x, s, ac)
Definition: md5.c:76
u32 b32[16]
Definition: md5.h:36
#define S21
unsigned long u64
Definition: types.h:89
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define S12
always_inline void md5_fill_buffer_aligned(md5_context_t *c, u32 *d32)
Definition: md5.c:224
#define S22
#define HH(a, b, c, d, x, s, ac)
Definition: md5.c:69
#define S14
#define S23
u64 n_bits
Definition: md5.h:30
#define S24
#define ARRAY_LEN(x)
Definition: clib.h:59
#define S42
#define FF(a, b, c, d, x, s, ac)
Definition: md5.c:55
#define S41
void md5_add(md5_context_t *c, void *data, int data_bytes)
Definition: md5.c:236
unsigned int u32
Definition: types.h:88
#define S33
#define S13
static void md5_transform(md5_context_t *m, u32 *data, u32 *result, int zero_buffer)
Definition: md5.c:86
unsigned char u8
Definition: types.h:56
u64 b64[8]
Definition: md5.h:35
#define S11
#define S34
#define BITS(x)
Definition: clib.h:58
union md5_context_t::@15 input_buffer