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