/ external / libecc / src / hash / bash.c
bash.c
  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