lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 1 | /*
|
| 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 |
|
| 51 | static void MD5Transform PROTO_LIST( ( UINT4[4],
|
| 52 | unsigned char[64] ) );
|
| 53 | static void Encode PROTO_LIST( ( unsigned char *,
|
| 54 | UINT4 *,
|
| 55 | unsigned int ) );
|
| 56 |
|
| 57 | static void Decode PROTO_LIST( ( UINT4 *,
|
| 58 | unsigned char *,
|
| 59 | unsigned int ) );
|
| 60 |
|
| 61 | static void MD5_memcpy PROTO_LIST( ( POINTER,
|
| 62 | POINTER,
|
| 63 | unsigned int ) );
|
| 64 | static void MD5_memset PROTO_LIST( ( POINTER,
|
| 65 | int,
|
| 66 | unsigned int ) );
|
| 67 |
|
| 68 | static 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 | */
|
| 119 | void
|
| 120 | cwmp_MD5Init( context )
|
| 121 | cwmp_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 |
|
| 140 | void
|
| 141 | cwmp_MD5Update( context,
|
| 142 | input,
|
| 143 | inputLen )
|
| 144 | cwmp_MD5_CTX *context; /* context */
|
| 145 | unsigned char *input; /* input block */
|
| 146 | unsigned 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 |
|
| 201 | void
|
| 202 | cwmp_MD5Final( digest,
|
| 203 | context )
|
| 204 | unsigned char digest[16]; /* message digest */
|
| 205 | cwmp_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 | */
|
| 246 | static void
|
| 247 | MD5Transform( state,
|
| 248 | block )
|
| 249 | UINT4 state[4];
|
| 250 | unsigned 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 | */
|
| 356 | static void
|
| 357 | Encode( output,
|
| 358 | input,
|
| 359 | len )
|
| 360 | unsigned char *output;
|
| 361 | UINT4 *input;
|
| 362 | unsigned 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 |
|
| 382 | static void
|
| 383 | Decode( output,
|
| 384 | input,
|
| 385 | len )
|
| 386 | UINT4 *output;
|
| 387 | unsigned char *input;
|
| 388 | unsigned 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 "for loop" with standard memcpy if possible.
|
| 402 | */
|
| 403 | static void
|
| 404 | MD5_memcpy( output,
|
| 405 | input,
|
| 406 | len )
|
| 407 | POINTER output;
|
| 408 | POINTER input;
|
| 409 | unsigned 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 "for loop" with standard memset if possible.
|
| 420 | */
|
| 421 | static void
|
| 422 | MD5_memset( output,
|
| 423 | value,
|
| 424 | len )
|
| 425 | POINTER output;
|
| 426 | int value;
|
| 427 | unsigned 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 |
|