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
_bash_init(bash_context * ctx,u8 digest_size)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
_bash_update(bash_context * ctx,const u8 * input,u32 ilen)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. */
_bash_finalize(bash_context * ctx,u8 * output)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