Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/libecc/src/hash/sha256.c
34889 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
#ifdef WITH_HASH_SHA256
18
19
#include <libecc/hash/sha256.h>
20
21
/* SHA-2 core processing */
22
ATTRIBUTE_WARN_UNUSED_RET static int sha256_process(sha256_context *ctx,
23
const u8 data[SHA256_BLOCK_SIZE])
24
{
25
u32 a, b, c, d, e, f, g, h;
26
u32 W[64];
27
unsigned int i;
28
int ret;
29
30
MUST_HAVE((data != NULL), ret, err);
31
SHA256_HASH_CHECK_INITIALIZED(ctx, ret, err);
32
33
/* Init our inner variables */
34
a = ctx->sha256_state[0];
35
b = ctx->sha256_state[1];
36
c = ctx->sha256_state[2];
37
d = ctx->sha256_state[3];
38
e = ctx->sha256_state[4];
39
f = ctx->sha256_state[5];
40
g = ctx->sha256_state[6];
41
h = ctx->sha256_state[7];
42
43
for (i = 0; i < 16; i++) {
44
GET_UINT32_BE(W[i], data, 4 * i);
45
SHA2CORE_SHA256(a, b, c, d, e, f, g, h, W[i], K_SHA256[i]);
46
}
47
48
for (i = 16; i < 64; i++) {
49
SHA2CORE_SHA256(a, b, c, d, e, f, g, h, UPDATEW_SHA256(W, i),
50
K_SHA256[i]);
51
}
52
53
/* Update state */
54
ctx->sha256_state[0] += a;
55
ctx->sha256_state[1] += b;
56
ctx->sha256_state[2] += c;
57
ctx->sha256_state[3] += d;
58
ctx->sha256_state[4] += e;
59
ctx->sha256_state[5] += f;
60
ctx->sha256_state[6] += g;
61
ctx->sha256_state[7] += h;
62
63
ret = 0;
64
65
err:
66
return ret;
67
}
68
69
/* Init hash function */
70
int sha256_init(sha256_context *ctx)
71
{
72
int ret;
73
74
MUST_HAVE((ctx != NULL), ret, err);
75
76
ctx->sha256_total = 0;
77
ctx->sha256_state[0] = 0x6A09E667;
78
ctx->sha256_state[1] = 0xBB67AE85;
79
ctx->sha256_state[2] = 0x3C6EF372;
80
ctx->sha256_state[3] = 0xA54FF53A;
81
ctx->sha256_state[4] = 0x510E527F;
82
ctx->sha256_state[5] = 0x9B05688C;
83
ctx->sha256_state[6] = 0x1F83D9AB;
84
ctx->sha256_state[7] = 0x5BE0CD19;
85
86
/* Tell that we are initialized */
87
ctx->magic = SHA256_HASH_MAGIC;
88
89
ret = 0;
90
91
err:
92
return ret;
93
}
94
95
/* Update hash function */
96
int sha256_update(sha256_context *ctx, const u8 *input, u32 ilen)
97
{
98
const u8 *data_ptr = input;
99
u32 remain_ilen = ilen;
100
u16 fill;
101
u8 left;
102
int ret;
103
104
MUST_HAVE((input != NULL) || (ilen == 0), ret, err);
105
SHA256_HASH_CHECK_INITIALIZED(ctx, ret, err);
106
107
/* Nothing to process, return */
108
if (ilen == 0) {
109
ret = 0;
110
goto err;
111
}
112
113
/* Get what's left in our local buffer */
114
left = (ctx->sha256_total & 0x3F);
115
fill = (u16)(SHA256_BLOCK_SIZE - left);
116
117
ctx->sha256_total += ilen;
118
119
if ((left > 0) && (remain_ilen >= fill)) {
120
/* Copy data at the end of the buffer */
121
ret = local_memcpy(ctx->sha256_buffer + left, data_ptr, fill); EG(ret, err);
122
ret = sha256_process(ctx, ctx->sha256_buffer); EG(ret, err);
123
data_ptr += fill;
124
remain_ilen -= fill;
125
left = 0;
126
}
127
128
while (remain_ilen >= SHA256_BLOCK_SIZE) {
129
ret = sha256_process(ctx, data_ptr); EG(ret, err);
130
data_ptr += SHA256_BLOCK_SIZE;
131
remain_ilen -= SHA256_BLOCK_SIZE;
132
}
133
134
if (remain_ilen > 0) {
135
ret = local_memcpy(ctx->sha256_buffer + left, data_ptr, remain_ilen); EG(ret, err);
136
}
137
138
ret = 0;
139
140
err:
141
return ret;
142
}
143
144
/* Finalize */
145
int sha256_final(sha256_context *ctx, u8 output[SHA256_DIGEST_SIZE])
146
{
147
unsigned int block_present = 0;
148
u8 last_padded_block[2 * SHA256_BLOCK_SIZE];
149
int ret;
150
151
MUST_HAVE((output != NULL), ret, err);
152
SHA256_HASH_CHECK_INITIALIZED(ctx, ret, err);
153
154
/* Fill in our last block with zeroes */
155
ret = local_memset(last_padded_block, 0, sizeof(last_padded_block)); EG(ret, err);
156
157
/* This is our final step, so we proceed with the padding */
158
block_present = (ctx->sha256_total % SHA256_BLOCK_SIZE);
159
if (block_present != 0) {
160
/* Copy what's left in our temporary context buffer */
161
ret = local_memcpy(last_padded_block, ctx->sha256_buffer,
162
block_present); EG(ret, err);
163
}
164
165
/* Put the 0x80 byte, beginning of padding */
166
last_padded_block[block_present] = 0x80;
167
168
/* Handle possible additional block */
169
if (block_present > (SHA256_BLOCK_SIZE - 1 - sizeof(u64))) {
170
/* We need an additional block */
171
PUT_UINT64_BE(8 * ctx->sha256_total, last_padded_block,
172
(2 * SHA256_BLOCK_SIZE) - sizeof(u64));
173
ret = sha256_process(ctx, last_padded_block); EG(ret, err);
174
ret = sha256_process(ctx, last_padded_block + SHA256_BLOCK_SIZE); EG(ret, err);
175
} else {
176
/* We do not need an additional block */
177
PUT_UINT64_BE(8 * ctx->sha256_total, last_padded_block,
178
SHA256_BLOCK_SIZE - sizeof(u64));
179
ret = sha256_process(ctx, last_padded_block); EG(ret, err);
180
}
181
182
/* Output the hash result */
183
PUT_UINT32_BE(ctx->sha256_state[0], output, 0);
184
PUT_UINT32_BE(ctx->sha256_state[1], output, 4);
185
PUT_UINT32_BE(ctx->sha256_state[2], output, 8);
186
PUT_UINT32_BE(ctx->sha256_state[3], output, 12);
187
PUT_UINT32_BE(ctx->sha256_state[4], output, 16);
188
PUT_UINT32_BE(ctx->sha256_state[5], output, 20);
189
PUT_UINT32_BE(ctx->sha256_state[6], output, 24);
190
PUT_UINT32_BE(ctx->sha256_state[7], output, 28);
191
192
/* Tell that we are uninitialized */
193
ctx->magic = WORD(0);
194
195
ret = 0;
196
197
err:
198
return ret;
199
}
200
201
int sha256_scattered(const u8 **inputs, const u32 *ilens,
202
u8 output[SHA256_DIGEST_SIZE])
203
{
204
sha256_context ctx;
205
int ret, pos = 0;
206
207
MUST_HAVE((inputs != NULL) && (ilens != NULL) && (output != NULL), ret, err);
208
209
ret = sha256_init(&ctx); EG(ret, err);
210
211
while (inputs[pos] != NULL) {
212
ret = sha256_update(&ctx, inputs[pos], ilens[pos]); EG(ret, err);
213
pos += 1;
214
}
215
216
ret = sha256_final(&ctx, output);
217
218
err:
219
return ret;
220
}
221
222
int sha256(const u8 *input, u32 ilen, u8 output[SHA256_DIGEST_SIZE])
223
{
224
sha256_context ctx;
225
int ret;
226
227
ret = sha256_init(&ctx); EG(ret, err);
228
ret = sha256_update(&ctx, input, ilen); EG(ret, err);
229
ret = sha256_final(&ctx, output);
230
231
err:
232
return ret;
233
}
234
235
#else /* WITH_HASH_SHA256 */
236
237
/*
238
* Dummy definition to avoid the empty translation unit ISO C warning
239
*/
240
typedef int dummy;
241
#endif /* WITH_HASH_SHA256 */
242
243