1 /********************************************************************** 2 Copyright(c) 2011-2016 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 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include "sha512_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 * ISAL_SHA512_BLOCK_SIZE 44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * ISAL_SHA512_BLOCK_SIZE)) 45 46 #ifdef DEBUG 47 #define debug_char(x) putchar(x) 48 #else 49 #define debug_char(x) \ 50 do { \ 51 } while (0) 52 #endif 53 54 /* Reference digest global to reduce stack usage */ 55 static uint64_t digest_ref[TEST_BUFS][ISAL_SHA512_DIGEST_NWORDS]; 56 57 extern void 58 sha512_ref(uint8_t *input_data, uint64_t *digest, uint32_t len); 59 60 // Generates pseudo-random data 61 62 void 63 rand_buffer(unsigned char *buf, const long buffer_size) 64 { 65 long i; 66 for (i = 0; i < buffer_size; i++) 67 buf[i] = rand(); 68 } 69 70 int 71 main(void) 72 { 73 ISAL_SHA512_HASH_CTX_MGR *mgr = NULL; 74 ISAL_SHA512_HASH_CTX ctxpool[TEST_BUFS], *ctx = NULL; 75 uint32_t i, j, fail = 0; 76 uint32_t len_done, len_rem, len_rand; 77 unsigned char *bufs[TEST_BUFS]; 78 unsigned char *buf_ptr[TEST_BUFS]; 79 uint32_t lens[TEST_BUFS]; 80 unsigned int joblen, jobs, t; 81 int ret; 82 83 printf("multibinary_sha512_update test, %d sets of %dx%d max: ", RANDOMS, TEST_BUFS, 84 TEST_LEN); 85 86 srand(TEST_SEED); 87 88 ret = posix_memalign((void *) &mgr, 16, sizeof(ISAL_SHA512_HASH_CTX_MGR)); 89 if ((ret != 0) || (mgr == NULL)) { 90 printf("posix_memalign failed test aborted\n"); 91 return 1; 92 } 93 94 ret = isal_sha512_ctx_mgr_init(mgr); 95 if (ret) 96 return 1; 97 98 for (i = 0; i < TEST_BUFS; i++) { 99 // Allocate and fill buffer 100 bufs[i] = (unsigned char *) malloc(TEST_LEN); 101 buf_ptr[i] = bufs[i]; 102 if (bufs[i] == NULL) { 103 printf("malloc failed test aborted\n"); 104 fail++; 105 goto end; 106 } 107 rand_buffer(bufs[i], TEST_LEN); 108 109 // Init ctx contents 110 isal_hash_ctx_init(&ctxpool[i]); 111 ctxpool[i].user_data = (void *) ((uint64_t) i); 112 113 // Run reference test 114 sha512_ref(bufs[i], digest_ref[i], TEST_LEN); 115 } 116 117 // Run sb_sha512 tests 118 for (i = 0; i < TEST_BUFS;) { 119 len_done = (uint32_t) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]); 120 len_rem = TEST_LEN - len_done; 121 122 if (len_done == 0) 123 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 124 UPDATE_SIZE, ISAL_HASH_FIRST); 125 else if (len_rem <= UPDATE_SIZE) 126 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 127 len_rem, ISAL_HASH_LAST); 128 else 129 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 130 UPDATE_SIZE, ISAL_HASH_UPDATE); 131 if (ret) 132 return 1; 133 134 // Add jobs while available or finished 135 if ((ctx == NULL) || isal_hash_ctx_complete(ctx)) { 136 i++; 137 continue; 138 } 139 // Resubmit unfinished job 140 i = (unsigned long) (uintptr_t) (ctx->user_data); 141 buf_ptr[i] += UPDATE_SIZE; 142 } 143 144 // Start flushing finished jobs, end on last flushed 145 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 146 if (ret) 147 return 1; 148 while (ctx) { 149 if (isal_hash_ctx_complete(ctx)) { 150 debug_char('-'); 151 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 152 if (ret) 153 return 1; 154 continue; 155 } 156 // Resubmit unfinished job 157 i = (unsigned long) (uintptr_t) (ctx->user_data); 158 buf_ptr[i] += UPDATE_SIZE; 159 160 len_done = (int) ((uintptr_t) buf_ptr[i] - (uintptr_t) bufs[i]); 161 len_rem = TEST_LEN - len_done; 162 163 if (len_rem <= UPDATE_SIZE) 164 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 165 len_rem, ISAL_HASH_LAST); 166 else 167 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 168 UPDATE_SIZE, ISAL_HASH_UPDATE); 169 if (ret) 170 return 1; 171 172 if (ctx == NULL) { 173 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 174 if (ret) 175 return 1; 176 } 177 } 178 179 // Check digests 180 for (i = 0; i < TEST_BUFS; i++) { 181 for (j = 0; j < ISAL_SHA512_DIGEST_NWORDS; j++) { 182 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) { 183 fail++; 184 printf("Test%d fixed size, digest%d fail %8llX <=> %8llX", i, j, 185 (unsigned long long) ctxpool[i].job.result_digest[j], 186 (unsigned long long) digest_ref[i][j]); 187 } 188 } 189 } 190 putchar('.'); 191 192 // Run tests with random size and number of jobs 193 for (t = 0; t < RANDOMS; t++) { 194 jobs = rand() % (TEST_BUFS); 195 196 for (i = 0; i < jobs; i++) { 197 joblen = rand() % (TEST_LEN); 198 rand_buffer(bufs[i], joblen); 199 lens[i] = joblen; 200 buf_ptr[i] = bufs[i]; 201 sha512_ref(bufs[i], digest_ref[i], lens[i]); 202 } 203 204 ret = isal_sha512_ctx_mgr_init(mgr); 205 if (ret) 206 return 1; 207 208 // Run sha512_sb jobs 209 i = 0; 210 while (i < jobs) { 211 // Submit a new job 212 len_rand = ISAL_SHA512_BLOCK_SIZE + 213 ISAL_SHA512_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS); 214 215 if (lens[i] > len_rand) 216 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 217 len_rand, ISAL_HASH_FIRST); 218 else 219 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 220 lens[i], ISAL_HASH_ENTIRE); 221 if (ret) 222 return 1; 223 224 // Returned ctx could be: 225 // - null context (we are just getting started and lanes aren't full yet), 226 // or 227 // - finished already (an ENTIRE we submitted or a previous LAST is 228 // returned), or 229 // - an unfinished ctx, we will resubmit 230 231 if ((ctx == NULL) || isal_hash_ctx_complete(ctx)) { 232 i++; 233 continue; 234 } else { 235 // unfinished ctx returned, choose another random update length and 236 // submit either UPDATE or LAST depending on the amount of buffer 237 // remaining 238 while ((ctx != NULL) && !(isal_hash_ctx_complete(ctx))) { 239 j = (unsigned long) (uintptr_t) (ctx->user_data); // Get 240 // index 241 // of the 242 // returned 243 // ctx 244 buf_ptr[j] = bufs[j] + ctx->total_length; 245 len_rand = (rand() % ISAL_SHA512_BLOCK_SIZE) * 246 (rand() % MAX_RAND_UPDATE_BLOCKS); 247 len_rem = lens[j] - (uint32_t) ctx->total_length; 248 249 if (len_rem <= 250 len_rand) // submit the rest of the job as LAST 251 ret = isal_sha512_ctx_mgr_submit( 252 mgr, &ctxpool[j], &ctx, buf_ptr[j], len_rem, 253 ISAL_HASH_LAST); 254 else // submit the random update length as UPDATE 255 ret = isal_sha512_ctx_mgr_submit( 256 mgr, &ctxpool[j], &ctx, buf_ptr[j], 257 len_rand, ISAL_HASH_UPDATE); 258 if (ret) 259 return 1; 260 } // Either continue submitting any contexts returned here as 261 // UPDATE/LAST, or 262 // go back to submitting new jobs using the index i. 263 264 i++; 265 } 266 } 267 268 // Start flushing finished jobs, end on last flushed 269 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 270 if (ret) 271 return 1; 272 while (ctx) { 273 if (isal_hash_ctx_complete(ctx)) { 274 debug_char('-'); 275 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 276 if (ret) 277 return 1; 278 continue; 279 } 280 // Resubmit unfinished job 281 i = (unsigned long) (uintptr_t) (ctx->user_data); 282 buf_ptr[i] = bufs[i] + ctx->total_length; // update buffer pointer 283 len_rem = lens[i] - (uint32_t) ctx->total_length; 284 len_rand = (rand() % ISAL_SHA512_BLOCK_SIZE) * 285 (rand() % MAX_RAND_UPDATE_BLOCKS); 286 debug_char('+'); 287 if (len_rem <= len_rand) 288 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 289 len_rem, ISAL_HASH_LAST); 290 else 291 ret = isal_sha512_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 292 len_rand, ISAL_HASH_UPDATE); 293 if (ret) 294 return 1; 295 296 if (ctx == NULL) { 297 ret = isal_sha512_ctx_mgr_flush(mgr, &ctx); 298 if (ret) 299 return 1; 300 } 301 } 302 303 // Check result digest 304 for (i = 0; i < jobs; i++) { 305 for (j = 0; j < ISAL_SHA512_DIGEST_NWORDS; j++) { 306 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) { 307 fail++; 308 printf("Test%d, digest%d fail %8llX <=> %8llX\n", i, j, 309 (unsigned long long) ctxpool[i].job.result_digest[j], 310 (unsigned long long) digest_ref[i][j]); 311 } 312 } 313 } 314 if (fail) { 315 printf("Test failed function check %d\n", fail); 316 goto end; 317 } 318 319 putchar('.'); 320 fflush(0); 321 } // random test t 322 323 end: 324 for (i = 0; i < TEST_BUFS; i++) 325 free(bufs[i]); 326 aligned_free(mgr); 327 328 if (fail) 329 printf("Test failed function check %d\n", fail); 330 else 331 printf(" multibinary_sha512_update rand: Pass\n"); 332 333 return fail; 334 } 335