xref: /isa-l_crypto/sha256_mb/sha256_mb_rand_update_test.c (revision 228b4c8d752832b075901a0857f4eed11e8e25ff)
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         int 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 = (int) ((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 = (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 = (uintptr_t) (ctx->user_data);
150                 buf_ptr[i] += UPDATE_SIZE;
151 
152                 len_done = (int) ((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 = (uintptr_t) (ctx->user_data); // Get index of the
222                                                                           // returned ctx
223                                         buf_ptr[j] = bufs[j] + ctx->total_length;
224                                         len_rand = (rand() % SHA256_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 = sha256_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 = sha256_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 = sha256_ctx_mgr_flush(mgr);
247                 while (ctx) {
248                         if (hash_ctx_complete(ctx)) {
249                                 debug_char('-');
250                                 ctx = sha256_ctx_mgr_flush(mgr);
251                                 continue;
252                         }
253                         // Resubmit unfinished job
254                         i = (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() % SHA256_BLOCK_SIZE) * (rand() % MAX_RAND_UPDATE_BLOCKS);
258                         debug_char('+');
259                         if (len_rem <= len_rand)
260                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rem,
261                                                             HASH_LAST);
262                         else
263                                 ctx = sha256_ctx_mgr_submit(mgr, &ctxpool[i], buf_ptr[i], len_rand,
264                                                             HASH_UPDATE);
265 
266                         if (ctx == NULL)
267                                 ctx = sha256_ctx_mgr_flush(mgr);
268                 }
269 
270                 // Check result digest
271                 for (i = 0; i < jobs; i++) {
272                         for (j = 0; j < SHA256_DIGEST_NWORDS; j++) {
273                                 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
274                                         fail++;
275                                         printf("Test%d, digest%d fail %8X <=> %8X\n", i, j,
276                                                ctxpool[i].job.result_digest[j], digest_ref[i][j]);
277                                 }
278                         }
279                 }
280                 if (fail) {
281                         printf("Test failed function check %d\n", fail);
282                         goto end;
283                 }
284 
285                 putchar('.');
286                 fflush(0);
287         } // random test t
288 
289 end:
290         for (i = 0; i < TEST_BUFS; i++)
291                 free(bufs[i]);
292         aligned_free(mgr);
293 
294         if (fail)
295                 printf("Test failed function check %d\n", fail);
296         else
297                 printf(" multibinary_sha256_update rand: Pass\n");
298 
299         return fail;
300 }
301