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