1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
18 const struct ltc_hash_descriptor rmd320_desc =
25 /* OID ... does not exist
26 * http://oid-info.com/get/1.3.36.3.2 */
37 /* the five basic functions F(), G() and H() */
38 #define F(x, y, z) ((x) ^ (y) ^ (z))
39 #define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
40 #define H(x, y, z) (((x) | ~(y)) ^ (z))
41 #define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
42 #define J(x, y, z) ((x) ^ ((y) | ~(z)))
44 /* the ten basic operations FF() through III() */
45 #define FF(a, b, c, d, e, x, s) \
46 (a) += F((b), (c), (d)) + (x);\
47 (a) = ROLc((a), (s)) + (e);\
50 #define GG(a, b, c, d, e, x, s) \
51 (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
52 (a) = ROLc((a), (s)) + (e);\
55 #define HH(a, b, c, d, e, x, s) \
56 (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
57 (a) = ROLc((a), (s)) + (e);\
60 #define II(a, b, c, d, e, x, s) \
61 (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
62 (a) = ROLc((a), (s)) + (e);\
65 #define JJ(a, b, c, d, e, x, s) \
66 (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
67 (a) = ROLc((a), (s)) + (e);\
70 #define FFF(a, b, c, d, e, x, s) \
71 (a) += F((b), (c), (d)) + (x);\
72 (a) = ROLc((a), (s)) + (e);\
75 #define GGG(a, b, c, d, e, x, s) \
76 (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
77 (a) = ROLc((a), (s)) + (e);\
80 #define HHH(a, b, c, d, e, x, s) \
81 (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
82 (a) = ROLc((a), (s)) + (e);\
85 #define III(a, b, c, d, e, x, s) \
86 (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
87 (a) = ROLc((a), (s)) + (e);\
90 #define JJJ(a, b, c, d, e, x, s) \
91 (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
92 (a) = ROLc((a), (s)) + (e);\
96 #ifdef LTC_CLEAN_STACK
97 static int _rmd320_compress(hash_state *md, unsigned char *buf)
99 static int rmd320_compress(hash_state *md, unsigned char *buf)
102 ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16];
106 for (i = 0; i < 16; i++){
107 LOAD32L(X[i], buf + (4 * i));
111 aa = md->rmd320.state[0];
112 bb = md->rmd320.state[1];
113 cc = md->rmd320.state[2];
114 dd = md->rmd320.state[3];
115 ee = md->rmd320.state[4];
116 aaa = md->rmd320.state[5];
117 bbb = md->rmd320.state[6];
118 ccc = md->rmd320.state[7];
119 ddd = md->rmd320.state[8];
120 eee = md->rmd320.state[9];
123 FF(aa, bb, cc, dd, ee, X[ 0], 11);
124 FF(ee, aa, bb, cc, dd, X[ 1], 14);
125 FF(dd, ee, aa, bb, cc, X[ 2], 15);
126 FF(cc, dd, ee, aa, bb, X[ 3], 12);
127 FF(bb, cc, dd, ee, aa, X[ 4], 5);
128 FF(aa, bb, cc, dd, ee, X[ 5], 8);
129 FF(ee, aa, bb, cc, dd, X[ 6], 7);
130 FF(dd, ee, aa, bb, cc, X[ 7], 9);
131 FF(cc, dd, ee, aa, bb, X[ 8], 11);
132 FF(bb, cc, dd, ee, aa, X[ 9], 13);
133 FF(aa, bb, cc, dd, ee, X[10], 14);
134 FF(ee, aa, bb, cc, dd, X[11], 15);
135 FF(dd, ee, aa, bb, cc, X[12], 6);
136 FF(cc, dd, ee, aa, bb, X[13], 7);
137 FF(bb, cc, dd, ee, aa, X[14], 9);
138 FF(aa, bb, cc, dd, ee, X[15], 8);
140 /* parallel round 1 */
141 JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
142 JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
143 JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
144 JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
145 JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
146 JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
147 JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
148 JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
149 JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
150 JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
151 JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
152 JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
153 JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
154 JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
155 JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
156 JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
158 tmp = aa; aa = aaa; aaa = tmp;
161 GG(ee, aa, bb, cc, dd, X[ 7], 7);
162 GG(dd, ee, aa, bb, cc, X[ 4], 6);
163 GG(cc, dd, ee, aa, bb, X[13], 8);
164 GG(bb, cc, dd, ee, aa, X[ 1], 13);
165 GG(aa, bb, cc, dd, ee, X[10], 11);
166 GG(ee, aa, bb, cc, dd, X[ 6], 9);
167 GG(dd, ee, aa, bb, cc, X[15], 7);
168 GG(cc, dd, ee, aa, bb, X[ 3], 15);
169 GG(bb, cc, dd, ee, aa, X[12], 7);
170 GG(aa, bb, cc, dd, ee, X[ 0], 12);
171 GG(ee, aa, bb, cc, dd, X[ 9], 15);
172 GG(dd, ee, aa, bb, cc, X[ 5], 9);
173 GG(cc, dd, ee, aa, bb, X[ 2], 11);
174 GG(bb, cc, dd, ee, aa, X[14], 7);
175 GG(aa, bb, cc, dd, ee, X[11], 13);
176 GG(ee, aa, bb, cc, dd, X[ 8], 12);
178 /* parallel round 2 */
179 III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
180 III(ddd, eee, aaa, bbb, ccc, X[11], 13);
181 III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
182 III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
183 III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
184 III(eee, aaa, bbb, ccc, ddd, X[13], 8);
185 III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
186 III(ccc, ddd, eee, aaa, bbb, X[10], 11);
187 III(bbb, ccc, ddd, eee, aaa, X[14], 7);
188 III(aaa, bbb, ccc, ddd, eee, X[15], 7);
189 III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
190 III(ddd, eee, aaa, bbb, ccc, X[12], 7);
191 III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
192 III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
193 III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
194 III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
196 tmp = bb; bb = bbb; bbb = tmp;
199 HH(dd, ee, aa, bb, cc, X[ 3], 11);
200 HH(cc, dd, ee, aa, bb, X[10], 13);
201 HH(bb, cc, dd, ee, aa, X[14], 6);
202 HH(aa, bb, cc, dd, ee, X[ 4], 7);
203 HH(ee, aa, bb, cc, dd, X[ 9], 14);
204 HH(dd, ee, aa, bb, cc, X[15], 9);
205 HH(cc, dd, ee, aa, bb, X[ 8], 13);
206 HH(bb, cc, dd, ee, aa, X[ 1], 15);
207 HH(aa, bb, cc, dd, ee, X[ 2], 14);
208 HH(ee, aa, bb, cc, dd, X[ 7], 8);
209 HH(dd, ee, aa, bb, cc, X[ 0], 13);
210 HH(cc, dd, ee, aa, bb, X[ 6], 6);
211 HH(bb, cc, dd, ee, aa, X[13], 5);
212 HH(aa, bb, cc, dd, ee, X[11], 12);
213 HH(ee, aa, bb, cc, dd, X[ 5], 7);
214 HH(dd, ee, aa, bb, cc, X[12], 5);
216 /* parallel round 3 */
217 HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
218 HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
219 HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
220 HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
221 HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
222 HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
223 HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
224 HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
225 HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
226 HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
227 HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
228 HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
229 HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
230 HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
231 HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
232 HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
234 tmp = cc; cc = ccc; ccc = tmp;
237 II(cc, dd, ee, aa, bb, X[ 1], 11);
238 II(bb, cc, dd, ee, aa, X[ 9], 12);
239 II(aa, bb, cc, dd, ee, X[11], 14);
240 II(ee, aa, bb, cc, dd, X[10], 15);
241 II(dd, ee, aa, bb, cc, X[ 0], 14);
242 II(cc, dd, ee, aa, bb, X[ 8], 15);
243 II(bb, cc, dd, ee, aa, X[12], 9);
244 II(aa, bb, cc, dd, ee, X[ 4], 8);
245 II(ee, aa, bb, cc, dd, X[13], 9);
246 II(dd, ee, aa, bb, cc, X[ 3], 14);
247 II(cc, dd, ee, aa, bb, X[ 7], 5);
248 II(bb, cc, dd, ee, aa, X[15], 6);
249 II(aa, bb, cc, dd, ee, X[14], 8);
250 II(ee, aa, bb, cc, dd, X[ 5], 6);
251 II(dd, ee, aa, bb, cc, X[ 6], 5);
252 II(cc, dd, ee, aa, bb, X[ 2], 12);
254 /* parallel round 4 */
255 GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
256 GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
257 GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
258 GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
259 GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
260 GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
261 GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
262 GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
263 GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
264 GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
265 GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
266 GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
267 GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
268 GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
269 GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
270 GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
272 tmp = dd; dd = ddd; ddd = tmp;
275 JJ(bb, cc, dd, ee, aa, X[ 4], 9);
276 JJ(aa, bb, cc, dd, ee, X[ 0], 15);
277 JJ(ee, aa, bb, cc, dd, X[ 5], 5);
278 JJ(dd, ee, aa, bb, cc, X[ 9], 11);
279 JJ(cc, dd, ee, aa, bb, X[ 7], 6);
280 JJ(bb, cc, dd, ee, aa, X[12], 8);
281 JJ(aa, bb, cc, dd, ee, X[ 2], 13);
282 JJ(ee, aa, bb, cc, dd, X[10], 12);
283 JJ(dd, ee, aa, bb, cc, X[14], 5);
284 JJ(cc, dd, ee, aa, bb, X[ 1], 12);
285 JJ(bb, cc, dd, ee, aa, X[ 3], 13);
286 JJ(aa, bb, cc, dd, ee, X[ 8], 14);
287 JJ(ee, aa, bb, cc, dd, X[11], 11);
288 JJ(dd, ee, aa, bb, cc, X[ 6], 8);
289 JJ(cc, dd, ee, aa, bb, X[15], 5);
290 JJ(bb, cc, dd, ee, aa, X[13], 6);
292 /* parallel round 5 */
293 FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
294 FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
295 FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
296 FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
297 FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
298 FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
299 FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
300 FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
301 FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
302 FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
303 FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
304 FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
305 FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
306 FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
307 FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
308 FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
310 tmp = ee; ee = eee; eee = tmp;
312 /* combine results */
313 md->rmd320.state[0] += aa;
314 md->rmd320.state[1] += bb;
315 md->rmd320.state[2] += cc;
316 md->rmd320.state[3] += dd;
317 md->rmd320.state[4] += ee;
318 md->rmd320.state[5] += aaa;
319 md->rmd320.state[6] += bbb;
320 md->rmd320.state[7] += ccc;
321 md->rmd320.state[8] += ddd;
322 md->rmd320.state[9] += eee;
327 #ifdef LTC_CLEAN_STACK
328 static int rmd320_compress(hash_state *md, unsigned char *buf)
331 err = _rmd320_compress(md, buf);
332 burn_stack(sizeof(ulong32) * 27 + sizeof(int));
338 Initialize the hash state
339 @param md The hash state you wish to initialize
340 @return CRYPT_OK if successful
342 int rmd320_init(hash_state * md)
344 LTC_ARGCHK(md != NULL);
345 md->rmd320.state[0] = 0x67452301UL;
346 md->rmd320.state[1] = 0xefcdab89UL;
347 md->rmd320.state[2] = 0x98badcfeUL;
348 md->rmd320.state[3] = 0x10325476UL;
349 md->rmd320.state[4] = 0xc3d2e1f0UL;
350 md->rmd320.state[5] = 0x76543210UL;
351 md->rmd320.state[6] = 0xfedcba98UL;
352 md->rmd320.state[7] = 0x89abcdefUL;
353 md->rmd320.state[8] = 0x01234567UL;
354 md->rmd320.state[9] = 0x3c2d1e0fUL;
355 md->rmd320.curlen = 0;
356 md->rmd320.length = 0;
361 Process a block of memory though the hash
362 @param md The hash state
363 @param in The data to hash
364 @param inlen The length of the data (octets)
365 @return CRYPT_OK if successful
367 HASH_PROCESS(rmd320_process, rmd320_compress, rmd320, 64)
370 Terminate the hash to get the digest
371 @param md The hash state
372 @param out [out] The destination of the hash (20 bytes)
373 @return CRYPT_OK if successful
375 int rmd320_done(hash_state * md, unsigned char *out)
379 LTC_ARGCHK(md != NULL);
380 LTC_ARGCHK(out != NULL);
382 if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) {
383 return CRYPT_INVALID_ARG;
387 /* increase the length of the message */
388 md->rmd320.length += md->rmd320.curlen * 8;
390 /* append the '1' bit */
391 md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0x80;
393 /* if the length is currently above 56 bytes we append zeros
394 * then compress. Then we can fall back to padding zeros and length
395 * encoding like normal.
397 if (md->rmd320.curlen > 56) {
398 while (md->rmd320.curlen < 64) {
399 md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0;
401 rmd320_compress(md, md->rmd320.buf);
402 md->rmd320.curlen = 0;
405 /* pad upto 56 bytes of zeroes */
406 while (md->rmd320.curlen < 56) {
407 md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0;
411 STORE64L(md->rmd320.length, md->rmd320.buf+56);
412 rmd320_compress(md, md->rmd320.buf);
415 for (i = 0; i < 10; i++) {
416 STORE32L(md->rmd320.state[i], out+(4*i));
418 #ifdef LTC_CLEAN_STACK
419 zeromem(md, sizeof(hash_state));
426 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
428 int rmd320_test(void)
433 static const struct {
435 unsigned char hash[40];
438 { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1,
439 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25,
440 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e,
441 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 }
444 { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5,
445 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57,
446 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54,
447 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d }
450 { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d,
451 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08,
452 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74,
453 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d }
456 { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68,
457 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa,
458 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d,
459 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 }
461 { "abcdefghijklmnopqrstuvwxyz",
462 { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93,
463 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4,
464 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed,
465 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 }
467 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
468 { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4,
469 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59,
470 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b,
471 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac }
476 unsigned char tmp[40];
479 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
481 rmd320_process(&md, (unsigned char *)tests[i].msg, strlen(tests[i].msg));
482 rmd320_done(&md, tmp);
483 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) {
484 return CRYPT_FAIL_TESTVECTOR;
493 /* ref: $Format:%D$ */
494 /* git commit: $Format:%H$ */
495 /* commit time: $Format:%ai$ */