xref: /isa-l_crypto/sha512_mb/sha512_ctx_base.c (revision 592e639e5cd0e9fa1a927dd7459a23176ec36070)
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 <string.h>
31  #include "sha512_mb_internal.h"
32  #include "memcpy_inline.h"
33  #include "endian_helper.h"
34  
35  #ifdef _MSC_VER
36  #include <intrin.h>
37  #define inline __inline
38  #endif
39  
40  /* From the FIPS, these are the same as for SHA256, but operating on 64 bit words
41   * instead of 32 bit.
42   */
43  #define ch(e, f, g)  ((e & f) ^ (g & ~e))
44  #define maj(a, b, c) ((a & b) ^ (a & c) ^ (b & c))
45  
46  /* Sigma functions have same form as SHA256 but
47   * 	- change the word size to 64bit
48   * 	- change the amount to rotate
49   */
50  #define ror64(x, r) (((x) >> (r)) ^ ((x) << (64 - (r))))
51  
52  /* Technically, s0 should be S0 as these are "capital sigma" functions, and likewise the case
53   * of the  S0 should be s0, but keep as-is to avoid confusion with the other reference functions.
54   */
55  #define s0(a) (ror64(a, 28) ^ ror64(a, 34) ^ ror64(a, 39))
56  #define s1(e) (ror64(e, 14) ^ ror64(e, 18) ^ ror64(e, 41))
57  
58  #define S0(w) (ror64(w, 1) ^ ror64(w, 8) ^ (w >> 7))
59  #define S1(w) (ror64(w, 19) ^ ror64(w, 61) ^ (w >> 6))
60  
61  #define W(x) w[(x) & 15]
62  
63  #define step(i, a, b, c, d, e, f, g, h, k)                                                         \
64          if (i < 16)                                                                                \
65                  W(i) = to_be64(ww[i]);                                                             \
66          else                                                                                       \
67                  W(i) = W(i - 16) + S0(W(i - 15)) + W(i - 7) + S1(W(i - 2));                        \
68          t2 = s0(a) + maj(a, b, c);                                                                 \
69          t1 = h + s1(e) + ch(e, f, g) + k + W(i);                                                   \
70          d += t1;                                                                                   \
71          h = t1 + t2;
72  
73  static void
74  sha512_init(ISAL_SHA512_HASH_CTX *ctx, const void *buffer, uint32_t len);
75  static void
76  sha512_update(ISAL_SHA512_HASH_CTX *ctx, const void *buffer, uint32_t len);
77  static void
78  sha512_final(ISAL_SHA512_HASH_CTX *ctx);
79  static void
80  sha512_single(const void *data, uint64_t digest[]);
81  static inline void
82  hash_init_digest(ISAL_SHA512_WORD_T *digest);
83  
84  void
_sha512_ctx_mgr_init_base(ISAL_SHA512_HASH_CTX_MGR * mgr)85  _sha512_ctx_mgr_init_base(ISAL_SHA512_HASH_CTX_MGR *mgr)
86  {
87  }
88  
89  ISAL_SHA512_HASH_CTX *
_sha512_ctx_mgr_submit_base(ISAL_SHA512_HASH_CTX_MGR * mgr,ISAL_SHA512_HASH_CTX * ctx,const void * buffer,uint32_t len,ISAL_HASH_CTX_FLAG flags)90  _sha512_ctx_mgr_submit_base(ISAL_SHA512_HASH_CTX_MGR *mgr, ISAL_SHA512_HASH_CTX *ctx,
91                              const void *buffer, uint32_t len, ISAL_HASH_CTX_FLAG flags)
92  {
93          if (flags & (~ISAL_HASH_ENTIRE)) {
94                  // User should not pass anything other than FIRST, UPDATE, or LAST
95                  ctx->error = ISAL_HASH_CTX_ERROR_INVALID_FLAGS;
96                  return ctx;
97          }
98  
99          if ((ctx->status & ISAL_HASH_CTX_STS_PROCESSING) && (flags == ISAL_HASH_ENTIRE)) {
100                  // Cannot submit a new entire job to a currently processing job.
101                  ctx->error = ISAL_HASH_CTX_ERROR_ALREADY_PROCESSING;
102                  return ctx;
103          }
104  
105          if ((ctx->status & ISAL_HASH_CTX_STS_COMPLETE) && !(flags & ISAL_HASH_FIRST)) {
106                  // Cannot update a finished job.
107                  ctx->error = ISAL_HASH_CTX_ERROR_ALREADY_COMPLETED;
108                  return ctx;
109          }
110  
111          if (flags == ISAL_HASH_FIRST) {
112  
113                  sha512_init(ctx, buffer, len);
114                  sha512_update(ctx, buffer, len);
115          }
116  
117          if (flags == ISAL_HASH_UPDATE) {
118                  sha512_update(ctx, buffer, len);
119          }
120  
121          if (flags == ISAL_HASH_LAST) {
122                  sha512_update(ctx, buffer, len);
123                  sha512_final(ctx);
124          }
125  
126          if (flags == ISAL_HASH_ENTIRE) {
127                  sha512_init(ctx, buffer, len);
128                  sha512_update(ctx, buffer, len);
129                  sha512_final(ctx);
130          }
131  
132          return ctx;
133  }
134  
135  ISAL_SHA512_HASH_CTX *
_sha512_ctx_mgr_flush_base(ISAL_SHA512_HASH_CTX_MGR * mgr)136  _sha512_ctx_mgr_flush_base(ISAL_SHA512_HASH_CTX_MGR *mgr)
137  {
138          return NULL;
139  }
140  
141  static void
sha512_init(ISAL_SHA512_HASH_CTX * ctx,const void * buffer,uint32_t len)142  sha512_init(ISAL_SHA512_HASH_CTX *ctx, const void *buffer, uint32_t len)
143  {
144          // Init digest
145          hash_init_digest(ctx->job.result_digest);
146  
147          // Reset byte counter
148          ctx->total_length = 0;
149  
150          // Clear extra blocks
151          ctx->partial_block_buffer_length = 0;
152  
153          // If we made it here, there were no errors during this call to submit
154          ctx->error = ISAL_HASH_CTX_ERROR_NONE;
155  
156          // Mark it as processing
157          ctx->status = ISAL_HASH_CTX_STS_PROCESSING;
158  }
159  
160  static void
sha512_update(ISAL_SHA512_HASH_CTX * ctx,const void * buffer,uint32_t len)161  sha512_update(ISAL_SHA512_HASH_CTX *ctx, const void *buffer, uint32_t len)
162  {
163          uint32_t remain_len = len;
164          uint64_t *digest = ctx->job.result_digest;
165  
166          // Advance byte counter
167          ctx->total_length += len;
168  
169          // If there is anything currently buffered in the extra blocks, append to it until it
170          // contains a whole block. Or if the user's buffer contains less than a whole block, append
171          // as much as possible to the extra block.
172          if ((ctx->partial_block_buffer_length) | (remain_len < ISAL_SHA512_BLOCK_SIZE)) {
173                  // Compute how many bytes to copy from user buffer into extra block
174                  uint32_t copy_len = ISAL_SHA512_BLOCK_SIZE - ctx->partial_block_buffer_length;
175                  if (remain_len < copy_len) {
176                          copy_len = remain_len;
177                  }
178  
179                  if (copy_len) {
180                          // Copy and update relevant pointers and counters
181                          memcpy(&ctx->partial_block_buffer[ctx->partial_block_buffer_length], buffer,
182                                 copy_len);
183  
184                          ctx->partial_block_buffer_length += copy_len;
185                          remain_len -= copy_len;
186                          buffer = (void *) ((uint8_t *) buffer + copy_len);
187                  }
188                  // The extra block should never contain more than 1 block here
189                  assert(ctx->partial_block_buffer_length <= ISAL_SHA512_BLOCK_SIZE);
190  
191                  // If the extra block buffer contains exactly 1 block, it can be hashed.
192                  if (ctx->partial_block_buffer_length >= ISAL_SHA512_BLOCK_SIZE) {
193                          ctx->partial_block_buffer_length = 0;
194                          sha512_single(ctx->partial_block_buffer, digest);
195                  }
196          }
197          // If the extra blocks are empty, begin hashing what remains in the user's buffer.
198          if (ctx->partial_block_buffer_length == 0) {
199                  while (remain_len >= ISAL_SHA512_BLOCK_SIZE) {
200                          sha512_single(buffer, digest);
201                          buffer = (void *) ((uint8_t *) buffer + ISAL_SHA512_BLOCK_SIZE);
202                          remain_len -= ISAL_SHA512_BLOCK_SIZE;
203                  }
204          }
205  
206          if (remain_len > 0) {
207                  memcpy(&ctx->partial_block_buffer, buffer, remain_len);
208                  ctx->partial_block_buffer_length = remain_len;
209          }
210  
211          ctx->status = ISAL_HASH_CTX_STS_IDLE;
212          return;
213  }
214  
215  static void
sha512_final(ISAL_SHA512_HASH_CTX * ctx)216  sha512_final(ISAL_SHA512_HASH_CTX *ctx)
217  {
218          const void *buffer = ctx->partial_block_buffer;
219          uint32_t i = ctx->partial_block_buffer_length;
220          uint8_t buf[2 * ISAL_SHA512_BLOCK_SIZE];
221          uint64_t *digest = ctx->job.result_digest;
222  
223          memcpy(buf, buffer, i);
224          buf[i++] = 0x80;
225          for (uint32_t j = i; j < (2 * ISAL_SHA512_BLOCK_SIZE); j++) {
226                  buf[j] = 0;
227          }
228  
229          if (i > ISAL_SHA512_BLOCK_SIZE - ISAL_SHA512_PADLENGTHFIELD_SIZE) {
230                  i = 2 * ISAL_SHA512_BLOCK_SIZE;
231          } else {
232                  i = ISAL_SHA512_BLOCK_SIZE;
233          }
234  
235          *(uint64_t *) (buf + i - 8) = to_be64((uint64_t) ctx->total_length * 8);
236  
237          sha512_single(buf, digest);
238          if (i == 2 * ISAL_SHA512_BLOCK_SIZE) {
239                  sha512_single(buf + ISAL_SHA512_BLOCK_SIZE, digest);
240          }
241  
242          ctx->status = ISAL_HASH_CTX_STS_COMPLETE;
243  }
244  
245  void
sha512_single(const void * data,uint64_t digest[])246  sha512_single(const void *data, uint64_t digest[])
247  {
248          /* Check these are all uint64_t */
249          uint64_t a, b, c, d, e, f, g, h, t1, t2;
250          uint64_t w[16];
251          uint64_t *ww = (uint64_t *) data;
252  
253          a = digest[0];
254          b = digest[1];
255          c = digest[2];
256          d = digest[3];
257          e = digest[4];
258          f = digest[5];
259          g = digest[6];
260          h = digest[7];
261  
262          step(0, a, b, c, d, e, f, g, h, 0x428a2f98d728ae22);
263          step(1, h, a, b, c, d, e, f, g, 0x7137449123ef65cd);
264          step(2, g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2f);
265          step(3, f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbc);
266          step(4, e, f, g, h, a, b, c, d, 0x3956c25bf348b538);
267          step(5, d, e, f, g, h, a, b, c, 0x59f111f1b605d019);
268          step(6, c, d, e, f, g, h, a, b, 0x923f82a4af194f9b);
269          step(7, b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118);
270          step(8, a, b, c, d, e, f, g, h, 0xd807aa98a3030242);
271          step(9, h, a, b, c, d, e, f, g, 0x12835b0145706fbe);
272          step(10, g, h, a, b, c, d, e, f, 0x243185be4ee4b28c);
273          step(11, f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2);
274          step(12, e, f, g, h, a, b, c, d, 0x72be5d74f27b896f);
275          step(13, d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1);
276          step(14, c, d, e, f, g, h, a, b, 0x9bdc06a725c71235);
277          step(15, b, c, d, e, f, g, h, a, 0xc19bf174cf692694);
278          step(16, a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2);
279          step(17, h, a, b, c, d, e, f, g, 0xefbe4786384f25e3);
280          step(18, g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5);
281          step(19, f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65);
282          step(20, e, f, g, h, a, b, c, d, 0x2de92c6f592b0275);
283          step(21, d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483);
284          step(22, c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4);
285          step(23, b, c, d, e, f, g, h, a, 0x76f988da831153b5);
286          step(24, a, b, c, d, e, f, g, h, 0x983e5152ee66dfab);
287          step(25, h, a, b, c, d, e, f, g, 0xa831c66d2db43210);
288          step(26, g, h, a, b, c, d, e, f, 0xb00327c898fb213f);
289          step(27, f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4);
290          step(28, e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2);
291          step(29, d, e, f, g, h, a, b, c, 0xd5a79147930aa725);
292          step(30, c, d, e, f, g, h, a, b, 0x06ca6351e003826f);
293          step(31, b, c, d, e, f, g, h, a, 0x142929670a0e6e70);
294          step(32, a, b, c, d, e, f, g, h, 0x27b70a8546d22ffc);
295          step(33, h, a, b, c, d, e, f, g, 0x2e1b21385c26c926);
296          step(34, g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aed);
297          step(35, f, g, h, a, b, c, d, e, 0x53380d139d95b3df);
298          step(36, e, f, g, h, a, b, c, d, 0x650a73548baf63de);
299          step(37, d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8);
300          step(38, c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6);
301          step(39, b, c, d, e, f, g, h, a, 0x92722c851482353b);
302          step(40, a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364);
303          step(41, h, a, b, c, d, e, f, g, 0xa81a664bbc423001);
304          step(42, g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791);
305          step(43, f, g, h, a, b, c, d, e, 0xc76c51a30654be30);
306          step(44, e, f, g, h, a, b, c, d, 0xd192e819d6ef5218);
307          step(45, d, e, f, g, h, a, b, c, 0xd69906245565a910);
308          step(46, c, d, e, f, g, h, a, b, 0xf40e35855771202a);
309          step(47, b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8);
310          step(48, a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8);
311          step(49, h, a, b, c, d, e, f, g, 0x1e376c085141ab53);
312          step(50, g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99);
313          step(51, f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8);
314          step(52, e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63);
315          step(53, d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acb);
316          step(54, c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373);
317          step(55, b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3);
318          step(56, a, b, c, d, e, f, g, h, 0x748f82ee5defb2fc);
319          step(57, h, a, b, c, d, e, f, g, 0x78a5636f43172f60);
320          step(58, g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72);
321          step(59, f, g, h, a, b, c, d, e, 0x8cc702081a6439ec);
322          step(60, e, f, g, h, a, b, c, d, 0x90befffa23631e28);
323          step(61, d, e, f, g, h, a, b, c, 0xa4506cebde82bde9);
324          step(62, c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915);
325          step(63, b, c, d, e, f, g, h, a, 0xc67178f2e372532b); // step 63
326          step(64, a, b, c, d, e, f, g, h, 0xca273eceea26619c);
327          step(65, h, a, b, c, d, e, f, g, 0xd186b8c721c0c207);
328          step(66, g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1e);
329          step(67, f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178);
330          step(68, e, f, g, h, a, b, c, d, 0x06f067aa72176fba);
331          step(69, d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6);
332          step(70, c, d, e, f, g, h, a, b, 0x113f9804bef90dae);
333          step(71, b, c, d, e, f, g, h, a, 0x1b710b35131c471b);
334          step(72, a, b, c, d, e, f, g, h, 0x28db77f523047d84);
335          step(73, h, a, b, c, d, e, f, g, 0x32caab7b40c72493);
336          step(74, g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebc);
337          step(75, f, g, h, a, b, c, d, e, 0x431d67c49c100d4c);
338          step(76, e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6);
339          step(77, d, e, f, g, h, a, b, c, 0x597f299cfc657e2a);
340          step(78, c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faec);
341          step(79, b, c, d, e, f, g, h, a, 0x6c44198c4a475817); // step 79
342  
343          digest[0] += a;
344          digest[1] += b;
345          digest[2] += c;
346          digest[3] += d;
347          digest[4] += e;
348          digest[5] += f;
349          digest[6] += g;
350          digest[7] += h;
351  }
352  
353  static inline void
hash_init_digest(ISAL_SHA512_WORD_T * digest)354  hash_init_digest(ISAL_SHA512_WORD_T *digest)
355  {
356          static const ISAL_SHA512_WORD_T hash_initial_digest[ISAL_SHA512_DIGEST_NWORDS] = {
357                  ISAL_SHA512_INITIAL_DIGEST
358          };
359          memcpy_fixedlen(digest, hash_initial_digest, sizeof(hash_initial_digest));
360  }
361  
362  struct slver {
363          uint16_t snum;
364          uint8_t ver;
365          uint8_t core;
366  };
367  struct slver sha512_ctx_mgr_init_base_slver_000002f3;
368  struct slver sha512_ctx_mgr_init_base_slver = { 0x02f3, 0x00, 0x00 };
369  
370  struct slver sha512_ctx_mgr_submit_base_slver_000002f4;
371  struct slver sha512_ctx_mgr_submit_base_slver = { 0x02f4, 0x00, 0x00 };
372  
373  struct slver sha512_ctx_mgr_flush_base_slver_000002f5;
374  struct slver sha512_ctx_mgr_flush_base_slver = { 0x02f5, 0x00, 0x00 };
375