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