122347Spst/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm" 222347Spst "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" 322347Spst 429964Sache%%% portions-copyright-cmetz-96 592906SmarkmPortions of this software are Copyright 1996-1999 by Craig Metz, All Rights 622347SpstReserved. The Inner Net License Version 2 applies to these portions of 722347Spstthe software. 822347SpstYou should have received a copy of the license with this software. If 922347Spstyou didn't get a copy, you may request one from <license@inner.net>. 1022347Spst 1122347SpstPortions of this software are Copyright 1995 by Randall Atkinson and Dan 1222347SpstMcDonald, All Rights Reserved. All Rights under this copyright are assigned 1322347Spstto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 1422347SpstLicense Agreement applies to this software. 1522347Spst 1622347Spst History: 1722347Spst 1822347Spst Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR. 1922347Spst Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 2022347Spst Don't play macro games with memset/memcpy. Renamed exported 2122347Spst functions to avoid conflicts. Use unified context structure. 2222347Spst Modified at NRL for OPIE 2.1. Minor autoconf mods. 2322347Spst Modified at NRL for OPIE 2.0. 2422347Spst Originally from RSADSI reference code. 2522347Spst*/ 2622347Spst/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 2722347Spst rights reserved. 2822347Spst 2922347Spst License to copy and use this software is granted provided that it 3022347Spst is identified as the "RSA Data Security, Inc. MD5 Message-Digest 3122347Spst Algorithm" in all material mentioning or referencing this software 3222347Spst or this function. 3322347Spst 3422347Spst License is also granted to make and use derivative works provided 3522347Spst that such works are identified as "derived from the RSA Data 3622347Spst Security, Inc. MD5 Message-Digest Algorithm" in all material 3722347Spst mentioning or referencing the derived work. 3822347Spst 3922347Spst RSA Data Security, Inc. makes no representations concerning either 4022347Spst the merchantability of this software or the suitability of this 4122347Spst software for any particular purpose. It is provided "as is" 4222347Spst without express or implied warranty of any kind. 4322347Spst 4422347Spst These notices must be retained in any copies of any part of this 4522347Spst documentation and/or software. 4622347Spst */ 4722347Spst 4822347Spst#include "opie_cfg.h" 4922347Spst#include "opie.h" 5022347Spst 5122347Spst/* Constants for MD5Transform routine. 5222347Spst */ 5322347Spst#define S11 7 5422347Spst#define S12 12 5522347Spst#define S13 17 5622347Spst#define S14 22 5722347Spst#define S21 5 5822347Spst#define S22 9 5922347Spst#define S23 14 6022347Spst#define S24 20 6122347Spst#define S31 4 6222347Spst#define S32 11 6322347Spst#define S33 16 6422347Spst#define S34 23 6522347Spst#define S41 6 6622347Spst#define S42 10 6722347Spst#define S43 15 6822347Spst#define S44 21 6922347Spst 7022347Spststatic VOIDRET MD5Transform __P((UINT4[4], unsigned char[64])); 7122347Spst 7222347Spststatic unsigned char PADDING[64] = 7322347Spst{ 7422347Spst 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7522347Spst 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7622347Spst 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 7722347Spst}; 7822347Spst 7922347Spst/* 8022347Spst * Encodes input (UINT4) into output (unsigned char). 8122347Spst * Assumes len is a multiple of 4. 8222347Spst */ 8322347Spststatic VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) 8422347Spst{ 8522347Spst unsigned int i, j; 8622347Spst 8722347Spst for (i = 0, j = 0; j < len; i++, j += 4) { 8822347Spst output[j] = (unsigned char) (input[i] & 0xff); 8922347Spst output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); 9022347Spst output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); 9122347Spst output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); 9222347Spst } 9322347Spst} 9422347Spst 9522347Spst/* 9622347Spst * Decodes input (unsigned char) into output (UINT4). 9722347Spst * Assumes len is a multiple of 4. 9822347Spst */ 9922347Spststatic VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) 10022347Spst{ 10122347Spst unsigned int i, j; 10222347Spst 10322347Spst for (i = 0, j = 0; j < len; i++, j += 4) 10422347Spst output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | 10522347Spst (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); 10622347Spst} 10722347Spst 10822347Spst/* F, G, H and I are basic MD5 functions. */ 10922347Spst#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 11022347Spst#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 11122347Spst#define H(x, y, z) ((x) ^ (y) ^ (z)) 11222347Spst#define I(x, y, z) ((y) ^ ((x) | (~z))) 11322347Spst 11422347Spst/* ROTATE_LEFT rotates x left n bits. */ 11522347Spst#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 11622347Spst 11722347Spst/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 11822347Spst Rotation is separate from addition to prevent recomputation. */ 11922347Spst 12022347Spst#define FF(a, b, c, d, x, s, ac) { \ 12122347Spst (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 12222347Spst (a) = ROTATE_LEFT ((a), (s)); \ 12322347Spst (a) += (b); \ 12422347Spst } 12522347Spst 12622347Spst#define GG(a, b, c, d, x, s, ac) { \ 12722347Spst (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 12822347Spst (a) = ROTATE_LEFT ((a), (s)); \ 12922347Spst (a) += (b); \ 13022347Spst } 13122347Spst 13222347Spst#define HH(a, b, c, d, x, s, ac) { \ 13322347Spst (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 13422347Spst (a) = ROTATE_LEFT ((a), (s)); \ 13522347Spst (a) += (b); \ 13622347Spst } 13722347Spst 13822347Spst#define II(a, b, c, d, x, s, ac) { \ 13922347Spst (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 14022347Spst (a) = ROTATE_LEFT ((a), (s)); \ 14122347Spst (a) += (b); \ 14222347Spst } 14322347Spst 14422347Spst/* MD5 initialization. Begins an MD5 operation, writing a new context. */ 14522347SpstVOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context) 14622347Spst{ 14722347Spst context->count[0] = context->count[1] = 0; 14822347Spst /* Load magic initialization constants. */ 14922347Spst context->state[0] = 0x67452301; 15022347Spst context->state[1] = 0xefcdab89; 15122347Spst context->state[2] = 0x98badcfe; 15222347Spst context->state[3] = 0x10325476; 15322347Spst} 15422347Spst 15522347Spst/* 15622347Spst * MD5 block update operation. Continues an MD5 message-digest 15722347Spst * operation, processing another message block, and updating the 15822347Spst * context. 15922347Spst */ 16022347SpstVOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) 16122347Spst{ 16222347Spst unsigned int i, index, partLen; 16322347Spst 16422347Spst /* Compute number of bytes mod 64 */ 16522347Spst index = (unsigned int) ((context->count[0] >> 3) & 0x3F); 16622347Spst 16722347Spst /* Update number of bits */ 16822347Spst if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3)) 16922347Spst context->count[1]++; 17022347Spst 17122347Spst context->count[1] += ((UINT4) inputLen >> 29); 17222347Spst partLen = 64 - index; 17322347Spst 17422347Spst /* Transform as many times as possible. */ 17522347Spst if (inputLen >= partLen) { 17622347Spst memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen); 17722347Spst MD5Transform(context->state, context->buffer); 17822347Spst 17922347Spst for (i = partLen; i + 63 < inputLen; i += 64) 18022347Spst MD5Transform(context->state, &input[i]); 18122347Spst 18222347Spst index = 0; 18322347Spst } else 18422347Spst i = 0; 18522347Spst 18622347Spst /* Buffer remaining input */ 18722347Spst memcpy((VOIDPTR) & context->buffer[index], 18822347Spst (VOIDPTR) & input[i], 18922347Spst inputLen - i); 19022347Spst} 19122347Spst 19222347Spst/* MD5 finalization. Ends an MD5 message-digest operation, writing the 19322347Spst the message digest and zeroizing the context. 19422347Spst */ 19522347SpstVOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) 19622347Spst{ 19722347Spst unsigned char bits[8]; 19822347Spst unsigned int index, padLen; 19922347Spst 20022347Spst /* Save number of bits */ 20122347Spst EEncode(bits, context->count, 8); 20222347Spst 20322347Spst /* Pad out to 56 mod 64. */ 20422347Spst index = (unsigned int) ((context->count[0] >> 3) & 0x3f); 20522347Spst padLen = (index < 56) ? (56 - index) : (120 - index); 20622347Spst opiemd5update(context, PADDING, padLen); 20722347Spst 20822347Spst /* Append length (before padding) */ 20922347Spst opiemd5update(context, bits, 8); 21022347Spst 21122347Spst /* Store state in digest */ 21222347Spst EEncode(digest, context->state, 16); 21322347Spst 21422347Spst /* Zeroize sensitive information. */ 21522347Spst memset((VOIDPTR) context, 0, sizeof(*context)); 21622347Spst} 21722347Spst 21822347Spst/* MD5 basic transformation. Transforms state based on block. */ 21922347Spststatic VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) 22022347Spst{ 22122347Spst UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 22222347Spst 22322347Spst EDecode(x, block, 64); 22422347Spst 22522347Spst /* Round 1 */ 22622347Spst FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ 22722347Spst FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ 22822347Spst FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ 22922347Spst FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ 23022347Spst FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ 23122347Spst FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ 23222347Spst FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ 23322347Spst FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ 23422347Spst FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ 23522347Spst FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ 23622347Spst FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 23722347Spst FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 23822347Spst FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 23922347Spst FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 24022347Spst FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 24122347Spst FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 24222347Spst 24322347Spst /* Round 2 */ 24422347Spst GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ 24522347Spst GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ 24622347Spst GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 24722347Spst GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ 24822347Spst GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ 24922347Spst GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 25022347Spst GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 25122347Spst GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ 25222347Spst GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ 25322347Spst GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 25422347Spst GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ 25522347Spst GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ 25622347Spst GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 25722347Spst GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ 25822347Spst GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ 25922347Spst GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 26022347Spst 26122347Spst /* Round 3 */ 26222347Spst HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ 26322347Spst HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ 26422347Spst HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 26522347Spst HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 26622347Spst HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ 26722347Spst HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ 26822347Spst HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ 26922347Spst HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 27022347Spst HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 27122347Spst HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ 27222347Spst HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ 27322347Spst HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ 27422347Spst HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ 27522347Spst HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 27622347Spst HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 27722347Spst HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ 27822347Spst 27922347Spst /* Round 4 */ 28022347Spst II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ 28122347Spst II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ 28222347Spst II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 28322347Spst II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ 28422347Spst II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 28522347Spst II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ 28622347Spst II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 28722347Spst II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ 28822347Spst II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ 28922347Spst II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 29022347Spst II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ 29122347Spst II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 29222347Spst II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ 29322347Spst II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 29422347Spst II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ 29522347Spst II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ 29622347Spst 29722347Spst state[0] += a; 29822347Spst state[1] += b; 29922347Spst state[2] += c; 30022347Spst state[3] += d; 30122347Spst 30222347Spst /* Zeroize sensitive information. */ 30322347Spst memset((VOIDPTR)x, 0, sizeof(x)); 30422347Spst} 305