Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/libecc/src/hash/sha512_core.c
34879 views
1
/*
2
* Copyright (C) 2017 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
7
* Jean-Pierre FLORI <[email protected]>
8
*
9
* Contributors:
10
* Nicolas VIVET <[email protected]>
11
* Karim KHALFALLAH <[email protected]>
12
*
13
* This software is licensed under a dual BSD and GPL v2 license.
14
* See LICENSE file at the root folder of the project.
15
*/
16
#include <libecc/lib_ecc_config.h>
17
#if defined(WITH_HASH_SHA512) || defined(WITH_HASH_SHA512_224) || defined(WITH_HASH_SHA512_256)
18
#include <libecc/hash/sha512_core.h>
19
20
/* SHA-2 core processing. Returns 0 on success, -1 on error. */
21
ATTRIBUTE_WARN_UNUSED_RET static int sha512_core_process(sha512_core_context *ctx,
22
const u8 data[SHA512_CORE_BLOCK_SIZE])
23
{
24
u64 a, b, c, d, e, f, g, h;
25
u64 W[80];
26
unsigned int i;
27
int ret;
28
29
MUST_HAVE(((ctx != NULL) && (data != NULL)), ret, err);
30
31
/* Init our inner variables */
32
a = ctx->sha512_state[0];
33
b = ctx->sha512_state[1];
34
c = ctx->sha512_state[2];
35
d = ctx->sha512_state[3];
36
e = ctx->sha512_state[4];
37
f = ctx->sha512_state[5];
38
g = ctx->sha512_state[6];
39
h = ctx->sha512_state[7];
40
41
for (i = 0; i < 16; i++) {
42
GET_UINT64_BE(W[i], data, 8 * i);
43
SHA2CORE_SHA512(a, b, c, d, e, f, g, h, W[i], K_SHA512[i]);
44
}
45
46
for (i = 16; i < 80; i++) {
47
SHA2CORE_SHA512(a, b, c, d, e, f, g, h, UPDATEW_SHA512(W, i),
48
K_SHA512[i]);
49
}
50
51
/* Update state */
52
ctx->sha512_state[0] += a;
53
ctx->sha512_state[1] += b;
54
ctx->sha512_state[2] += c;
55
ctx->sha512_state[3] += d;
56
ctx->sha512_state[4] += e;
57
ctx->sha512_state[5] += f;
58
ctx->sha512_state[6] += g;
59
ctx->sha512_state[7] += h;
60
61
ret = 0;
62
63
err:
64
return ret;
65
}
66
67
/* Core update hash function. Returns 0 on success, -1 on error. */
68
int sha512_core_update(sha512_core_context *ctx, const u8 *input, u32 ilen)
69
{
70
const u8 *data_ptr = input;
71
u32 remain_ilen = ilen;
72
u16 fill;
73
u8 left;
74
int ret;
75
76
MUST_HAVE(((ctx != NULL) && ((input != NULL) || (ilen == 0))), ret, err);
77
78
/* Nothing to process, return */
79
if (ilen == 0) {
80
ret = 0;
81
goto err;
82
}
83
84
/* Get what's left in our local buffer */
85
left = ctx->sha512_total[0] & 0x7F;
86
fill = (u16)(SHA512_CORE_BLOCK_SIZE - left);
87
88
ADD_UINT128_UINT64(ctx->sha512_total[0], ctx->sha512_total[1], ilen);
89
90
if ((left > 0) && (remain_ilen >= fill)) {
91
/* Copy data at the end of the buffer */
92
ret = local_memcpy(ctx->sha512_buffer + left, data_ptr, fill); EG(ret, err);
93
ret = sha512_core_process(ctx, ctx->sha512_buffer); EG(ret, err);
94
data_ptr += fill;
95
remain_ilen -= fill;
96
left = 0;
97
}
98
99
while (remain_ilen >= SHA512_CORE_BLOCK_SIZE) {
100
ret = sha512_core_process(ctx, data_ptr); EG(ret, err);
101
data_ptr += SHA512_CORE_BLOCK_SIZE;
102
remain_ilen -= SHA512_CORE_BLOCK_SIZE;
103
}
104
105
if (remain_ilen > 0) {
106
ret = local_memcpy(ctx->sha512_buffer + left, data_ptr, remain_ilen); EG(ret, err);
107
}
108
109
ret = 0;
110
111
err:
112
return ret;
113
}
114
115
/* Core finalize. Returns 0 on success, -1 on error. */
116
int sha512_core_final(sha512_core_context *ctx, u8 *output, u32 output_size)
117
{
118
unsigned int block_present = 0;
119
u8 last_padded_block[2 * SHA512_CORE_BLOCK_SIZE];
120
int ret;
121
122
MUST_HAVE(((ctx != NULL) && (output != NULL)), ret, err);
123
124
/* Fill in our last block with zeroes */
125
ret = local_memset(last_padded_block, 0, sizeof(last_padded_block)); EG(ret, err);
126
127
/* This is our final step, so we proceed with the padding */
128
block_present = ctx->sha512_total[0] % SHA512_CORE_BLOCK_SIZE;
129
if (block_present != 0) {
130
/* Copy what's left in our temporary context buffer */
131
ret = local_memcpy(last_padded_block, ctx->sha512_buffer,
132
block_present); EG(ret, err);
133
}
134
135
/* Put the 0x80 byte, beginning of padding */
136
last_padded_block[block_present] = 0x80;
137
138
/* Handle possible additional block */
139
if (block_present > (SHA512_CORE_BLOCK_SIZE - 1 - (2 * sizeof(u64)))) {
140
/* We need an additional block */
141
PUT_MUL8_UINT128_BE(ctx->sha512_total[0], ctx->sha512_total[1],
142
last_padded_block,
143
2 * (SHA512_CORE_BLOCK_SIZE - sizeof(u64)));
144
ret = sha512_core_process(ctx, last_padded_block); EG(ret, err);
145
ret = sha512_core_process(ctx, last_padded_block + SHA512_CORE_BLOCK_SIZE); EG(ret, err);
146
} else {
147
/* We do not need an additional block */
148
PUT_MUL8_UINT128_BE(ctx->sha512_total[0], ctx->sha512_total[1],
149
last_padded_block,
150
SHA512_CORE_BLOCK_SIZE - (2 * sizeof(u64)));
151
ret = sha512_core_process(ctx, last_padded_block); EG(ret, err);
152
}
153
154
/* Output the hash result truncated to the output size */
155
if(output_size >= SHA512_CORE_DIGEST_SIZE){
156
PUT_UINT64_BE(ctx->sha512_state[0], output, 0);
157
PUT_UINT64_BE(ctx->sha512_state[1], output, 8);
158
PUT_UINT64_BE(ctx->sha512_state[2], output, 16);
159
PUT_UINT64_BE(ctx->sha512_state[3], output, 24);
160
PUT_UINT64_BE(ctx->sha512_state[4], output, 32);
161
PUT_UINT64_BE(ctx->sha512_state[5], output, 40);
162
PUT_UINT64_BE(ctx->sha512_state[6], output, 48);
163
PUT_UINT64_BE(ctx->sha512_state[7], output, 56);
164
} else {
165
u8 tmp_output[SHA512_CORE_DIGEST_SIZE] = { 0 };
166
PUT_UINT64_BE(ctx->sha512_state[0], tmp_output, 0);
167
PUT_UINT64_BE(ctx->sha512_state[1], tmp_output, 8);
168
PUT_UINT64_BE(ctx->sha512_state[2], tmp_output, 16);
169
PUT_UINT64_BE(ctx->sha512_state[3], tmp_output, 24);
170
PUT_UINT64_BE(ctx->sha512_state[4], tmp_output, 32);
171
PUT_UINT64_BE(ctx->sha512_state[5], tmp_output, 40);
172
PUT_UINT64_BE(ctx->sha512_state[6], tmp_output, 48);
173
PUT_UINT64_BE(ctx->sha512_state[7], tmp_output, 56);
174
ret = local_memcpy(output, tmp_output, output_size); EG(ret, err);
175
}
176
177
ret = 0;
178
179
err:
180
return ret;
181
}
182
183
#else /* defined(WITH_HASH_SHA512) || defined(WITH_HASH_SHA512_224) || defined(WITH_HASH_SHA512_256) */
184
185
/*
186
* Dummy definition to avoid the empty translation unit ISO C warning
187
*/
188
typedef int dummy;
189
#endif /* WITH_HASH_SHA512 */
190
191