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 */ 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 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 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 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 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 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 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> 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