]> git.ipfire.org Git - thirdparty/nettle.git/blame - md5.c
Add ChangeLog entry for nettle-3.10 release.
[thirdparty/nettle.git] / md5.c
CommitLineData
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
49void
50md5_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
66void
67md5_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 74void
2f43e1c8 75md5_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
114void
115nettle_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}