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