xref: /isa-l_crypto/sha1_mb/sha1_mb_rand_update_test.c (revision a4de01928f9e63e0ef03e8ef48b1b7f5de29b7ec)
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 "sha1_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*SHA1_BLOCK_SIZE
44 #define MAX_RAND_UPDATE_BLOCKS 	(TEST_LEN/(16*SHA1_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][SHA1_DIGEST_NWORDS];
54 
55 extern void sha1_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 	SHA1_HASH_CTX_MGR *mgr = NULL;
69 	SHA1_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_sha1_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(SHA1_HASH_CTX_MGR));
84 	if ((ret != 0) || (mgr == NULL)) {
85 		printf("posix_memalign failed test aborted\n");
86 		return 1;
87 	}
88 
89 	sha1_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 		sha1_ref(bufs[i], digest_ref[i], TEST_LEN);
108 	}
109 
110 	// Run sb_sha1 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 = sha1_ctx_mgr_submit(mgr,
117 						  &ctxpool[i],
118 						  buf_ptr[i], UPDATE_SIZE, HASH_FIRST);
119 		else if (len_rem <= UPDATE_SIZE)
120 			ctx = sha1_ctx_mgr_submit(mgr,
121 						  &ctxpool[i], buf_ptr[i], len_rem, HASH_LAST);
122 		else
123 			ctx = sha1_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 = sha1_ctx_mgr_flush(mgr);
139 	while (ctx) {
140 		if (hash_ctx_complete(ctx)) {
141 			debug_char('-');
142 			ctx = sha1_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 = sha1_ctx_mgr_submit(mgr,
155 						  &ctxpool[i], buf_ptr[i], len_rem, HASH_LAST);
156 		else
157 			ctx = sha1_ctx_mgr_submit(mgr,
158 						  &ctxpool[i],
159 						  buf_ptr[i], UPDATE_SIZE, HASH_UPDATE);
160 
161 		if (ctx == NULL)
162 			ctx = sha1_ctx_mgr_flush(mgr);
163 	}
164 
165 	// Check digests
166 	for (i = 0; i < TEST_BUFS; i++) {
167 		for (j = 0; j < SHA1_DIGEST_NWORDS; j++) {
168 			if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
169 				fail++;
170 				printf("Test%d fixed size, digest%d fail %8X <=> %8X",
171 				       i, j, ctxpool[i].job.result_digest[j],
172 				       digest_ref[i][j]);
173 			}
174 		}
175 	}
176 	putchar('.');
177 
178 	// Run tests with random size and number of jobs
179 	for (t = 0; t < RANDOMS; t++) {
180 		jobs = rand() % (TEST_BUFS);
181 
182 		for (i = 0; i < jobs; i++) {
183 			joblen = rand() % (TEST_LEN);
184 			rand_buffer(bufs[i], joblen);
185 			lens[i] = joblen;
186 			buf_ptr[i] = bufs[i];
187 			sha1_ref(bufs[i], digest_ref[i], lens[i]);
188 		}
189 
190 		sha1_ctx_mgr_init(mgr);
191 
192 		// Run sha1_sb jobs
193 		i = 0;
194 		while (i < jobs) {
195 			// Submit a new job
196 			len_rand = SHA1_BLOCK_SIZE +
197 			    SHA1_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS);
198 
199 			if (lens[i] > len_rand)
200 				ctx = sha1_ctx_mgr_submit(mgr,
201 							  &ctxpool[i],
202 							  buf_ptr[i], len_rand, HASH_FIRST);
203 			else
204 				ctx = sha1_ctx_mgr_submit(mgr,
205 							  &ctxpool[i],
206 							  buf_ptr[i], lens[i], HASH_ENTIRE);
207 
208 			// Returned ctx could be:
209 			//  - null context (we are just getting started and lanes aren't full yet), or
210 			//  - finished already (an ENTIRE we submitted or a previous LAST is returned), or
211 			//  - an unfinished ctx, we will resubmit
212 
213 			if ((ctx == NULL) || hash_ctx_complete(ctx)) {
214 				i++;
215 				continue;
216 			} else {
217 				// unfinished ctx returned, choose another random update length and submit either
218 				// UPDATE or LAST depending on the amount of buffer remaining
219 				while ((ctx != NULL) && !(hash_ctx_complete(ctx))) {
220 					j = (unsigned long)(ctx->user_data);	// Get index of the returned ctx
221 					buf_ptr[j] = bufs[j] + ctx->total_length;
222 					len_rand = (rand() % SHA1_BLOCK_SIZE)
223 					    * (rand() % MAX_RAND_UPDATE_BLOCKS);
224 					len_rem = lens[j] - ctx->total_length;
225 
226 					if (len_rem <= len_rand)	// submit the rest of the job as LAST
227 						ctx = sha1_ctx_mgr_submit(mgr,
228 									  &ctxpool[j],
229 									  buf_ptr[j],
230 									  len_rem, HASH_LAST);
231 					else	// submit the random update length as UPDATE
232 						ctx = sha1_ctx_mgr_submit(mgr,
233 									  &ctxpool[j],
234 									  buf_ptr[j],
235 									  len_rand,
236 									  HASH_UPDATE);
237 				}	// Either continue submitting any contexts returned here as UPDATE/LAST, or
238 				// go back to submitting new jobs using the index i.
239 
240 				i++;
241 			}
242 		}
243 
244 		// Start flushing finished jobs, end on last flushed
245 		ctx = sha1_ctx_mgr_flush(mgr);
246 		while (ctx) {
247 			if (hash_ctx_complete(ctx)) {
248 				debug_char('-');
249 				ctx = sha1_ctx_mgr_flush(mgr);
250 				continue;
251 			}
252 			// Resubmit unfinished job
253 			i = (unsigned long)(ctx->user_data);
254 			buf_ptr[i] = bufs[i] + ctx->total_length;	// update buffer pointer
255 			len_rem = lens[i] - ctx->total_length;
256 			len_rand = (rand() % SHA1_BLOCK_SIZE)
257 			    * (rand() % MAX_RAND_UPDATE_BLOCKS);
258 			debug_char('+');
259 			if (len_rem <= len_rand)
260 				ctx = sha1_ctx_mgr_submit(mgr,
261 							  &ctxpool[i],
262 							  buf_ptr[i], len_rem, HASH_LAST);
263 			else
264 				ctx = sha1_ctx_mgr_submit(mgr,
265 							  &ctxpool[i],
266 							  buf_ptr[i], len_rand, HASH_UPDATE);
267 
268 			if (ctx == NULL)
269 				ctx = sha1_ctx_mgr_flush(mgr);
270 		}
271 
272 		// Check result digest
273 		for (i = 0; i < jobs; i++) {
274 			for (j = 0; j < SHA1_DIGEST_NWORDS; j++) {
275 				if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) {
276 					fail++;
277 					printf("Test%d, digest%d fail %8X <=> %8X\n",
278 					       i, j, ctxpool[i].job.result_digest[j],
279 					       digest_ref[i][j]);
280 				}
281 			}
282 		}
283 		if (fail) {
284 			printf("Test failed function check %d\n", fail);
285 			goto end;
286 		}
287 
288 		putchar('.');
289 		fflush(0);
290 	}			// random test t
291 
292       end:
293 	for (i = 0; i < TEST_BUFS; i++)
294 		free(bufs[i]);
295 	aligned_free(mgr);
296 
297 	if (fail)
298 		printf("Test failed function check %d\n", fail);
299 	else
300 		printf(" multibinary_sha1_update rand: Pass\n");
301 
302 	return fail;
303 }
304