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