/* dot1xMdLib.c - 802.1X message digest library */ /* * Copyright (c) 2005 - 2006 Wind River Systems, Inc. * * The right to copy, distribute, modify, or otherwise make use * of this software may be licensed only pursuant to the terms * of an applicable Wind River license agreement. */ /* modification history -------------------- 01d,16mar06,rjh Add NOMANUAL 01c,04sep03,ggg Remove warnings for diab MIPS and SH 01b,23apr03,ggg Add LOCAL to MD5_PADDING 01a,21apr03,ggg written */ /* DESCRIPTION This library contains routines for perfoming message digest functions needed for 802.1X: MD4, MD5, and HMAC-MD5. INCLUDE FILES: dot1xMdLib.h \NOROUTINES \NOMANUAL */ /* Code within this module is derived from the example appendices to RFCs 1320 (MD4) and 1321 (MD5). MD.C - RSA Data Security, Inc., MD4 and MD5 message-digest algorithms Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "vxWorks.h" #include "string.h" /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* MD4 transform definitions appear here ...*/ /* Constants for MD4Transform routine.*/ #define MD4_S11 3 #define MD4_S12 7 #define MD4_S13 11 #define MD4_S14 19 #define MD4_S21 3 #define MD4_S22 5 #define MD4_S23 9 #define MD4_S24 13 #define MD4_S31 3 #define MD4_S32 9 #define MD4_S33 11 #define MD4_S34 15 /* F, G, and H are basic MD4 functions. */ #define MD4_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define MD4_H(x, y, z) ((x) ^ (y) ^ (z)) /* FF, GG, and HH transformations for rounds 1, 2, and 3. Rotation is separate from addition to prevent recomputation. */ #define MD4_FF(a, b, c, d, x, s) { \ (a) += MD4_F ((b), (c), (d)) + (x); \ (a) = ROTATE_LEFT ((a), (s)); \ } #define MD4_GG(a, b, c, d, x, s) { \ (a) += MD4_G ((b), (c), (d)) + (x) + (unsigned long)0x5a827999; \ (a) = ROTATE_LEFT ((a), (s)); \ } #define MD4_HH(a, b, c, d, x, s) { \ (a) += MD4_H ((b), (c), (d)) + (x) + (unsigned long)0x6ed9eba1; \ (a) = ROTATE_LEFT ((a), (s)); \ } /* MD5 transform definitions appear here ...*/ /* Constants for MD5Transform routine.*/ #define MD5_S11 7 #define MD5_S12 12 #define MD5_S13 17 #define MD5_S14 22 #define MD5_S21 5 #define MD5_S22 9 #define MD5_S23 14 #define MD5_S24 20 #define MD5_S31 4 #define MD5_S32 11 #define MD5_S33 16 #define MD5_S34 23 #define MD5_S41 6 #define MD5_S42 10 #define MD5_S43 15 #define MD5_S44 21 /* F, G, H and I are basic MD5 functions. */ #define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) #define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define MD5_FF(a, b, c, d, x, s, ac) { \ (a) += MD5_F ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_GG(a, b, c, d, x, s, ac) { \ (a) += MD5_G ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_HH(a, b, c, d, x, s, ac) { \ (a) += MD5_H ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_II(a, b, c, d, x, s, ac) { \ (a) += MD5_I ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } typedef enum { MD4 = 0x04, MD5 = 0x05 } MD_ALGORITHM; LOCAL unsigned char MD5_PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* MD4 transform definitions appear here ...*/ /* Constants for MD4Transform routine.*/ #define MD4_S11 3 #define MD4_S12 7 #define MD4_S13 11 #define MD4_S14 19 #define MD4_S21 3 #define MD4_S22 5 #define MD4_S23 9 #define MD4_S24 13 #define MD4_S31 3 #define MD4_S32 9 #define MD4_S33 11 #define MD4_S34 15 /* F, G, and H are basic MD4 functions. */ #define MD4_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define MD4_H(x, y, z) ((x) ^ (y) ^ (z)) /* FF, GG, and HH transformations for rounds 1, 2, and 3. Rotation is separate from addition to prevent recomputation. */ #define MD4_FF(a, b, c, d, x, s) { \ (a) += MD4_F ((b), (c), (d)) + (x); \ (a) = ROTATE_LEFT ((a), (s)); \ } #define MD4_GG(a, b, c, d, x, s) { \ (a) += MD4_G ((b), (c), (d)) + (x) + (unsigned long)0x5a827999; \ (a) = ROTATE_LEFT ((a), (s)); \ } #define MD4_HH(a, b, c, d, x, s) { \ (a) += MD4_H ((b), (c), (d)) + (x) + (unsigned long)0x6ed9eba1; \ (a) = ROTATE_LEFT ((a), (s)); \ } /* MD5 transform definitions appear here ...*/ /* Constants for MD5Transform routine.*/ #define MD5_S11 7 #define MD5_S12 12 #define MD5_S13 17 #define MD5_S14 22 #define MD5_S21 5 #define MD5_S22 9 #define MD5_S23 14 #define MD5_S24 20 #define MD5_S31 4 #define MD5_S32 11 #define MD5_S33 16 #define MD5_S34 23 #define MD5_S41 6 #define MD5_S42 10 #define MD5_S43 15 #define MD5_S44 21 /* F, G, H and I are basic MD5 functions. */ #define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) #define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define MD5_FF(a, b, c, d, x, s, ac) { \ (a) += MD5_F ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_GG(a, b, c, d, x, s, ac) { \ (a) += MD5_G ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_HH(a, b, c, d, x, s, ac) { \ (a) += MD5_H ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define MD5_II(a, b, c, d, x, s, ac) { \ (a) += MD5_I ((b), (c), (d)) + (x) + (unsigned long)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } typedef struct { unsigned long state[4]; /* state (ABCD) */ unsigned long count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD_CONTEXT; LOCAL void MD_init (MD_CONTEXT *sptr_context); LOCAL void MD_update (MD_CONTEXT *sptr_context, unsigned char * input, unsigned long inputLen, MD_ALGORITHM algorithm); LOCAL void MD_final (unsigned char * bptr_digest, MD_CONTEXT *sptr_context, MD_ALGORITHM algorithm); LOCAL void MD4_transform (unsigned long state[4], unsigned char block[64]); LOCAL void MD5_transform (unsigned long state[4], unsigned char block[64]); LOCAL void MD_encode (unsigned char * bptr_output, unsigned long *ulptr_input, unsigned long length); LOCAL void MD_decode (unsigned long *ulptr_output, unsigned char * bptr_input, unsigned long length); /******************************************************************************* * * dot1xMd - Generates a message digest * * This routine generates a message digest of the passed in buffer of the * specified type of MD4 or MD5. * * RETURNS: N/A * */ void dot1xMd ( unsigned char * bptr_string, /* buffer to take digest of */ unsigned long length, /* length of buffer to digest */ unsigned char * bptr_digest, /* where output digest is stored */ MD_ALGORITHM algorithm /* digest algorithm: MD4 or MD5 */ ) { MD_CONTEXT sptr_context; if (bptr_digest == NULL) { return; } if (length == 0x00000000L) { length = strlen ((const char *)bptr_string); } #ifdef OPENSSL_FIPS /* MD5 cannot be used */ if (FIPS_mode()) { /* Authentication failed. */ printf("dot1x: MD5 is not supported when FIPS mode is enabled!"); return; } #endif MD_init (&sptr_context); MD_update (&sptr_context, bptr_string, length, algorithm); MD_final (bptr_digest, &sptr_context, algorithm); } /******************************************************************************* * * dot1xHmacMd5 - Generates an HMAC-MD5 hash for message authentication * * This routine generates an HMAC-MD5 hash for message authentication using * the passed input data and key and lengths. * * RETURNS: N/A * */ void dot1xHmacMd5 ( unsigned char * text, /* pointer to data stream */ int text_len, /* length of data stream */ unsigned char * key, /* pointer to authentication key */ int key_len, /* length of authentication key */ unsigned char * digest /* caller digest to be filled in */ ) { MD_CONTEXT context; unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ unsigned char k_opad[65]; /* outer padding - key XORd with opad */ unsigned char tk[16]; int i; #ifdef OPENSSL_FIPS /* MD5 cannot be used */ if (FIPS_mode()) { /* Authentication failed. */ printf("dot1x: MD5 is not supported when FIPS mode is enabled!"); return; } #endif /* if key is longer than 64 bytes reset it to key=MD5(key) */ if (key_len > 64) { MD_CONTEXT tctx; MD_init(&tctx); MD_update(&tctx, key, key_len, MD5); MD_final(tk, &tctx, MD5); key = tk; key_len = 16; } /* * the HMAC_MD5 transform looks like: * * MD5(K XOR opad, MD5(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in pads */ bzero( (char *)k_ipad, sizeof k_ipad); bzero( (char *)k_opad, sizeof k_opad); bcopy( (char *)key, (char *)k_ipad, key_len); bcopy( (char *)key, (char *)k_opad, key_len); /* XOR key with ipad and opad values */ for (i=0; i<64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* perform inner MD5 */ MD_init(&context); /* init context for 1st pass */ MD_update(&context, k_ipad, 64, MD5); /* start with inner pad */ MD_update(&context, text, text_len, MD5); /* then text of datagram */ MD_final(digest, &context, MD5); /* finish up 1st pass */ /* perform outer MD5 */ MD_init(&context); /* init context for 2nd pass */ MD_update(&context, k_opad, 64, MD5); /* start with outer pad */ MD_update(&context, digest, 16, MD5); /* then results of 1st hash */ MD_final(digest, &context, MD5); /* finish up 2nd pass */ } /*****************************************************************************/ /* MD initialization. Begins an MD operation, writing a new sptr_context. */ /*****************************************************************************/ LOCAL void MD_init ( MD_CONTEXT * sptr_context ) { sptr_context->count[0] = 0x00000000L; sptr_context->count[1] = 0x00000000L; /* Load magic initialization constants.*/ sptr_context->state[0] = 0x67452301; sptr_context->state[1] = 0xefcdab89; sptr_context->state[2] = 0x98badcfe; sptr_context->state[3] = 0x10325476; } /* MD block update operation. Continues an MD message-digest operation, */ /* processing another message block, and updating the sptr_context. */ LOCAL void MD_update ( MD_CONTEXT * sptr_context, unsigned char * bptr_input, unsigned long input_length, MD_ALGORITHM algorithm ) /* sptr_context, input block and length of input block and algorithm to use */ { unsigned long i; unsigned long index; unsigned long part_length; i = 0x00000000L; /* Compute number of bytes mod 64 */ index = (unsigned long)((sptr_context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((sptr_context->count[0] += ((unsigned long)input_length << 3)) < ((unsigned long)input_length << 3)) { sptr_context->count[1]++; } sptr_context->count[1] += ((unsigned long)input_length >> 29); part_length = 64 - index; /* Transform as many times as possible.*/ if (input_length >= part_length) { memcpy ((void *)&sptr_context->buffer[index], (void *)bptr_input, (size_t)part_length); switch (algorithm) { case MD4: MD4_transform (sptr_context->state, sptr_context->buffer); for (i = part_length; (i + 63) < input_length; i += 64) { MD4_transform (sptr_context->state, &bptr_input[i]); } break; case MD5: MD5_transform (sptr_context->state, sptr_context->buffer); for (i = part_length; (i + 63) < input_length; i += 64) { MD5_transform (sptr_context->state, &bptr_input[i]); } break; default: /* error print */ break; } index = 0x00000000L; } else { i = 0x00000000L; } /* Buffer remaining input */ memcpy ((void *)&sptr_context->buffer[index], (void *)&bptr_input[i], (size_t)(input_length-i)); } /* MD finalization. Ends an MD5 message-digest operation, writing the message digest and zeroizing the sptr_context. */ LOCAL void MD_final ( unsigned char * bptr_digest, MD_CONTEXT * sptr_context, MD_ALGORITHM algorithm ) { unsigned char bits[8]; unsigned long index; unsigned long padding_length; /* Save number of bits */ MD_encode (bits, sptr_context->count, 8); /* Pad out to 56 mod 64.*/ index = (unsigned long)((sptr_context->count[0] >> 3) & 0x3f); padding_length = (index < 56) ? (56 - index) : (120 - index); MD_update (sptr_context, MD5_PADDING, padding_length, algorithm); /* Append length (before padding) */ MD_update (sptr_context, bits, 8, algorithm); /* Store state in digest */ MD_encode (bptr_digest, sptr_context->state, 16); /* Zeroize sensitive information.*/ memset ((void *)sptr_context, 0, sizeof (*sptr_context)); } /**********************************************************************/ /* MD4 Basic transform. Transforms state based on block. */ /**********************************************************************/ LOCAL void MD4_transform ( unsigned long state[4], unsigned char block[64] ) { unsigned long a = state[0]; unsigned long b = state[1]; unsigned long c = state[2]; unsigned long d = state[3]; unsigned long x[16]; MD_decode (x, block, 64); /* Round 1 */ MD4_FF (a, b, c, d, x[ 0], MD4_S11); /* 1 */ MD4_FF (d, a, b, c, x[ 1], MD4_S12); /* 2 */ MD4_FF (c, d, a, b, x[ 2], MD4_S13); /* 3 */ MD4_FF (b, c, d, a, x[ 3], MD4_S14); /* 4 */ MD4_FF (a, b, c, d, x[ 4], MD4_S11); /* 5 */ MD4_FF (d, a, b, c, x[ 5], MD4_S12); /* 6 */ MD4_FF (c, d, a, b, x[ 6], MD4_S13); /* 7 */ MD4_FF (b, c, d, a, x[ 7], MD4_S14); /* 8 */ MD4_FF (a, b, c, d, x[ 8], MD4_S11); /* 9 */ MD4_FF (d, a, b, c, x[ 9], MD4_S12); /* 10 */ MD4_FF (c, d, a, b, x[10], MD4_S13); /* 11 */ MD4_FF (b, c, d, a, x[11], MD4_S14); /* 12 */ MD4_FF (a, b, c, d, x[12], MD4_S11); /* 13 */ MD4_FF (d, a, b, c, x[13], MD4_S12); /* 14 */ MD4_FF (c, d, a, b, x[14], MD4_S13); /* 15 */ MD4_FF (b, c, d, a, x[15], MD4_S14); /* 16 */ /* Round 2 */ MD4_GG (a, b, c, d, x[ 0], MD4_S21); /* 17 */ MD4_GG (d, a, b, c, x[ 4], MD4_S22); /* 18 */ MD4_GG (c, d, a, b, x[ 8], MD4_S23); /* 19 */ MD4_GG (b, c, d, a, x[12], MD4_S24); /* 20 */ MD4_GG (a, b, c, d, x[ 1], MD4_S21); /* 21 */ MD4_GG (d, a, b, c, x[ 5], MD4_S22); /* 22 */ MD4_GG (c, d, a, b, x[ 9], MD4_S23); /* 23 */ MD4_GG (b, c, d, a, x[13], MD4_S24); /* 24 */ MD4_GG (a, b, c, d, x[ 2], MD4_S21); /* 25 */ MD4_GG (d, a, b, c, x[ 6], MD4_S22); /* 26 */ MD4_GG (c, d, a, b, x[10], MD4_S23); /* 27 */ MD4_GG (b, c, d, a, x[14], MD4_S24); /* 28 */ MD4_GG (a, b, c, d, x[ 3], MD4_S21); /* 29 */ MD4_GG (d, a, b, c, x[ 7], MD4_S22); /* 30 */ MD4_GG (c, d, a, b, x[11], MD4_S23); /* 31 */ MD4_GG (b, c, d, a, x[15], MD4_S24); /* 32 */ /* Round 3 */ MD4_HH (a, b, c, d, x[ 0], MD4_S31); /* 33 */ MD4_HH (d, a, b, c, x[ 8], MD4_S32); /* 34 */ MD4_HH (c, d, a, b, x[ 4], MD4_S33); /* 35 */ MD4_HH (b, c, d, a, x[12], MD4_S34); /* 36 */ MD4_HH (a, b, c, d, x[ 2], MD4_S31); /* 37 */ MD4_HH (d, a, b, c, x[10], MD4_S32); /* 38 */ MD4_HH (c, d, a, b, x[ 6], MD4_S33); /* 39 */ MD4_HH (b, c, d, a, x[14], MD4_S34); /* 40 */ MD4_HH (a, b, c, d, x[ 1], MD4_S31); /* 41 */ MD4_HH (d, a, b, c, x[ 9], MD4_S32); /* 42 */ MD4_HH (c, d, a, b, x[ 5], MD4_S33); /* 43 */ MD4_HH (b, c, d, a, x[13], MD4_S34); /* 44 */ MD4_HH (a, b, c, d, x[ 3], MD4_S31); /* 45 */ MD4_HH (d, a, b, c, x[11], MD4_S32); /* 46 */ MD4_HH (c, d, a, b, x[ 7], MD4_S33); /* 47 */ MD4_HH (b, c, d, a, x[15], MD4_S34); /* 48 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information.*/ memset ((void *) x, 0, sizeof (x)); } /*****************************************************************************/ /* MD5 basic transformation. Transforms state based on block. */ /*****************************************************************************/ LOCAL void MD5_transform ( unsigned long state[4], unsigned char block[64] ) { unsigned long a = state[0]; unsigned long b = state[1]; unsigned long c = state[2]; unsigned long d = state[3]; unsigned long x[16]; MD_decode (x, block, 64); /* Round 1 */ MD5_FF (a, b, c, d, x[ 0], MD5_S11, 0xd76aa478); /* 1 */ MD5_FF (d, a, b, c, x[ 1], MD5_S12, 0xe8c7b756); /* 2 */ MD5_FF (c, d, a, b, x[ 2], MD5_S13, 0x242070db); /* 3 */ MD5_FF (b, c, d, a, x[ 3], MD5_S14, 0xc1bdceee); /* 4 */ MD5_FF (a, b, c, d, x[ 4], MD5_S11, 0xf57c0faf); /* 5 */ MD5_FF (d, a, b, c, x[ 5], MD5_S12, 0x4787c62a); /* 6 */ MD5_FF (c, d, a, b, x[ 6], MD5_S13, 0xa8304613); /* 7 */ MD5_FF (b, c, d, a, x[ 7], MD5_S14, 0xfd469501); /* 8 */ MD5_FF (a, b, c, d, x[ 8], MD5_S11, 0x698098d8); /* 9 */ MD5_FF (d, a, b, c, x[ 9], MD5_S12, 0x8b44f7af); /* 10 */ MD5_FF (c, d, a, b, x[10], MD5_S13, 0xffff5bb1); /* 11 */ MD5_FF (b, c, d, a, x[11], MD5_S14, 0x895cd7be); /* 12 */ MD5_FF (a, b, c, d, x[12], MD5_S11, 0x6b901122); /* 13 */ MD5_FF (d, a, b, c, x[13], MD5_S12, 0xfd987193); /* 14 */ MD5_FF (c, d, a, b, x[14], MD5_S13, 0xa679438e); /* 15 */ MD5_FF (b, c, d, a, x[15], MD5_S14, 0x49b40821); /* 16 */ /* Round 2 */ MD5_GG (a, b, c, d, x[ 1], MD5_S21, 0xf61e2562); /* 17 */ MD5_GG (d, a, b, c, x[ 6], MD5_S22, 0xc040b340); /* 18 */ MD5_GG (c, d, a, b, x[11], MD5_S23, 0x265e5a51); /* 19 */ MD5_GG (b, c, d, a, x[ 0], MD5_S24, 0xe9b6c7aa); /* 20 */ MD5_GG (a, b, c, d, x[ 5], MD5_S21, 0xd62f105d); /* 21 */ MD5_GG (d, a, b, c, x[10], MD5_S22, 0x2441453); /* 22 */ MD5_GG (c, d, a, b, x[15], MD5_S23, 0xd8a1e681); /* 23 */ MD5_GG (b, c, d, a, x[ 4], MD5_S24, 0xe7d3fbc8); /* 24 */ MD5_GG (a, b, c, d, x[ 9], MD5_S21, 0x21e1cde6); /* 25 */ MD5_GG (d, a, b, c, x[14], MD5_S22, 0xc33707d6); /* 26 */ MD5_GG (c, d, a, b, x[ 3], MD5_S23, 0xf4d50d87); /* 27 */ MD5_GG (b, c, d, a, x[ 8], MD5_S24, 0x455a14ed); /* 28 */ MD5_GG (a, b, c, d, x[13], MD5_S21, 0xa9e3e905); /* 29 */ MD5_GG (d, a, b, c, x[ 2], MD5_S22, 0xfcefa3f8); /* 30 */ MD5_GG (c, d, a, b, x[ 7], MD5_S23, 0x676f02d9); /* 31 */ MD5_GG (b, c, d, a, x[12], MD5_S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ MD5_HH (a, b, c, d, x[ 5], MD5_S31, 0xfffa3942); /* 33 */ MD5_HH (d, a, b, c, x[ 8], MD5_S32, 0x8771f681); /* 34 */ MD5_HH (c, d, a, b, x[11], MD5_S33, 0x6d9d6122); /* 35 */ MD5_HH (b, c, d, a, x[14], MD5_S34, 0xfde5380c); /* 36 */ MD5_HH (a, b, c, d, x[ 1], MD5_S31, 0xa4beea44); /* 37 */ MD5_HH (d, a, b, c, x[ 4], MD5_S32, 0x4bdecfa9); /* 38 */ MD5_HH (c, d, a, b, x[ 7], MD5_S33, 0xf6bb4b60); /* 39 */ MD5_HH (b, c, d, a, x[10], MD5_S34, 0xbebfbc70); /* 40 */ MD5_HH (a, b, c, d, x[13], MD5_S31, 0x289b7ec6); /* 41 */ MD5_HH (d, a, b, c, x[ 0], MD5_S32, 0xeaa127fa); /* 42 */ MD5_HH (c, d, a, b, x[ 3], MD5_S33, 0xd4ef3085); /* 43 */ MD5_HH (b, c, d, a, x[ 6], MD5_S34, 0x4881d05); /* 44 */ MD5_HH (a, b, c, d, x[ 9], MD5_S31, 0xd9d4d039); /* 45 */ MD5_HH (d, a, b, c, x[12], MD5_S32, 0xe6db99e5); /* 46 */ MD5_HH (c, d, a, b, x[15], MD5_S33, 0x1fa27cf8); /* 47 */ MD5_HH (b, c, d, a, x[ 2], MD5_S34, 0xc4ac5665); /* 48 */ /* Round 4 */ MD5_II (a, b, c, d, x[ 0], MD5_S41, 0xf4292244); /* 49 */ MD5_II (d, a, b, c, x[ 7], MD5_S42, 0x432aff97); /* 50 */ MD5_II (c, d, a, b, x[14], MD5_S43, 0xab9423a7); /* 51 */ MD5_II (b, c, d, a, x[ 5], MD5_S44, 0xfc93a039); /* 52 */ MD5_II (a, b, c, d, x[12], MD5_S41, 0x655b59c3); /* 53 */ MD5_II (d, a, b, c, x[ 3], MD5_S42, 0x8f0ccc92); /* 54 */ MD5_II (c, d, a, b, x[10], MD5_S43, 0xffeff47d); /* 55 */ MD5_II (b, c, d, a, x[ 1], MD5_S44, 0x85845dd1); /* 56 */ MD5_II (a, b, c, d, x[ 8], MD5_S41, 0x6fa87e4f); /* 57 */ MD5_II (d, a, b, c, x[15], MD5_S42, 0xfe2ce6e0); /* 58 */ MD5_II (c, d, a, b, x[ 6], MD5_S43, 0xa3014314); /* 59 */ MD5_II (b, c, d, a, x[13], MD5_S44, 0x4e0811a1); /* 60 */ MD5_II (a, b, c, d, x[ 4], MD5_S41, 0xf7537e82); /* 61 */ MD5_II (d, a, b, c, x[11], MD5_S42, 0xbd3af235); /* 62 */ MD5_II (c, d, a, b, x[ 2], MD5_S43, 0x2ad7d2bb); /* 63 */ MD5_II (b, c, d, a, x[ 9], MD5_S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information.*/ memset ((void *)x, 0, sizeof (x)); } /* Encodes input (unsigned long) into output (unsigned char). Assumes length is a multiple of 4. */ LOCAL void MD_encode ( unsigned char * bptr_output, unsigned long * ulptr_input, unsigned long length ) { unsigned long i; unsigned long j; for (i = 0x00000000L, j = 0x00000000L; j < length; ++i, j += 4) { bptr_output[j] = (unsigned char)(ulptr_input[i] & 0xff); bptr_output[j+1] = (unsigned char)((ulptr_input[i] >> 8) & 0xff); bptr_output[j+2] = (unsigned char)((ulptr_input[i] >> 16) & 0xff); bptr_output[j+3] = (unsigned char)((ulptr_input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (unsigned long). Assumes length is a multiple of 4. */ LOCAL void MD_decode ( unsigned long * ulptr_output, unsigned char * bptr_input, unsigned long length ) { unsigned long i; unsigned long j; for (i = 0x00000000L, j = 0x00000000L; j < length; ++i, j += 4) { ulptr_output[i] = ((unsigned long)bptr_input[j]) | (((unsigned long)bptr_input[j+1]) << 8) | (((unsigned long)bptr_input[j+2]) << 16) | (((unsigned long)bptr_input[j+3]) << 24); } }