1/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm" 2 "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" 3 4%%% portions-copyright-cmetz-96 5Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights 6Reserved. The Inner Net License Version 2 applies to these portions of 7the software. 8You should have received a copy of the license with this software. If 9you didn't get a copy, you may request one from <license@inner.net>. 10 11Portions of this software are Copyright 1995 by Randall Atkinson and Dan 12McDonald, All Rights Reserved. All Rights under this copyright are assigned 13to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 14License Agreement applies to this software. 15 16 History: 17 18 Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR. 19 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 20 Don't play macro games with memset/memcpy. Renamed exported 21 functions to avoid conflicts. Use unified context structure. 22 Modified at NRL for OPIE 2.1. Minor autoconf mods. 23 Modified at NRL for OPIE 2.0. 24 Originally from RSADSI reference code. 25*/ 26/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 27 rights reserved. 28 29 License to copy and use this software is granted provided that it 30 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 31 Algorithm" in all material mentioning or referencing this software 32 or this function. 33 34 License is also granted to make and use derivative works provided 35 that such works are identified as "derived from the RSA Data 36 Security, Inc. MD5 Message-Digest Algorithm" in all material 37 mentioning or referencing the derived work. 38 39 RSA Data Security, Inc. makes no representations concerning either 40 the merchantability of this software or the suitability of this 41 software for any particular purpose. It is provided "as is" 42 without express or implied warranty of any kind. 43 44 These notices must be retained in any copies of any part of this 45 documentation and/or software. 46 */ 47 48#include "opie_cfg.h" 49#include "opie.h" 50 51/* Constants for MD5Transform routine. 52 */ 53#define S11 7 54#define S12 12 55#define S13 17 56#define S14 22 57#define S21 5 58#define S22 9 59#define S23 14 60#define S24 20 61#define S31 4 62#define S32 11 63#define S33 16 64#define S34 23 65#define S41 6 66#define S42 10 67#define S43 15 68#define S44 21 69 70static VOIDRET MD5Transform __P((UINT4[4], unsigned char[64])); 71 72static unsigned char PADDING[64] = 73{ 74 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 77}; 78 79/* 80 * Encodes input (UINT4) into output (unsigned char). 81 * Assumes len is a multiple of 4. 82 */ 83static VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) 84{ 85 unsigned int i, j; 86 87 for (i = 0, j = 0; j < len; i++, j += 4) { 88 output[j] = (unsigned char) (input[i] & 0xff); 89 output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); 90 output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); 91 output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); 92 } 93} 94 95/* 96 * Decodes input (unsigned char) into output (UINT4). 97 * Assumes len is a multiple of 4. 98 */ 99static VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) 100{ 101 unsigned int i, j; 102 103 for (i = 0, j = 0; j < len; i++, j += 4) 104 output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | 105 (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); 106} 107 108/* F, G, H and I are basic MD5 functions. */ 109#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 110#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 111#define H(x, y, z) ((x) ^ (y) ^ (z)) 112#define I(x, y, z) ((y) ^ ((x) | (~z))) 113 114/* ROTATE_LEFT rotates x left n bits. */ 115#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 116 117/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 118 Rotation is separate from addition to prevent recomputation. */ 119 120#define FF(a, b, c, d, x, s, ac) { \ 121 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 122 (a) = ROTATE_LEFT ((a), (s)); \ 123 (a) += (b); \ 124 } 125 126#define GG(a, b, c, d, x, s, ac) { \ 127 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 128 (a) = ROTATE_LEFT ((a), (s)); \ 129 (a) += (b); \ 130 } 131 132#define HH(a, b, c, d, x, s, ac) { \ 133 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 134 (a) = ROTATE_LEFT ((a), (s)); \ 135 (a) += (b); \ 136 } 137 138#define II(a, b, c, d, x, s, ac) { \ 139 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 140 (a) = ROTATE_LEFT ((a), (s)); \ 141 (a) += (b); \ 142 } 143 144/* MD5 initialization. Begins an MD5 operation, writing a new context. */ 145VOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context) 146{ 147 context->count[0] = context->count[1] = 0; 148 /* Load magic initialization constants. */ 149 context->state[0] = 0x67452301; 150 context->state[1] = 0xefcdab89; 151 context->state[2] = 0x98badcfe; 152 context->state[3] = 0x10325476; 153} 154 155/* 156 * MD5 block update operation. Continues an MD5 message-digest 157 * operation, processing another message block, and updating the 158 * context. 159 */ 160VOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) 161{ 162 unsigned int i, index, partLen; 163 164 /* Compute number of bytes mod 64 */ 165 index = (unsigned int) ((context->count[0] >> 3) & 0x3F); 166 167 /* Update number of bits */ 168 if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3)) 169 context->count[1]++; 170 171 context->count[1] += ((UINT4) inputLen >> 29); 172 partLen = 64 - index; 173 174 /* Transform as many times as possible. */ 175 if (inputLen >= partLen) { 176 memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, 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 } else 184 i = 0; 185 186 /* Buffer remaining input */ 187 memcpy((VOIDPTR) & context->buffer[index], 188 (VOIDPTR) & input[i], 189 inputLen - i); 190} 191 192/* MD5 finalization. Ends an MD5 message-digest operation, writing the 193 the message digest and zeroizing the context. 194 */ 195VOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) 196{ 197 unsigned char bits[8]; 198 unsigned int index, padLen; 199 200 /* Save number of bits */ 201 EEncode(bits, context->count, 8); 202 203 /* Pad out to 56 mod 64. */ 204 index = (unsigned int) ((context->count[0] >> 3) & 0x3f); 205 padLen = (index < 56) ? (56 - index) : (120 - index); 206 opiemd5update(context, PADDING, padLen); 207 208 /* Append length (before padding) */ 209 opiemd5update(context, bits, 8); 210 211 /* Store state in digest */ 212 EEncode(digest, context->state, 16); 213 214 /* Zeroize sensitive information. */ 215 memset((VOIDPTR) context, 0, sizeof(*context)); 216} 217 218/* MD5 basic transformation. Transforms state based on block. */ 219static VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) 220{ 221 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 222 223 EDecode(x, block, 64); 224 225 /* Round 1 */ 226 FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ 227 FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ 228 FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ 229 FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ 230 FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ 231 FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ 232 FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ 233 FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ 234 FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ 235 FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ 236 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 237 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 238 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 239 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 240 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 241 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 242 243 /* Round 2 */ 244 GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ 245 GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ 246 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 247 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ 248 GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ 249 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 250 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 251 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ 252 GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ 253 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 254 GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ 255 GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ 256 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 257 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ 258 GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ 259 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 260 261 /* Round 3 */ 262 HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ 263 HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ 264 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 265 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 266 HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ 267 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ 268 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ 269 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 270 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 271 HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ 272 HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ 273 HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ 274 HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ 275 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 276 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 277 HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ 278 279 /* Round 4 */ 280 II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ 281 II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ 282 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 283 II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ 284 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 285 II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ 286 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 287 II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ 288 II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ 289 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 290 II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ 291 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 292 II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ 293 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 294 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ 295 II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ 296 297 state[0] += a; 298 state[1] += b; 299 state[2] += c; 300 state[3] += d; 301 302 /* Zeroize sensitive information. */ 303 memset((VOIDPTR)x, 0, sizeof(x)); 304} 305