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