xref: /freebsd/crypto/libecc/src/hash/sha512_core.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1 /*
2  *  Copyright (C) 2017 - 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  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8  *
9  *  Contributors:
10  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
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. */
sha512_core_process(sha512_core_context * ctx,const u8 data[SHA512_CORE_BLOCK_SIZE])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. */
sha512_core_update(sha512_core_context * ctx,const u8 * input,u32 ilen)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. */
sha512_core_final(sha512_core_context * ctx,u8 * output,u32 output_size)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