xref: /isa-l_crypto/sha256_mb/sha256_mb_rand_update_test.c (revision 122c17795e4bee7e9242fceb7a09851e8f4e3a31)
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 * SHA256_BLOCK_SIZE
44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * 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][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
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
71 main(void)
72 {
73         SHA256_HASH_CTX_MGR *mgr = NULL;
74         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(SHA256_HASH_CTX_MGR));
89         if ((ret != 0) || (mgr == NULL)) {
90                 printf("posix_memalign failed test aborted\n");
91                 return 1;
92         }
93 
94         sha256_ctx_mgr_init(mgr);
95 
96         for (i = 0; i < TEST_BUFS; i++) {
97                 // Allocate and fill buffer
98                 bufs[i] = (unsigned char *) malloc(TEST_LEN);
99                 buf_ptr[i] = bufs[i];
100                 if (bufs[i] == NULL) {
101                         printf("malloc failed test aborted\n");
102                         fail++;
103                         goto end;
104                 }
105                 rand_buffer(bufs[i], TEST_LEN);
106 
107                 // Init ctx contents
108                 hash_ctx_init(&ctxpool[i]);
109                 ctxpool[i].user_data = (void *) ((uint64_t) i);
110 
111                 // Run reference test
112                 sha256_ref(bufs[i], digest_ref[i], TEST_LEN);
113         }
114 
115         // Run sb_sha256 tests
116         for (i = 0; i < TEST_BUFS;) {
117                 len_done = (uint32_t) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]);
118                 len_rem = TEST_LEN - len_done;
119 
120                 if (len_done == 0)
121                         ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
122                                                     HASH_FIRST);
123                 else if (len_rem <= UPDATE_SIZE)
124                         ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem,
125                                                     HASH_LAST);
126                 else
127                         ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
128                                                     HASH_UPDATE);
129 
130                 // Add jobs while available or finished
131                 if ((ctx == NULL) || hash_ctx_complete(ctx)) {
132                         i++;
133                         continue;
134                 }
135                 // Resubmit unfinished job
136                 i = (uint32_t) (uintptr_t) (ctx->user_data);
137                 buf_ptr[i] += UPDATE_SIZE;
138         }
139 
140         // Start flushing finished jobs, end on last flushed
141         ctx = sha256_ctx_mgr_flush(mgr);
142         while (ctx) {
143                 if (hash_ctx_complete(ctx)) {
144                         debug_char('-');
145                         ctx = sha256_ctx_mgr_flush(mgr);
146                         continue;
147                 }
148                 // Resubmit unfinished job
149                 i = (uint32_t) (uintptr_t) (ctx->user_data);
150                 buf_ptr[i] += UPDATE_SIZE;
151 
152                 len_done = (uint32_t) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]);
153                 len_rem = TEST_LEN - len_done;
154 
155                 if (len_rem <= UPDATE_SIZE)
156                         ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem,
157                                                     HASH_LAST);
158                 else
159                         ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], UPDATE_SIZE,
160                                                     HASH_UPDATE);
161 
162                 if (ctx == NULL)
163                         ctx = sha256_ctx_mgr_flush(mgr);
164         }
165 
166         // Check digests
167         for (i = 0; i < TEST_BUFS; i++) {
168                 for (j = 0; j < SHA256_DIGEST_NWORDS; j++) {
169                         if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
170                                 fail++;
171                                 printf("Test%d fixed size, digest%d fail %8X <=> %8X", i, j,
172                                        ctxpool[i].job.result_digest[j], digest_ref[i][j]);
173                         }
174                 }
175         }
176         putchar('.');
177 
178         // Run tests with random size and number of jobs
179         for (t = 0; t < RANDOMS; t++) {
180                 jobs = rand() % (TEST_BUFS);
181 
182                 for (i = 0; i < jobs; i++) {
183                         joblen = rand() % (TEST_LEN);
184                         rand_buffer(bufs[i], joblen);
185                         lens[i] = joblen;
186                         buf_ptr[i] = bufs[i];
187                         sha256_ref(bufs[i], digest_ref[i], lens[i]);
188                 }
189 
190                 sha256_ctx_mgr_init(mgr);
191 
192                 // Run sha256_sb jobs
193                 i = 0;
194                 while (i < jobs) {
195                         // Submit a new job
196                         len_rand = SHA256_BLOCK_SIZE +
197                                    SHA256_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
198 
199                         if (lens[i] > len_rand)
200                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rand,
201                                                             HASH_FIRST);
202                         else
203                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], lens[i],
204                                                             HASH_ENTIRE);
205 
206                         // Returned ctx could be:
207                         //  - null context (we are just getting started and lanes aren't full yet),
208                         //  or
209                         //  - finished already (an ENTIRE we submitted or a previous LAST is
210                         //  returned), or
211                         //  - an unfinished ctx, we will resubmit
212 
213                         if ((ctx == NULL) || hash_ctx_complete(ctx)) {
214                                 i++;
215                                 continue;
216                         } else {
217                                 // unfinished ctx returned, choose another random update length and
218                                 // submit either UPDATE or LAST depending on the amount of buffer
219                                 // remaining
220                                 while ((ctx != NULL) && !(hash_ctx_complete(ctx))) {
221                                         j = (uint32_t) (uintptr_t) (ctx->user_data); // Get index of
222                                                                                      // the returned
223                                                                                      // ctx
224                                         buf_ptr[j] = bufs[j] + ctx->total_length;
225                                         len_rand = (rand() % SHA256_BLOCK_SIZE) *
226                                                    (rand() % MAX_RAND_UPDATE_BLOCKS);
227                                         len_rem = lens[j] - (uint32_t) ctx->total_length;
228 
229                                         if (len_rem <=
230                                             len_rand) // submit the rest of the job as LAST
231                                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[j],
232                                                                             buf_ptr[j], len_rem,
233                                                                             HASH_LAST);
234                                         else // submit the random update length as UPDATE
235                                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[j],
236                                                                             buf_ptr[j], len_rand,
237                                                                             HASH_UPDATE);
238                                 } // Either continue submitting any contexts returned here as
239                                   // UPDATE/LAST, or
240                                 // go back to submitting new jobs using the index i.
241 
242                                 i++;
243                         }
244                 }
245 
246                 // Start flushing finished jobs, end on last flushed
247                 ctx = sha256_ctx_mgr_flush(mgr);
248                 while (ctx) {
249                         if (hash_ctx_complete(ctx)) {
250                                 debug_char('-');
251                                 ctx = sha256_ctx_mgr_flush(mgr);
252                                 continue;
253                         }
254                         // Resubmit unfinished job
255                         i = (uint32_t) (uintptr_t) (ctx->user_data);
256                         buf_ptr[i] = bufs[i] + ctx->total_length; // update buffer pointer
257                         len_rem = lens[i] - (uint32_t) ctx->total_length;
258                         len_rand = (rand() % SHA256_BLOCK_SIZE) * (rand() % MAX_RAND_UPDATE_BLOCKS);
259                         debug_char('+');
260                         if (len_rem <= len_rand)
261                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem,
262                                                             HASH_LAST);
263                         else
264                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rand,
265                                                             HASH_UPDATE);
266 
267                         if (ctx == NULL)
268                                 ctx = sha256_ctx_mgr_flush(mgr);
269                 }
270 
271                 // Check result digest
272                 for (i = 0; i < jobs; i++) {
273                         for (j = 0; j < SHA256_DIGEST_NWORDS; j++) {
274                                 if (ctxpool[i].job.result_digest[j] != 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], digest_ref[i][j]);
278                                 }
279                         }
280                 }
281                 if (fail) {
282                         printf("Test failed function check %d\n", fail);
283                         goto end;
284                 }
285 
286                 putchar('.');
287                 fflush(0);
288         } // random test t
289 
290 end:
291         for (i = 0; i < TEST_BUFS; i++)
292                 free(bufs[i]);
293         aligned_free(mgr);
294 
295         if (fail)
296                 printf("Test failed function check %d\n", fail);
297         else
298                 printf(" multibinary_sha256_update rand: Pass\n");
299 
300         return fail;
301 }
302