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