FD.io VPP  v17.04-9-g99c0734
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
87 md5_transform (md5_context_t * m, u32 * data, u32 * result, int zero_buffer)
88 {
89  u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3];
90  u32 *x = data;
91 
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 */
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 */
127 
128  /* Round 2 */
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 */
145 
146  /* Round 3 */
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 */
163 
164  /* Round 4 */
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 */
181 
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. */
210 void
212 {
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 
222 always_inline void __attribute__ ((unused))
224 {
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  */
234 void
235 md5_add (md5_context_t * c, void *data, int data_bytes)
236 {
237  u32 data_bytes_left;
238  void *d;
239 
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. */
252  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);
261  }
262 
263  /* Slow unaligned version. */
264  {
265  int bi;
266  u8 *d8 = d;
267 
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;
280  /* result */ 0,
281  /* zero_buffer */ 1);
282  }
283  }
284  }
285 
286  c->n_bits += data_bytes * BITS (u8);
287 }
288 
289 void
291 {
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 
305  = clib_host_to_little_u64 (n_bits_save);
306 
307  md5_transform (c, c->input_buffer.b32, (u32 *) digest,
308  /* zero_buffer */ 1);
309 }
310 
311 /*
312  * fd.io coding-style-patch-verification: ON
313  *
314  * Local Variables:
315  * eval: (c-set-style "gnu")
316  * End:
317  */
void md5_finish(md5_context_t *c, u8 *digest)
Definition: md5.c:290
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u8 b8[16 *4]
Definition: md5.h:39
a
Definition: bitmap.h:516
#define S44
#define S43
u32 state[4]
Definition: md5.h:33
#define S32
void md5_init(md5_context_t *c)
Definition: md5.c:211
u32 padding
Definition: vhost-user.h:78
#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:38
#define S21
union md5_context_t::@13 input_buffer
static void md5_fill_buffer_aligned(md5_context_t *c, u32 *d32)
Definition: md5.c:223
unsigned long u64
Definition: types.h:89
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define S12
#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:31
svmdb_client_t * c
#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:235
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:87
unsigned char u8
Definition: types.h:56
u64 b64[8]
Definition: md5.h:37
#define S11
#define S34
#define BITS(x)
Definition: clib.h:58