4 * MD5 Message Digest Algorithm (RFC1321).
6 * Derived from cryptoapi implementation, originally based on the
7 * public domain implementation written by Colin Plumb in 1993.
9 * Reduced object size by around 50% compared to the original Linux
10 * version for use in Etherboot by Michael Brown.
12 * Copyright (c) Cryptoapi developers.
13 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
14 * Copyright (c) 2006 Michael Brown <mbrown@fensystems.co.uk>
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)
26 #include <gpxe/crypto.h>
29 #define MD5_DIGEST_SIZE 16
30 #define MD5_BLOCK_WORDS 16
31 #define MD5_HASH_WORDS 4
34 u32 hash[MD5_HASH_WORDS];
35 u32 block[MD5_BLOCK_WORDS];
39 #define __md5step __attribute__ (( regparm ( 3 ) ))
42 u32 __md5step ( * f ) ( u32 b, u32 c, u32 d );
47 static u32 __md5step f1(u32 b, u32 c, u32 d)
49 return ( d ^ ( b & ( c ^ d ) ) );
52 static u32 __md5step f2(u32 b, u32 c, u32 d)
54 return ( c ^ ( d & ( b ^ c ) ) );
57 static u32 __md5step f3(u32 b, u32 c, u32 d)
62 static u32 __md5step f4(u32 b, u32 c, u32 d)
64 return ( c ^ ( b | ~d ) );
67 struct md5_step md5_steps[4] = {
90 static const u8 r[64] = {
91 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
92 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
93 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
94 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
97 static const u32 k[64] = {
98 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
99 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
100 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
101 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
102 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
103 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
104 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
105 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
106 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
107 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
108 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
109 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
110 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
111 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
112 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
113 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL,
116 static void md5_transform(u32 *hash, const u32 *in)
118 u32 a, b, c, d, f, g, temp;
120 struct md5_step *step;
127 for ( i = 0 ; i < 64 ; i++ ) {
128 step = &md5_steps[i >> 4];
129 f = step->f ( b, c, d );
130 g = ( ( i * step->coefficient + step->constant ) & 0xf );
134 a += ( f + k[i] + in[g] );
135 a = ( ( a << r[i] ) | ( a >> ( 32-r[i] ) ) );
146 /* XXX: this stuff can be optimized */
147 static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
155 static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
163 static inline void md5_transform_helper(struct md5_ctx *ctx)
165 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
166 md5_transform(ctx->hash, ctx->block);
169 static void md5_init(void *context)
171 struct md5_ctx *mctx = context;
173 mctx->hash[0] = 0x67452301;
174 mctx->hash[1] = 0xefcdab89;
175 mctx->hash[2] = 0x98badcfe;
176 mctx->hash[3] = 0x10325476;
177 mctx->byte_count = 0;
180 static void md5_update(void *context, const void *data, size_t len)
182 struct md5_ctx *mctx = context;
183 const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
185 mctx->byte_count += len;
188 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
193 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
196 md5_transform_helper(mctx);
200 while (len >= sizeof(mctx->block)) {
201 memcpy(mctx->block, data, sizeof(mctx->block));
202 md5_transform_helper(mctx);
203 data += sizeof(mctx->block);
204 len -= sizeof(mctx->block);
207 memcpy(mctx->block, data, len);
210 static void md5_finish(void *context, void *out)
212 struct md5_ctx *mctx = context;
213 const unsigned int offset = mctx->byte_count & 0x3f;
214 char *p = (char *)mctx->block + offset;
215 int padding = 56 - (offset + 1);
219 memset(p, 0x00, padding + sizeof (u64));
220 md5_transform_helper(mctx);
221 p = (char *)mctx->block;
225 memset(p, 0, padding);
226 mctx->block[14] = mctx->byte_count << 3;
227 mctx->block[15] = mctx->byte_count >> 29;
228 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
229 sizeof(u64)) / sizeof(u32));
230 md5_transform(mctx->hash, mctx->block);
231 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
232 memcpy(out, mctx->hash, sizeof(mctx->hash));
233 memset(mctx, 0, sizeof(*mctx));
236 struct digest_algorithm md5_algorithm = {
237 .context_len = sizeof ( struct md5_ctx ),
238 .digest_len = MD5_DIGEST_SIZE,
240 .update = md5_update,
241 .finish = md5_finish,