Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/crypto/md4c.c
48033 views
1
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
2
*/
3
4
/*-
5
SPDX-License-Identifier: RSA-MD
6
7
Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
8
9
License to copy and use this software is granted provided that it
10
is identified as the "RSA Data Security, Inc. MD4 Message-Digest
11
Algorithm" in all material mentioning or referencing this software
12
or this function.
13
14
License is also granted to make and use derivative works provided
15
that such works are identified as "derived from the RSA Data
16
Security, Inc. MD4 Message-Digest Algorithm" in all material
17
mentioning or referencing the derived work.
18
19
RSA Data Security, Inc. makes no representations concerning either
20
the merchantability of this software or the suitability of this
21
software for any particular purpose. It is provided "as is"
22
without express or implied warranty of any kind.
23
24
These notices must be retained in any copies of any part of this
25
documentation and/or software.
26
*/
27
28
#include <sys/param.h>
29
#ifdef _KERNEL
30
#include <sys/systm.h>
31
#else
32
#include <string.h>
33
#endif
34
#include <sys/md4.h>
35
36
typedef unsigned char *POINTER;
37
typedef uint16_t UINT2;
38
typedef uint32_t UINT4;
39
40
#define PROTO_LIST(list) list
41
42
/* Constants for MD4Transform routine.
43
*/
44
#define S11 3
45
#define S12 7
46
#define S13 11
47
#define S14 19
48
#define S21 3
49
#define S22 5
50
#define S23 9
51
#define S24 13
52
#define S31 3
53
#define S32 9
54
#define S33 11
55
#define S34 15
56
57
static void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
58
static void Encode PROTO_LIST
59
((unsigned char *, UINT4 *, unsigned int));
60
static void Decode PROTO_LIST
61
((UINT4 *, const unsigned char *, unsigned int));
62
63
static unsigned char PADDING[64] = {
64
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
67
};
68
69
/* F, G and H are basic MD4 functions.
70
*/
71
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
72
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
73
#define H(x, y, z) ((x) ^ (y) ^ (z))
74
75
/* ROTATE_LEFT rotates x left n bits.
76
*/
77
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
78
79
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
80
/* Rotation is separate from addition to prevent recomputation */
81
#define FF(a, b, c, d, x, s) { \
82
(a) += F ((b), (c), (d)) + (x); \
83
(a) = ROTATE_LEFT ((a), (s)); \
84
}
85
#define GG(a, b, c, d, x, s) { \
86
(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
87
(a) = ROTATE_LEFT ((a), (s)); \
88
}
89
#define HH(a, b, c, d, x, s) { \
90
(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
91
(a) = ROTATE_LEFT ((a), (s)); \
92
}
93
94
/* MD4 initialization. Begins an MD4 operation, writing a new context.
95
*/
96
void
97
MD4Init(MD4_CTX *context)
98
{
99
context->count[0] = context->count[1] = 0;
100
101
/* Load magic initialization constants.
102
*/
103
context->state[0] = 0x67452301;
104
context->state[1] = 0xefcdab89;
105
context->state[2] = 0x98badcfe;
106
context->state[3] = 0x10325476;
107
}
108
109
/* MD4 block update operation. Continues an MD4 message-digest
110
operation, processing another message block, and updating the
111
context.
112
*/
113
void
114
MD4Update(MD4_CTX *context, const unsigned char *input,
115
unsigned int inputLen)
116
{
117
unsigned int i, index, partLen;
118
119
/* Compute number of bytes mod 64 */
120
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
121
/* Update number of bits */
122
if ((context->count[0] += ((UINT4)inputLen << 3))
123
< ((UINT4)inputLen << 3))
124
context->count[1]++;
125
context->count[1] += ((UINT4)inputLen >> 29);
126
127
partLen = 64 - index;
128
/* Transform as many times as possible.
129
*/
130
if (inputLen >= partLen) {
131
bcopy(input, &context->buffer[index], partLen);
132
MD4Transform (context->state, context->buffer);
133
134
for (i = partLen; i + 63 < inputLen; i += 64)
135
MD4Transform (context->state, &input[i]);
136
137
index = 0;
138
}
139
else
140
i = 0;
141
142
/* Buffer remaining input */
143
bcopy(&input[i], &context->buffer[index], inputLen-i);
144
}
145
146
/* MD4 padding. */
147
void
148
MD4Pad(MD4_CTX *context)
149
{
150
unsigned char bits[8];
151
unsigned int index, padLen;
152
153
/* Save number of bits */
154
Encode (bits, context->count, 8);
155
156
/* Pad out to 56 mod 64.
157
*/
158
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
159
padLen = (index < 56) ? (56 - index) : (120 - index);
160
MD4Update (context, PADDING, padLen);
161
162
/* Append length (before padding) */
163
MD4Update (context, bits, 8);
164
}
165
166
/* MD4 finalization. Ends an MD4 message-digest operation, writing the
167
the message digest and zeroizing the context.
168
*/
169
void
170
MD4Final(unsigned char digest[static 16], MD4_CTX *context)
171
{
172
/* Do padding */
173
MD4Pad (context);
174
175
/* Store state in digest */
176
Encode (digest, context->state, 16);
177
178
/* Zeroize sensitive information.
179
*/
180
bzero(context, sizeof (*context));
181
}
182
183
/* MD4 basic transformation. Transforms state based on block.
184
*/
185
static void
186
MD4Transform(UINT4 state[4], const unsigned char block[64])
187
{
188
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
189
190
Decode (x, block, 64);
191
192
/* Round 1 */
193
FF (a, b, c, d, x[ 0], S11); /* 1 */
194
FF (d, a, b, c, x[ 1], S12); /* 2 */
195
FF (c, d, a, b, x[ 2], S13); /* 3 */
196
FF (b, c, d, a, x[ 3], S14); /* 4 */
197
FF (a, b, c, d, x[ 4], S11); /* 5 */
198
FF (d, a, b, c, x[ 5], S12); /* 6 */
199
FF (c, d, a, b, x[ 6], S13); /* 7 */
200
FF (b, c, d, a, x[ 7], S14); /* 8 */
201
FF (a, b, c, d, x[ 8], S11); /* 9 */
202
FF (d, a, b, c, x[ 9], S12); /* 10 */
203
FF (c, d, a, b, x[10], S13); /* 11 */
204
FF (b, c, d, a, x[11], S14); /* 12 */
205
FF (a, b, c, d, x[12], S11); /* 13 */
206
FF (d, a, b, c, x[13], S12); /* 14 */
207
FF (c, d, a, b, x[14], S13); /* 15 */
208
FF (b, c, d, a, x[15], S14); /* 16 */
209
210
/* Round 2 */
211
GG (a, b, c, d, x[ 0], S21); /* 17 */
212
GG (d, a, b, c, x[ 4], S22); /* 18 */
213
GG (c, d, a, b, x[ 8], S23); /* 19 */
214
GG (b, c, d, a, x[12], S24); /* 20 */
215
GG (a, b, c, d, x[ 1], S21); /* 21 */
216
GG (d, a, b, c, x[ 5], S22); /* 22 */
217
GG (c, d, a, b, x[ 9], S23); /* 23 */
218
GG (b, c, d, a, x[13], S24); /* 24 */
219
GG (a, b, c, d, x[ 2], S21); /* 25 */
220
GG (d, a, b, c, x[ 6], S22); /* 26 */
221
GG (c, d, a, b, x[10], S23); /* 27 */
222
GG (b, c, d, a, x[14], S24); /* 28 */
223
GG (a, b, c, d, x[ 3], S21); /* 29 */
224
GG (d, a, b, c, x[ 7], S22); /* 30 */
225
GG (c, d, a, b, x[11], S23); /* 31 */
226
GG (b, c, d, a, x[15], S24); /* 32 */
227
228
/* Round 3 */
229
HH (a, b, c, d, x[ 0], S31); /* 33 */
230
HH (d, a, b, c, x[ 8], S32); /* 34 */
231
HH (c, d, a, b, x[ 4], S33); /* 35 */
232
HH (b, c, d, a, x[12], S34); /* 36 */
233
HH (a, b, c, d, x[ 2], S31); /* 37 */
234
HH (d, a, b, c, x[10], S32); /* 38 */
235
HH (c, d, a, b, x[ 6], S33); /* 39 */
236
HH (b, c, d, a, x[14], S34); /* 40 */
237
HH (a, b, c, d, x[ 1], S31); /* 41 */
238
HH (d, a, b, c, x[ 9], S32); /* 42 */
239
HH (c, d, a, b, x[ 5], S33); /* 43 */
240
HH (b, c, d, a, x[13], S34); /* 44 */
241
HH (a, b, c, d, x[ 3], S31); /* 45 */
242
HH (d, a, b, c, x[11], S32); /* 46 */
243
HH (c, d, a, b, x[ 7], S33); /* 47 */
244
HH (b, c, d, a, x[15], S34); /* 48 */
245
246
state[0] += a;
247
state[1] += b;
248
state[2] += c;
249
state[3] += d;
250
251
/* Zeroize sensitive information.
252
*/
253
bzero((POINTER)x, sizeof (x));
254
}
255
256
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
257
a multiple of 4.
258
*/
259
static void
260
Encode(unsigned char *output, UINT4 *input, unsigned int len)
261
{
262
unsigned int i, j;
263
264
for (i = 0, j = 0; j < len; i++, j += 4) {
265
output[j] = (unsigned char)(input[i] & 0xff);
266
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
267
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
268
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
269
}
270
}
271
272
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
273
a multiple of 4.
274
*/
275
static void
276
Decode(UINT4 *output, const unsigned char *input, unsigned int len)
277
{
278
unsigned int i, j;
279
280
for (i = 0, j = 0; j < len; i++, j += 4)
281
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
282
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
283
}
284
285
#ifdef WEAK_REFS
286
/* When building libmd, provide weak references. Note: this is not
287
activated in the context of compiling these sources for internal
288
use in libcrypt.
289
*/
290
#undef MD4Init
291
__weak_reference(_libmd_MD4Init, MD4Init);
292
#undef MD4Update
293
__weak_reference(_libmd_MD4Update, MD4Update);
294
#undef MD4Pad
295
__weak_reference(_libmd_MD4Pad, MD4Pad);
296
#undef MD4Final
297
__weak_reference(_libmd_MD4Final, MD4Final);
298
#endif
299
300