1 /**********************************************************************
2 Copyright(c) 2020 Arm 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 Arm 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 <string.h>
33
34 #ifndef FIPS_MODE
35 #include "sm3_mb.h"
36
37 typedef struct {
38 const char *msg;
39 uint32_t resultDigest[ISAL_SM3_DIGEST_NWORDS];
40 } TestData;
41
42 static TestData test_data[] = {
43 { .msg = "abc",
44 .resultDigest = { 0xf4f0c766, 0xd9edee62, 0x6bd4f2d1, 0xe2e410dc, 0x87c46741, 0xa2f7f25c,
45 0x2ba07d29, 0xe0a84b8f } },
46 { .msg = "abcdabcdabcdabcdabcdabcdabcdabcd"
47 "abcdabcdabcdabcdabcdabcdabcdabcd",
48 .resultDigest = { 0xf99fbede, 0xa1b87522, 0x89486038, 0x4d5a8ec1, 0xe570db6f, 0x65577e38,
49 0xa3cb3d29, 0x32570c9c }
50
51 },
52 { .msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
53 .resultDigest = { 0xc56c9b63, 0x379e4de6, 0x92b190a3, 0xeaa14fdf, 0x74ab2007, 0xb992f67f,
54 0x664e8cf3, 0x058c7bad } },
55
56 { .msg = "0123456789:;<=>?@ABCDEFGHIJKLMNO",
57 .resultDigest = { 0x076833d0, 0xd089ec39, 0xad857685, 0x8089797a, 0x9df9e8fd, 0x4126eb9a,
58 0xf38c22e8, 0x054bb846 } },
59 { .msg = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
60 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
61 "0123456789:;<",
62 .resultDigest = { 0x6cb9d38e, 0x846ac99e, 0x6d05634b, 0x3fe1bb26, 0x90368c4b, 0xee8c4299,
63 0x08c0e96a, 0x2233cdc7 } },
64 { .msg = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
65 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
66 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
67 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQR",
68 .resultDigest = { 0x83758189, 0x050f14d1, 0x91d8a730, 0x4a2825e4, 0x11723273, 0x2114ee3f,
69 0x18cac172, 0xa9c5b07a } },
70 {
71 .msg = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
72 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
73 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
74 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
75 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
76 "0123456789:;<=>?",
77 .resultDigest = { 0xb80f8aba, 0x55e96119, 0x851ac77b, 0xae31b3a5, 0x1333e764,
78 0xc86ac40d, 0x34878db1, 0x7da873f6 },
79 },
80 { .msg = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
81 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
82 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
83 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
84 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
85 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX"
86 "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU",
87 .resultDigest = { 0xbd5736a7, 0x55977d13, 0xa950c78a, 0x71eeb7cb, 0xe9ef0ba5, 0x95a9302e,
88 0x155e5c33, 0xad96ce3c } },
89 { .msg = "",
90 .resultDigest = { 0x831db21a, 0x7fa1cf55, 0x4819618e, 0x8f1ae831, 0xc7c8be22, 0x74fbfe28,
91 0xeb35d07e, 0x2baa8250 }
92
93 },
94
95 };
96
97 #define MSGS sizeof(test_data) / sizeof(TestData)
98 #define NUM_JOBS 1000
99
100 #define PSEUDO_RANDOM_NUM(seed) ((seed) * 5 + ((seed) * (seed)) / 64) % MSGS
101
102 #define NUM_CHUNKS 4
103 #define DATA_BUF_LEN 4096
104 int
non_blocksize_updates_test(ISAL_SM3_HASH_CTX_MGR * mgr)105 non_blocksize_updates_test(ISAL_SM3_HASH_CTX_MGR *mgr)
106 {
107 ISAL_SM3_HASH_CTX ctx_refer;
108 ISAL_SM3_HASH_CTX ctx_pool[NUM_CHUNKS];
109 ISAL_SM3_HASH_CTX *ctx = NULL;
110
111 const int update_chunks[NUM_CHUNKS] = { 32, 64, 128, 256 };
112 unsigned char data_buf[DATA_BUF_LEN];
113
114 memset(data_buf, 0xA, DATA_BUF_LEN);
115
116 // Init contexts before first use
117 isal_hash_ctx_init(&ctx_refer);
118
119 if (isal_sm3_ctx_mgr_submit(mgr, &ctx_refer, &ctx, data_buf, DATA_BUF_LEN,
120 ISAL_HASH_ENTIRE) != 0)
121 return -1;
122
123 if (isal_sm3_ctx_mgr_flush(mgr, &ctx) != 0)
124 return -1;
125
126 for (int c = 0; c < NUM_CHUNKS; c++) {
127 const int chunk = update_chunks[c];
128
129 isal_hash_ctx_init(&ctx_pool[c]);
130 for (int i = 0; i * chunk < DATA_BUF_LEN; i++) {
131 const ISAL_HASH_CTX_FLAG flags =
132 (i == 0) ? ISAL_HASH_FIRST : ISAL_HASH_UPDATE;
133
134 if (isal_sm3_ctx_mgr_submit(mgr, &ctx_pool[c], &ctx, data_buf + i * chunk,
135 chunk, flags) != 0)
136 return -1;
137 if (isal_sm3_ctx_mgr_flush(mgr, &ctx) != 0)
138 return -1;
139 }
140 }
141
142 for (int c = 0; c < NUM_CHUNKS; c++) {
143 if (isal_sm3_ctx_mgr_submit(mgr, &ctx_pool[c], &ctx, NULL, 0, ISAL_HASH_LAST) != 0)
144 return -1;
145 if (isal_sm3_ctx_mgr_flush(mgr, &ctx) != 0)
146 return -1;
147 if (ctx_pool[c].status != ISAL_HASH_CTX_STS_COMPLETE)
148 return -1;
149 for (int i = 0; i < ISAL_SM3_DIGEST_NWORDS; i++) {
150 if (ctx_refer.job.result_digest[i] != ctx_pool[c].job.result_digest[i]) {
151 printf("sm3 calc error! chunk %d, digest[%d], (%d) != (%d)\n",
152 update_chunks[c], i, ctx_refer.job.result_digest[i],
153 ctx_pool[c].job.result_digest[i]);
154 return -2;
155 }
156 }
157 }
158 return 0;
159 }
160 #endif /* !FIPS_MODE */
161
162 int
main(void)163 main(void)
164 {
165 #ifndef FIPS_MODE
166 ISAL_SM3_HASH_CTX_MGR *mgr = NULL;
167 ISAL_SM3_HASH_CTX ctxpool[NUM_JOBS], *ctx = NULL;
168 uint32_t i, j, k, t, checked = 0;
169 uint32_t *good;
170 int rc, ret = -1;
171 rc = posix_memalign((void *) &mgr, 16, sizeof(ISAL_SM3_HASH_CTX_MGR));
172 if (rc) {
173 printf("alloc error: Fail");
174 return -1;
175 }
176 isal_sm3_ctx_mgr_init(mgr);
177 // Init contexts before first use
178 for (i = 0; i < MSGS; i++) {
179 isal_hash_ctx_init(&ctxpool[i]);
180 ctxpool[i].user_data = (void *) ((uint64_t) i);
181 }
182
183 for (i = 0; i < MSGS; i++) {
184 const int errc = isal_sm3_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, test_data[i].msg,
185 strlen((char *) test_data[i].msg),
186 ISAL_HASH_ENTIRE);
187
188 if (errc == 0) {
189 if (ctx != NULL) {
190 t = (unsigned long) (uintptr_t) (ctx->user_data);
191 good = test_data[t].resultDigest;
192 checked++;
193 for (j = 0; j < ISAL_SM3_DIGEST_NWORDS; j++) {
194 if (good[j] != ctxpool[t].job.result_digest[j]) {
195 printf("Test %d, digest %d is %08X, should be "
196 "%08X\n",
197 t, j, ctxpool[t].job.result_digest[j],
198 good[j]);
199 goto end;
200 }
201 }
202 }
203 } else {
204 printf("Something bad happened during the submit. Error code: %d", errc);
205 goto end;
206 }
207 }
208
209 while (1) {
210 const int errc = isal_sm3_ctx_mgr_flush(mgr, &ctx);
211
212 if (errc == 0) {
213 if (ctx == NULL)
214 break;
215
216 t = (unsigned long) (uintptr_t) (ctx->user_data);
217 good = test_data[t].resultDigest;
218 checked++;
219 for (j = 0; j < ISAL_SM3_DIGEST_NWORDS; j++) {
220 if (good[j] != ctxpool[t].job.result_digest[j]) {
221 printf("Test %d, digest %d is %08X, should be %08X\n", t, j,
222 ctxpool[t].job.result_digest[j], good[j]);
223 goto end;
224 }
225 }
226 } else {
227 printf("Something bad happened during the flush. Error code: %d", errc);
228 goto end;
229 }
230 }
231
232 // do larger test in pseudo-random order
233
234 // Init contexts before first use
235 for (i = 0; i < NUM_JOBS; i++) {
236 isal_hash_ctx_init(&ctxpool[i]);
237 ctxpool[i].user_data = (void *) ((uint64_t) i);
238 }
239
240 checked = 0;
241 for (i = 0; i < NUM_JOBS; i++) {
242 j = PSEUDO_RANDOM_NUM(i);
243
244 const int errc = isal_sm3_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, test_data[j].msg,
245 strlen((char *) test_data[j].msg),
246 ISAL_HASH_ENTIRE);
247 if (errc == 0) {
248 if (ctx != NULL) {
249 t = (unsigned long) (uintptr_t) (ctx->user_data);
250 k = PSEUDO_RANDOM_NUM(t);
251 good = test_data[k].resultDigest;
252 checked++;
253 for (j = 0; j < ISAL_SM3_DIGEST_NWORDS; j++) {
254 if (good[j] != ctxpool[t].job.result_digest[j]) {
255 printf("Test %d, digest %d is %08X, should be "
256 "%08X\n",
257 t, j, ctxpool[t].job.result_digest[j],
258 good[j]);
259 goto end;
260 }
261 }
262 }
263 } else {
264 printf("Something bad happened during the submit. Error code: %d", errc);
265 goto end;
266 }
267 }
268 while (1) {
269 const int errc = isal_sm3_ctx_mgr_flush(mgr, &ctx);
270
271 if (errc == 0) {
272 if (ctx == NULL)
273 break;
274
275 t = (unsigned long) (uintptr_t) (ctx->user_data);
276 k = PSEUDO_RANDOM_NUM(t);
277 good = test_data[k].resultDigest;
278 checked++;
279 for (j = 0; j < ISAL_SM3_DIGEST_NWORDS; j++) {
280 if (good[j] != ctxpool[t].job.result_digest[j]) {
281 printf("Test %d, digest %d is %08X, should be %08X\n", t, j,
282 ctxpool[t].job.result_digest[j], good[j]);
283 goto end;
284 }
285 }
286 } else {
287 printf("Something bad happened during the flush. Error code: %d", errc);
288 goto end;
289 }
290 }
291
292 if (checked != NUM_JOBS) {
293 printf("only tested %d rather than %d\n", checked, NUM_JOBS);
294 goto end;
295 }
296
297 rc = non_blocksize_updates_test(mgr);
298 if (rc) {
299 printf("multi updates test fail %d\n", rc);
300 goto end;
301 }
302 ret = 0;
303
304 printf(" multibinary_sm3 test: Pass\n");
305 end:
306 aligned_free(mgr);
307
308 return ret;
309 #else
310 printf("Not Executed\n");
311 return 0;
312 #endif /* FIPS_MODE */
313 }
314