xref: /isa-l_crypto/mh_sha256/mh_sha256_ref.c (revision 15f45959d342594afa975e58d4e7e8bbe34e2f0b)
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