1 /*
2 * Copyright (C) 2021 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 *
8 * This software is licensed under a dual BSD and GPL v2 license.
9 * See LICENSE file at the root folder of the project.
10 */
11 #include "hash.h"
12
13 /* Get a libecc hash type and mapping from a generic hash type */
get_libecc_hash(gen_hash_alg_type gen_hash_type,hash_alg_type * hash_type,const hash_mapping ** hm,u8 * hlen,u8 * block_size)14 ATTRIBUTE_WARN_UNUSED_RET static int get_libecc_hash(gen_hash_alg_type gen_hash_type, hash_alg_type *hash_type, const hash_mapping **hm, u8 *hlen, u8 *block_size)
15 {
16 int ret;
17 hash_alg_type htype = UNKNOWN_HASH_ALG;
18
19 MUST_HAVE((hash_type != NULL) && (hm != NULL), ret, err);
20
21 switch(gen_hash_type){
22 case HASH_SHA224:{
23 #ifdef WITH_HASH_SHA224
24 htype = SHA224;
25 #endif
26 break;
27 }
28 case HASH_SHA256:{
29 #ifdef WITH_HASH_SHA256
30 htype = SHA256;
31 #endif
32 break;
33 }
34 case HASH_SHA384:{
35 #ifdef WITH_HASH_SHA384
36 htype = SHA384;
37 #endif
38 break;
39 }
40 case HASH_SHA512:{
41 #ifdef WITH_HASH_SHA512
42 htype = SHA512;
43 #endif
44 break;
45 }
46 case HASH_SHA512_224:{
47 #ifdef WITH_HASH_SHA512_224
48 htype = SHA512_224;
49 #endif
50 break;
51 }
52 case HASH_SHA512_256:{
53 #ifdef WITH_HASH_SHA512_256
54 htype = SHA512_256;
55 #endif
56 break;
57 }
58 case HASH_SHA3_224:{
59 #ifdef WITH_HASH_SHA3_224
60 htype = SHA3_224;
61 #endif
62 break;
63 }
64 case HASH_SHA3_256:{
65 #ifdef WITH_HASH_SHA3_256
66 htype = SHA3_256;
67 #endif
68 break;
69 }
70 case HASH_SHA3_384:{
71 #ifdef WITH_HASH_SHA3_384
72 htype = SHA3_384;
73 #endif
74 break;
75 }
76 case HASH_SHA3_512:{
77 #ifdef WITH_HASH_SHA3_512
78 htype = SHA3_512;
79 #endif
80 break;
81 }
82 case HASH_SM3:{
83 #ifdef WITH_HASH_SM3
84 htype = SM3;
85 #endif
86 break;
87 }
88 case HASH_STREEBOG256:{
89 #ifdef WITH_HASH_STREEBOG256
90 htype = STREEBOG256;
91 #endif
92 break;
93 }
94 case HASH_STREEBOG512:{
95 #ifdef WITH_HASH_STREEBOG512
96 htype = STREEBOG512;
97 #endif
98 break;
99 }
100 case HASH_SHAKE256:{
101 #ifdef WITH_HASH_SHAKE256
102 htype = SHAKE256;
103 #endif
104 break;
105 }
106 case HASH_RIPEMD160:{
107 #ifdef WITH_HASH_RIPEMD160
108 htype = RIPEMD160;
109 #endif
110 break;
111 }
112 case HASH_BELT_HASH:{
113 #ifdef WITH_HASH_BELT_HASH
114 htype = BELT_HASH;
115 #endif
116 break;
117 }
118 case HASH_BASH224:{
119 #ifdef WITH_HASH_BASH224
120 htype = BASH224;
121 #endif
122 break;
123 }
124 case HASH_BASH256:{
125 #ifdef WITH_HASH_BASH256
126 htype = BASH256;
127 #endif
128 break;
129 }
130 case HASH_BASH384:{
131 #ifdef WITH_HASH_BASH384
132 htype = BASH384;
133 #endif
134 break;
135 }
136 case HASH_BASH512:{
137 #ifdef WITH_HASH_BASH512
138 htype = BASH512;
139 #endif
140 break;
141 }
142
143 default:{
144 htype = UNKNOWN_HASH_ALG;
145 break;
146 }
147 }
148 if(htype != UNKNOWN_HASH_ALG){
149 (*hash_type) = htype;
150 ret = get_hash_by_type(htype, hm); EG(ret, err);
151 ret = get_hash_sizes(htype, hlen, block_size); EG(ret, err);
152 MUST_HAVE(((*hlen) <= MAX_DIGEST_SIZE), ret, err);
153 ret = 0;
154 }
155 else{
156 ret = -1;
157 }
158
159 err:
160 if(ret && (hm != NULL)){
161 (*hm) = NULL;
162 }
163 if(ret && (hash_type != NULL)){
164 (*hash_type) = UNKNOWN_HASH_ALG;
165 }
166 return ret;
167 }
168
gen_hash_get_hash_sizes(gen_hash_alg_type gen_hash_type,u8 * hlen,u8 * block_size)169 int gen_hash_get_hash_sizes(gen_hash_alg_type gen_hash_type, u8 *hlen, u8 *block_size)
170 {
171 int ret;
172
173 MUST_HAVE((hlen != NULL) && (block_size != NULL), ret, err);
174
175 switch(gen_hash_type){
176 case HASH_MD2:{
177 (*hlen) = MD2_DIGEST_SIZE;
178 (*block_size) = MD2_BLOCK_SIZE;
179 ret = 0;
180 break;
181 }
182 case HASH_MD4:{
183 (*hlen) = MD4_DIGEST_SIZE;
184 (*block_size) = MD4_BLOCK_SIZE;
185 ret = 0;
186 break;
187 }
188 case HASH_MD5:{
189 (*hlen) = MD5_DIGEST_SIZE;
190 (*block_size) = MD5_BLOCK_SIZE;
191 ret = 0;
192 break;
193 }
194 case HASH_SHA0:{
195 (*hlen) = SHA0_DIGEST_SIZE;
196 (*block_size) = SHA0_BLOCK_SIZE;
197 ret = 0;
198 break;
199 }
200 case HASH_SHA1:{
201 (*hlen) = SHA1_DIGEST_SIZE;
202 (*block_size) = SHA1_BLOCK_SIZE;
203 ret = 0;
204 break;
205 }
206 case HASH_MDC2_PADDING1:
207 case HASH_MDC2_PADDING2:{
208 (*hlen) = MDC2_DIGEST_SIZE;
209 (*block_size) = MDC2_BLOCK_SIZE;
210 ret = 0;
211 break;
212 }
213 case HASH_GOST34_11_94_NORM:
214 case HASH_GOST34_11_94_RFC4357:{
215 (*hlen) = GOSTR34_11_94_DIGEST_SIZE;
216 (*block_size) = GOSTR34_11_94_BLOCK_SIZE;
217 ret = 0;
218 break;
219 }
220 /* The default case falls back to a genuine libecc hash function */
221 default:{
222 const hash_mapping *hm;
223 hash_alg_type hash_type;
224 ret = get_libecc_hash(gen_hash_type, &hash_type, &hm, hlen, block_size); EG(ret, err);
225 break;
226 }
227 }
228
229 err:
230 return ret;
231 }
232
gen_hash_hfunc_scattered(const u8 ** input,const u32 * ilen,u8 * digest,gen_hash_alg_type gen_hash_type)233 int gen_hash_hfunc_scattered(const u8 **input, const u32 *ilen, u8 *digest, gen_hash_alg_type gen_hash_type)
234 {
235 int ret;
236
237 switch(gen_hash_type){
238 case HASH_MD2:{
239 ret = md2_scattered(input, ilen, digest); EG(ret, err);
240 break;
241 }
242 case HASH_MD4:{
243 ret = md4_scattered(input, ilen, digest); EG(ret, err);
244 break;
245 }
246 case HASH_MD5:{
247 ret = md5_scattered(input, ilen, digest); EG(ret, err);
248 break;
249 }
250 case HASH_SHA0:{
251 ret = sha0_scattered(input, ilen, digest); EG(ret, err);
252 break;
253 }
254 case HASH_SHA1:{
255 ret = sha1_scattered(input, ilen, digest); EG(ret, err);
256 break;
257 }
258 case HASH_MDC2_PADDING1:{
259 ret = mdc2_scattered_padding1(input, ilen, digest); EG(ret, err);
260 break;
261 }
262 case HASH_MDC2_PADDING2:{
263 ret = mdc2_scattered_padding2(input, ilen, digest); EG(ret, err);
264 break;
265 }
266 case HASH_GOST34_11_94_NORM:{
267 ret = gostr34_11_94_scattered_norm(input, ilen, digest); EG(ret, err);
268 break;
269 }
270 case HASH_GOST34_11_94_RFC4357:{
271 ret = gostr34_11_94_scattered_rfc4357(input, ilen, digest); EG(ret, err);
272 break;
273 }
274 /* The fallback should be libecc type */
275 default:{
276 const hash_mapping *hm;
277 hash_alg_type hash_type;
278 u8 hlen, block_size;
279 ret = get_libecc_hash(gen_hash_type, &hash_type, &hm, &hlen, &block_size); EG(ret, err);
280 MUST_HAVE((hm != NULL), ret, err);
281 ret = hm->hfunc_scattered(input, ilen, digest); EG(ret, err);
282 break;
283 }
284 }
285
286 err:
287 return ret;
288 }
289
gen_hash_hfunc(const u8 * input,u32 ilen,u8 * digest,gen_hash_alg_type gen_hash_type)290 int gen_hash_hfunc(const u8 *input, u32 ilen, u8 *digest, gen_hash_alg_type gen_hash_type)
291 {
292 const u8 *inputs[2] = { input, NULL };
293 u32 ilens[2] = { ilen, 0 };
294
295 return gen_hash_hfunc_scattered(inputs, ilens, digest, gen_hash_type);
296 }
297
gen_hash_init(gen_hash_context * ctx,gen_hash_alg_type gen_hash_type)298 int gen_hash_init(gen_hash_context *ctx, gen_hash_alg_type gen_hash_type)
299 {
300 int ret;
301
302 MUST_HAVE((ctx != NULL), ret, err);
303
304 switch(gen_hash_type){
305 case HASH_MD2:{
306 ret = md2_init(&(ctx->md2ctx)); EG(ret, err);
307 break;
308 }
309 case HASH_MD4:{
310 ret = md4_init(&(ctx->md4ctx)); EG(ret, err);
311 break;
312 }
313 case HASH_MD5:{
314 ret = md5_init(&(ctx->md5ctx)); EG(ret, err);
315 break;
316 }
317 case HASH_SHA0:{
318 ret = sha0_init(&(ctx->sha0ctx)); EG(ret, err);
319 break;
320 }
321 case HASH_SHA1:{
322 ret = sha1_init(&(ctx->sha1ctx)); EG(ret, err);
323 break;
324 }
325 case HASH_MDC2_PADDING1:{
326 ret = mdc2_init(&(ctx->mdc2ctx)); EG(ret, err);
327 ret = mdc2_set_padding_type(&(ctx->mdc2ctx), ISOIEC10118_TYPE1); EG(ret, err);
328 break;
329 }
330 case HASH_MDC2_PADDING2:{
331 ret = mdc2_init(&(ctx->mdc2ctx)); EG(ret, err);
332 ret = mdc2_set_padding_type(&(ctx->mdc2ctx), ISOIEC10118_TYPE2); EG(ret, err);
333 break;
334 }
335 case HASH_GOST34_11_94_NORM:{
336 ret = gostr34_11_94_init(&(ctx->gostr34_11_94ctx)); EG(ret, err);
337 ret = gostr34_11_94_set_type(&(ctx->gostr34_11_94ctx), GOST34_11_94_NORM); EG(ret, err);
338 break;
339 }
340 case HASH_GOST34_11_94_RFC4357:{
341 ret = gostr34_11_94_init(&(ctx->gostr34_11_94ctx)); EG(ret, err);
342 ret = gostr34_11_94_set_type(&(ctx->gostr34_11_94ctx), GOST34_11_94_RFC4357); EG(ret, err);
343 break;
344 }
345 /* The fallback should be libecc type */
346 default:{
347 const hash_mapping *hm;
348 hash_alg_type hash_type;
349 u8 hlen, block_size;
350 ret = get_libecc_hash(gen_hash_type, &hash_type, &hm, &hlen, &block_size); EG(ret, err);
351 MUST_HAVE((hm != NULL), ret, err);
352 ret = hm->hfunc_init(&(ctx->hctx)); EG(ret, err);
353 break;
354 }
355 }
356
357 err:
358 return ret;
359 }
360
gen_hash_update(gen_hash_context * ctx,const u8 * chunk,u32 chunklen,gen_hash_alg_type gen_hash_type)361 int gen_hash_update(gen_hash_context *ctx, const u8 *chunk, u32 chunklen, gen_hash_alg_type gen_hash_type)
362 {
363 int ret;
364
365 MUST_HAVE((ctx != NULL), ret, err);
366
367 switch(gen_hash_type){
368 case HASH_MD2:{
369 ret = md2_update(&(ctx->md2ctx), chunk, chunklen); EG(ret, err);
370 break;
371 }
372 case HASH_MD4:{
373 ret = md4_update(&(ctx->md4ctx), chunk, chunklen); EG(ret, err);
374 break;
375 }
376 case HASH_MD5:{
377 ret = md5_update(&(ctx->md5ctx), chunk, chunklen); EG(ret, err);
378 break;
379 }
380 case HASH_SHA0:{
381 ret = sha0_update(&(ctx->sha0ctx), chunk, chunklen); EG(ret, err);
382 break;
383 }
384 case HASH_SHA1:{
385 ret = sha1_update(&(ctx->sha1ctx), chunk, chunklen); EG(ret, err);
386 break;
387 }
388 case HASH_MDC2_PADDING1:
389 case HASH_MDC2_PADDING2:{
390 ret = mdc2_update(&(ctx->mdc2ctx), chunk, chunklen); EG(ret, err);
391 break;
392 }
393 case HASH_GOST34_11_94_NORM:
394 case HASH_GOST34_11_94_RFC4357:{
395 ret = gostr34_11_94_update(&(ctx->gostr34_11_94ctx), chunk, chunklen); EG(ret, err);
396 break;
397 }
398 /* The fallback should be libecc type */
399 default:{
400 const hash_mapping *hm;
401 hash_alg_type hash_type;
402 u8 hlen, block_size;
403 ret = get_libecc_hash(gen_hash_type, &hash_type, &hm, &hlen, &block_size); EG(ret, err);
404 MUST_HAVE((hm != NULL), ret, err);
405 ret = hm->hfunc_update(&(ctx->hctx), chunk, chunklen); EG(ret, err);
406 break;
407 }
408 }
409
410 err:
411 return ret;
412 }
413
gen_hash_final(gen_hash_context * ctx,u8 * output,gen_hash_alg_type gen_hash_type)414 int gen_hash_final(gen_hash_context *ctx, u8 *output, gen_hash_alg_type gen_hash_type)
415 {
416 int ret;
417
418 MUST_HAVE((ctx != NULL), ret, err);
419
420 switch(gen_hash_type){
421 case HASH_MD2:{
422 ret = md2_final(&(ctx->md2ctx), output); EG(ret, err);
423 break;
424 }
425 case HASH_MD4:{
426 ret = md4_final(&(ctx->md4ctx), output); EG(ret, err);
427 break;
428 }
429 case HASH_MD5:{
430 ret = md5_final(&(ctx->md5ctx), output); EG(ret, err);
431 break;
432 }
433 case HASH_SHA0:{
434 ret = sha0_final(&(ctx->sha0ctx), output); EG(ret, err);
435 break;
436 }
437 case HASH_SHA1:{
438 ret = sha1_final(&(ctx->sha1ctx), output); EG(ret, err);
439 break;
440 }
441 case HASH_MDC2_PADDING1:
442 case HASH_MDC2_PADDING2:{
443 ret = mdc2_final(&(ctx->mdc2ctx), output); EG(ret, err);
444 break;
445 }
446 case HASH_GOST34_11_94_NORM:
447 case HASH_GOST34_11_94_RFC4357:{
448 ret = gostr34_11_94_final(&(ctx->gostr34_11_94ctx), output); EG(ret, err);
449 break;
450 }
451 /* The fallback should be libecc type */
452 default:{
453 const hash_mapping *hm;
454 hash_alg_type hash_type;
455 u8 hlen, block_size;
456 ret = get_libecc_hash(gen_hash_type, &hash_type, &hm, &hlen, &block_size); EG(ret, err);
457 MUST_HAVE((hm != NULL), ret, err);
458 ret = hm->hfunc_finalize(&(ctx->hctx), output); EG(ret, err);
459 break;
460 }
461 }
462
463 err:
464 return ret;
465 }
466
467 #ifdef HASH
468 #include <libecc/utils/print_buf.h>
main(int argc,char * argv[])469 int main(int argc, char *argv[])
470 {
471 int ret = 0;
472 unsigned int i;
473
474 const u8 input[] = "Now is the time for all ";
475 const u8 input2[] = "\x54\x68\x69\x73\x20\x69\x73\x20\x6D\x65\x73\x73\x61\x67\x65\x2C\x20\x6C\x65\x6E\x67\x74\x68\x3D\x33\x32\x20\x62\x79\x74\x65\x73";
476 const u8 input3[] = "";
477 const u8 input4[] = "Suppose the original message has length = 50 bytes";
478 u8 input5[128];
479 u8 output[32];
480
481 FORCE_USED_VAR(argc);
482 FORCE_USED_VAR(argv);
483
484 ret = local_memset(input5, 0, sizeof(input5)); EG(ret, err);
485
486 ret = gen_hash_hfunc(input, sizeof(input)-1, output, HASH_MDC2_PADDING1); EG(ret, err);
487 buf_print("mdc2 padding1", output, 16);
488
489 ret = gen_hash_hfunc(input, sizeof(input)-1, output, HASH_MDC2_PADDING2); EG(ret, err);
490 buf_print("mdc2 padding2", output, 16);
491
492 ret = gen_hash_hfunc(input2, sizeof(input2)-1, output, HASH_GOST34_11_94_NORM); EG(ret, err);
493 buf_print("gostr34_11_94 NORM", output, 32);
494
495 ret = gen_hash_hfunc(input3, sizeof(input3)-1, output, HASH_GOST34_11_94_NORM); EG(ret, err);
496 buf_print("gostr34_11_94 NORM", output, 32);
497
498 ret = gen_hash_hfunc(input4, sizeof(input4)-1, output, HASH_GOST34_11_94_NORM); EG(ret, err);
499 buf_print("gostr34_11_94 NORM", output, 32);
500
501 for(i = 0; i < sizeof(input5); i++){
502 input5[i] = 'U';
503 }
504 ret = gen_hash_hfunc(input5, sizeof(input5), output, HASH_GOST34_11_94_NORM); EG(ret, err);
505 buf_print("gostr34_11_94 NORM", output, 32);
506
507 err:
508 return ret;
509 }
510 #endif
511