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