Add n_signal(), our future (v15) sigaction(2) call-in
[s-mailx.git] / rfc1321.h
blob4833ec058400c760f5858b454085e1354e9f9b56
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ RFC 1321 derived MD5 algorithm implementation.
3 *@ This is included by nailfuns.h if 'HAVE_MD5 && !HAVE_OPENSSL_MD5',
4 *@ and contains MD5.H as well as MD5C.C from the RFC.
6 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
7 * Copyright (c) 2012 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
8 */
10 /* MD5.H - header file for MD5C.C
12 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13 rights reserved.
15 License to copy and use this software is granted provided that it
16 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17 Algorithm" in all material mentioning or referencing this software
18 or this function.
20 License is also granted to make and use derivative works provided
21 that such works are identified as "derived from the RSA Data
22 Security, Inc. MD5 Message-Digest Algorithm" in all material
23 mentioning or referencing the derived work.
25 RSA Data Security, Inc. makes no representations concerning either
26 the merchantability of this software or the suitability of this
27 software for any particular purpose. It is provided "as is"
28 without express or implied warranty of any kind.
30 These notices must be retained in any copies of any part of this
31 documentation and/or software.
35 * This version of MD5 has been changed such that any unsigned type with
36 * at least 32 bits is acceptable. This is important e.g. for Cray vector
37 * machines which provide only 64-bit integers.
39 typedef unsigned long md5_type;
41 typedef struct {
42 md5_type state[4]; /* state (ABCD) */
43 md5_type count[2]; /* number of bits, modulo 2^64 (lsb first) */
44 unsigned char buffer[64]; /* input buffer */
45 } md5_ctx;
47 FL void md5_init(md5_ctx *);
48 FL void md5_update(md5_ctx *, unsigned char *, unsigned int);
49 FL void md5_final(unsigned char[16], md5_ctx *);
51 #ifdef n_MAIN_SOURCE
52 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
54 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
55 rights reserved.
57 License to copy and use this software is granted provided that it
58 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
59 Algorithm" in all material mentioning or referencing this software
60 or this function.
62 License is also granted to make and use derivative works provided
63 that such works are identified as "derived from the RSA Data
64 Security, Inc. MD5 Message-Digest Algorithm" in all material
65 mentioning or referencing the derived work.
67 RSA Data Security, Inc. makes no representations concerning either
68 the merchantability of this software or the suitability of this
69 software for any particular purpose. It is provided "as is"
70 without express or implied warranty of any kind.
72 These notices must be retained in any copies of any part of this
73 documentation and/or software.
76 # include <string.h>
78 #define UINT4B_MAX 0xFFFFFFFFul
80 /* Constants for MD5Transform routine.
82 #define S11 7
83 #define S12 12
84 #define S13 17
85 #define S14 22
86 #define S21 5
87 #define S22 9
88 #define S23 14
89 #define S24 20
90 #define S31 4
91 #define S32 11
92 #define S33 16
93 #define S34 23
94 #define S41 6
95 #define S42 10
96 #define S43 15
97 #define S44 21
99 static unsigned char PADDING[64] = {
100 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
107 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
110 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
111 * simplified to the code below. Wei attributes these optimizations
112 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
114 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
115 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
116 #define H(b,c,d) ((b) ^ (c) ^ (d))
117 #define I(b,c,d) (((~(d) & UINT4B_MAX) | (b)) ^ (c))
119 /* ROTATE_LEFT rotates x left n bits.
121 #define ROTATE_LEFT(x, n) ((((x) << (n)) & UINT4B_MAX) | ((x) >> (32 - (n))))
124 * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
125 * Rotation is separate from addition to prevent recomputation.
127 #define FF(a, b, c, d, x, s, ac) { \
128 (a) = ((a) + F(b, c, d) + (x) + ((ac) & UINT4B_MAX)) & UINT4B_MAX; \
129 (a) = ROTATE_LEFT((a), (s)); \
130 (a) = ((a) + (b)) & UINT4B_MAX; \
133 #define GG(a, b, c, d, x, s, ac) { \
134 (a) = ((a) + G(b, c, d) + (x) + ((ac) & UINT4B_MAX)) & UINT4B_MAX; \
135 (a) = ROTATE_LEFT((a), (s)); \
136 (a) = ((a) + (b)) & UINT4B_MAX; \
139 #define HH(a, b, c, d, x, s, ac) { \
140 (a) = ((a) + H(b, c, d) + (x) + ((ac) & UINT4B_MAX)) & UINT4B_MAX; \
141 (a) = ROTATE_LEFT((a), (s)); \
142 (a) = ((a) + (b)) & UINT4B_MAX; \
145 #define II(a, b, c, d, x, s, ac) { \
146 (a) = ((a) + I(b, c, d) + (x) + ((ac) & UINT4B_MAX)) & UINT4B_MAX; \
147 (a) = ROTATE_LEFT((a), (s)); \
148 (a) = ((a) + (b)) & UINT4B_MAX; \
151 static void * (* volatile _volatile_memset)(void*, int, size_t) = &(memset);
153 static void Encode(unsigned char *outp, md5_type *inp, unsigned int len);
154 static void Decode(md5_type *outp, unsigned char *inp, unsigned int len);
155 static void MD5Transform(md5_type state[], unsigned char block[]);
158 * Encodes input (md5_type) into output (unsigned char). Assumes len is
159 * a multiple of 4.
161 static void
162 Encode(unsigned char *outp, md5_type *inp, unsigned int len)
164 unsigned int i, j;
166 for (i = 0, j = 0; j < len; i++, j += 4) {
167 outp[j] = inp[i] & 0xff;
168 outp[j+1] = (inp[i] >> 8) & 0xff;
169 outp[j+2] = (inp[i] >> 16) & 0xff;
170 outp[j+3] = (inp[i] >> 24) & 0xff;
175 * Decodes input (unsigned char) into output (md5_type). Assumes len is
176 * a multiple of 4.
178 static void
179 Decode(md5_type *outp, unsigned char *inp, unsigned int len)
181 unsigned int i, j;
183 for (i = 0, j = 0; j < len; i++, j += 4)
184 outp[i] = ((md5_type)inp[j] |
185 (md5_type)inp[j+1] << 8 |
186 (md5_type)inp[j+2] << 16 |
187 (md5_type)inp[j+3] << 24) & UINT4B_MAX;
190 /* MD5 basic transformation. Transforms state based on block. */
191 static void
192 MD5Transform(md5_type state[4], unsigned char block[64])
194 md5_type a = state[0], b = state[1], c = state[2], d = state[3],
195 x[16];
197 Decode(x, block, 64);
199 /* Round 1 */
200 FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
201 FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
202 FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
203 FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
204 FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
205 FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
206 FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
207 FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
208 FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
209 FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
210 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
211 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
212 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
213 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
214 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
215 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
217 /* Round 2 */
218 GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
219 GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
220 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
221 GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
222 GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
223 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
224 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
225 GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
226 GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
227 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
228 GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
229 GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
230 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
231 GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
232 GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
233 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
235 /* Round 3 */
236 HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
237 HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
238 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
239 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
240 HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
241 HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
242 HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
243 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
244 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
245 HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
246 HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
247 HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
248 HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
249 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
250 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
251 HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
253 /* Round 4 */
254 II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
255 II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
256 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
257 II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
258 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
259 II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
260 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
261 II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
262 II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
263 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
264 II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
265 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
266 II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
267 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
268 II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
269 II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
271 state[0] = (state[0] + a) & UINT4B_MAX;
272 state[1] = (state[1] + b) & UINT4B_MAX;
273 state[2] = (state[2] + c) & UINT4B_MAX;
274 state[3] = (state[3] + d) & UINT4B_MAX;
277 * Zeroize sensitive information.
279 (*_volatile_memset)(x, 0, sizeof x);
283 * MD5 initialization. Begins an MD5 operation, writing a new context.
285 FL void
286 md5_init(
287 md5_ctx *context /* context */
290 context->count[0] = context->count[1] = 0;
292 * Load magic initialization constants.
294 context->state[0] = 0x67452301;
295 context->state[1] = 0xefcdab89;
296 context->state[2] = 0x98badcfe;
297 context->state[3] = 0x10325476;
301 * MD5 block update operation. Continues an MD5 message-digest
302 * operation, processing another message block, and updating the
303 * context.
305 FL void
306 md5_update(
307 md5_ctx *context, /* context */
308 unsigned char *input, /* input block */
309 unsigned int inputLen /* length of input block */
312 unsigned int i, idx, partLen;
314 /* Compute number of bytes mod 64 */
315 idx = context->count[0]>>3 & 0x3F;
317 /* Update number of bits */
318 if ((context->count[0] = (context->count[0] + (inputLen<<3)) &
319 UINT4B_MAX)
320 < ((inputLen << 3) & UINT4B_MAX))
321 context->count[1] = (context->count[1] + 1) & UINT4B_MAX;
322 context->count[1] = (context->count[1] + (inputLen >> 29)) & UINT4B_MAX;
324 partLen = 64 - idx;
327 * Transform as many times as possible.
329 if (inputLen >= partLen) {
330 memcpy(&context->buffer[idx], input, partLen);
331 MD5Transform(context->state, context->buffer);
333 for (i = partLen; i + 63 < inputLen; i += 64)
334 MD5Transform(context->state, &input[i]);
336 idx = 0;
337 } else
338 i = 0;
340 /* Buffer remaining input */
341 memcpy(&context->buffer[idx], &input[i], inputLen-i);
345 * MD5 finalization. Ends an MD5 message-digest operation, writing the
346 * the message digest and zeroizing the context.
348 FL void
349 md5_final(
350 unsigned char digest[16], /* message digest */
351 md5_ctx *context /* context */
354 unsigned char bits[8];
355 unsigned int idx, padLen;
357 /* Save number of bits */
358 Encode(bits, context->count, 8);
361 * Pad out to 56 mod 64.
363 idx = context->count[0]>>3 & 0x3f;
364 padLen = idx < 56 ? 56 - idx : 120 - idx;
365 md5_update(context, PADDING, padLen);
367 /* Append length (before padding) */
368 md5_update(context, bits, 8);
369 /* Store state in digest */
370 Encode(digest, context->state, 16);
373 * Zeroize sensitive information.
375 (*_volatile_memset)(context, 0, sizeof *context);
378 # undef UINT4B_MAX
379 # undef S11
380 # undef S12
381 # undef S13
382 # undef S14
383 # undef S21
384 # undef S22
385 # undef S23
386 # undef S24
387 # undef S31
388 # undef S32
389 # undef S33
390 # undef S34
391 # undef S41
392 # undef S42
393 # undef S43
394 # undef S44
395 # undef F
396 # undef G
397 # undef H
398 # undef I
399 # undef ROTATE_LEFT
400 # undef FF
401 # undef GG
402 # undef HH
403 # undef II
404 #endif /* n_MAIN_SOURCE */