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