/src/nettle-with-mini-gmp/md4.c
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  | 5.47k  | #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  | 644  | { | 
62  |  |   /* Same constants as for md5. */  | 
63  | 644  |   const uint32_t iv[_MD4_DIGEST_LENGTH] =  | 
64  | 644  |     { | 
65  | 644  |       0x67452301,  | 
66  | 644  |       0xefcdab89,  | 
67  | 644  |       0x98badcfe,  | 
68  | 644  |       0x10325476,  | 
69  | 644  |     };  | 
70  | 644  |   memcpy(ctx->state, iv, sizeof(ctx->state));  | 
71  |  |     | 
72  | 644  |   ctx->count = 0;  | 
73  | 644  |   ctx->index = 0;  | 
74  | 644  | }  | 
75  |  |  | 
76  |  | void  | 
77  |  | md4_update(struct md4_ctx *ctx,  | 
78  |  |      size_t length,  | 
79  |  |      const uint8_t *data)  | 
80  | 18.2k  | { | 
81  | 18.2k  |   MD_UPDATE(ctx, length, data, md4_compress, ctx->count++);  | 
82  | 18.2k  | }  | 
83  |  |  | 
84  |  | void  | 
85  |  | md4_digest(struct md4_ctx *ctx,  | 
86  |  |      size_t length,  | 
87  |  |      uint8_t *digest)  | 
88  | 322  | { | 
89  | 322  |   uint64_t bit_count;  | 
90  | 322  |   uint32_t data[MD4_DATA_LENGTH];  | 
91  | 322  |   unsigned i;  | 
92  |  |  | 
93  | 322  |   assert(length <= MD4_DIGEST_SIZE);  | 
94  |  |  | 
95  | 322  |   MD_PAD(ctx, 8, md4_compress);  | 
96  | 4.83k  |   for (i = 0; i < MD4_DATA_LENGTH - 2; i++)  | 
97  | 4.50k  |     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  | 322  |   bit_count = (ctx->count << 9) | (ctx->index << 3);  | 
102  | 322  |   data[MD4_DATA_LENGTH-2] = bit_count;  | 
103  | 322  |   data[MD4_DATA_LENGTH-1] = bit_count >> 32;  | 
104  | 322  |   md4_transform(ctx->state, data);  | 
105  |  |  | 
106  | 322  |   _nettle_write_le32(length, digest, ctx->state);  | 
107  | 322  |   md4_init(ctx);  | 
108  | 322  | }  | 
109  |  |  | 
110  |  | /* MD4 functions */  | 
111  | 355k  | #define F(x, y, z) (((y) & (x)) | ((z) & ~(x)))  | 
112  | 355k  | #define G(x, y, z) (((y) & (x)) | ((z) & (x)) | ((y) & (z)))  | 
113  | 355k  | #define H(x, y, z) ((x) ^ (y) ^ (z))  | 
114  |  |  | 
115  | 1.06M  | #define ROUND(f, w, x, y, z, data, s) \  | 
116  | 1.06M  | ( 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  | 22.2k  | { | 
123  | 22.2k  |   uint32_t a, b, c, d;  | 
124  | 22.2k  |   a = digest[0];  | 
125  | 22.2k  |   b = digest[1];  | 
126  | 22.2k  |   c = digest[2];  | 
127  | 22.2k  |   d = digest[3];  | 
128  |  |  | 
129  | 22.2k  |   ROUND(F, a, b, c, d, data[ 0], 3);  | 
130  | 22.2k  |   ROUND(F, d, a, b, c, data[ 1], 7);  | 
131  | 22.2k  |   ROUND(F, c, d, a, b, data[ 2], 11);  | 
132  | 22.2k  |   ROUND(F, b, c, d, a, data[ 3], 19);  | 
133  | 22.2k  |   ROUND(F, a, b, c, d, data[ 4], 3);  | 
134  | 22.2k  |   ROUND(F, d, a, b, c, data[ 5], 7);  | 
135  | 22.2k  |   ROUND(F, c, d, a, b, data[ 6], 11);  | 
136  | 22.2k  |   ROUND(F, b, c, d, a, data[ 7], 19);  | 
137  | 22.2k  |   ROUND(F, a, b, c, d, data[ 8], 3);  | 
138  | 22.2k  |   ROUND(F, d, a, b, c, data[ 9], 7);  | 
139  | 22.2k  |   ROUND(F, c, d, a, b, data[10], 11);  | 
140  | 22.2k  |   ROUND(F, b, c, d, a, data[11], 19);  | 
141  | 22.2k  |   ROUND(F, a, b, c, d, data[12], 3);  | 
142  | 22.2k  |   ROUND(F, d, a, b, c, data[13], 7);  | 
143  | 22.2k  |   ROUND(F, c, d, a, b, data[14], 11);  | 
144  | 22.2k  |   ROUND(F, b, c, d, a, data[15], 19);  | 
145  |  |  | 
146  | 22.2k  |   ROUND(G, a, b, c, d, data[ 0] + 0x5a827999, 3);  | 
147  | 22.2k  |   ROUND(G, d, a, b, c, data[ 4] + 0x5a827999, 5);  | 
148  | 22.2k  |   ROUND(G, c, d, a, b, data[ 8] + 0x5a827999, 9);  | 
149  | 22.2k  |   ROUND(G, b, c, d, a, data[12] + 0x5a827999, 13);  | 
150  | 22.2k  |   ROUND(G, a, b, c, d, data[ 1] + 0x5a827999, 3);  | 
151  | 22.2k  |   ROUND(G, d, a, b, c, data[ 5] + 0x5a827999, 5);  | 
152  | 22.2k  |   ROUND(G, c, d, a, b, data[ 9] + 0x5a827999, 9);  | 
153  | 22.2k  |   ROUND(G, b, c, d, a, data[13] + 0x5a827999, 13);  | 
154  | 22.2k  |   ROUND(G, a, b, c, d, data[ 2] + 0x5a827999, 3);  | 
155  | 22.2k  |   ROUND(G, d, a, b, c, data[ 6] + 0x5a827999, 5);  | 
156  | 22.2k  |   ROUND(G, c, d, a, b, data[10] + 0x5a827999, 9);  | 
157  | 22.2k  |   ROUND(G, b, c, d, a, data[14] + 0x5a827999, 13);  | 
158  | 22.2k  |   ROUND(G, a, b, c, d, data[ 3] + 0x5a827999, 3);  | 
159  | 22.2k  |   ROUND(G, d, a, b, c, data[ 7] + 0x5a827999, 5);  | 
160  | 22.2k  |   ROUND(G, c, d, a, b, data[11] + 0x5a827999, 9);  | 
161  | 22.2k  |   ROUND(G, b, c, d, a, data[15] + 0x5a827999, 13);  | 
162  |  |  | 
163  | 22.2k  |   ROUND(H, a, b, c, d, data[ 0] + 0x6ed9eba1, 3);  | 
164  | 22.2k  |   ROUND(H, d, a, b, c, data[ 8] + 0x6ed9eba1, 9);  | 
165  | 22.2k  |   ROUND(H, c, d, a, b, data[ 4] + 0x6ed9eba1, 11);  | 
166  | 22.2k  |   ROUND(H, b, c, d, a, data[12] + 0x6ed9eba1, 15);  | 
167  | 22.2k  |   ROUND(H, a, b, c, d, data[ 2] + 0x6ed9eba1, 3);  | 
168  | 22.2k  |   ROUND(H, d, a, b, c, data[10] + 0x6ed9eba1, 9);  | 
169  | 22.2k  |   ROUND(H, c, d, a, b, data[ 6] + 0x6ed9eba1, 11);  | 
170  | 22.2k  |   ROUND(H, b, c, d, a, data[14] + 0x6ed9eba1, 15);  | 
171  | 22.2k  |   ROUND(H, a, b, c, d, data[ 1] + 0x6ed9eba1, 3);  | 
172  | 22.2k  |   ROUND(H, d, a, b, c, data[ 9] + 0x6ed9eba1, 9);  | 
173  | 22.2k  |   ROUND(H, c, d, a, b, data[ 5] + 0x6ed9eba1, 11);  | 
174  | 22.2k  |   ROUND(H, b, c, d, a, data[13] + 0x6ed9eba1, 15);  | 
175  | 22.2k  |   ROUND(H, a, b, c, d, data[ 3] + 0x6ed9eba1, 3);  | 
176  | 22.2k  |   ROUND(H, d, a, b, c, data[11] + 0x6ed9eba1, 9);  | 
177  | 22.2k  |   ROUND(H, c, d, a, b, data[ 7] + 0x6ed9eba1, 11);  | 
178  | 22.2k  |   ROUND(H, b, c, d, a, data[15] + 0x6ed9eba1, 15);  | 
179  |  |  | 
180  | 22.2k  |   digest[0] += a;  | 
181  | 22.2k  |   digest[1] += b;  | 
182  | 22.2k  |   digest[2] += c;  | 
183  | 22.2k  |   digest[3] += d;  | 
184  | 22.2k  | }  | 
185  |  |  | 
186  |  | static void  | 
187  |  | md4_compress(struct md4_ctx *ctx, const uint8_t *block)  | 
188  | 21.8k  | { | 
189  | 21.8k  |   uint32_t data[MD4_DATA_LENGTH];  | 
190  | 21.8k  |   unsigned i;  | 
191  |  |     | 
192  |  |   /* Endian independent conversion */  | 
193  | 372k  |   for (i = 0; i<16; i++, block += 4)  | 
194  | 350k  |     data[i] = LE_READ_UINT32(block);  | 
195  |  |  | 
196  | 21.8k  |   md4_transform(ctx->state, data);  | 
197  | 21.8k  | }  |