xref: /isa-l_crypto/sha256_mb/sha256_mb_rand_update_test.c (revision 860585444755e926bd72600b39758458c0a1c9da)
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];
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 			return 1;
98 		}
99 		rand_buffer(bufs[i], TEST_LEN);
100 
101 		// Init ctx contents
102 		hash_ctx_init(&ctxpool[i]);
103 		ctxpool[i].user_data = (void *)((uint64_t) i);
104 
105 		// Run reference test
106 		sha256_ref(bufs[i], digest_ref[i], TEST_LEN);
107 	}
108 
109 	// Run sb_sha256 tests
110 	for (i = 0; i < TEST_BUFS;) {
111 		len_done = (int)((unsigned long)buf_ptr[i] - (unsigned long)bufs[i]);
112 		len_rem = TEST_LEN - len_done;
113 
114 		if (len_done == 0)
115 			ctx = sha256_ctx_mgr_submit(mgr,
116 						    &ctxpool[i],
117 						    buf_ptr[i], UPDATE_SIZE, HASH_FIRST);
118 		else if (len_rem <= UPDATE_SIZE)
119 			ctx = sha256_ctx_mgr_submit(mgr,
120 						    &ctxpool[i],
121 						    buf_ptr[i], len_rem, HASH_LAST);
122 		else
123 			ctx = sha256_ctx_mgr_submit(mgr,
124 						    &ctxpool[i],
125 						    buf_ptr[i], UPDATE_SIZE, HASH_UPDATE);
126 
127 		// Add jobs while available or finished
128 		if ((ctx == NULL) || hash_ctx_complete(ctx)) {
129 			i++;
130 			continue;
131 		}
132 		// Resubmit unfinished job
133 		i = (unsigned long)(ctx->user_data);
134 		buf_ptr[i] += UPDATE_SIZE;
135 	}
136 
137 	// Start flushing finished jobs, end on last flushed
138 	ctx = sha256_ctx_mgr_flush(mgr);
139 	while (ctx) {
140 		if (hash_ctx_complete(ctx)) {
141 			debug_char('-');
142 			ctx = sha256_ctx_mgr_flush(mgr);
143 			continue;
144 		}
145 		// Resubmit unfinished job
146 		i = (unsigned long)(ctx->user_data);
147 		buf_ptr[i] += UPDATE_SIZE;
148 
149 		len_done = (int)((unsigned long)buf_ptr[i]
150 				 - (unsigned long)bufs[i]);
151 		len_rem = TEST_LEN - len_done;
152 
153 		if (len_rem <= UPDATE_SIZE)
154 			ctx = sha256_ctx_mgr_submit(mgr,
155 						    &ctxpool[i],
156 						    buf_ptr[i], len_rem, HASH_LAST);
157 		else
158 			ctx = sha256_ctx_mgr_submit(mgr,
159 						    &ctxpool[i],
160 						    buf_ptr[i], UPDATE_SIZE, HASH_UPDATE);
161 
162 		if (ctx == NULL)
163 			ctx = sha256_ctx_mgr_flush(mgr);
164 	}
165 
166 	// Check digests
167 	for (i = 0; i < TEST_BUFS; i++) {
168 		for (j = 0; j < SHA256_DIGEST_NWORDS; j++) {
169 			if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
170 				fail++;
171 				printf("Test%d fixed size, digest%d fail %8X <=> %8X",
172 				       i, j, ctxpool[i].job.result_digest[j],
173 				       digest_ref[i][j]);
174 			}
175 		}
176 	}
177 	putchar('.');
178 
179 	// Run tests with random size and number of jobs
180 	for (t = 0; t < RANDOMS; t++) {
181 		jobs = rand() % (TEST_BUFS);
182 
183 		for (i = 0; i < jobs; i++) {
184 			joblen = rand() % (TEST_LEN);
185 			rand_buffer(bufs[i], joblen);
186 			lens[i] = joblen;
187 			buf_ptr[i] = bufs[i];
188 			sha256_ref(bufs[i], digest_ref[i], lens[i]);
189 		}
190 
191 		sha256_ctx_mgr_init(mgr);
192 
193 		// Run sha256_sb jobs
194 		i = 0;
195 		while (i < jobs) {
196 			// Submit a new job
197 			len_rand = SHA256_BLOCK_SIZE +
198 			    SHA256_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
199 
200 			if (lens[i] > len_rand)
201 				ctx = sha256_ctx_mgr_submit(mgr,
202 							    &ctxpool[i],
203 							    buf_ptr[i], len_rand, HASH_FIRST);
204 			else
205 				ctx = sha256_ctx_mgr_submit(mgr,
206 							    &ctxpool[i],
207 							    buf_ptr[i], lens[i], HASH_ENTIRE);
208 
209 			// Returned ctx could be:
210 			//  - null context (we are just getting started and lanes aren't full yet), or
211 			//  - finished already (an ENTIRE we submitted or a previous LAST is returned), or
212 			//  - an unfinished ctx, we will resubmit
213 
214 			if ((ctx == NULL) || hash_ctx_complete(ctx)) {
215 				i++;
216 				continue;
217 			} else {
218 				// unfinished ctx returned, choose another random update length and submit either
219 				// UPDATE or LAST depending on the amount of buffer remaining
220 				while ((ctx != NULL) && !(hash_ctx_complete(ctx))) {
221 					j = (unsigned long)(ctx->user_data);	// Get index of the returned ctx
222 					buf_ptr[j] = bufs[j] + ctx->total_length;
223 					len_rand = (rand() % SHA256_BLOCK_SIZE)
224 					    * (rand() % MAX_RAND_UPDATE_BLOCKS);
225 					len_rem = lens[j] - ctx->total_length;
226 
227 					if (len_rem <= len_rand)	// submit the rest of the job as LAST
228 						ctx = sha256_ctx_mgr_submit(mgr,
229 									    &ctxpool[j],
230 									    buf_ptr[j],
231 									    len_rem,
232 									    HASH_LAST);
233 					else	// submit the random update length as UPDATE
234 						ctx = sha256_ctx_mgr_submit(mgr,
235 									    &ctxpool[j],
236 									    buf_ptr[j],
237 									    len_rand,
238 									    HASH_UPDATE);
239 				}	// Either continue submitting any contexts returned here as UPDATE/LAST, or
240 				// go back to submitting new jobs using the index i.
241 
242 				i++;
243 			}
244 		}
245 
246 		// Start flushing finished jobs, end on last flushed
247 		ctx = sha256_ctx_mgr_flush(mgr);
248 		while (ctx) {
249 			if (hash_ctx_complete(ctx)) {
250 				debug_char('-');
251 				ctx = sha256_ctx_mgr_flush(mgr);
252 				continue;
253 			}
254 			// Resubmit unfinished job
255 			i = (unsigned long)(ctx->user_data);
256 			buf_ptr[i] = bufs[i] + ctx->total_length;	// update buffer pointer
257 			len_rem = lens[i] - ctx->total_length;
258 			len_rand = (rand() % SHA256_BLOCK_SIZE)
259 			    * (rand() % MAX_RAND_UPDATE_BLOCKS);
260 			debug_char('+');
261 			if (len_rem <= len_rand)
262 				ctx = sha256_ctx_mgr_submit(mgr,
263 							    &ctxpool[i],
264 							    buf_ptr[i], len_rem, HASH_LAST);
265 			else
266 				ctx = sha256_ctx_mgr_submit(mgr,
267 							    &ctxpool[i],
268 							    buf_ptr[i], len_rand, HASH_UPDATE);
269 
270 			if (ctx == NULL)
271 				ctx = sha256_ctx_mgr_flush(mgr);
272 		}
273 
274 		// Check result digest
275 		for (i = 0; i < jobs; i++) {
276 			for (j = 0; j < SHA256_DIGEST_NWORDS; j++) {
277 				if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
278 					fail++;
279 					printf("Test%d, digest%d fail %8X <=> %8X\n",
280 					       i, j, ctxpool[i].job.result_digest[j],
281 					       digest_ref[i][j]);
282 				}
283 			}
284 		}
285 		if (fail) {
286 			printf("Test failed function check %d\n", fail);
287 			return fail;
288 		}
289 
290 		putchar('.');
291 		fflush(0);
292 	}			// random test t
293 
294 	if (fail)
295 		printf("Test failed function check %d\n", fail);
296 	else
297 		printf(" multibinary_sha256_update rand: Pass\n");
298 
299 	return fail;
300 }
301