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