Line | Count | Source |
1 | | /* md4.c |
2 | | |
3 | | The MD4 hash function, described in RFC 1320. |
4 | | |
5 | | Copyright (C) 2003 Niels Möller, Marcus Comstedt |
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 | | */ |
33 | | |
34 | | /* Based on the public domain md5 code, and modified by Marcus |
35 | | Comstedt */ |
36 | | |
37 | | #if HAVE_CONFIG_H |
38 | | # include "config.h" |
39 | | #endif |
40 | | |
41 | | #include <assert.h> |
42 | | #include <string.h> |
43 | | |
44 | | #include "md4.h" |
45 | | |
46 | | #include "macros.h" |
47 | | #include "nettle-write.h" |
48 | | |
49 | | /* A block, treated as a sequence of 32-bit words. */ |
50 | 2.56k | #define MD4_DATA_LENGTH 16 |
51 | | |
52 | | static void |
53 | | md4_transform(uint32_t *digest, const uint32_t *data); |
54 | | |
55 | | static void |
56 | | md4_compress(struct md4_ctx *ctx, const uint8_t *block); |
57 | | |
58 | | /* FIXME: Could be an alias for md5_init */ |
59 | | void |
60 | | md4_init(struct md4_ctx *ctx) |
61 | 302 | { |
62 | | /* Same constants as for md5. */ |
63 | 302 | const uint32_t iv[_MD4_DIGEST_LENGTH] = |
64 | 302 | { |
65 | 302 | 0x67452301, |
66 | 302 | 0xefcdab89, |
67 | 302 | 0x98badcfe, |
68 | 302 | 0x10325476, |
69 | 302 | }; |
70 | 302 | memcpy(ctx->state, iv, sizeof(ctx->state)); |
71 | | |
72 | 302 | ctx->count = 0; |
73 | 302 | ctx->index = 0; |
74 | 302 | } |
75 | | |
76 | | void |
77 | | md4_update(struct md4_ctx *ctx, |
78 | | size_t length, |
79 | | const uint8_t *data) |
80 | 151 | { |
81 | 151 | MD_UPDATE(ctx, length, data, md4_compress, ctx->count++); |
82 | 151 | } |
83 | | |
84 | | void |
85 | | md4_digest(struct md4_ctx *ctx, |
86 | | size_t length, |
87 | | uint8_t *digest) |
88 | 151 | { |
89 | 151 | uint64_t bit_count; |
90 | 151 | uint32_t data[MD4_DATA_LENGTH]; |
91 | 151 | unsigned i; |
92 | | |
93 | 151 | assert(length <= MD4_DIGEST_SIZE); |
94 | | |
95 | 151 | MD_PAD(ctx, 8, md4_compress); |
96 | 2.26k | for (i = 0; i < MD4_DATA_LENGTH - 2; i++) |
97 | 2.11k | data[i] = LE_READ_UINT32(ctx->block + 4*i); |
98 | | |
99 | | /* There are 512 = 2^9 bits in one block |
100 | | * Little-endian order => Least significant word first */ |
101 | 151 | bit_count = (ctx->count << 9) | (ctx->index << 3); |
102 | 151 | data[MD4_DATA_LENGTH-2] = bit_count; |
103 | 151 | data[MD4_DATA_LENGTH-1] = bit_count >> 32; |
104 | 151 | md4_transform(ctx->state, data); |
105 | | |
106 | 151 | _nettle_write_le32(length, digest, ctx->state); |
107 | 151 | md4_init(ctx); |
108 | 151 | } |
109 | | |
110 | | /* MD4 functions */ |
111 | 3.07k | #define F(x, y, z) (((y) & (x)) | ((z) & ~(x))) |
112 | 3.07k | #define G(x, y, z) (((y) & (x)) | ((z) & (x)) | ((y) & (z))) |
113 | 3.07k | #define H(x, y, z) ((x) ^ (y) ^ (z)) |
114 | | |
115 | 9.21k | #define ROUND(f, w, x, y, z, data, s) \ |
116 | 9.21k | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s) ) |
117 | | |
118 | | /* Perform the MD4 transformation on one full block of 16 32-bit words. */ |
119 | | |
120 | | static void |
121 | | md4_transform(uint32_t *digest, const uint32_t *data) |
122 | 192 | { |
123 | 192 | uint32_t a, b, c, d; |
124 | 192 | a = digest[0]; |
125 | 192 | b = digest[1]; |
126 | 192 | c = digest[2]; |
127 | 192 | d = digest[3]; |
128 | | |
129 | 192 | ROUND(F, a, b, c, d, data[ 0], 3); |
130 | 192 | ROUND(F, d, a, b, c, data[ 1], 7); |
131 | 192 | ROUND(F, c, d, a, b, data[ 2], 11); |
132 | 192 | ROUND(F, b, c, d, a, data[ 3], 19); |
133 | 192 | ROUND(F, a, b, c, d, data[ 4], 3); |
134 | 192 | ROUND(F, d, a, b, c, data[ 5], 7); |
135 | 192 | ROUND(F, c, d, a, b, data[ 6], 11); |
136 | 192 | ROUND(F, b, c, d, a, data[ 7], 19); |
137 | 192 | ROUND(F, a, b, c, d, data[ 8], 3); |
138 | 192 | ROUND(F, d, a, b, c, data[ 9], 7); |
139 | 192 | ROUND(F, c, d, a, b, data[10], 11); |
140 | 192 | ROUND(F, b, c, d, a, data[11], 19); |
141 | 192 | ROUND(F, a, b, c, d, data[12], 3); |
142 | 192 | ROUND(F, d, a, b, c, data[13], 7); |
143 | 192 | ROUND(F, c, d, a, b, data[14], 11); |
144 | 192 | ROUND(F, b, c, d, a, data[15], 19); |
145 | | |
146 | 192 | ROUND(G, a, b, c, d, data[ 0] + 0x5a827999, 3); |
147 | 192 | ROUND(G, d, a, b, c, data[ 4] + 0x5a827999, 5); |
148 | 192 | ROUND(G, c, d, a, b, data[ 8] + 0x5a827999, 9); |
149 | 192 | ROUND(G, b, c, d, a, data[12] + 0x5a827999, 13); |
150 | 192 | ROUND(G, a, b, c, d, data[ 1] + 0x5a827999, 3); |
151 | 192 | ROUND(G, d, a, b, c, data[ 5] + 0x5a827999, 5); |
152 | 192 | ROUND(G, c, d, a, b, data[ 9] + 0x5a827999, 9); |
153 | 192 | ROUND(G, b, c, d, a, data[13] + 0x5a827999, 13); |
154 | 192 | ROUND(G, a, b, c, d, data[ 2] + 0x5a827999, 3); |
155 | 192 | ROUND(G, d, a, b, c, data[ 6] + 0x5a827999, 5); |
156 | 192 | ROUND(G, c, d, a, b, data[10] + 0x5a827999, 9); |
157 | 192 | ROUND(G, b, c, d, a, data[14] + 0x5a827999, 13); |
158 | 192 | ROUND(G, a, b, c, d, data[ 3] + 0x5a827999, 3); |
159 | 192 | ROUND(G, d, a, b, c, data[ 7] + 0x5a827999, 5); |
160 | 192 | ROUND(G, c, d, a, b, data[11] + 0x5a827999, 9); |
161 | 192 | ROUND(G, b, c, d, a, data[15] + 0x5a827999, 13); |
162 | | |
163 | 192 | ROUND(H, a, b, c, d, data[ 0] + 0x6ed9eba1, 3); |
164 | 192 | ROUND(H, d, a, b, c, data[ 8] + 0x6ed9eba1, 9); |
165 | 192 | ROUND(H, c, d, a, b, data[ 4] + 0x6ed9eba1, 11); |
166 | 192 | ROUND(H, b, c, d, a, data[12] + 0x6ed9eba1, 15); |
167 | 192 | ROUND(H, a, b, c, d, data[ 2] + 0x6ed9eba1, 3); |
168 | 192 | ROUND(H, d, a, b, c, data[10] + 0x6ed9eba1, 9); |
169 | 192 | ROUND(H, c, d, a, b, data[ 6] + 0x6ed9eba1, 11); |
170 | 192 | ROUND(H, b, c, d, a, data[14] + 0x6ed9eba1, 15); |
171 | 192 | ROUND(H, a, b, c, d, data[ 1] + 0x6ed9eba1, 3); |
172 | 192 | ROUND(H, d, a, b, c, data[ 9] + 0x6ed9eba1, 9); |
173 | 192 | ROUND(H, c, d, a, b, data[ 5] + 0x6ed9eba1, 11); |
174 | 192 | ROUND(H, b, c, d, a, data[13] + 0x6ed9eba1, 15); |
175 | 192 | ROUND(H, a, b, c, d, data[ 3] + 0x6ed9eba1, 3); |
176 | 192 | ROUND(H, d, a, b, c, data[11] + 0x6ed9eba1, 9); |
177 | 192 | ROUND(H, c, d, a, b, data[ 7] + 0x6ed9eba1, 11); |
178 | 192 | ROUND(H, b, c, d, a, data[15] + 0x6ed9eba1, 15); |
179 | | |
180 | 192 | digest[0] += a; |
181 | 192 | digest[1] += b; |
182 | 192 | digest[2] += c; |
183 | 192 | digest[3] += d; |
184 | 192 | } |
185 | | |
186 | | static void |
187 | | md4_compress(struct md4_ctx *ctx, const uint8_t *block) |
188 | 41 | { |
189 | 41 | uint32_t data[MD4_DATA_LENGTH]; |
190 | 41 | unsigned i; |
191 | | |
192 | | /* Endian independent conversion */ |
193 | 697 | for (i = 0; i<16; i++, block += 4) |
194 | 656 | data[i] = LE_READ_UINT32(block); |
195 | | |
196 | 41 | md4_transform(ctx->state, data); |
197 | 41 | } |