blob: 61ce06226ae48dd0161b6093a514a5bdb317173b [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
3 */
4
5/*
6 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
7 rights reserved.
8
9 License to copy and use this software is granted provided that it
10 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
11 Algorithm" in all material mentioning or referencing this software
12 or this function.
13
14 License is also granted to make and use derivative works provided
15 that such works are identified as "derived from the RSA Data
16 Security, Inc. MD5 Message-Digest Algorithm" in all material
17 mentioning or referencing the derived work.
18
19 RSA Data Security, Inc. makes no representations concerning either
20 the merchantability of this software or the suitability of this
21 software for any particular purpose. It is provided "as is"
22 without express or implied warranty of any kind.
23
24 These notices must be retained in any copies of any part of this
25 documentation and/or software.
26
27 */
28
29#include "cwmp/md5.h"
30
31/*
32 Constants for MD5Transform routine.
33 */
34#define S11 7
35#define S12 12
36#define S13 17
37#define S14 22
38#define S21 5
39#define S22 9
40#define S23 14
41#define S24 20
42#define S31 4
43#define S32 11
44#define S33 16
45#define S34 23
46#define S41 6
47#define S42 10
48#define S43 15
49#define S44 21
50
51static void MD5Transform PROTO_LIST( ( UINT4[4],
52 unsigned char[64] ) );
53static void Encode PROTO_LIST( ( unsigned char *,
54 UINT4 *,
55 unsigned int ) );
56
57static void Decode PROTO_LIST( ( UINT4 *,
58 unsigned char *,
59 unsigned int ) );
60
61static void MD5_memcpy PROTO_LIST( ( POINTER,
62 POINTER,
63 unsigned int ) );
64static void MD5_memset PROTO_LIST( ( POINTER,
65 int,
66 unsigned int ) );
67
68static unsigned char PADDING[64] =
69{
70 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73};
74
75/*
76 F, G, H and I are basic MD5 functions.
77 */
78#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
79#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
80#define H(x, y, z) ((x) ^ (y) ^ (z))
81#define I(x, y, z) ((y) ^ ((x) | (~z)))
82
83/*
84 ROTATE_LEFT rotates x left n bits.
85 */
86#define ROTATE_LEFT(x, n) (((x) <<(n)) | ((x) >> (32-(n))))
87
88/*
89 FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
90 Rotation is separate from addition to prevent recomputation.
91 */
92#define FF(a, b, c, d, x, s, ac) { \
93 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
94 (a) = ROTATE_LEFT ((a), (s)); \
95 (a) += (b); \
96 }
97
98#define GG(a, b, c, d, x, s, ac) { \
99 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
100 (a) = ROTATE_LEFT ((a), (s)); \
101 (a) += (b); \
102 }
103
104#define HH(a, b, c, d, x, s, ac) { \
105 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
106 (a) = ROTATE_LEFT ((a), (s)); \
107 (a) += (b); \
108 }
109
110#define II(a, b, c, d, x, s, ac) { \
111 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
112 (a) = ROTATE_LEFT ((a), (s)); \
113 (a) += (b); \
114 }
115
116/*
117 MD5 initialization. Begins an MD5 operation, writing a new context.
118 */
119void
120cwmp_MD5Init( context )
121cwmp_MD5_CTX *context; /* context */
122{
123 context->count[0] = context->count[1] = 0;
124
125 /*
126 Load magic initialization constants.
127 */
128 context->state[0] = 0x67452301;
129 context->state[1] = 0xefcdab89;
130 context->state[2] = 0x98badcfe;
131 context->state[3] = 0x10325476;
132}
133
134/*
135 MD5 block update operation. Continues an MD5 message-digest
136 operation, processing another message block, and updating the
137 context.
138 */
139
140void
141cwmp_MD5Update( context,
142 input,
143 inputLen )
144cwmp_MD5_CTX *context; /* context */
145unsigned char *input; /* input block */
146unsigned int inputLen; /* length of input block */
147{
148 unsigned int i,
149 index,
150 partLen;
151
152 /*
153 Compute number of bytes mod 64
154 */
155 index = ( unsigned int )( ( context->count[0] >> 3 ) & 0x3F );
156
157 /*
158 Update number of bits
159 */
160 if ( ( context->count[0] +=
161 ( ( UINT4 ) inputLen << 3 ) ) < ( ( UINT4 ) inputLen << 3 ) )
162 context->count[1]++;
163
164 context->count[1] += ( ( UINT4 ) inputLen >> 29 );
165
166 partLen = 64 - index;
167
168 /*
169 Transform as many times as possible.
170 */
171 if ( inputLen >= partLen )
172 {
173
174 MD5_memcpy
175 ( ( POINTER ) & context->buffer[index], ( POINTER ) input,
176 partLen );
177 MD5Transform( context->state, context->buffer );
178
179 for ( i = partLen; i + 63 < inputLen; i += 64 )
180 MD5Transform( context->state, &input[i] );
181
182 index = 0;
183 }
184 else
185 i = 0;
186
187 /*
188 Buffer remaining input
189 */
190 MD5_memcpy
191 ( ( POINTER ) & context->buffer[index], ( POINTER ) & input[i],
192 inputLen - i );
193
194}
195
196/*
197 MD5 finalization. Ends an MD5 message-digest operation, writing the
198 the message digest and zeroizing the context.
199 */
200
201void
202cwmp_MD5Final( digest,
203 context )
204unsigned char digest[16]; /* message digest */
205cwmp_MD5_CTX *context; /* context */
206{
207
208 unsigned char bits[8];
209 unsigned int index,
210 padLen;
211
212 /*
213 Save number of bits
214 */
215 Encode( bits, context->count, 8 );
216
217 /*
218 Pad out to 56 mod 64.
219 */
220 index = ( unsigned int )( ( context->count[0] >> 3 ) & 0x3f );
221
222 padLen = ( index < 56 ) ? ( 56 - index ) : ( 120 - index );
223
224 cwmp_MD5Update( context, PADDING, padLen );
225
226 /*
227 Append length (before padding)
228 */
229 cwmp_MD5Update( context, bits, 8 );
230
231 /*
232 Store state in digest
233 */
234 Encode( digest, context->state, 16 );
235
236 /*
237 Zeroize sensitive information.
238 */
239 MD5_memset( ( POINTER ) context, 0, sizeof( *context ) );
240
241}
242
243/*
244 MD5 basic transformation. Transforms state based on block.
245 */
246static void
247MD5Transform( state,
248 block )
249UINT4 state[4];
250unsigned char block[64];
251{
252 UINT4 a = state[0],
253 b = state[1],
254 c = state[2],
255 d = state[3],
256 x[16];
257
258 Decode( x, block, 64 );
259
260 /*
261 Round 1
262 */
263 FF( a, b, c, d, x[0], S11, 0xd76aa478 ); /* 1 */
264 FF( d, a, b, c, x[1], S12, 0xe8c7b756 ); /* 2 */
265 FF( c, d, a, b, x[2], S13, 0x242070db ); /* 3 */
266 FF( b, c, d, a, x[3], S14, 0xc1bdceee ); /* 4 */
267 FF( a, b, c, d, x[4], S11, 0xf57c0faf ); /* 5 */
268 FF( d, a, b, c, x[5], S12, 0x4787c62a ); /* 6 */
269 FF( c, d, a, b, x[6], S13, 0xa8304613 ); /* 7 */
270 FF( b, c, d, a, x[7], S14, 0xfd469501 ); /* 8 */
271 FF( a, b, c, d, x[8], S11, 0x698098d8 ); /* 9 */
272 FF( d, a, b, c, x[9], S12, 0x8b44f7af ); /* 10 */
273 FF( c, d, a, b, x[10], S13, 0xffff5bb1 ); /* 11 */
274 FF( b, c, d, a, x[11], S14, 0x895cd7be ); /* 12 */
275 FF( a, b, c, d, x[12], S11, 0x6b901122 ); /* 13 */
276 FF( d, a, b, c, x[13], S12, 0xfd987193 ); /* 14 */
277 FF( c, d, a, b, x[14], S13, 0xa679438e ); /* 15 */
278 FF( b, c, d, a, x[15], S14, 0x49b40821 ); /* 16 */
279
280 /*
281 Round 2
282 */
283 GG( a, b, c, d, x[1], S21, 0xf61e2562 ); /* 17 */
284 GG( d, a, b, c, x[6], S22, 0xc040b340 ); /* 18 */
285 GG( c, d, a, b, x[11], S23, 0x265e5a51 ); /* 19 */
286 GG( b, c, d, a, x[0], S24, 0xe9b6c7aa ); /* 20 */
287 GG( a, b, c, d, x[5], S21, 0xd62f105d ); /* 21 */
288 GG( d, a, b, c, x[10], S22, 0x2441453 ); /* 22 */
289 GG( c, d, a, b, x[15], S23, 0xd8a1e681 ); /* 23 */
290 GG( b, c, d, a, x[4], S24, 0xe7d3fbc8 ); /* 24 */
291 GG( a, b, c, d, x[9], S21, 0x21e1cde6 ); /* 25 */
292 GG( d, a, b, c, x[14], S22, 0xc33707d6 ); /* 26 */
293 GG( c, d, a, b, x[3], S23, 0xf4d50d87 ); /* 27 */
294 GG( b, c, d, a, x[8], S24, 0x455a14ed ); /* 28 */
295 GG( a, b, c, d, x[13], S21, 0xa9e3e905 ); /* 29 */
296 GG( d, a, b, c, x[2], S22, 0xfcefa3f8 ); /* 30 */
297 GG( c, d, a, b, x[7], S23, 0x676f02d9 ); /* 31 */
298 GG( b, c, d, a, x[12], S24, 0x8d2a4c8a ); /* 32 */
299
300 /*
301 Round 3
302 */
303 HH( a, b, c, d, x[5], S31, 0xfffa3942 ); /* 33 */
304 HH( d, a, b, c, x[8], S32, 0x8771f681 ); /* 34 */
305 HH( c, d, a, b, x[11], S33, 0x6d9d6122 ); /* 35 */
306 HH( b, c, d, a, x[14], S34, 0xfde5380c ); /* 36 */
307 HH( a, b, c, d, x[1], S31, 0xa4beea44 ); /* 37 */
308 HH( d, a, b, c, x[4], S32, 0x4bdecfa9 ); /* 38 */
309 HH( c, d, a, b, x[7], S33, 0xf6bb4b60 ); /* 39 */
310 HH( b, c, d, a, x[10], S34, 0xbebfbc70 ); /* 40 */
311 HH( a, b, c, d, x[13], S31, 0x289b7ec6 ); /* 41 */
312 HH( d, a, b, c, x[0], S32, 0xeaa127fa ); /* 42 */
313 HH( c, d, a, b, x[3], S33, 0xd4ef3085 ); /* 43 */
314 HH( b, c, d, a, x[6], S34, 0x4881d05 ); /* 44 */
315 HH( a, b, c, d, x[9], S31, 0xd9d4d039 ); /* 45 */
316 HH( d, a, b, c, x[12], S32, 0xe6db99e5 ); /* 46 */
317 HH( c, d, a, b, x[15], S33, 0x1fa27cf8 ); /* 47 */
318 HH( b, c, d, a, x[2], S34, 0xc4ac5665 ); /* 48 */
319
320 /*
321 Round 4
322 */
323 II( a, b, c, d, x[0], S41, 0xf4292244 ); /* 49 */
324 II( d, a, b, c, x[7], S42, 0x432aff97 ); /* 50 */
325 II( c, d, a, b, x[14], S43, 0xab9423a7 ); /* 51 */
326 II( b, c, d, a, x[5], S44, 0xfc93a039 ); /* 52 */
327 II( a, b, c, d, x[12], S41, 0x655b59c3 ); /* 53 */
328 II( d, a, b, c, x[3], S42, 0x8f0ccc92 ); /* 54 */
329 II( c, d, a, b, x[10], S43, 0xffeff47d ); /* 55 */
330 II( b, c, d, a, x[1], S44, 0x85845dd1 ); /* 56 */
331 II( a, b, c, d, x[8], S41, 0x6fa87e4f ); /* 57 */
332 II( d, a, b, c, x[15], S42, 0xfe2ce6e0 ); /* 58 */
333 II( c, d, a, b, x[6], S43, 0xa3014314 ); /* 59 */
334 II( b, c, d, a, x[13], S44, 0x4e0811a1 ); /* 60 */
335 II( a, b, c, d, x[4], S41, 0xf7537e82 ); /* 61 */
336 II( d, a, b, c, x[11], S42, 0xbd3af235 ); /* 62 */
337 II( c, d, a, b, x[2], S43, 0x2ad7d2bb ); /* 63 */
338 II( b, c, d, a, x[9], S44, 0xeb86d391 ); /* 64 */
339
340 state[0] += a;
341 state[1] += b;
342 state[2] += c;
343 state[3] += d;
344
345 /*
346 Zeroize sensitive information.
347 */
348 MD5_memset( ( POINTER ) x, 0, sizeof( x ) );
349
350}
351
352/*
353 Encodes input (UINT4) into output (unsigned char). Assumes len is
354 a multiple of 4.
355 */
356static void
357Encode( output,
358 input,
359 len )
360unsigned char *output;
361UINT4 *input;
362unsigned int len;
363{
364 unsigned int i,
365 j;
366
367 for ( i = 0, j = 0; j < len; i++, j += 4 )
368 {
369 output[j] = ( unsigned char )( input[i] & 0xff );
370 output[j + 1] = ( unsigned char )( ( input[i] >> 8 ) & 0xff );
371 output[j + 2] = ( unsigned char )( ( input[i] >> 16 ) & 0xff );
372 output[j + 3] = ( unsigned char )( ( input[i] >> 24 ) & 0xff );
373 }
374
375}
376
377/*
378 Decodes input (unsigned char) into output (UINT4). Assumes len is
379 a multiple of 4.
380 */
381
382static void
383Decode( output,
384 input,
385 len )
386UINT4 *output;
387unsigned char *input;
388unsigned int len;
389{
390 unsigned int i,
391 j;
392
393 for ( i = 0, j = 0; j < len; i++, j += 4 )
394 output[i] =
395 ( ( UINT4 ) input[j] ) | ( ( ( UINT4 ) input[j + 1] ) << 8 ) |
396 ( ( ( UINT4 ) input[j + 2] ) << 16 ) |
397 ( ( ( UINT4 ) input[j + 3] ) << 24 );
398}
399
400/*
401 Note: Replace &quot;for loop&quot; with standard memcpy if possible.
402 */
403static void
404MD5_memcpy( output,
405 input,
406 len )
407POINTER output;
408POINTER input;
409unsigned int len;
410{
411 unsigned int i;
412
413 for ( i = 0; i < len; i++ )
414 output[i] = input[i];
415
416}
417
418/*
419 Note: Replace &quot;for loop&quot; with standard memset if possible.
420 */
421static void
422MD5_memset( output,
423 value,
424 len )
425POINTER output;
426int value;
427unsigned int len;
428{
429 unsigned int i;
430
431 for ( i = 0; i < len; i++ )
432 ( ( char * )output )[i] = ( char )value;
433
434}
435
436
437
438