xref: /freebsd/crypto/libecc/src/examples/hash/hash.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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