1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * MD5 hash implementation and interface functions 3e5b75505Sopenharmony_ci * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "common.h" 12e5b75505Sopenharmony_ci#include "md5.h" 13e5b75505Sopenharmony_ci#include "md5_i.h" 14e5b75505Sopenharmony_ci#include "crypto.h" 15e5b75505Sopenharmony_ci 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_cistatic void MD5Transform(u32 buf[4], u32 const in[16]); 18e5b75505Sopenharmony_ci 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_citypedef struct MD5Context MD5_CTX; 21e5b75505Sopenharmony_ci 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci/** 24e5b75505Sopenharmony_ci * md5_vector - MD5 hash for data vector 25e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector 26e5b75505Sopenharmony_ci * @addr: Pointers to the data areas 27e5b75505Sopenharmony_ci * @len: Lengths of the data blocks 28e5b75505Sopenharmony_ci * @mac: Buffer for the hash 29e5b75505Sopenharmony_ci * Returns: 0 on success, -1 of failure 30e5b75505Sopenharmony_ci */ 31e5b75505Sopenharmony_ciint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 32e5b75505Sopenharmony_ci{ 33e5b75505Sopenharmony_ci MD5_CTX ctx; 34e5b75505Sopenharmony_ci size_t i; 35e5b75505Sopenharmony_ci 36e5b75505Sopenharmony_ci if (TEST_FAIL()) 37e5b75505Sopenharmony_ci return -1; 38e5b75505Sopenharmony_ci 39e5b75505Sopenharmony_ci MD5Init(&ctx); 40e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 41e5b75505Sopenharmony_ci MD5Update(&ctx, addr[i], len[i]); 42e5b75505Sopenharmony_ci MD5Final(mac, &ctx); 43e5b75505Sopenharmony_ci return 0; 44e5b75505Sopenharmony_ci} 45e5b75505Sopenharmony_ci 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci/* ===== start - public domain MD5 implementation ===== */ 48e5b75505Sopenharmony_ci/* 49e5b75505Sopenharmony_ci * This code implements the MD5 message-digest algorithm. 50e5b75505Sopenharmony_ci * The algorithm is due to Ron Rivest. This code was 51e5b75505Sopenharmony_ci * written by Colin Plumb in 1993, no copyright is claimed. 52e5b75505Sopenharmony_ci * This code is in the public domain; do with it what you wish. 53e5b75505Sopenharmony_ci * 54e5b75505Sopenharmony_ci * Equivalent code is available from RSA Data Security, Inc. 55e5b75505Sopenharmony_ci * This code has been tested against that, and is equivalent, 56e5b75505Sopenharmony_ci * except that you don't need to include two pages of legalese 57e5b75505Sopenharmony_ci * with every copy. 58e5b75505Sopenharmony_ci * 59e5b75505Sopenharmony_ci * To compute the message digest of a chunk of bytes, declare an 60e5b75505Sopenharmony_ci * MD5Context structure, pass it to MD5Init, call MD5Update as 61e5b75505Sopenharmony_ci * needed on buffers full of bytes, and then call MD5Final, which 62e5b75505Sopenharmony_ci * will fill a supplied 16-byte array with the digest. 63e5b75505Sopenharmony_ci */ 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_ci#ifndef WORDS_BIGENDIAN 66e5b75505Sopenharmony_ci#define byteReverse(buf, len) /* Nothing */ 67e5b75505Sopenharmony_ci#else 68e5b75505Sopenharmony_ci/* 69e5b75505Sopenharmony_ci * Note: this code is harmless on little-endian machines. 70e5b75505Sopenharmony_ci */ 71e5b75505Sopenharmony_cistatic void byteReverse(unsigned char *buf, unsigned longs) 72e5b75505Sopenharmony_ci{ 73e5b75505Sopenharmony_ci u32 t; 74e5b75505Sopenharmony_ci do { 75e5b75505Sopenharmony_ci t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | 76e5b75505Sopenharmony_ci ((unsigned) buf[1] << 8 | buf[0]); 77e5b75505Sopenharmony_ci *(u32 *) buf = t; 78e5b75505Sopenharmony_ci buf += 4; 79e5b75505Sopenharmony_ci } while (--longs); 80e5b75505Sopenharmony_ci} 81e5b75505Sopenharmony_ci#endif 82e5b75505Sopenharmony_ci 83e5b75505Sopenharmony_ci/* 84e5b75505Sopenharmony_ci * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 85e5b75505Sopenharmony_ci * initialization constants. 86e5b75505Sopenharmony_ci */ 87e5b75505Sopenharmony_civoid MD5Init(struct MD5Context *ctx) 88e5b75505Sopenharmony_ci{ 89e5b75505Sopenharmony_ci ctx->buf[0] = 0x67452301; 90e5b75505Sopenharmony_ci ctx->buf[1] = 0xefcdab89; 91e5b75505Sopenharmony_ci ctx->buf[2] = 0x98badcfe; 92e5b75505Sopenharmony_ci ctx->buf[3] = 0x10325476; 93e5b75505Sopenharmony_ci 94e5b75505Sopenharmony_ci ctx->bits[0] = 0; 95e5b75505Sopenharmony_ci ctx->bits[1] = 0; 96e5b75505Sopenharmony_ci} 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_ci/* 99e5b75505Sopenharmony_ci * Update context to reflect the concatenation of another buffer full 100e5b75505Sopenharmony_ci * of bytes. 101e5b75505Sopenharmony_ci */ 102e5b75505Sopenharmony_civoid MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) 103e5b75505Sopenharmony_ci{ 104e5b75505Sopenharmony_ci u32 t; 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ci /* Update bitcount */ 107e5b75505Sopenharmony_ci 108e5b75505Sopenharmony_ci t = ctx->bits[0]; 109e5b75505Sopenharmony_ci if ((ctx->bits[0] = t + ((u32) len << 3)) < t) 110e5b75505Sopenharmony_ci ctx->bits[1]++; /* Carry from low to high */ 111e5b75505Sopenharmony_ci ctx->bits[1] += len >> 29; 112e5b75505Sopenharmony_ci 113e5b75505Sopenharmony_ci t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ 114e5b75505Sopenharmony_ci 115e5b75505Sopenharmony_ci /* Handle any leading odd-sized chunks */ 116e5b75505Sopenharmony_ci 117e5b75505Sopenharmony_ci if (t) { 118e5b75505Sopenharmony_ci unsigned char *p = (unsigned char *) ctx->in + t; 119e5b75505Sopenharmony_ci 120e5b75505Sopenharmony_ci t = 64 - t; 121e5b75505Sopenharmony_ci if (len < t) { 122e5b75505Sopenharmony_ci os_memcpy(p, buf, len); 123e5b75505Sopenharmony_ci return; 124e5b75505Sopenharmony_ci } 125e5b75505Sopenharmony_ci os_memcpy(p, buf, t); 126e5b75505Sopenharmony_ci byteReverse(ctx->in, 16); 127e5b75505Sopenharmony_ci MD5Transform(ctx->buf, (u32 *) ctx->in); 128e5b75505Sopenharmony_ci buf += t; 129e5b75505Sopenharmony_ci len -= t; 130e5b75505Sopenharmony_ci } 131e5b75505Sopenharmony_ci /* Process data in 64-byte chunks */ 132e5b75505Sopenharmony_ci 133e5b75505Sopenharmony_ci while (len >= 64) { 134e5b75505Sopenharmony_ci os_memcpy(ctx->in, buf, 64); 135e5b75505Sopenharmony_ci byteReverse(ctx->in, 16); 136e5b75505Sopenharmony_ci MD5Transform(ctx->buf, (u32 *) ctx->in); 137e5b75505Sopenharmony_ci buf += 64; 138e5b75505Sopenharmony_ci len -= 64; 139e5b75505Sopenharmony_ci } 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_ci /* Handle any remaining bytes of data. */ 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ci os_memcpy(ctx->in, buf, len); 144e5b75505Sopenharmony_ci} 145e5b75505Sopenharmony_ci 146e5b75505Sopenharmony_ci/* 147e5b75505Sopenharmony_ci * Final wrapup - pad to 64-byte boundary with the bit pattern 148e5b75505Sopenharmony_ci * 1 0* (64-bit count of bits processed, MSB-first) 149e5b75505Sopenharmony_ci */ 150e5b75505Sopenharmony_civoid MD5Final(unsigned char digest[16], struct MD5Context *ctx) 151e5b75505Sopenharmony_ci{ 152e5b75505Sopenharmony_ci unsigned count; 153e5b75505Sopenharmony_ci unsigned char *p; 154e5b75505Sopenharmony_ci 155e5b75505Sopenharmony_ci /* Compute number of bytes mod 64 */ 156e5b75505Sopenharmony_ci count = (ctx->bits[0] >> 3) & 0x3F; 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci /* Set the first char of padding to 0x80. This is safe since there is 159e5b75505Sopenharmony_ci always at least one byte free */ 160e5b75505Sopenharmony_ci p = ctx->in + count; 161e5b75505Sopenharmony_ci *p++ = 0x80; 162e5b75505Sopenharmony_ci 163e5b75505Sopenharmony_ci /* Bytes of padding needed to make 64 bytes */ 164e5b75505Sopenharmony_ci count = 64 - 1 - count; 165e5b75505Sopenharmony_ci 166e5b75505Sopenharmony_ci /* Pad out to 56 mod 64 */ 167e5b75505Sopenharmony_ci if (count < 8) { 168e5b75505Sopenharmony_ci /* Two lots of padding: Pad the first block to 64 bytes */ 169e5b75505Sopenharmony_ci os_memset(p, 0, count); 170e5b75505Sopenharmony_ci byteReverse(ctx->in, 16); 171e5b75505Sopenharmony_ci MD5Transform(ctx->buf, (u32 *) ctx->in); 172e5b75505Sopenharmony_ci 173e5b75505Sopenharmony_ci /* Now fill the next block with 56 bytes */ 174e5b75505Sopenharmony_ci os_memset(ctx->in, 0, 56); 175e5b75505Sopenharmony_ci } else { 176e5b75505Sopenharmony_ci /* Pad block to 56 bytes */ 177e5b75505Sopenharmony_ci os_memset(p, 0, count - 8); 178e5b75505Sopenharmony_ci } 179e5b75505Sopenharmony_ci byteReverse(ctx->in, 14); 180e5b75505Sopenharmony_ci 181e5b75505Sopenharmony_ci /* Append length in bits and transform */ 182e5b75505Sopenharmony_ci ((u32 *) aliasing_hide_typecast(ctx->in, u32))[14] = ctx->bits[0]; 183e5b75505Sopenharmony_ci ((u32 *) aliasing_hide_typecast(ctx->in, u32))[15] = ctx->bits[1]; 184e5b75505Sopenharmony_ci 185e5b75505Sopenharmony_ci MD5Transform(ctx->buf, (u32 *) ctx->in); 186e5b75505Sopenharmony_ci byteReverse((unsigned char *) ctx->buf, 4); 187e5b75505Sopenharmony_ci os_memcpy(digest, ctx->buf, 16); 188e5b75505Sopenharmony_ci os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ 189e5b75505Sopenharmony_ci} 190e5b75505Sopenharmony_ci 191e5b75505Sopenharmony_ci/* The four core functions - F1 is optimized somewhat */ 192e5b75505Sopenharmony_ci 193e5b75505Sopenharmony_ci/* #define F1(x, y, z) (x & y | ~x & z) */ 194e5b75505Sopenharmony_ci#define F1(x, y, z) (z ^ (x & (y ^ z))) 195e5b75505Sopenharmony_ci#define F2(x, y, z) F1(z, x, y) 196e5b75505Sopenharmony_ci#define F3(x, y, z) (x ^ y ^ z) 197e5b75505Sopenharmony_ci#define F4(x, y, z) (y ^ (x | ~z)) 198e5b75505Sopenharmony_ci 199e5b75505Sopenharmony_ci/* This is the central step in the MD5 algorithm. */ 200e5b75505Sopenharmony_ci#define MD5STEP(f, w, x, y, z, data, s) \ 201e5b75505Sopenharmony_ci ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) 202e5b75505Sopenharmony_ci 203e5b75505Sopenharmony_ci/* 204e5b75505Sopenharmony_ci * The core of the MD5 algorithm, this alters an existing MD5 hash to 205e5b75505Sopenharmony_ci * reflect the addition of 16 longwords of new data. MD5Update blocks 206e5b75505Sopenharmony_ci * the data and converts bytes into longwords for this routine. 207e5b75505Sopenharmony_ci */ 208e5b75505Sopenharmony_cistatic void MD5Transform(u32 buf[4], u32 const in[16]) 209e5b75505Sopenharmony_ci{ 210e5b75505Sopenharmony_ci register u32 a, b, c, d; 211e5b75505Sopenharmony_ci 212e5b75505Sopenharmony_ci a = buf[0]; 213e5b75505Sopenharmony_ci b = buf[1]; 214e5b75505Sopenharmony_ci c = buf[2]; 215e5b75505Sopenharmony_ci d = buf[3]; 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 218e5b75505Sopenharmony_ci MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 219e5b75505Sopenharmony_ci MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 220e5b75505Sopenharmony_ci MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 221e5b75505Sopenharmony_ci MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 222e5b75505Sopenharmony_ci MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 223e5b75505Sopenharmony_ci MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 224e5b75505Sopenharmony_ci MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 225e5b75505Sopenharmony_ci MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 226e5b75505Sopenharmony_ci MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 227e5b75505Sopenharmony_ci MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 228e5b75505Sopenharmony_ci MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 229e5b75505Sopenharmony_ci MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 230e5b75505Sopenharmony_ci MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 231e5b75505Sopenharmony_ci MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 232e5b75505Sopenharmony_ci MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 233e5b75505Sopenharmony_ci 234e5b75505Sopenharmony_ci MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 235e5b75505Sopenharmony_ci MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 236e5b75505Sopenharmony_ci MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 237e5b75505Sopenharmony_ci MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 238e5b75505Sopenharmony_ci MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 239e5b75505Sopenharmony_ci MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 240e5b75505Sopenharmony_ci MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 241e5b75505Sopenharmony_ci MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 242e5b75505Sopenharmony_ci MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 243e5b75505Sopenharmony_ci MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 244e5b75505Sopenharmony_ci MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 245e5b75505Sopenharmony_ci MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 246e5b75505Sopenharmony_ci MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 247e5b75505Sopenharmony_ci MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 248e5b75505Sopenharmony_ci MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 249e5b75505Sopenharmony_ci MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 250e5b75505Sopenharmony_ci 251e5b75505Sopenharmony_ci MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 252e5b75505Sopenharmony_ci MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 253e5b75505Sopenharmony_ci MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 254e5b75505Sopenharmony_ci MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 255e5b75505Sopenharmony_ci MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 256e5b75505Sopenharmony_ci MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 257e5b75505Sopenharmony_ci MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 258e5b75505Sopenharmony_ci MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 259e5b75505Sopenharmony_ci MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 260e5b75505Sopenharmony_ci MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 261e5b75505Sopenharmony_ci MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 262e5b75505Sopenharmony_ci MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 263e5b75505Sopenharmony_ci MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 264e5b75505Sopenharmony_ci MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 265e5b75505Sopenharmony_ci MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 266e5b75505Sopenharmony_ci MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 267e5b75505Sopenharmony_ci 268e5b75505Sopenharmony_ci MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 269e5b75505Sopenharmony_ci MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 270e5b75505Sopenharmony_ci MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 271e5b75505Sopenharmony_ci MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 272e5b75505Sopenharmony_ci MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 273e5b75505Sopenharmony_ci MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 274e5b75505Sopenharmony_ci MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 275e5b75505Sopenharmony_ci MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 276e5b75505Sopenharmony_ci MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 277e5b75505Sopenharmony_ci MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 278e5b75505Sopenharmony_ci MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 279e5b75505Sopenharmony_ci MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 280e5b75505Sopenharmony_ci MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 281e5b75505Sopenharmony_ci MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 282e5b75505Sopenharmony_ci MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 283e5b75505Sopenharmony_ci MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 284e5b75505Sopenharmony_ci 285e5b75505Sopenharmony_ci buf[0] += a; 286e5b75505Sopenharmony_ci buf[1] += b; 287e5b75505Sopenharmony_ci buf[2] += c; 288e5b75505Sopenharmony_ci buf[3] += d; 289e5b75505Sopenharmony_ci} 290e5b75505Sopenharmony_ci/* ===== end - public domain MD5 implementation ===== */ 291