]>
Commit | Line | Data |
---|---|---|
8ae5b576 | 1 | /* md5.c |
90112edb NM |
2 | |
3 | The MD5 hash function, described in RFC 1321. | |
4 | ||
5 | Copyright (C) 2001 Niels Möller | |
6 | ||
7 | This file is part of GNU Nettle. | |
8 | ||
9 | GNU Nettle is free software: you can redistribute it and/or | |
10 | modify it under the terms of either: | |
11 | ||
12 | * the GNU Lesser General Public License as published by the Free | |
13 | Software Foundation; either version 3 of the License, or (at your | |
14 | option) any later version. | |
15 | ||
16 | or | |
17 | ||
18 | * the GNU General Public License as published by the Free | |
19 | Software Foundation; either version 2 of the License, or (at your | |
20 | option) any later version. | |
21 | ||
22 | or both in parallel, as here. | |
23 | ||
24 | GNU Nettle is distributed in the hope that it will be useful, | |
25 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 | General Public License for more details. | |
28 | ||
29 | You should have received copies of the GNU General Public License and | |
30 | the GNU Lesser General Public License along with this program. If | |
31 | not, see http://www.gnu.org/licenses/. | |
32 | */ | |
94cb1bf0 | 33 | |
8ae5b576 | 34 | /* Based on public domain code hacked by Colin Plumb, Andrew Kuchling, and |
a16dd13f | 35 | * Niels Möller. */ |
8ae5b576 | 36 | |
c5c15385 | 37 | #if HAVE_CONFIG_H |
a0b3dc84 | 38 | # include "config.h" |
c5c15385 | 39 | #endif |
a9efcd8a | 40 | |
8ae5b576 | 41 | #include <assert.h> |
2d51740f | 42 | #include <string.h> |
94cb1bf0 | 43 | |
c5c15385 NM |
44 | #include "md5.h" |
45 | ||
46 | #include "macros.h" | |
13b956bb | 47 | #include "nettle-write.h" |
c5c15385 | 48 | |
8ae5b576 NM |
49 | void |
50 | md5_init(struct md5_ctx *ctx) | |
94cb1bf0 | 51 | { |
f773cbd7 NM |
52 | const uint32_t iv[_MD5_DIGEST_LENGTH] = |
53 | { | |
54 | 0x67452301, | |
55 | 0xefcdab89, | |
56 | 0x98badcfe, | |
57 | 0x10325476, | |
58 | }; | |
59 | memcpy(ctx->state, iv, sizeof(ctx->state)); | |
cb83bd33 | 60 | ctx->count = 0; |
94cb1bf0 NM |
61 | ctx->index = 0; |
62 | } | |
63 | ||
da81c86a | 64 | #define COMPRESS(ctx, data) (nettle_md5_compress((ctx)->state, (data))) |
45b5553e | 65 | |
8ae5b576 NM |
66 | void |
67 | md5_update(struct md5_ctx *ctx, | |
b8bfc32f | 68 | size_t length, |
8ae5b576 NM |
69 | const uint8_t *data) |
70 | { | |
cb83bd33 | 71 | MD_UPDATE(ctx, length, data, COMPRESS, ctx->count++); |
8ae5b576 NM |
72 | } |
73 | ||
8ae5b576 | 74 | void |
2f43e1c8 | 75 | md5_digest(struct md5_ctx *ctx, |
b8bfc32f | 76 | size_t length, |
8ae5b576 | 77 | uint8_t *digest) |
5046486e | 78 | { |
cb83bd33 | 79 | uint64_t bit_count; |
5046486e | 80 | |
f773cbd7 | 81 | assert(length <= MD5_DIGEST_SIZE); |
5046486e | 82 | |
f773cbd7 | 83 | MD_PAD(ctx, 8, COMPRESS); |
5046486e | 84 | |
cb83bd33 NM |
85 | /* There are 512 = 2^9 bits in one block */ |
86 | bit_count = (ctx->count << 9) | (ctx->index << 3); | |
5046486e | 87 | |
d22bac82 | 88 | LE_WRITE_UINT64(ctx->block + (MD5_BLOCK_SIZE - 8), bit_count); |
da81c86a | 89 | nettle_md5_compress(ctx->state, ctx->block); |
f773cbd7 NM |
90 | |
91 | _nettle_write_le32(length, digest, ctx->state); | |
92 | md5_init(ctx); | |
5046486e | 93 | } |
8238898d NM |
94 | |
95 | /* A block, treated as a sequence of 32-bit words. */ | |
96 | #define MD5_DATA_LENGTH 16 | |
97 | ||
98 | /* MD5 functions */ | |
99 | ||
100 | #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | |
101 | #define F2(x, y, z) F1((z), (x), (y)) | |
102 | #define F3(x, y, z) ((x) ^ (y) ^ (z)) | |
103 | #define F4(x, y, z) ((y) ^ ((x) | ~(z))) | |
104 | ||
105 | #define ROUND(f, w, x, y, z, data, s) \ | |
106 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | |
107 | ||
108 | /* Perform the MD5 transformation on one full block of 16 32-bit | |
109 | * words. | |
110 | * | |
111 | * Compresses 20 (_MD5_DIGEST_LENGTH + MD5_DATA_LENGTH) words into 4 | |
112 | * (_MD5_DIGEST_LENGTH) words. */ | |
113 | ||
114 | void | |
115 | nettle_md5_compress(uint32_t *digest, const uint8_t *input) | |
116 | { | |
117 | uint32_t data[MD5_DATA_LENGTH]; | |
118 | uint32_t a, b, c, d; | |
119 | unsigned i; | |
120 | ||
121 | for (i = 0; i < MD5_DATA_LENGTH; i++, input += 4) | |
122 | data[i] = LE_READ_UINT32(input); | |
123 | ||
124 | a = digest[0]; | |
125 | b = digest[1]; | |
126 | c = digest[2]; | |
127 | d = digest[3]; | |
128 | ||
129 | ROUND(F1, a, b, c, d, data[ 0] + 0xd76aa478, 7); | |
130 | ROUND(F1, d, a, b, c, data[ 1] + 0xe8c7b756, 12); | |
131 | ROUND(F1, c, d, a, b, data[ 2] + 0x242070db, 17); | |
132 | ROUND(F1, b, c, d, a, data[ 3] + 0xc1bdceee, 22); | |
133 | ROUND(F1, a, b, c, d, data[ 4] + 0xf57c0faf, 7); | |
134 | ROUND(F1, d, a, b, c, data[ 5] + 0x4787c62a, 12); | |
135 | ROUND(F1, c, d, a, b, data[ 6] + 0xa8304613, 17); | |
136 | ROUND(F1, b, c, d, a, data[ 7] + 0xfd469501, 22); | |
137 | ROUND(F1, a, b, c, d, data[ 8] + 0x698098d8, 7); | |
138 | ROUND(F1, d, a, b, c, data[ 9] + 0x8b44f7af, 12); | |
139 | ROUND(F1, c, d, a, b, data[10] + 0xffff5bb1, 17); | |
140 | ROUND(F1, b, c, d, a, data[11] + 0x895cd7be, 22); | |
141 | ROUND(F1, a, b, c, d, data[12] + 0x6b901122, 7); | |
142 | ROUND(F1, d, a, b, c, data[13] + 0xfd987193, 12); | |
143 | ROUND(F1, c, d, a, b, data[14] + 0xa679438e, 17); | |
144 | ROUND(F1, b, c, d, a, data[15] + 0x49b40821, 22); | |
145 | ||
146 | ROUND(F2, a, b, c, d, data[ 1] + 0xf61e2562, 5); | |
147 | ROUND(F2, d, a, b, c, data[ 6] + 0xc040b340, 9); | |
148 | ROUND(F2, c, d, a, b, data[11] + 0x265e5a51, 14); | |
149 | ROUND(F2, b, c, d, a, data[ 0] + 0xe9b6c7aa, 20); | |
150 | ROUND(F2, a, b, c, d, data[ 5] + 0xd62f105d, 5); | |
151 | ROUND(F2, d, a, b, c, data[10] + 0x02441453, 9); | |
152 | ROUND(F2, c, d, a, b, data[15] + 0xd8a1e681, 14); | |
153 | ROUND(F2, b, c, d, a, data[ 4] + 0xe7d3fbc8, 20); | |
154 | ROUND(F2, a, b, c, d, data[ 9] + 0x21e1cde6, 5); | |
155 | ROUND(F2, d, a, b, c, data[14] + 0xc33707d6, 9); | |
156 | ROUND(F2, c, d, a, b, data[ 3] + 0xf4d50d87, 14); | |
157 | ROUND(F2, b, c, d, a, data[ 8] + 0x455a14ed, 20); | |
158 | ROUND(F2, a, b, c, d, data[13] + 0xa9e3e905, 5); | |
159 | ROUND(F2, d, a, b, c, data[ 2] + 0xfcefa3f8, 9); | |
160 | ROUND(F2, c, d, a, b, data[ 7] + 0x676f02d9, 14); | |
161 | ROUND(F2, b, c, d, a, data[12] + 0x8d2a4c8a, 20); | |
162 | ||
163 | ROUND(F3, a, b, c, d, data[ 5] + 0xfffa3942, 4); | |
164 | ROUND(F3, d, a, b, c, data[ 8] + 0x8771f681, 11); | |
165 | ROUND(F3, c, d, a, b, data[11] + 0x6d9d6122, 16); | |
166 | ROUND(F3, b, c, d, a, data[14] + 0xfde5380c, 23); | |
167 | ROUND(F3, a, b, c, d, data[ 1] + 0xa4beea44, 4); | |
168 | ROUND(F3, d, a, b, c, data[ 4] + 0x4bdecfa9, 11); | |
169 | ROUND(F3, c, d, a, b, data[ 7] + 0xf6bb4b60, 16); | |
170 | ROUND(F3, b, c, d, a, data[10] + 0xbebfbc70, 23); | |
171 | ROUND(F3, a, b, c, d, data[13] + 0x289b7ec6, 4); | |
172 | ROUND(F3, d, a, b, c, data[ 0] + 0xeaa127fa, 11); | |
173 | ROUND(F3, c, d, a, b, data[ 3] + 0xd4ef3085, 16); | |
174 | ROUND(F3, b, c, d, a, data[ 6] + 0x04881d05, 23); | |
175 | ROUND(F3, a, b, c, d, data[ 9] + 0xd9d4d039, 4); | |
176 | ROUND(F3, d, a, b, c, data[12] + 0xe6db99e5, 11); | |
177 | ROUND(F3, c, d, a, b, data[15] + 0x1fa27cf8, 16); | |
178 | ROUND(F3, b, c, d, a, data[ 2] + 0xc4ac5665, 23); | |
179 | ||
180 | ROUND(F4, a, b, c, d, data[ 0] + 0xf4292244, 6); | |
181 | ROUND(F4, d, a, b, c, data[ 7] + 0x432aff97, 10); | |
182 | ROUND(F4, c, d, a, b, data[14] + 0xab9423a7, 15); | |
183 | ROUND(F4, b, c, d, a, data[ 5] + 0xfc93a039, 21); | |
184 | ROUND(F4, a, b, c, d, data[12] + 0x655b59c3, 6); | |
185 | ROUND(F4, d, a, b, c, data[ 3] + 0x8f0ccc92, 10); | |
186 | ROUND(F4, c, d, a, b, data[10] + 0xffeff47d, 15); | |
187 | ROUND(F4, b, c, d, a, data[ 1] + 0x85845dd1, 21); | |
188 | ROUND(F4, a, b, c, d, data[ 8] + 0x6fa87e4f, 6); | |
189 | ROUND(F4, d, a, b, c, data[15] + 0xfe2ce6e0, 10); | |
190 | ROUND(F4, c, d, a, b, data[ 6] + 0xa3014314, 15); | |
191 | ROUND(F4, b, c, d, a, data[13] + 0x4e0811a1, 21); | |
192 | ROUND(F4, a, b, c, d, data[ 4] + 0xf7537e82, 6); | |
193 | ROUND(F4, d, a, b, c, data[11] + 0xbd3af235, 10); | |
194 | ROUND(F4, c, d, a, b, data[ 2] + 0x2ad7d2bb, 15); | |
195 | ROUND(F4, b, c, d, a, data[ 9] + 0xeb86d391, 21); | |
196 | ||
197 | digest[0] += a; | |
198 | digest[1] += b; | |
199 | digest[2] += c; | |
200 | digest[3] += d; | |
201 | } |