|
|
1.1 ! root 1: /* ! 2: * Cryptographic API. ! 3: * ! 4: * MD5 Message Digest Algorithm (RFC1321). ! 5: * ! 6: * Derived from cryptoapi implementation, originally based on the ! 7: * public domain implementation written by Colin Plumb in 1993. ! 8: * ! 9: * Reduced object size by around 50% compared to the original Linux ! 10: * version for use in Etherboot by Michael Brown. ! 11: * ! 12: * Copyright (c) Cryptoapi developers. ! 13: * Copyright (c) 2002 James Morris <[email protected]> ! 14: * Copyright (c) 2006 Michael Brown <[email protected]> ! 15: * ! 16: * This program is free software; you can redistribute it and/or modify it ! 17: * under the terms of the GNU General Public License as published by the Free ! 18: * Software Foundation; either version 2 of the License, or (at your option) ! 19: * any later version. ! 20: * ! 21: */ ! 22: ! 23: FILE_LICENCE ( GPL2_OR_LATER ); ! 24: ! 25: #include <stdint.h> ! 26: #include <string.h> ! 27: #include <byteswap.h> ! 28: #include <ipxe/crypto.h> ! 29: #include <ipxe/md5.h> ! 30: ! 31: struct md5_step { ! 32: u32 ( * f ) ( u32 b, u32 c, u32 d ); ! 33: u8 coefficient; ! 34: u8 constant; ! 35: }; ! 36: ! 37: static u32 f1(u32 b, u32 c, u32 d) ! 38: { ! 39: return ( d ^ ( b & ( c ^ d ) ) ); ! 40: } ! 41: ! 42: static u32 f2(u32 b, u32 c, u32 d) ! 43: { ! 44: return ( c ^ ( d & ( b ^ c ) ) ); ! 45: } ! 46: ! 47: static u32 f3(u32 b, u32 c, u32 d) ! 48: { ! 49: return ( b ^ c ^ d ); ! 50: } ! 51: ! 52: static u32 f4(u32 b, u32 c, u32 d) ! 53: { ! 54: return ( c ^ ( b | ~d ) ); ! 55: } ! 56: ! 57: static struct md5_step md5_steps[4] = { ! 58: { ! 59: .f = f1, ! 60: .coefficient = 1, ! 61: .constant = 0, ! 62: }, ! 63: { ! 64: .f = f2, ! 65: .coefficient = 5, ! 66: .constant = 1, ! 67: }, ! 68: { ! 69: .f = f3, ! 70: .coefficient = 3, ! 71: .constant = 5, ! 72: }, ! 73: { ! 74: .f = f4, ! 75: .coefficient = 7, ! 76: .constant = 0, ! 77: } ! 78: }; ! 79: ! 80: static const u8 r[64] = { ! 81: 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, ! 82: 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, ! 83: 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, ! 84: 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 ! 85: }; ! 86: ! 87: static const u32 k[64] = { ! 88: 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, ! 89: 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, ! 90: 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, ! 91: 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, ! 92: 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, ! 93: 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, ! 94: 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, ! 95: 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, ! 96: 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, ! 97: 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, ! 98: 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, ! 99: 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, ! 100: 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, ! 101: 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, ! 102: 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, ! 103: 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL, ! 104: }; ! 105: ! 106: static void md5_transform(u32 *hash, const u32 *in) ! 107: { ! 108: u32 a, b, c, d, f, g, temp; ! 109: int i; ! 110: struct md5_step *step; ! 111: ! 112: a = hash[0]; ! 113: b = hash[1]; ! 114: c = hash[2]; ! 115: d = hash[3]; ! 116: ! 117: for ( i = 0 ; i < 64 ; i++ ) { ! 118: step = &md5_steps[i >> 4]; ! 119: f = step->f ( b, c, d ); ! 120: g = ( ( i * step->coefficient + step->constant ) & 0xf ); ! 121: temp = d; ! 122: d = c; ! 123: c = b; ! 124: a += ( f + k[i] + in[g] ); ! 125: a = ( ( a << r[i] ) | ( a >> ( 32-r[i] ) ) ); ! 126: b += a; ! 127: a = temp; ! 128: } ! 129: ! 130: hash[0] += a; ! 131: hash[1] += b; ! 132: hash[2] += c; ! 133: hash[3] += d; ! 134: } ! 135: ! 136: /* XXX: this stuff can be optimized */ ! 137: static inline void le32_to_cpu_array(u32 *buf, unsigned int words) ! 138: { ! 139: while (words--) { ! 140: le32_to_cpus(buf); ! 141: buf++; ! 142: } ! 143: } ! 144: ! 145: static inline void cpu_to_le32_array(u32 *buf, unsigned int words) ! 146: { ! 147: while (words--) { ! 148: cpu_to_le32s(buf); ! 149: buf++; ! 150: } ! 151: } ! 152: ! 153: static inline void md5_transform_helper(struct md5_ctx *ctx) ! 154: { ! 155: le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); ! 156: md5_transform(ctx->hash, ctx->block); ! 157: } ! 158: ! 159: static void md5_init(void *context) ! 160: { ! 161: struct md5_ctx *mctx = context; ! 162: ! 163: mctx->hash[0] = 0x67452301; ! 164: mctx->hash[1] = 0xefcdab89; ! 165: mctx->hash[2] = 0x98badcfe; ! 166: mctx->hash[3] = 0x10325476; ! 167: mctx->byte_count = 0; ! 168: } ! 169: ! 170: static void md5_update(void *context, const void *data, size_t len) ! 171: { ! 172: struct md5_ctx *mctx = context; ! 173: const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); ! 174: ! 175: mctx->byte_count += len; ! 176: ! 177: if (avail > len) { ! 178: memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), ! 179: data, len); ! 180: return; ! 181: } ! 182: ! 183: memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), ! 184: data, avail); ! 185: ! 186: md5_transform_helper(mctx); ! 187: data += avail; ! 188: len -= avail; ! 189: ! 190: while (len >= sizeof(mctx->block)) { ! 191: memcpy(mctx->block, data, sizeof(mctx->block)); ! 192: md5_transform_helper(mctx); ! 193: data += sizeof(mctx->block); ! 194: len -= sizeof(mctx->block); ! 195: } ! 196: ! 197: memcpy(mctx->block, data, len); ! 198: } ! 199: ! 200: static void md5_final(void *context, void *out) ! 201: { ! 202: struct md5_ctx *mctx = context; ! 203: const unsigned int offset = mctx->byte_count & 0x3f; ! 204: char *p = (char *)mctx->block + offset; ! 205: int padding = 56 - (offset + 1); ! 206: ! 207: *p++ = 0x80; ! 208: if (padding < 0) { ! 209: memset(p, 0x00, padding + sizeof (u64)); ! 210: md5_transform_helper(mctx); ! 211: p = (char *)mctx->block; ! 212: padding = 56; ! 213: } ! 214: ! 215: memset(p, 0, padding); ! 216: mctx->block[14] = mctx->byte_count << 3; ! 217: mctx->block[15] = mctx->byte_count >> 29; ! 218: le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - ! 219: sizeof(u64)) / sizeof(u32)); ! 220: md5_transform(mctx->hash, mctx->block); ! 221: cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); ! 222: memcpy(out, mctx->hash, sizeof(mctx->hash)); ! 223: memset(mctx, 0, sizeof(*mctx)); ! 224: } ! 225: ! 226: struct digest_algorithm md5_algorithm = { ! 227: .name = "md5", ! 228: .ctxsize = MD5_CTX_SIZE, ! 229: .blocksize = ( MD5_BLOCK_WORDS * 4 ), ! 230: .digestsize = MD5_DIGEST_SIZE, ! 231: .init = md5_init, ! 232: .update = md5_update, ! 233: .final = md5_final, ! 234: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.