xref: /isa-l_crypto/mh_sha256/mh_sha256_ref.c (revision 228b4c8d752832b075901a0857f4eed11e8e25ff)
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
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
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 * 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 >= SHA256_BLOCK_SIZE) {
164                 sha256_single_for_mh_sha256_ref(input_data, digest);
165                 input_data += SHA256_BLOCK_SIZE;
166                 i -= SHA256_BLOCK_SIZE;
167         }
168 
169         memcpy(buf, input_data, i);
170         buf[i++] = 0x80;
171         for (j = i; j < ((2 * SHA256_BLOCK_SIZE) - 8); j++)
172                 buf[j] = 0;
173 
174         if (i > SHA256_BLOCK_SIZE - 8)
175                 i = 2 * SHA256_BLOCK_SIZE;
176         else
177                 i = 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 * SHA256_BLOCK_SIZE))
183                 sha256_single_for_mh_sha256_ref(buf + 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
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
234 transform_input(uint32_t *new_data, uint32_t *input, uint32_t block)
235 {
236         uint32_t *current_input = input + block * 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
270 sha256_update_all_segs(uint32_t *new_data, uint32_t (*mh_sha256_seg_digests)[SHA256_DIGEST_WORDS])
271 {
272         sha256_update_one_seg(&(new_data)[16 * 0], mh_sha256_seg_digests[0]);
273         sha256_update_one_seg(&(new_data)[16 * 1], mh_sha256_seg_digests[1]);
274         sha256_update_one_seg(&(new_data)[16 * 2], mh_sha256_seg_digests[2]);
275         sha256_update_one_seg(&(new_data)[16 * 3], mh_sha256_seg_digests[3]);
276         sha256_update_one_seg(&(new_data)[16 * 4], mh_sha256_seg_digests[4]);
277         sha256_update_one_seg(&(new_data)[16 * 5], mh_sha256_seg_digests[5]);
278         sha256_update_one_seg(&(new_data)[16 * 6], mh_sha256_seg_digests[6]);
279         sha256_update_one_seg(&(new_data)[16 * 7], mh_sha256_seg_digests[7]);
280         sha256_update_one_seg(&(new_data)[16 * 8], mh_sha256_seg_digests[8]);
281         sha256_update_one_seg(&(new_data)[16 * 9], mh_sha256_seg_digests[9]);
282         sha256_update_one_seg(&(new_data)[16 * 10], mh_sha256_seg_digests[10]);
283         sha256_update_one_seg(&(new_data)[16 * 11], mh_sha256_seg_digests[11]);
284         sha256_update_one_seg(&(new_data)[16 * 12], mh_sha256_seg_digests[12]);
285         sha256_update_one_seg(&(new_data)[16 * 13], mh_sha256_seg_digests[13]);
286         sha256_update_one_seg(&(new_data)[16 * 14], mh_sha256_seg_digests[14]);
287         sha256_update_one_seg(&(new_data)[16 * 15], mh_sha256_seg_digests[15]);
288 }
289 
290 void
291 mh_sha256_block_ref(const uint8_t *input_data, uint32_t (*digests)[HASH_SEGS],
292                     uint8_t frame_buffer[MH_SHA256_BLOCK_SIZE], uint32_t num_blocks)
293 {
294         uint32_t i, j;
295         uint32_t *temp_buffer = (uint32_t *) frame_buffer;
296         uint32_t(*trans_digests)[SHA256_DIGEST_WORDS];
297 
298         trans_digests = (uint32_t(*)[SHA256_DIGEST_WORDS]) digests;
299 
300         // Re-structure seg_digests from 5*16 to 16*5
301         for (j = 0; j < HASH_SEGS; j++) {
302                 for (i = 0; i < SHA256_DIGEST_WORDS; i++) {
303                         temp_buffer[j * SHA256_DIGEST_WORDS + i] = digests[i][j];
304                 }
305         }
306         memcpy(trans_digests, temp_buffer, 4 * SHA256_DIGEST_WORDS * HASH_SEGS);
307 
308         // Calculate digests for all segments, leveraging sha256 API
309         for (i = 0; i < num_blocks; i++) {
310                 transform_input(temp_buffer, (uint32_t *) input_data, i);
311                 sha256_update_all_segs(temp_buffer, trans_digests);
312         }
313 
314         // Re-structure seg_digests from 16*5 to 5*16
315         for (j = 0; j < HASH_SEGS; j++) {
316                 for (i = 0; i < SHA256_DIGEST_WORDS; i++) {
317                         temp_buffer[i * HASH_SEGS + j] = trans_digests[j][i];
318                 }
319         }
320         memcpy(digests, temp_buffer, 4 * SHA256_DIGEST_WORDS * HASH_SEGS);
321 
322         return;
323 }
324 
325 void
326 mh_sha256_tail_ref(uint8_t *partial_buffer, uint32_t total_len,
327                    uint32_t (*mh_sha256_segs_digests)[HASH_SEGS], uint8_t *frame_buffer,
328                    uint32_t digests[SHA256_DIGEST_WORDS])
329 {
330         uint64_t partial_buffer_len, len_in_bit;
331 
332         partial_buffer_len = total_len % MH_SHA256_BLOCK_SIZE;
333 
334         // Padding the first block
335         partial_buffer[partial_buffer_len] = 0x80;
336         partial_buffer_len++;
337         memset(partial_buffer + partial_buffer_len, 0, MH_SHA256_BLOCK_SIZE - partial_buffer_len);
338 
339         // Calculate the first block without total_length if padding needs 2 block
340         if (partial_buffer_len > (MH_SHA256_BLOCK_SIZE - 8)) {
341                 mh_sha256_block_ref(partial_buffer, mh_sha256_segs_digests, frame_buffer, 1);
342                 // Padding the second block
343                 memset(partial_buffer, 0, MH_SHA256_BLOCK_SIZE);
344         }
345         // Padding the block
346         len_in_bit = to_be64((uint64_t) total_len * 8);
347         *(uint64_t *) (partial_buffer + MH_SHA256_BLOCK_SIZE - 8) = len_in_bit;
348         mh_sha256_block_ref(partial_buffer, mh_sha256_segs_digests, frame_buffer, 1);
349 
350         // Calculate multi-hash SHA256 digests (segment digests as input message)
351         sha256_for_mh_sha256_ref((uint8_t *) mh_sha256_segs_digests, digests,
352                                  4 * SHA256_DIGEST_WORDS * HASH_SEGS);
353 
354         return;
355 }
356 
357 void
358 mh_sha256_ref(const void *buffer, uint32_t len, uint32_t *mh_sha256_digest)
359 {
360         uint64_t total_len;
361         uint64_t num_blocks;
362         uint32_t mh_sha256_segs_digests[SHA256_DIGEST_WORDS][HASH_SEGS];
363         uint8_t frame_buffer[MH_SHA256_BLOCK_SIZE];
364         uint8_t partial_block_buffer[MH_SHA256_BLOCK_SIZE * 2];
365         uint32_t mh_sha256_hash_dword[SHA256_DIGEST_WORDS];
366         uint32_t i;
367         const uint8_t *input_data = (const uint8_t *) buffer;
368 
369         /* Initialize digests of all segments */
370         for (i = 0; i < HASH_SEGS; i++) {
371                 mh_sha256_segs_digests[0][i] = MH_SHA256_H0;
372                 mh_sha256_segs_digests[1][i] = MH_SHA256_H1;
373                 mh_sha256_segs_digests[2][i] = MH_SHA256_H2;
374                 mh_sha256_segs_digests[3][i] = MH_SHA256_H3;
375                 mh_sha256_segs_digests[4][i] = MH_SHA256_H4;
376                 mh_sha256_segs_digests[5][i] = MH_SHA256_H5;
377                 mh_sha256_segs_digests[6][i] = MH_SHA256_H6;
378                 mh_sha256_segs_digests[7][i] = MH_SHA256_H7;
379         }
380 
381         total_len = len;
382 
383         // Calculate blocks
384         num_blocks = len / MH_SHA256_BLOCK_SIZE;
385         if (num_blocks > 0) {
386                 // do num_blocks process
387                 mh_sha256_block_ref(input_data, mh_sha256_segs_digests, frame_buffer, num_blocks);
388                 len -= num_blocks * MH_SHA256_BLOCK_SIZE;
389                 input_data += num_blocks * MH_SHA256_BLOCK_SIZE;
390         }
391         // Store the partial block
392         if (len != 0) {
393                 memcpy(partial_block_buffer, input_data, len);
394         }
395 
396         /* Finalize */
397         mh_sha256_tail_ref(partial_block_buffer, total_len, mh_sha256_segs_digests, frame_buffer,
398                            mh_sha256_hash_dword);
399 
400         // Output the digests of mh_sha256
401         if (mh_sha256_digest != NULL) {
402                 mh_sha256_digest[0] = mh_sha256_hash_dword[0];
403                 mh_sha256_digest[1] = mh_sha256_hash_dword[1];
404                 mh_sha256_digest[2] = mh_sha256_hash_dword[2];
405                 mh_sha256_digest[3] = mh_sha256_hash_dword[3];
406                 mh_sha256_digest[4] = mh_sha256_hash_dword[4];
407                 mh_sha256_digest[5] = mh_sha256_hash_dword[5];
408                 mh_sha256_digest[6] = mh_sha256_hash_dword[6];
409                 mh_sha256_digest[7] = mh_sha256_hash_dword[7];
410         }
411 
412         return;
413 }
414