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