Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/libecc/src/hash/shake.c
34879 views
1
/*
2
* Copyright (C) 2021 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
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/utils/utils.h>
12
#include <libecc/hash/shake.h>
13
14
/* Init function depending on the digest size */
15
int _shake_init(shake_context *ctx, u8 digest_size, u8 block_size)
16
{
17
int ret;
18
19
MUST_HAVE((ctx != NULL), ret, err);
20
21
/* Zeroize the internal state */
22
ret = local_memset(ctx->shake_state, 0, sizeof(ctx->shake_state)); EG(ret, err);
23
24
ctx->shake_idx = 0;
25
ctx->shake_digest_size = digest_size;
26
ctx->shake_block_size = block_size;
27
28
/* Detect endianness */
29
ctx->shake_endian = arch_is_big_endian() ? SHAKE_BIG : SHAKE_LITTLE;
30
31
err:
32
return ret;
33
}
34
35
/* Update hash function */
36
int _shake_update(shake_context *ctx, const u8 *input, u32 ilen)
37
{
38
u32 i;
39
u8 *state;
40
int ret;
41
42
MUST_HAVE((ctx != NULL) && ((input != NULL) || (ilen == 0)), ret, err);
43
44
state = (u8*)(ctx->shake_state);
45
46
for(i = 0; i < ilen; i++){
47
/* Compute the index depending on the endianness */
48
u64 idx = (ctx->shake_endian == SHAKE_LITTLE) ? ctx->shake_idx : SWAP64_Idx(ctx->shake_idx);
49
ctx->shake_idx++;
50
/* Update the state, and adapt endianness order */
51
state[idx] ^= input[i];
52
if(ctx->shake_idx == ctx->shake_block_size){
53
KECCAKF(ctx->shake_state);
54
ctx->shake_idx = 0;
55
}
56
}
57
ret = 0;
58
59
err:
60
return ret;
61
}
62
63
/* Finalize hash function */
64
int _shake_finalize(shake_context *ctx, u8 *output)
65
{
66
unsigned int i;
67
u8 *state;
68
int ret;
69
70
MUST_HAVE((ctx != NULL) && (output != NULL), ret, err);
71
MUST_HAVE((ctx->shake_digest_size <= sizeof(ctx->shake_state)), ret, err);
72
73
state = (u8*)(ctx->shake_state);
74
75
/* Proceed with the padding of the last block */
76
/* Compute the index depending on the endianness */
77
if(ctx->shake_endian == SHAKE_LITTLE){
78
/* Little endian case */
79
state[ctx->shake_idx] ^= 0x1f;
80
state[ctx->shake_block_size - 1] ^= 0x80;
81
}
82
else{
83
/* Big endian case */
84
state[SWAP64_Idx(ctx->shake_idx)] ^= 0x1f;
85
state[SWAP64_Idx(ctx->shake_block_size - 1)] ^= 0x80;
86
}
87
/* Produce the output.
88
* NOTE: we should have a fixed version of SHAKE producing an output size
89
* with size less than the state size.
90
*/
91
KECCAKF(ctx->shake_state);
92
for(i = 0; i < ctx->shake_digest_size; i++){
93
output[i] = (ctx->shake_endian == SHAKE_LITTLE) ? state[i] : state[SWAP64_Idx(i)];
94
}
95
96
/* Uninit our context magic */
97
ctx->magic = WORD(0);
98
99
ret = 0;
100
101
err:
102
return ret;
103
}
104
105