xref: /isa-l_crypto/sha1_mb/sha1_mb_rand_update_test.c (revision 14a3d2588eef9fb46549cd21844320d7e31d7d54)
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 "sha1_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 * SHA1_BLOCK_SIZE
44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * SHA1_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][SHA1_DIGEST_NWORDS];
56 
57 extern void
58 sha1_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         SHA1_HASH_CTX_MGR *mgr = NULL;
74         SHA1_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_sha1_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(SHA1_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_sha1_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                 hash_ctx_init(&ctxpool[i]);
111                 ctxpool[i].user_data = (void *) ((uint64_t) i);
112 
113                 // Run reference test
114                 sha1_ref(bufs[i], digest_ref[i], TEST_LEN);
115         }
116 
117         // Run sb_sha1 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_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
124                                                        UPDATE_SIZE, HASH_FIRST);
125                 else if (len_rem <= UPDATE_SIZE)
126                         ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], len_rem,
127                                                        HASH_LAST);
128                 else
129                         ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
130                                                        UPDATE_SIZE, HASH_UPDATE);
131                 if (ret)
132                         return 1;
133 
134                 // Add jobs while available or finished
135                 if ((ctx == NULL) || 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_sha1_ctx_mgr_flush(mgr, &ctx);
146         if (ret)
147                 return 1;
148         while (ctx) {
149                 if (hash_ctx_complete(ctx)) {
150                         debug_char('-');
151                         ret = isal_sha1_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_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], len_rem,
165                                                        HASH_LAST);
166                 else
167                         ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
168                                                        UPDATE_SIZE, HASH_UPDATE);
169                 if (ret)
170                         return 1;
171 
172                 if (ctx == NULL) {
173                         ret = isal_sha1_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 < SHA1_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                         sha1_ref(bufs[i], digest_ref[i], lens[i]);
201                 }
202 
203                 ret = isal_sha1_ctx_mgr_init(mgr);
204                 if (ret)
205                         return 1;
206 
207                 // Run sha1_sb jobs
208                 i = 0;
209                 while (i < jobs) {
210                         // Submit a new job
211                         len_rand = SHA1_BLOCK_SIZE +
212                                    SHA1_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
213 
214                         if (lens[i] > len_rand)
215                                 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
216                                                                len_rand, HASH_FIRST);
217                         else
218                                 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
219                                                                lens[i], 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) || 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) && !(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() % SHA1_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_sha1_ctx_mgr_submit(mgr, &ctxpool[j],
249                                                                                &ctx, buf_ptr[j],
250                                                                                len_rem, HASH_LAST);
251                                         else // submit the random update length as UPDATE
252                                                 ret = isal_sha1_ctx_mgr_submit(
253                                                         mgr, &ctxpool[j], &ctx, buf_ptr[j],
254                                                         len_rand, 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_sha1_ctx_mgr_flush(mgr, &ctx);
267                 if (ret)
268                         return 1;
269                 while (ctx) {
270                         if (hash_ctx_complete(ctx)) {
271                                 debug_char('-');
272                                 ret = isal_sha1_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() % SHA1_BLOCK_SIZE) * (rand() % MAX_RAND_UPDATE_BLOCKS);
282                         debug_char('+');
283                         if (len_rem <= len_rand)
284                                 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
285                                                                len_rem, HASH_LAST);
286                         else
287                                 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
288                                                                len_rand, HASH_UPDATE);
289                         if (ret)
290                                 return 1;
291 
292                         if (ctx == NULL) {
293                                 ret = isal_sha1_ctx_mgr_flush(mgr, &ctx);
294                                 if (ret)
295                                         return 1;
296                         }
297                 }
298 
299                 // Check result digest
300                 for (i = 0; i < jobs; i++) {
301                         for (j = 0; j < SHA1_DIGEST_NWORDS; j++) {
302                                 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
303                                         fail++;
304                                         printf("Test%d, digest%d fail %8X <=> %8X\n", i, j,
305                                                ctxpool[i].job.result_digest[j], digest_ref[i][j]);
306                                 }
307                         }
308                 }
309                 if (fail) {
310                         printf("Test failed function check %d\n", fail);
311                         goto end;
312                 }
313 
314                 putchar('.');
315                 fflush(0);
316         } // random test t
317 
318 end:
319         for (i = 0; i < TEST_BUFS; i++)
320                 free(bufs[i]);
321         aligned_free(mgr);
322 
323         if (fail)
324                 printf("Test failed function check %d\n", fail);
325         else
326                 printf(" multibinary_sha1_update rand: Pass\n");
327 
328         return fail;
329 }
330