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 "sha512_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_SHA512_BLOCK_SIZE
44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * ISAL_SHA512_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 uint64_t digest_ref[TEST_BUFS][ISAL_SHA512_DIGEST_NWORDS];
56
57 extern void
58 sha512_ref(uint8_t *input_data, uint64_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_SHA512_HASH_CTX_MGR *mgr = NULL;
74 ISAL_SHA512_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];
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_sha512_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_SHA512_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_sha512_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 sha512_ref(bufs[i], digest_ref[i], TEST_LEN);
115 }
116
117 // Run sb_sha512 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_sha512_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_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
127 len_rem, ISAL_HASH_LAST);
128 else
129 ret = isal_sha512_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 = (unsigned long) (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_sha512_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_sha512_ctx_mgr_flush(mgr, &ctx);
152 if (ret)
153 return 1;
154 continue;
155 }
156 // Resubmit unfinished job
157 i = (unsigned long) (uintptr_t) (ctx->user_data);
158 buf_ptr[i] += UPDATE_SIZE;
159
160 len_done = (int) ((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_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
165 len_rem, ISAL_HASH_LAST);
166 else
167 ret = isal_sha512_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_sha512_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_SHA512_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 %8llX <=> %8llX", i, j,
185 (unsigned long long) ctxpool[i].job.result_digest[j],
186 (unsigned long long) digest_ref[i][j]);
187 }
188 }
189 }
190 putchar('.');
191
192 // Run tests with random size and number of jobs
193 for (t = 0; t < RANDOMS; t++) {
194 jobs = rand() % (TEST_BUFS);
195
196 for (i = 0; i < jobs; i++) {
197 joblen = rand() % (TEST_LEN);
198 rand_buffer(bufs[i], joblen);
199 lens[i] = joblen;
200 buf_ptr[i] = bufs[i];
201 sha512_ref(bufs[i], digest_ref[i], lens[i]);
202 }
203
204 ret = isal_sha512_ctx_mgr_init(mgr);
205 if (ret)
206 return 1;
207
208 // Run sha512_sb jobs
209 i = 0;
210 while (i < jobs) {
211 // Submit a new job
212 len_rand = ISAL_SHA512_BLOCK_SIZE +
213 ISAL_SHA512_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
214
215 if (lens[i] > len_rand)
216 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
217 len_rand, ISAL_HASH_FIRST);
218 else
219 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
220 lens[i], ISAL_HASH_ENTIRE);
221 if (ret)
222 return 1;
223
224 // Returned ctx could be:
225 // - null context (we are just getting started and lanes aren't full yet),
226 // or
227 // - finished already (an ENTIRE we submitted or a previous LAST is
228 // returned), or
229 // - an unfinished ctx, we will resubmit
230
231 if ((ctx == NULL) || isal_hash_ctx_complete(ctx)) {
232 i++;
233 continue;
234 } else {
235 // unfinished ctx returned, choose another random update length and
236 // submit either UPDATE or LAST depending on the amount of buffer
237 // remaining
238 while ((ctx != NULL) && !(isal_hash_ctx_complete(ctx))) {
239 j = (unsigned long) (uintptr_t) (ctx->user_data); // Get
240 // index
241 // of the
242 // returned
243 // ctx
244 buf_ptr[j] = bufs[j] + ctx->total_length;
245 len_rand = (rand() % ISAL_SHA512_BLOCK_SIZE) *
246 (rand() % MAX_RAND_UPDATE_BLOCKS);
247 len_rem = lens[j] - (uint32_t) ctx->total_length;
248
249 if (len_rem <=
250 len_rand) // submit the rest of the job as LAST
251 ret = isal_sha512_ctx_mgr_submit(
252 mgr, &ctxpool[j], &ctx, buf_ptr[j], len_rem,
253 ISAL_HASH_LAST);
254 else // submit the random update length as UPDATE
255 ret = isal_sha512_ctx_mgr_submit(
256 mgr, &ctxpool[j], &ctx, buf_ptr[j],
257 len_rand, ISAL_HASH_UPDATE);
258 if (ret)
259 return 1;
260 } // Either continue submitting any contexts returned here as
261 // UPDATE/LAST, or
262 // go back to submitting new jobs using the index i.
263
264 i++;
265 }
266 }
267
268 // Start flushing finished jobs, end on last flushed
269 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx);
270 if (ret)
271 return 1;
272 while (ctx) {
273 if (isal_hash_ctx_complete(ctx)) {
274 debug_char('-');
275 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx);
276 if (ret)
277 return 1;
278 continue;
279 }
280 // Resubmit unfinished job
281 i = (unsigned long) (uintptr_t) (ctx->user_data);
282 buf_ptr[i] = bufs[i] + ctx->total_length; // update buffer pointer
283 len_rem = lens[i] - (uint32_t) ctx->total_length;
284 len_rand = (rand() % ISAL_SHA512_BLOCK_SIZE) *
285 (rand() % MAX_RAND_UPDATE_BLOCKS);
286 debug_char('+');
287 if (len_rem <= len_rand)
288 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
289 len_rem, ISAL_HASH_LAST);
290 else
291 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i],
292 len_rand, ISAL_HASH_UPDATE);
293 if (ret)
294 return 1;
295
296 if (ctx == NULL) {
297 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx);
298 if (ret)
299 return 1;
300 }
301 }
302
303 // Check result digest
304 for (i = 0; i < jobs; i++) {
305 for (j = 0; j < ISAL_SHA512_DIGEST_NWORDS; j++) {
306 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
307 fail++;
308 printf("Test%d, digest%d fail %8llX <=> %8llX\n", i, j,
309 (unsigned long long) ctxpool[i].job.result_digest[j],
310 (unsigned long long) digest_ref[i][j]);
311 }
312 }
313 }
314 if (fail) {
315 printf("Test failed function check %d\n", fail);
316 goto end;
317 }
318
319 putchar('.');
320 fflush(0);
321 } // random test t
322
323 end:
324 for (i = 0; i < TEST_BUFS; i++)
325 free(bufs[i]);
326 aligned_free(mgr);
327
328 if (fail)
329 printf("Test failed function check %d\n", fail);
330 else
331 printf(" multibinary_sha512_update rand: Pass\n");
332
333 return fail;
334 }
335