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 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 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