Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: md5c.c,v 1.2 2009/06/30 02:44:52 agc Exp $	*/
      2 
      3 /*
      4  * This file is derived from the RSA Data Security, Inc. MD5 Message-Digest
      5  * Algorithm and has been modifed by Jason R. Thorpe <thorpej (at) NetBSD.ORG>
      6  * for portability and formatting.
      7  */
      8 
      9 /*
     10  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     11  * rights reserved.
     12  *
     13  * License to copy and use this software is granted provided that it
     14  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
     15  * Algorithm" in all material mentioning or referencing this software
     16  * or this function.
     17  *
     18  * License is also granted to make and use derivative works provided
     19  * that such works are identified as "derived from the RSA Data
     20  * Security, Inc. MD5 Message-Digest Algorithm" in all material
     21  * mentioning or referencing the derived work.
     22  *
     23  * RSA Data Security, Inc. makes no representations concerning either
     24  * the merchantability of this software or the suitability of this
     25  * software for any particular purpose. It is provided "as is"
     26  * without express or implied warranty of any kind.
     27  *
     28  * These notices must be retained in any copies of any part of this
     29  * documentation and/or software.
     30  */
     31 
     32 #ifdef HAVE_CONFIG_H
     33 #include <config.h>
     34 #endif
     35 
     36 #if defined(_KERNEL) || defined(_STANDALONE)
     37 #include <lib/libkern/libkern.h>
     38 #include <sys/param.h>
     39 #include <sys/md5.h>
     40 #define _DIAGASSERT(x)	(void)0
     41 #else
     42 /* #include "namespace.h" */
     43 #include <assert.h>
     44 #include <string.h>
     45 #include "iscsi-md5.h"
     46 #endif /* _KERNEL || _STANDALONE */
     47 
     48 #if defined(HAVE_MEMSET)
     49 #define	ZEROIZE(d, l)		memset((d), 0, (l))
     50 #else
     51 # if defined(HAVE_BZERO)
     52 #define ZEROIZE(d, l)		bzero((d), (l))
     53 # else
     54 #error You need either memset or bzero
     55 # endif
     56 #endif
     57 
     58 typedef unsigned char *POINTER;
     59 typedef uint16_t UINT2;
     60 typedef uint32_t UINT4;
     61 
     62 /*
     63  * Constants for MD5Transform routine.
     64  */
     65 #define S11 7
     66 #define S12 12
     67 #define S13 17
     68 #define S14 22
     69 #define S21 5
     70 #define S22 9
     71 #define S23 14
     72 #define S24 20
     73 #define S31 4
     74 #define S32 11
     75 #define S33 16
     76 #define S34 23
     77 #define S41 6
     78 #define S42 10
     79 #define S43 15
     80 #define S44 21
     81 
     82 #if 0
     83 #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
     84 __weak_alias(iSCSI_MD5Init,_MD5Init)
     85 __weak_alias(iSCSI_MD5Update,_MD5Update)
     86 __weak_alias(iSCSI_MD5Final,_MD5Final)
     87 #endif
     88 #endif
     89 
     90 #ifndef _DIAGASSERT
     91 #define _DIAGASSERT(cond)	assert(cond)
     92 #endif
     93 
     94 static void iSCSI_MD5Transform(UINT4 [4], const unsigned char [64]);
     95 
     96 static void Encode(unsigned char *, UINT4 *, unsigned int);
     97 static void Decode(UINT4 *, const unsigned char *, unsigned int);
     98 
     99 /*
    100  * Encodes input (UINT4) into output (unsigned char).  Assumes len is
    101  * a multiple of 4.
    102  */
    103 static void
    104 Encode (output, input, len)
    105 	unsigned char *output;
    106 	UINT4 *input;
    107 	unsigned int len;
    108 {
    109 	unsigned int i, j;
    110 
    111 	for (i = 0, j = 0; j < len; i++, j += 4) {
    112 		output[j] = (unsigned char)(input[i] & 0xff);
    113 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
    114 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
    115 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
    116 	}
    117 }
    118 
    119 /*
    120  * Decodes input (unsigned char) into output (UINT4).  Assumes len is
    121  * a multiple of 4.
    122  */
    123 static void
    124 Decode (output, input, len)
    125 	UINT4 *output;
    126 	const unsigned char *input;
    127 	unsigned int len;
    128 {
    129 	unsigned int i, j;
    130 
    131 	for (i = 0, j = 0; j < len; i++, j += 4)
    132 		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
    133 		    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
    134 }
    135 
    136 static const unsigned char PADDING[64] = {
    137 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    138 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    139 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    140 };
    141 
    142 /*
    143  * F, G, H and I are basic MD5 functions.
    144  */
    145 #define F(x, y, z)	(((x) & (y)) | ((~x) & (z)))
    146 #define G(x, y, z)	(((x) & (z)) | ((y) & (~z)))
    147 #define H(x, y, z)	((x) ^ (y) ^ (z))
    148 #define I(x, y, z)	((y) ^ ((x) | (~z)))
    149 
    150 /*
    151  * ROTATE_LEFT rotates x left n bits.
    152  */
    153 #define ROTATE_LEFT(x, n)	(((x) << (n)) | ((x) >> (32-(n))))
    154 
    155 /*
    156  * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
    157  * Rotation is separate from addition to prevent recomputation.
    158  */
    159 #define FF(a, b, c, d, x, s, ac) { \
    160 	(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
    161 	(a) = ROTATE_LEFT ((a), (s)); \
    162 	(a) += (b); \
    163 }
    164 
    165 #define GG(a, b, c, d, x, s, ac) { \
    166 	(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
    167 	(a) = ROTATE_LEFT ((a), (s)); \
    168 	(a) += (b); \
    169 }
    170 
    171 #define HH(a, b, c, d, x, s, ac) { \
    172 	(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
    173 	(a) = ROTATE_LEFT ((a), (s)); \
    174 	(a) += (b); \
    175 }
    176 
    177 #define II(a, b, c, d, x, s, ac) { \
    178 	(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
    179 	(a) = ROTATE_LEFT ((a), (s)); \
    180 	(a) += (b); \
    181 }
    182 
    183 /*
    184  * MD5 initialization. Begins an MD5 operation, writing a new context.
    185  */
    186 void
    187 iSCSI_MD5Init(iSCSI_MD5_CTX *context)
    188 {
    189 
    190 	_DIAGASSERT(context != 0);
    191 
    192 	context->count[0] = context->count[1] = 0;
    193 
    194 	/* Load magic initialization constants. */
    195 	context->state[0] = 0x67452301;
    196 	context->state[1] = 0xefcdab89;
    197 	context->state[2] = 0x98badcfe;
    198 	context->state[3] = 0x10325476;
    199 }
    200 
    201 /*
    202  * MD5 block update operation.  Continues an MD5 message-digest
    203  * operation, processing another message block, and updating the
    204  * context.
    205  */
    206 void
    207 iSCSI_MD5Update(iSCSI_MD5_CTX *context, const uint8_t *input, size_t inputLen)
    208 {
    209 	unsigned int i, idx, partLen;
    210 
    211 	_DIAGASSERT(context != 0);
    212 	_DIAGASSERT(input != 0);
    213 
    214 	/* Compute number of bytes mod 64 */
    215 	idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
    216 
    217 	/* Update number of bits */
    218 	if ((context->count[0] += ((UINT4)inputLen << 3))
    219 	    < ((UINT4)inputLen << 3))
    220 		context->count[1]++;
    221 	context->count[1] += ((UINT4)inputLen >> 29);
    222 
    223 	partLen = 64 - idx;
    224 
    225 	/* Transform as many times as possible. */
    226 	if (inputLen >= partLen) {
    227 		/* LINTED const castaway ok */
    228 		memcpy((POINTER)&context->buffer[idx],
    229 		    input, partLen);
    230 		iSCSI_MD5Transform(context->state, context->buffer);
    231 
    232 		for (i = partLen; i + 63 < inputLen; i += 64)
    233 			iSCSI_MD5Transform(context->state, &input[i]);
    234 
    235 		idx = 0;
    236 	} else
    237 		i = 0;
    238 
    239 	/* Buffer remaining input */
    240 	/* LINTED const castaway ok */
    241 	memcpy((POINTER)&context->buffer[idx], &input[i],
    242 	    inputLen - i);
    243 }
    244 
    245 /*
    246  * MD5 finalization.  Ends an MD5 message-digest operation, writing the
    247  * message digest and zeroing the context.
    248  */
    249 void
    250 iSCSI_MD5Final(unsigned char digest[16], iSCSI_MD5_CTX *context)
    251 {
    252 	unsigned char bits[8];
    253 	unsigned int idx;
    254 	size_t padLen;
    255 
    256 	_DIAGASSERT(digest != 0);
    257 	_DIAGASSERT(context != 0);
    258 
    259 	/* Save number of bits */
    260 	Encode(bits, context->count, 8);
    261 
    262 	/* Pad out to 56 mod 64. */
    263 	idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
    264 	padLen = (idx < 56) ? (56 - idx) : (120 - idx);
    265 	iSCSI_MD5Update (context, PADDING, padLen);
    266 
    267 	/* Append length (before padding) */
    268 	iSCSI_MD5Update(context, bits, 8);
    269 
    270 	/* Store state in digest */
    271 	Encode(digest, context->state, 16);
    272 
    273 	/* Zeroize sensitive information. */
    274 	ZEROIZE((POINTER)(void *)context, sizeof(*context));
    275 }
    276 
    277 /*
    278  * MD5 basic transformation. Transforms state based on block.
    279  */
    280 static void
    281 iSCSI_MD5Transform(state, block)
    282 	UINT4 state[4];
    283 	const unsigned char block[64];
    284 {
    285 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    286 
    287 	Decode(x, block, 64);
    288 
    289 	/* Round 1 */
    290 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
    291 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
    292 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
    293 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
    294 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
    295 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
    296 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
    297 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
    298 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
    299 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
    300 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    301 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    302 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    303 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    304 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    305 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
    306 
    307 	/* Round 2 */
    308 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
    309 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
    310 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    311 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
    312 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
    313 	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
    314 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    315 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
    316 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
    317 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    318 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
    319 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
    320 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    321 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
    322 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
    323 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
    324 
    325 	/* Round 3 */
    326 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
    327 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
    328 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    329 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    330 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
    331 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
    332 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
    333 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    334 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    335 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
    336 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
    337 	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
    338 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
    339 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    340 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    341 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
    342 
    343 	/* Round 4 */
    344 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
    345 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
    346 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    347 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
    348 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    349 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
    350 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    351 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
    352 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
    353 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    354 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
    355 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    356 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
    357 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    358 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
    359 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
    360 
    361 	state[0] += a;
    362 	state[1] += b;
    363 	state[2] += c;
    364 	state[3] += d;
    365 
    366 	/* Zeroize sensitive information. */
    367 	ZEROIZE((POINTER)(void *)x, sizeof (x));
    368 }
    369