xref: /isa-l_crypto/sm3_mb/sm3_mb_rand_update_test.c (revision 87dde3ad650cd28eb5a214cb0fb138f82da022dc)
1  /**********************************************************************
2    Copyright(c) 2011-2019 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  #define ISAL_UNIT_TEST
30  #include <stdio.h>
31  #include <stdlib.h>
32  #include "sm3_mb.h"
33  #include "endian_helper.h"
34  
35  #define TEST_LEN  (1024 * 1024)
36  #define TEST_BUFS 100
37  #ifndef RANDOMS
38  #define RANDOMS 10
39  #endif
40  #ifndef TEST_SEED
41  #define TEST_SEED 0x1234
42  #endif
43  
44  #define UPDATE_SIZE            13 * SM3_BLOCK_SIZE
45  #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * SM3_BLOCK_SIZE))
46  
47  #ifdef DEBUG
48  #define debug_char(x) putchar(x)
49  #else
50  #define debug_char(x)                                                                              \
51          do {                                                                                       \
52          } while (0)
53  #endif
54  
55  /* Reference digest global to reduce stack usage */
56  static uint8_t digest_ref[TEST_BUFS][4 * SM3_DIGEST_NWORDS];
57  extern void
58  sm3_ossl(const unsigned char *buf, size_t length, unsigned char *digest);
59  
60  // Generates pseudo-random data
61  static void
62  rand_buffer(unsigned char *buf, const long buffer_size)
63  {
64          long i;
65          for (i = 0; i < buffer_size; i++)
66                  buf[i] = rand();
67  }
68  
69  int
70  main(void)
71  {
72          SM3_HASH_CTX_MGR *mgr = NULL;
73          SM3_HASH_CTX ctxpool[TEST_BUFS], *ctx = NULL;
74          uint32_t i, j, fail = 0;
75          int len_done, len_rem, len_rand;
76          unsigned char *bufs[TEST_BUFS];
77          unsigned char *buf_ptr[TEST_BUFS];
78          uint32_t lens[TEST_BUFS];
79          unsigned int joblen, jobs, t;
80          int ret;
81  
82          printf("multibinary_sm3_update test, %d sets of %dx%d max: ", RANDOMS, TEST_BUFS, TEST_LEN);
83  
84          srand(TEST_SEED);
85  
86          ret = posix_memalign((void *) &mgr, 16, sizeof(SM3_HASH_CTX_MGR));
87          if ((ret != 0) || (mgr == NULL)) {
88                  printf("posix_memalign failed test aborted\n");
89                  return 1;
90          }
91  
92          sm3_ctx_mgr_init(mgr);
93  
94          for (i = 0; i < TEST_BUFS; i++) {
95                  // Allocate and fill buffer
96                  bufs[i] = (unsigned char *) malloc(TEST_LEN);
97                  buf_ptr[i] = bufs[i];
98                  if (bufs[i] == NULL) {
99                          printf("malloc failed test aborted\n");
100                          return 1;
101                  }
102                  rand_buffer(bufs[i], TEST_LEN);
103  
104                  // Init ctx contents
105                  hash_ctx_init(&ctxpool[i]);
106                  ctxpool[i].user_data = (void *) ((uint64_t) i);
107  
108                  // Run reference test
109                  sm3_ossl(bufs[i], TEST_LEN, digest_ref[i]);
110          }
111  
112          // Run sb_sm3 tests
113          for (i = 0; i < TEST_BUFS;) {
114                  len_done = (int) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]);
115                  len_rem = TEST_LEN - len_done;
116  
117                  if (len_done == 0)
118                          ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
119                                                   HASH_FIRST);
120                  else if (len_rem <= UPDATE_SIZE)
121                          ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem, HASH_LAST);
122                  else
123                          ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
124                                                   HASH_UPDATE);
125  
126                  // Add jobs while available or finished
127                  if ((ctx == NULL) || hash_ctx_complete(ctx)) {
128                          i++;
129                          continue;
130                  }
131                  // Resubmit unfinished job
132                  i = (unsigned long) (uintptr_t) (ctx->user_data);
133                  buf_ptr[i] += UPDATE_SIZE;
134          }
135  
136          // Start flushing finished jobs, end on last flushed
137          ctx = sm3_ctx_mgr_flush(mgr);
138          while (ctx) {
139                  if (hash_ctx_complete(ctx)) {
140                          debug_char('-');
141                          ctx = sm3_ctx_mgr_flush(mgr);
142                          continue;
143                  }
144                  // Resubmit unfinished job
145                  i = (unsigned long) (uintptr_t) (ctx->user_data);
146                  buf_ptr[i] += UPDATE_SIZE;
147  
148                  len_done = (int) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]);
149                  len_rem = TEST_LEN - len_done;
150  
151                  if (len_rem <= UPDATE_SIZE)
152                          ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem, HASH_LAST);
153                  else
154                          ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
155                                                   HASH_UPDATE);
156  
157                  if (ctx == NULL)
158                          ctx = sm3_ctx_mgr_flush(mgr);
159          }
160  
161          // Check digests
162          for (i = 0; i < TEST_BUFS; i++) {
163                  for (j = 0; j < SM3_DIGEST_NWORDS; j++) {
164                          if (ctxpool[i].job.result_digest[j] !=
165                              to_le32(((uint32_t *) digest_ref[i])[j])) {
166                                  fail++;
167                                  printf("Test%d fixed size, digest%d fail %8X <=> %8X", i, j,
168                                         ctxpool[i].job.result_digest[j],
169                                         to_le32(((uint32_t *) digest_ref[i])[j]));
170                          }
171                  }
172          }
173          putchar('.');
174  
175          // Run tests with random size and number of jobs
176          for (t = 0; t < RANDOMS; t++) {
177                  jobs = rand() % (TEST_BUFS);
178  
179                  for (i = 0; i < jobs; i++) {
180                          joblen = rand() % (TEST_LEN);
181                          rand_buffer(bufs[i], joblen);
182                          lens[i] = joblen;
183                          buf_ptr[i] = bufs[i];
184                          sm3_ossl(bufs[i], lens[i], digest_ref[i]);
185                  }
186  
187                  sm3_ctx_mgr_init(mgr);
188  
189                  // Run sm3_sb jobs
190                  i = 0;
191                  while (i < jobs) {
192                          // Submit a new job
193                          len_rand =
194                                  SM3_BLOCK_SIZE + SM3_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
195  
196                          if (lens[i] > len_rand)
197                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rand,
198                                                           HASH_FIRST);
199                          else
200                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], lens[i],
201                                                           HASH_ENTIRE);
202  
203                          // Returned ctx could be:
204                          //  - null context (we are just getting started and lanes aren't full yet),
205                          //  or
206                          //  - finished already (an ENTIRE we submitted or a previous LAST is
207                          //  returned), or
208                          //  - an unfinished ctx, we will resubmit
209  
210                          if ((ctx == NULL) || hash_ctx_complete(ctx)) {
211                                  i++;
212                                  continue;
213                          } else {
214                                  // unfinished ctx returned, choose another random update length and
215                                  // submit either UPDATE or LAST depending on the amount of buffer
216                                  // remaining
217                                  while ((ctx != NULL) && !(hash_ctx_complete(ctx))) {
218                                          j = (unsigned long) (uintptr_t) (ctx->user_data); // Get
219                                                                                            // index
220                                                                                            // of the
221                                                                                            // returned
222                                                                                            // ctx
223                                          buf_ptr[j] = bufs[j] + ctx->total_length;
224                                          len_rand = (rand() % SM3_BLOCK_SIZE) *
225                                                     (rand() % MAX_RAND_UPDATE_BLOCKS);
226                                          len_rem = lens[j] - ctx->total_length;
227  
228                                          if (len_rem <=
229                                              len_rand) // submit the rest of the job as LAST
230                                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[j],
231                                                                           buf_ptr[j], len_rem,
232                                                                           HASH_LAST);
233                                          else // submit the random update length as UPDATE
234                                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[j],
235                                                                           buf_ptr[j], len_rand,
236                                                                           HASH_UPDATE);
237                                  } // Either continue submitting any contexts returned here as
238                                    // UPDATE/LAST, or
239                                  // go back to submitting new jobs using the index i.
240  
241                                  i++;
242                          }
243                  }
244  
245                  // Start flushing finished jobs, end on last flushed
246                  ctx = sm3_ctx_mgr_flush(mgr);
247                  while (ctx) {
248                          if (hash_ctx_complete(ctx)) {
249                                  debug_char('-');
250                                  ctx = sm3_ctx_mgr_flush(mgr);
251                                  continue;
252                          }
253                          // Resubmit unfinished job
254                          i = (unsigned long) (uintptr_t) (ctx->user_data);
255                          buf_ptr[i] = bufs[i] + ctx->total_length; // update buffer pointer
256                          len_rem = lens[i] - ctx->total_length;
257                          len_rand = (rand() % SM3_BLOCK_SIZE) * (rand() % MAX_RAND_UPDATE_BLOCKS);
258                          debug_char('+');
259                          if (len_rem <= len_rand)
260                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem,
261                                                           HASH_LAST);
262                          else
263                                  ctx = sm3_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rand,
264                                                           HASH_UPDATE);
265  
266                          if (ctx == NULL)
267                                  ctx = sm3_ctx_mgr_flush(mgr);
268                  }
269  
270                  // Check result digest
271                  for (i = 0; i < jobs; i++) {
272                          for (j = 0; j < SM3_DIGEST_NWORDS; j++) {
273                                  if (ctxpool[i].job.result_digest[j] !=
274                                      to_le32(((uint32_t *) digest_ref[i])[j])) {
275                                          fail++;
276                                          printf("Test%d, digest%d fail %8X <=> %8X\n", i, j,
277                                                 ctxpool[i].job.result_digest[j],
278                                                 to_le32(((uint32_t *) digest_ref[i])[j]));
279                                  }
280                          }
281                  }
282                  if (fail) {
283                          printf("Test failed function check %d\n", fail);
284                          return fail;
285                  }
286  
287                  putchar('.');
288                  fflush(0);
289          } // random test t
290  
291          if (fail)
292                  printf("Test failed function check %d\n", fail);
293          else
294                  printf(" multibinary_sm3_update rand: Pass\n");
295  
296          return fail;
297  }
298