9ac1efc708d280c177931c4ad69e14748b4af327
[vpp.git] / vppinfra / vppinfra / md5.c
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
211 md5_init (md5_context_t * c)
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))
223 md5_fill_buffer_aligned (md5_context_t * c, u32 * d32)
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;
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
289 void
290 md5_finish (md5_context_t * c, u8 * digest)
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
304   c->input_buffer.b64[ARRAY_LEN (c->input_buffer.b64) - 1]
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  */