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 * ISAL_SHA256_BLOCK_SIZE
44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * ISAL_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][ISAL_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
rand_buffer(unsigned char * buf,const long buffer_size)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
main(void)71 main(void)
72 {
73 ISAL_SHA256_HASH_CTX_MGR *mgr = NULL;
74 ISAL_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(ISAL_SHA256_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_sha256_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 isal_hash_ctx_init(&ctxpool[i]);
111 ctxpool[i].user_data = (void *) ((uint64_t) i);
112
113 // Run reference test
114 sha256_ref(bufs[i], digest_ref[i], TEST_LEN);
115 }
116
117 // Run sb_sha256 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_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
124 UPDATE_SIZE, ISAL_HASH_FIRST);
125 else if (len_rem <= UPDATE_SIZE)
126 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
127 len_rem, ISAL_HASH_LAST);
128 else
129 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
130 UPDATE_SIZE, ISAL_HASH_UPDATE);
131 if (ret)
132 return 1;
133
134 // Add jobs while available or finished
135 if ((ctx == NULL) || isal_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_sha256_ctx_mgr_flush(mgr, &ctx);
146 if (ret)
147 return 1;
148 while (ctx) {
149 if (isal_hash_ctx_complete(ctx)) {
150 debug_char('-');
151 ret = isal_sha256_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_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
165 len_rem, ISAL_HASH_LAST);
166 else
167 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
168 UPDATE_SIZE, ISAL_HASH_UPDATE);
169 if (ret)
170 return 1;
171
172 if (ctx == NULL) {
173 ret = isal_sha256_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 < ISAL_SHA256_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 sha256_ref(bufs[i], digest_ref[i], lens[i]);
201 }
202
203 ret = isal_sha256_ctx_mgr_init(mgr);
204 if (ret)
205 return 1;
206
207 // Run sha256_sb jobs
208 i = 0;
209 while (i < jobs) {
210 // Submit a new job
211 len_rand = ISAL_SHA256_BLOCK_SIZE +
212 ISAL_SHA256_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
213
214 if (lens[i] > len_rand)
215 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
216 len_rand, ISAL_HASH_FIRST);
217 else
218 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
219 lens[i], ISAL_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) || isal_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) && !(isal_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() % ISAL_SHA256_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_sha256_ctx_mgr_submit(
249 mgr, &ctxpool[j], &ctx, buf_ptr[j], len_rem,
250 ISAL_HASH_LAST);
251 else // submit the random update length as UPDATE
252 ret = isal_sha256_ctx_mgr_submit(
253 mgr, &ctxpool[j], &ctx, buf_ptr[j],
254 len_rand, ISAL_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_sha256_ctx_mgr_flush(mgr, &ctx);
267 if (ret)
268 return 1;
269 while (ctx) {
270 if (isal_hash_ctx_complete(ctx)) {
271 debug_char('-');
272 ret = isal_sha256_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() % ISAL_SHA256_BLOCK_SIZE) *
282 (rand() % MAX_RAND_UPDATE_BLOCKS);
283 debug_char('+');
284 if (len_rem <= len_rand)
285 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
286 len_rem, ISAL_HASH_LAST);
287 else
288 ret = isal_sha256_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
289 len_rand, ISAL_HASH_UPDATE);
290 if (ret)
291 return 1;
292
293 if (ctx == NULL) {
294 ret = isal_sha256_ctx_mgr_flush(mgr, &ctx);
295 if (ret)
296 return 1;
297 }
298 }
299
300 // Check result digest
301 for (i = 0; i < jobs; i++) {
302 for (j = 0; j < ISAL_SHA256_DIGEST_NWORDS; j++) {
303 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
304 fail++;
305 printf("Test%d, digest%d fail %8X <=> %8X\n", i, j,
306 ctxpool[i].job.result_digest[j], digest_ref[i][j]);
307 }
308 }
309 }
310 if (fail) {
311 printf("Test failed function check %d\n", fail);
312 goto end;
313 }
314
315 putchar('.');
316 fflush(0);
317 } // random test t
318
319 end:
320 for (i = 0; i < TEST_BUFS; i++)
321 free(bufs[i]);
322 aligned_free(mgr);
323
324 if (fail)
325 printf("Test failed function check %d\n", fail);
326 else
327 printf(" multibinary_sha256_update rand: Pass\n");
328
329 return fail;
330 }
331