1 /* 2 * Copyright (C) 2022 - 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 <libecc/lib_ecc_config.h> 12 13 #if defined(WITH_HASH_BASH224) || defined(WITH_HASH_BASH256) || defined(WITH_HASH_BASH384) || defined(WITH_HASH_BASH512) 14 #include <libecc/utils/utils.h> 15 #include <libecc/hash/bash.h> 16 17 /* 18 * This is an implementation of the BASH hash functions family (for sizes 224, 256, 384 and 512) 19 * following the standard STB 34.101.77-2020 (http://apmi.bsu.by/assets/files/std/bash-spec24.pdf). 20 * An english version of the specifications exist here: https://eprint.iacr.org/2016/587.pdf 21 */ 22 23 int _bash_init(bash_context *ctx, u8 digest_size) 24 { 25 int ret; 26 u8 *state = NULL; 27 28 /* 29 * Check given inpur digest size: we only consider BASH versions 30 * mapped on instances (224, 256, 384, 512). 31 */ 32 MUST_HAVE(((digest_size == (224/8)) || (digest_size == (256/8)) || 33 (digest_size == (384/8)) || (digest_size == (512/8))), ret, err); 34 MUST_HAVE((ctx != NULL), ret, err); 35 36 state = (u8*)(ctx->bash_state); 37 38 /* Zeroize the internal state */ 39 ret = local_memset(state, 0, sizeof(ctx->bash_state)); EG(ret, err); 40 41 ctx->bash_total = 0; 42 ctx->bash_digest_size = digest_size; 43 ctx->bash_block_size = (u8)((BASH_SLICES_X * BASH_SLICES_Y * sizeof(u64)) - (u8)(2 * digest_size)); 44 45 /* Put <l / 4>64 at the end of the state */ 46 state[(BASH_SLICES_X * BASH_SLICES_Y * sizeof(u64)) - sizeof(u64)] = (u8)digest_size; 47 48 /* Detect endianness */ 49 ctx->bash_endian = arch_is_big_endian() ? BASH_BIG : BASH_LITTLE; 50 51 ret = 0; 52 53 err: 54 return ret; 55 } 56 57 int _bash_update(bash_context *ctx, const u8 *input, u32 ilen) 58 { 59 const u8 *data_ptr = input; 60 u32 remain_ilen = ilen; 61 u16 fill; 62 u8 left; 63 int ret; 64 u8 *state = NULL; 65 66 MUST_HAVE(((ctx != NULL) && ((input != NULL) || (ilen == 0))), ret, err); 67 68 state = (u8*)(ctx->bash_state); 69 70 /* Nothing to process, return */ 71 if (ilen == 0) { 72 ret = 0; 73 goto err; 74 } 75 76 /* Get what's left in our local buffer */ 77 left = (u8)(ctx->bash_total % ctx->bash_block_size); 78 fill = (u16)(ctx->bash_block_size - left); 79 80 ctx->bash_total += ilen; 81 82 if ((left > 0) && (remain_ilen >= fill)) { 83 /* Copy data at the end of the buffer */ 84 ret = local_memcpy(state + left, data_ptr, fill); EG(ret, err); 85 data_ptr += fill; 86 remain_ilen -= fill; 87 left = 0; 88 BASHF(ctx->bash_state, ctx->bash_endian); 89 } 90 while (remain_ilen >= ctx->bash_block_size) { 91 ret = local_memcpy(state, data_ptr, ctx->bash_block_size); EG(ret, err); 92 BASHF(ctx->bash_state, ctx->bash_endian); 93 data_ptr += ctx->bash_block_size; 94 remain_ilen -= ctx->bash_block_size; 95 } 96 if (remain_ilen > 0) { 97 ret = local_memcpy(state + left, data_ptr, remain_ilen); EG(ret, err); 98 } 99 100 ret = 0; 101 102 err: 103 return ret; 104 } 105 106 /* Finalize hash function. Returns 0 on success, -1 on error. */ 107 int _bash_finalize(bash_context *ctx, u8 *output) 108 { 109 u8 pos; 110 int ret; 111 u8 *state = NULL; 112 113 MUST_HAVE((ctx != NULL) && (output != NULL), ret, err); 114 115 state = (u8*)(ctx->bash_state); 116 117 /* Handle the padding */ 118 pos = (u8)(ctx->bash_total % ctx->bash_block_size); 119 120 ret = local_memset(state + pos, 0, (u8)((ctx->bash_block_size) - pos)); EG(ret, err); 121 state[pos] = 0x40; 122 123 BASHF(ctx->bash_state, ctx->bash_endian); 124 125 /* Output the digest */ 126 ret = local_memcpy(output, state, ctx->bash_digest_size); EG(ret, err); 127 128 ret = 0; 129 err: 130 return ret; 131 } 132 133 #else 134 /* 135 * Dummy definition to avoid the empty translation unit ISO C warning 136 */ 137 typedef int dummy; 138 #endif 139