1 /**********************************************************************
2 Copyright(c) 2011-2017 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #include <string.h>
31 #include "mh_sha256_internal.h"
32
33 ////////////////////////////////////////////////////////////////////////
34 ////////////////////////////////////////////////////////////////////////
35 // Macros and sub-functions which already exist in source code file
36 // (sha256_for_mh_sha256.c) is part of ISA-L library as internal functions.
37 // The reason why writing them twice is the linking issue caused by
38 // mh_sha256_ref(). mh_sha256_ref() needs these macros and sub-functions
39 // without linking ISA-L library. So mh_sha256_ref() includes them in
40 // order to contain essential sub-functions in its own object file.
41 ////////////////////////////////////////////////////////////////////////
42 ////////////////////////////////////////////////////////////////////////
43
44 #define W(x) w[(x) & 15]
45
46 #define step(i, a, b, c, d, e, f, g, h, k) \
47 if (i < 16) \
48 W(i) = to_be32(ww[i]); \
49 else \
50 W(i) = W(i - 16) + S0(W(i - 15)) + W(i - 7) + S1(W(i - 2)); \
51 t2 = s0(a) + maj(a, b, c); \
52 t1 = h + s1(e) + ch(e, f, g) + k + W(i); \
53 d += t1; \
54 h = t1 + t2;
55
56 void
sha256_single_for_mh_sha256_ref(const uint8_t * data,uint32_t digest[])57 sha256_single_for_mh_sha256_ref(const uint8_t *data, uint32_t digest[])
58 {
59 uint32_t a, b, c, d, e, f, g, h, t1, t2;
60 uint32_t w[16];
61 uint32_t *ww = (uint32_t *) data;
62
63 a = digest[0];
64 b = digest[1];
65 c = digest[2];
66 d = digest[3];
67 e = digest[4];
68 f = digest[5];
69 g = digest[6];
70 h = digest[7];
71
72 step(0, a, b, c, d, e, f, g, h, 0x428a2f98);
73 step(1, h, a, b, c, d, e, f, g, 0x71374491);
74 step(2, g, h, a, b, c, d, e, f, 0xb5c0fbcf);
75 step(3, f, g, h, a, b, c, d, e, 0xe9b5dba5);
76 step(4, e, f, g, h, a, b, c, d, 0x3956c25b);
77 step(5, d, e, f, g, h, a, b, c, 0x59f111f1);
78 step(6, c, d, e, f, g, h, a, b, 0x923f82a4);
79 step(7, b, c, d, e, f, g, h, a, 0xab1c5ed5);
80 step(8, a, b, c, d, e, f, g, h, 0xd807aa98);
81 step(9, h, a, b, c, d, e, f, g, 0x12835b01);
82 step(10, g, h, a, b, c, d, e, f, 0x243185be);
83 step(11, f, g, h, a, b, c, d, e, 0x550c7dc3);
84 step(12, e, f, g, h, a, b, c, d, 0x72be5d74);
85 step(13, d, e, f, g, h, a, b, c, 0x80deb1fe);
86 step(14, c, d, e, f, g, h, a, b, 0x9bdc06a7);
87 step(15, b, c, d, e, f, g, h, a, 0xc19bf174);
88 step(16, a, b, c, d, e, f, g, h, 0xe49b69c1);
89 step(17, h, a, b, c, d, e, f, g, 0xefbe4786);
90 step(18, g, h, a, b, c, d, e, f, 0x0fc19dc6);
91 step(19, f, g, h, a, b, c, d, e, 0x240ca1cc);
92 step(20, e, f, g, h, a, b, c, d, 0x2de92c6f);
93 step(21, d, e, f, g, h, a, b, c, 0x4a7484aa);
94 step(22, c, d, e, f, g, h, a, b, 0x5cb0a9dc);
95 step(23, b, c, d, e, f, g, h, a, 0x76f988da);
96 step(24, a, b, c, d, e, f, g, h, 0x983e5152);
97 step(25, h, a, b, c, d, e, f, g, 0xa831c66d);
98 step(26, g, h, a, b, c, d, e, f, 0xb00327c8);
99 step(27, f, g, h, a, b, c, d, e, 0xbf597fc7);
100 step(28, e, f, g, h, a, b, c, d, 0xc6e00bf3);
101 step(29, d, e, f, g, h, a, b, c, 0xd5a79147);
102 step(30, c, d, e, f, g, h, a, b, 0x06ca6351);
103 step(31, b, c, d, e, f, g, h, a, 0x14292967);
104 step(32, a, b, c, d, e, f, g, h, 0x27b70a85);
105 step(33, h, a, b, c, d, e, f, g, 0x2e1b2138);
106 step(34, g, h, a, b, c, d, e, f, 0x4d2c6dfc);
107 step(35, f, g, h, a, b, c, d, e, 0x53380d13);
108 step(36, e, f, g, h, a, b, c, d, 0x650a7354);
109 step(37, d, e, f, g, h, a, b, c, 0x766a0abb);
110 step(38, c, d, e, f, g, h, a, b, 0x81c2c92e);
111 step(39, b, c, d, e, f, g, h, a, 0x92722c85);
112 step(40, a, b, c, d, e, f, g, h, 0xa2bfe8a1);
113 step(41, h, a, b, c, d, e, f, g, 0xa81a664b);
114 step(42, g, h, a, b, c, d, e, f, 0xc24b8b70);
115 step(43, f, g, h, a, b, c, d, e, 0xc76c51a3);
116 step(44, e, f, g, h, a, b, c, d, 0xd192e819);
117 step(45, d, e, f, g, h, a, b, c, 0xd6990624);
118 step(46, c, d, e, f, g, h, a, b, 0xf40e3585);
119 step(47, b, c, d, e, f, g, h, a, 0x106aa070);
120 step(48, a, b, c, d, e, f, g, h, 0x19a4c116);
121 step(49, h, a, b, c, d, e, f, g, 0x1e376c08);
122 step(50, g, h, a, b, c, d, e, f, 0x2748774c);
123 step(51, f, g, h, a, b, c, d, e, 0x34b0bcb5);
124 step(52, e, f, g, h, a, b, c, d, 0x391c0cb3);
125 step(53, d, e, f, g, h, a, b, c, 0x4ed8aa4a);
126 step(54, c, d, e, f, g, h, a, b, 0x5b9cca4f);
127 step(55, b, c, d, e, f, g, h, a, 0x682e6ff3);
128 step(56, a, b, c, d, e, f, g, h, 0x748f82ee);
129 step(57, h, a, b, c, d, e, f, g, 0x78a5636f);
130 step(58, g, h, a, b, c, d, e, f, 0x84c87814);
131 step(59, f, g, h, a, b, c, d, e, 0x8cc70208);
132 step(60, e, f, g, h, a, b, c, d, 0x90befffa);
133 step(61, d, e, f, g, h, a, b, c, 0xa4506ceb);
134 step(62, c, d, e, f, g, h, a, b, 0xbef9a3f7);
135 step(63, b, c, d, e, f, g, h, a, 0xc67178f2);
136
137 digest[0] += a;
138 digest[1] += b;
139 digest[2] += c;
140 digest[3] += d;
141 digest[4] += e;
142 digest[5] += f;
143 digest[6] += g;
144 digest[7] += h;
145 }
146
147 void
sha256_for_mh_sha256_ref(const uint8_t * input_data,uint32_t * digest,const uint32_t len)148 sha256_for_mh_sha256_ref(const uint8_t *input_data, uint32_t *digest, const uint32_t len)
149 {
150 uint32_t i, j;
151 uint8_t buf[2 * ISAL_SHA256_BLOCK_SIZE];
152
153 digest[0] = MH_SHA256_H0;
154 digest[1] = MH_SHA256_H1;
155 digest[2] = MH_SHA256_H2;
156 digest[3] = MH_SHA256_H3;
157 digest[4] = MH_SHA256_H4;
158 digest[5] = MH_SHA256_H5;
159 digest[6] = MH_SHA256_H6;
160 digest[7] = MH_SHA256_H7;
161
162 i = len;
163 while (i >= ISAL_SHA256_BLOCK_SIZE) {
164 sha256_single_for_mh_sha256_ref(input_data, digest);
165 input_data += ISAL_SHA256_BLOCK_SIZE;
166 i -= ISAL_SHA256_BLOCK_SIZE;
167 }
168
169 memcpy(buf, input_data, i);
170 buf[i++] = 0x80;
171 for (j = i; j < ((2 * ISAL_SHA256_BLOCK_SIZE) - 8); j++)
172 buf[j] = 0;
173
174 if (i > ISAL_SHA256_BLOCK_SIZE - 8)
175 i = 2 * ISAL_SHA256_BLOCK_SIZE;
176 else
177 i = ISAL_SHA256_BLOCK_SIZE;
178
179 *(uint64_t *) (buf + i - 8) = to_be64((uint64_t) len * 8);
180
181 sha256_single_for_mh_sha256_ref(buf, digest);
182 if (i == (2 * ISAL_SHA256_BLOCK_SIZE))
183 sha256_single_for_mh_sha256_ref(buf + ISAL_SHA256_BLOCK_SIZE, digest);
184 }
185
186 /*
187 * buffer to rearrange one segment data from one block.
188 *
189 * Layout of new_data:
190 * segment
191 * -------------------------
192 * w0 | w1 | ... | w15
193 *
194 */
195 static inline void
transform_input_single(uint32_t * new_data,uint32_t * input,uint32_t segment)196 transform_input_single(uint32_t *new_data, uint32_t *input, uint32_t segment)
197 {
198 new_data[16 * segment + 0] = input[16 * 0 + segment];
199 new_data[16 * segment + 1] = input[16 * 1 + segment];
200 new_data[16 * segment + 2] = input[16 * 2 + segment];
201 new_data[16 * segment + 3] = input[16 * 3 + segment];
202 new_data[16 * segment + 4] = input[16 * 4 + segment];
203 new_data[16 * segment + 5] = input[16 * 5 + segment];
204 new_data[16 * segment + 6] = input[16 * 6 + segment];
205 new_data[16 * segment + 7] = input[16 * 7 + segment];
206 new_data[16 * segment + 8] = input[16 * 8 + segment];
207 new_data[16 * segment + 9] = input[16 * 9 + segment];
208 new_data[16 * segment + 10] = input[16 * 10 + segment];
209 new_data[16 * segment + 11] = input[16 * 11 + segment];
210 new_data[16 * segment + 12] = input[16 * 12 + segment];
211 new_data[16 * segment + 13] = input[16 * 13 + segment];
212 new_data[16 * segment + 14] = input[16 * 14 + segment];
213 new_data[16 * segment + 15] = input[16 * 15 + segment];
214 }
215
216 // Adapt parameters to sha256_single_for_mh_sha256_ref
217 #define sha256_update_one_seg(data, digest) \
218 sha256_single_for_mh_sha256_ref((const uint8_t *) (data), (uint32_t *) (digest))
219
220 /*
221 * buffer to Rearrange all segments data from one block.
222 *
223 * Layout of new_data:
224 * segment
225 * -------------------------
226 * seg0: | w0 | w1 | ... | w15
227 * seg1: | w0 | w1 | ... | w15
228 * seg2: | w0 | w1 | ... | w15
229 * ....
230 * seg15: | w0 | w1 | ... | w15
231 *
232 */
233 static inline void
transform_input(uint32_t * new_data,uint32_t * input,uint32_t block)234 transform_input(uint32_t *new_data, uint32_t *input, uint32_t block)
235 {
236 uint32_t *current_input = input + block * ISAL_MH_SHA256_BLOCK_SIZE / 4;
237
238 transform_input_single(new_data, current_input, 0);
239 transform_input_single(new_data, current_input, 1);
240 transform_input_single(new_data, current_input, 2);
241 transform_input_single(new_data, current_input, 3);
242 transform_input_single(new_data, current_input, 4);
243 transform_input_single(new_data, current_input, 5);
244 transform_input_single(new_data, current_input, 6);
245 transform_input_single(new_data, current_input, 7);
246 transform_input_single(new_data, current_input, 8);
247 transform_input_single(new_data, current_input, 9);
248 transform_input_single(new_data, current_input, 10);
249 transform_input_single(new_data, current_input, 11);
250 transform_input_single(new_data, current_input, 12);
251 transform_input_single(new_data, current_input, 13);
252 transform_input_single(new_data, current_input, 14);
253 transform_input_single(new_data, current_input, 15);
254 }
255
256 /*
257 * buffer to Calculate all segments' digests from one block.
258 *
259 * Layout of seg_digest:
260 * segment
261 * -------------------------
262 * seg0: | H0 | H1 | ... | H7
263 * seg1: | H0 | H1 | ... | H7
264 * seg2: | H0 | H1 | ... | H7
265 * ....
266 * seg15: | H0 | H1 | ... | H7
267 *
268 */
269 static inline void
sha256_update_all_segs(uint32_t * new_data,uint32_t (* mh_sha256_seg_digests)[ISAL_SHA256_DIGEST_WORDS])270 sha256_update_all_segs(uint32_t *new_data,
271 uint32_t (*mh_sha256_seg_digests)[ISAL_SHA256_DIGEST_WORDS])
272 {
273 sha256_update_one_seg(&(new_data)[16 * 0], mh_sha256_seg_digests[0]);
274 sha256_update_one_seg(&(new_data)[16 * 1], mh_sha256_seg_digests[1]);
275 sha256_update_one_seg(&(new_data)[16 * 2], mh_sha256_seg_digests[2]);
276 sha256_update_one_seg(&(new_data)[16 * 3], mh_sha256_seg_digests[3]);
277 sha256_update_one_seg(&(new_data)[16 * 4], mh_sha256_seg_digests[4]);
278 sha256_update_one_seg(&(new_data)[16 * 5], mh_sha256_seg_digests[5]);
279 sha256_update_one_seg(&(new_data)[16 * 6], mh_sha256_seg_digests[6]);
280 sha256_update_one_seg(&(new_data)[16 * 7], mh_sha256_seg_digests[7]);
281 sha256_update_one_seg(&(new_data)[16 * 8], mh_sha256_seg_digests[8]);
282 sha256_update_one_seg(&(new_data)[16 * 9], mh_sha256_seg_digests[9]);
283 sha256_update_one_seg(&(new_data)[16 * 10], mh_sha256_seg_digests[10]);
284 sha256_update_one_seg(&(new_data)[16 * 11], mh_sha256_seg_digests[11]);
285 sha256_update_one_seg(&(new_data)[16 * 12], mh_sha256_seg_digests[12]);
286 sha256_update_one_seg(&(new_data)[16 * 13], mh_sha256_seg_digests[13]);
287 sha256_update_one_seg(&(new_data)[16 * 14], mh_sha256_seg_digests[14]);
288 sha256_update_one_seg(&(new_data)[16 * 15], mh_sha256_seg_digests[15]);
289 }
290
291 void
mh_sha256_block_ref(const uint8_t * input_data,uint32_t (* digests)[ISAL_HASH_SEGS],uint8_t frame_buffer[ISAL_MH_SHA256_BLOCK_SIZE],uint32_t num_blocks)292 mh_sha256_block_ref(const uint8_t *input_data, uint32_t (*digests)[ISAL_HASH_SEGS],
293 uint8_t frame_buffer[ISAL_MH_SHA256_BLOCK_SIZE], uint32_t num_blocks)
294 {
295 uint32_t i, j;
296 uint32_t *temp_buffer = (uint32_t *) frame_buffer;
297 uint32_t(*trans_digests)[ISAL_SHA256_DIGEST_WORDS];
298
299 trans_digests = (uint32_t(*)[ISAL_SHA256_DIGEST_WORDS]) digests;
300
301 // Re-structure seg_digests from 5*16 to 16*5
302 for (j = 0; j < ISAL_HASH_SEGS; j++) {
303 for (i = 0; i < ISAL_SHA256_DIGEST_WORDS; i++) {
304 temp_buffer[j * ISAL_SHA256_DIGEST_WORDS + i] = digests[i][j];
305 }
306 }
307 memcpy(trans_digests, temp_buffer, 4 * ISAL_SHA256_DIGEST_WORDS * ISAL_HASH_SEGS);
308
309 // Calculate digests for all segments, leveraging sha256 API
310 for (i = 0; i < num_blocks; i++) {
311 transform_input(temp_buffer, (uint32_t *) input_data, i);
312 sha256_update_all_segs(temp_buffer, trans_digests);
313 }
314
315 // Re-structure seg_digests from 16*5 to 5*16
316 for (j = 0; j < ISAL_HASH_SEGS; j++) {
317 for (i = 0; i < ISAL_SHA256_DIGEST_WORDS; i++) {
318 temp_buffer[i * ISAL_HASH_SEGS + j] = trans_digests[j][i];
319 }
320 }
321 memcpy(digests, temp_buffer, 4 * ISAL_SHA256_DIGEST_WORDS * ISAL_HASH_SEGS);
322
323 return;
324 }
325
326 void
mh_sha256_tail_ref(uint8_t * partial_buffer,uint32_t total_len,uint32_t (* mh_sha256_segs_digests)[ISAL_HASH_SEGS],uint8_t * frame_buffer,uint32_t digests[ISAL_SHA256_DIGEST_WORDS])327 mh_sha256_tail_ref(uint8_t *partial_buffer, uint32_t total_len,
328 uint32_t (*mh_sha256_segs_digests)[ISAL_HASH_SEGS], uint8_t *frame_buffer,
329 uint32_t digests[ISAL_SHA256_DIGEST_WORDS])
330 {
331 uint64_t partial_buffer_len, len_in_bit;
332
333 partial_buffer_len = total_len % ISAL_MH_SHA256_BLOCK_SIZE;
334
335 // Padding the first block
336 partial_buffer[partial_buffer_len] = 0x80;
337 partial_buffer_len++;
338 memset(partial_buffer + partial_buffer_len, 0,
339 ISAL_MH_SHA256_BLOCK_SIZE - partial_buffer_len);
340
341 // Calculate the first block without total_length if padding needs 2 block
342 if (partial_buffer_len > (ISAL_MH_SHA256_BLOCK_SIZE - 8)) {
343 mh_sha256_block_ref(partial_buffer, mh_sha256_segs_digests, frame_buffer, 1);
344 // Padding the second block
345 memset(partial_buffer, 0, ISAL_MH_SHA256_BLOCK_SIZE);
346 }
347 // Padding the block
348 len_in_bit = to_be64((uint64_t) total_len * 8);
349 *(uint64_t *) (partial_buffer + ISAL_MH_SHA256_BLOCK_SIZE - 8) = len_in_bit;
350 mh_sha256_block_ref(partial_buffer, mh_sha256_segs_digests, frame_buffer, 1);
351
352 // Calculate multi-hash SHA256 digests (segment digests as input message)
353 sha256_for_mh_sha256_ref((uint8_t *) mh_sha256_segs_digests, digests,
354 4 * ISAL_SHA256_DIGEST_WORDS * ISAL_HASH_SEGS);
355
356 return;
357 }
358
359 void
mh_sha256_ref(const void * buffer,uint32_t len,uint32_t * mh_sha256_digest)360 mh_sha256_ref(const void *buffer, uint32_t len, uint32_t *mh_sha256_digest)
361 {
362 uint64_t total_len;
363 uint32_t num_blocks, mh_sha256_segs_digests[ISAL_SHA256_DIGEST_WORDS][ISAL_HASH_SEGS];
364 uint8_t frame_buffer[ISAL_MH_SHA256_BLOCK_SIZE];
365 uint8_t partial_block_buffer[ISAL_MH_SHA256_BLOCK_SIZE * 2];
366 uint32_t mh_sha256_hash_dword[ISAL_SHA256_DIGEST_WORDS];
367 uint32_t i;
368 const uint8_t *input_data = (const uint8_t *) buffer;
369
370 /* Initialize digests of all segments */
371 for (i = 0; i < ISAL_HASH_SEGS; i++) {
372 mh_sha256_segs_digests[0][i] = MH_SHA256_H0;
373 mh_sha256_segs_digests[1][i] = MH_SHA256_H1;
374 mh_sha256_segs_digests[2][i] = MH_SHA256_H2;
375 mh_sha256_segs_digests[3][i] = MH_SHA256_H3;
376 mh_sha256_segs_digests[4][i] = MH_SHA256_H4;
377 mh_sha256_segs_digests[5][i] = MH_SHA256_H5;
378 mh_sha256_segs_digests[6][i] = MH_SHA256_H6;
379 mh_sha256_segs_digests[7][i] = MH_SHA256_H7;
380 }
381
382 total_len = len;
383
384 // Calculate blocks
385 num_blocks = len / ISAL_MH_SHA256_BLOCK_SIZE;
386 if (num_blocks > 0) {
387 // do num_blocks process
388 mh_sha256_block_ref(input_data, mh_sha256_segs_digests, frame_buffer, num_blocks);
389 len -= num_blocks * ISAL_MH_SHA256_BLOCK_SIZE;
390 input_data += num_blocks * ISAL_MH_SHA256_BLOCK_SIZE;
391 }
392 // Store the partial block
393 if (len != 0) {
394 memcpy(partial_block_buffer, input_data, len);
395 }
396
397 /* Finalize */
398 mh_sha256_tail_ref(partial_block_buffer, (uint32_t) total_len, mh_sha256_segs_digests,
399 frame_buffer, mh_sha256_hash_dword);
400
401 // Output the digests of mh_sha256
402 if (mh_sha256_digest != NULL) {
403 mh_sha256_digest[0] = mh_sha256_hash_dword[0];
404 mh_sha256_digest[1] = mh_sha256_hash_dword[1];
405 mh_sha256_digest[2] = mh_sha256_hash_dword[2];
406 mh_sha256_digest[3] = mh_sha256_hash_dword[3];
407 mh_sha256_digest[4] = mh_sha256_hash_dword[4];
408 mh_sha256_digest[5] = mh_sha256_hash_dword[5];
409 mh_sha256_digest[6] = mh_sha256_hash_dword[6];
410 mh_sha256_digest[7] = mh_sha256_hash_dword[7];
411 }
412
413 return;
414 }
415