xref: /isa-l_crypto/sha1_mb/sha1_ctx_base.c (revision 8cb7fe780eac8ee5f1e0aa3ca37466e89c673ccd)
1 /**********************************************************************
2   Copyright(c) 2011-2016 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 <stdint.h>
31 #include <string.h>
32 #include "sha1_mb_internal.h"
33 #include "memcpy_inline.h"
34 #include "endian_helper.h"
35 
36 #ifdef _MSC_VER
37 #include <intrin.h>
38 #define inline __inline
39 #endif
40 
41 #if (__GNUC__ >= 11)
42 #define OPT_FIX __attribute__((noipa))
43 #else
44 #define OPT_FIX
45 #endif
46 
47 #define F1(b, c, d) (d ^ (b & (c ^ d)))
48 #define F2(b, c, d) (b ^ c ^ d)
49 #define F3(b, c, d) ((b & c) | (d & (b | c)))
50 #define F4(b, c, d) (b ^ c ^ d)
51 
52 #define rol32(x, r) (((x) << (r)) ^ ((x) >> (32 - (r))))
53 
54 #define W(x) w[(x) & 15]
55 
56 #define step00_19(i, a, b, c, d, e)                                                                \
57         if (i > 15)                                                                                \
58                 W(i) = rol32(W(i - 3) ^ W(i - 8) ^ W(i - 14) ^ W(i - 16), 1);                      \
59         else                                                                                       \
60                 W(i) = to_be32(ww[i]);                                                             \
61         e += rol32(a, 5) + F1(b, c, d) + 0x5A827999 + W(i);                                        \
62         b = rol32(b, 30)
63 
64 #define step20_39(i, a, b, c, d, e)                                                                \
65         W(i) = rol32(W(i - 3) ^ W(i - 8) ^ W(i - 14) ^ W(i - 16), 1);                              \
66         e += rol32(a, 5) + F2(b, c, d) + 0x6ED9EBA1 + W(i);                                        \
67         b = rol32(b, 30)
68 
69 #define step40_59(i, a, b, c, d, e)                                                                \
70         W(i) = rol32(W(i - 3) ^ W(i - 8) ^ W(i - 14) ^ W(i - 16), 1);                              \
71         e += rol32(a, 5) + F3(b, c, d) + 0x8F1BBCDC + W(i);                                        \
72         b = rol32(b, 30)
73 
74 #define step60_79(i, a, b, c, d, e)                                                                \
75         W(i) = rol32(W(i - 3) ^ W(i - 8) ^ W(i - 14) ^ W(i - 16), 1);                              \
76         e += rol32(a, 5) + F4(b, c, d) + 0xCA62C1D6 + W(i);                                        \
77         b = rol32(b, 30)
78 
79 static void
80 sha1_init(ISAL_SHA1_HASH_CTX *ctx, const void *buffer, uint32_t len);
81 static void
82 sha1_update(ISAL_SHA1_HASH_CTX *ctx, const void *buffer, uint32_t len);
83 static void
84 sha1_final(ISAL_SHA1_HASH_CTX *ctx);
85 static void OPT_FIX
86 sha1_single(const void *data, uint32_t digest[]);
87 static inline void
88 hash_init_digest(ISAL_SHA1_WORD_T *digest);
89 
90 void
_sha1_ctx_mgr_init_base(ISAL_SHA1_HASH_CTX_MGR * mgr)91 _sha1_ctx_mgr_init_base(ISAL_SHA1_HASH_CTX_MGR *mgr)
92 {
93 }
94 
95 ISAL_SHA1_HASH_CTX *
_sha1_ctx_mgr_submit_base(ISAL_SHA1_HASH_CTX_MGR * mgr,ISAL_SHA1_HASH_CTX * ctx,const void * buffer,uint32_t len,ISAL_HASH_CTX_FLAG flags)96 _sha1_ctx_mgr_submit_base(ISAL_SHA1_HASH_CTX_MGR *mgr, ISAL_SHA1_HASH_CTX *ctx, const void *buffer,
97                           uint32_t len, ISAL_HASH_CTX_FLAG flags)
98 {
99 
100         if (flags & (~ISAL_HASH_ENTIRE)) {
101                 // User should not pass anything other than FIRST, UPDATE, or LAST
102                 ctx->error = ISAL_HASH_CTX_ERROR_INVALID_FLAGS;
103                 return ctx;
104         }
105 
106         if ((ctx->status & ISAL_HASH_CTX_STS_PROCESSING) && (flags == ISAL_HASH_ENTIRE)) {
107                 // Cannot submit a new entire job to a currently processing job.
108                 ctx->error = ISAL_HASH_CTX_ERROR_ALREADY_PROCESSING;
109                 return ctx;
110         }
111 
112         if ((ctx->status & ISAL_HASH_CTX_STS_COMPLETE) && !(flags & ISAL_HASH_FIRST)) {
113                 // Cannot update a finished job.
114                 ctx->error = ISAL_HASH_CTX_ERROR_ALREADY_COMPLETED;
115                 return ctx;
116         }
117 
118         if (flags == ISAL_HASH_FIRST) {
119 
120                 sha1_init(ctx, buffer, len);
121                 sha1_update(ctx, buffer, len);
122         }
123 
124         if (flags == ISAL_HASH_UPDATE) {
125                 sha1_update(ctx, buffer, len);
126         }
127 
128         if (flags == ISAL_HASH_LAST) {
129                 sha1_update(ctx, buffer, len);
130                 sha1_final(ctx);
131         }
132 
133         if (flags == ISAL_HASH_ENTIRE) {
134                 sha1_init(ctx, buffer, len);
135                 sha1_update(ctx, buffer, len);
136                 sha1_final(ctx);
137         }
138 
139         return ctx;
140 }
141 
142 ISAL_SHA1_HASH_CTX *
_sha1_ctx_mgr_flush_base(ISAL_SHA1_HASH_CTX_MGR * mgr)143 _sha1_ctx_mgr_flush_base(ISAL_SHA1_HASH_CTX_MGR *mgr)
144 {
145         return NULL;
146 }
147 
148 static void
sha1_init(ISAL_SHA1_HASH_CTX * ctx,const void * buffer,uint32_t len)149 sha1_init(ISAL_SHA1_HASH_CTX *ctx, const void *buffer, uint32_t len)
150 {
151         // Init digest
152         hash_init_digest(ctx->job.result_digest);
153 
154         // Reset byte counter
155         ctx->total_length = 0;
156 
157         // Clear extra blocks
158         ctx->partial_block_buffer_length = 0;
159 
160         // If we made it here, there were no errors during this call to submit
161         ctx->error = ISAL_HASH_CTX_ERROR_NONE;
162 
163         // Mark it as processing
164         ctx->status = ISAL_HASH_CTX_STS_PROCESSING;
165 }
166 
167 static void
sha1_update(ISAL_SHA1_HASH_CTX * ctx,const void * buffer,uint32_t len)168 sha1_update(ISAL_SHA1_HASH_CTX *ctx, const void *buffer, uint32_t len)
169 {
170         uint32_t remain_len = len;
171         uint32_t *digest = ctx->job.result_digest;
172 
173         // Advance byte counter
174         ctx->total_length += len;
175 
176         // If there is anything currently buffered in the extra blocks, append to it until it
177         // contains a whole block. Or if the user's buffer contains less than a whole block, append
178         // as much as possible to the extra block.
179         if ((ctx->partial_block_buffer_length) | (remain_len < ISAL_SHA1_BLOCK_SIZE)) {
180                 // Compute how many bytes to copy from user buffer into extra block
181                 uint32_t copy_len = ISAL_SHA1_BLOCK_SIZE - ctx->partial_block_buffer_length;
182                 if (remain_len < copy_len) {
183                         copy_len = remain_len;
184                 }
185 
186                 if (copy_len) {
187                         // Copy and update relevant pointers and counters
188                         memcpy_fixedlen(
189                                 &ctx->partial_block_buffer[ctx->partial_block_buffer_length],
190                                 buffer, copy_len);
191 
192                         ctx->partial_block_buffer_length += copy_len;
193                         remain_len -= copy_len;
194                         buffer = (void *) ((uint8_t *) buffer + copy_len);
195                 }
196                 // The extra block should never contain more than 1 block here
197                 assert(ctx->partial_block_buffer_length <= ISAL_SHA1_BLOCK_SIZE);
198 
199                 // If the extra block buffer contains exactly 1 block, it can be hashed.
200                 if (ctx->partial_block_buffer_length >= ISAL_SHA1_BLOCK_SIZE) {
201                         ctx->partial_block_buffer_length = 0;
202                         sha1_single(ctx->partial_block_buffer, digest);
203                 }
204         }
205         // If the extra blocks are empty, begin hashing what remains in the user's buffer.
206         if (ctx->partial_block_buffer_length == 0) {
207                 while (remain_len >= ISAL_SHA1_BLOCK_SIZE) {
208                         sha1_single(buffer, digest);
209                         buffer = (void *) ((uint8_t *) buffer + ISAL_SHA1_BLOCK_SIZE);
210                         remain_len -= ISAL_SHA1_BLOCK_SIZE;
211                 }
212         }
213 
214         if (remain_len > 0) {
215                 memcpy_fixedlen(&ctx->partial_block_buffer, buffer, remain_len);
216                 ctx->partial_block_buffer_length = remain_len;
217         }
218 
219         ctx->status = ISAL_HASH_CTX_STS_IDLE;
220         return;
221 }
222 
223 static void
sha1_final(ISAL_SHA1_HASH_CTX * ctx)224 sha1_final(ISAL_SHA1_HASH_CTX *ctx)
225 {
226         const void *buffer = ctx->partial_block_buffer;
227         uint32_t i = ctx->partial_block_buffer_length;
228         uint8_t buf[2 * ISAL_SHA1_BLOCK_SIZE];
229         uint32_t *digest = ctx->job.result_digest;
230 
231         memcpy(buf, buffer, i);
232         buf[i++] = 0x80;
233         for (uint32_t j = i; j < (2 * ISAL_SHA1_BLOCK_SIZE); j++) {
234                 buf[j] = 0;
235         }
236 
237         if (i > ISAL_SHA1_BLOCK_SIZE - ISAL_SHA1_PADLENGTHFIELD_SIZE) {
238                 i = 2 * ISAL_SHA1_BLOCK_SIZE;
239         } else {
240                 i = ISAL_SHA1_BLOCK_SIZE;
241         }
242 
243         *(uint64_t *) (buf + i - 8) = to_be64((uint64_t) ctx->total_length * 8);
244 
245         sha1_single(buf, digest);
246         if (i == 2 * ISAL_SHA1_BLOCK_SIZE) {
247                 sha1_single(buf + ISAL_SHA1_BLOCK_SIZE, digest);
248         }
249 
250         ctx->status = ISAL_HASH_CTX_STS_COMPLETE;
251 }
252 
253 void
sha1_single(const void * data,uint32_t digest[])254 sha1_single(const void *data, uint32_t digest[])
255 {
256         uint32_t a, b, c, d, e;
257         uint32_t w[16] = { 0 };
258         uint32_t *ww = (uint32_t *) data;
259 
260         a = digest[0];
261         b = digest[1];
262         c = digest[2];
263         d = digest[3];
264         e = digest[4];
265 
266         step00_19(0, a, b, c, d, e);
267         step00_19(1, e, a, b, c, d);
268         step00_19(2, d, e, a, b, c);
269         step00_19(3, c, d, e, a, b);
270         step00_19(4, b, c, d, e, a);
271         step00_19(5, a, b, c, d, e);
272         step00_19(6, e, a, b, c, d);
273         step00_19(7, d, e, a, b, c);
274         step00_19(8, c, d, e, a, b);
275         step00_19(9, b, c, d, e, a);
276         step00_19(10, a, b, c, d, e);
277         step00_19(11, e, a, b, c, d);
278         step00_19(12, d, e, a, b, c);
279         step00_19(13, c, d, e, a, b);
280         step00_19(14, b, c, d, e, a);
281         step00_19(15, a, b, c, d, e);
282         step00_19(16, e, a, b, c, d);
283         step00_19(17, d, e, a, b, c);
284         step00_19(18, c, d, e, a, b);
285         step00_19(19, b, c, d, e, a);
286 
287         step20_39(20, a, b, c, d, e);
288         step20_39(21, e, a, b, c, d);
289         step20_39(22, d, e, a, b, c);
290         step20_39(23, c, d, e, a, b);
291         step20_39(24, b, c, d, e, a);
292         step20_39(25, a, b, c, d, e);
293         step20_39(26, e, a, b, c, d);
294         step20_39(27, d, e, a, b, c);
295         step20_39(28, c, d, e, a, b);
296         step20_39(29, b, c, d, e, a);
297         step20_39(30, a, b, c, d, e);
298         step20_39(31, e, a, b, c, d);
299         step20_39(32, d, e, a, b, c);
300         step20_39(33, c, d, e, a, b);
301         step20_39(34, b, c, d, e, a);
302         step20_39(35, a, b, c, d, e);
303         step20_39(36, e, a, b, c, d);
304         step20_39(37, d, e, a, b, c);
305         step20_39(38, c, d, e, a, b);
306         step20_39(39, b, c, d, e, a);
307 
308         step40_59(40, a, b, c, d, e);
309         step40_59(41, e, a, b, c, d);
310         step40_59(42, d, e, a, b, c);
311         step40_59(43, c, d, e, a, b);
312         step40_59(44, b, c, d, e, a);
313         step40_59(45, a, b, c, d, e);
314         step40_59(46, e, a, b, c, d);
315         step40_59(47, d, e, a, b, c);
316         step40_59(48, c, d, e, a, b);
317         step40_59(49, b, c, d, e, a);
318         step40_59(50, a, b, c, d, e);
319         step40_59(51, e, a, b, c, d);
320         step40_59(52, d, e, a, b, c);
321         step40_59(53, c, d, e, a, b);
322         step40_59(54, b, c, d, e, a);
323         step40_59(55, a, b, c, d, e);
324         step40_59(56, e, a, b, c, d);
325         step40_59(57, d, e, a, b, c);
326         step40_59(58, c, d, e, a, b);
327         step40_59(59, b, c, d, e, a);
328 
329         step60_79(60, a, b, c, d, e);
330         step60_79(61, e, a, b, c, d);
331         step60_79(62, d, e, a, b, c);
332         step60_79(63, c, d, e, a, b);
333         step60_79(64, b, c, d, e, a);
334         step60_79(65, a, b, c, d, e);
335         step60_79(66, e, a, b, c, d);
336         step60_79(67, d, e, a, b, c);
337         step60_79(68, c, d, e, a, b);
338         step60_79(69, b, c, d, e, a);
339         step60_79(70, a, b, c, d, e);
340         step60_79(71, e, a, b, c, d);
341         step60_79(72, d, e, a, b, c);
342         step60_79(73, c, d, e, a, b);
343         step60_79(74, b, c, d, e, a);
344         step60_79(75, a, b, c, d, e);
345         step60_79(76, e, a, b, c, d);
346         step60_79(77, d, e, a, b, c);
347         step60_79(78, c, d, e, a, b);
348         step60_79(79, b, c, d, e, a);
349 
350         digest[0] += a;
351         digest[1] += b;
352         digest[2] += c;
353         digest[3] += d;
354         digest[4] += e;
355 }
356 
357 static inline void
hash_init_digest(ISAL_SHA1_WORD_T * digest)358 hash_init_digest(ISAL_SHA1_WORD_T *digest)
359 {
360         static const ISAL_SHA1_WORD_T hash_initial_digest[ISAL_SHA1_DIGEST_NWORDS] = {
361                 ISAL_SHA1_INITIAL_DIGEST
362         };
363         memcpy_fixedlen(digest, hash_initial_digest, sizeof(hash_initial_digest));
364 }
365 
366 struct slver {
367         uint16_t snum;
368         uint8_t ver;
369         uint8_t core;
370 };
371 
372 struct slver _sha1_ctx_mgr_init_base_slver_00000192;
373 struct slver _sha1_ctx_mgr_init_base_slver = { 0x0192, 0x00, 0x00 };
374 
375 struct slver _sha1_ctx_mgr_submit_base_slver_00000193;
376 struct slver _sha1_ctx_mgr_submit_base_slver = { 0x0193, 0x00, 0x00 };
377 
378 struct slver _sha1_ctx_mgr_flush_base_slver_00000194;
379 struct slver _sha1_ctx_mgr_flush_base_slver = { 0x0194, 0x00, 0x00 };
380