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 "sha1_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 * SHA1_BLOCK_SIZE 44 #define MAX_RAND_UPDATE_BLOCKS (TEST_LEN / (16 * SHA1_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 uint32_t digest_ref[TEST_BUFS][SHA1_DIGEST_NWORDS]; 56 57 extern void 58 sha1_ref(uint8_t *input_data, uint32_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 SHA1_HASH_CTX_MGR *mgr = NULL; 74 SHA1_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] = { 0 }; 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_sha1_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(SHA1_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_sha1_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 hash_ctx_init(&ctxpool[i]); 111 ctxpool[i].user_data = (void *) ((uint64_t) i); 112 113 // Run reference test 114 sha1_ref(bufs[i], digest_ref[i], TEST_LEN); 115 } 116 117 // Run sb_sha1 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_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 124 UPDATE_SIZE, HASH_FIRST); 125 else if (len_rem <= UPDATE_SIZE) 126 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], len_rem, 127 HASH_LAST); 128 else 129 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 130 UPDATE_SIZE, HASH_UPDATE); 131 if (ret) 132 return 1; 133 134 // Add jobs while available or finished 135 if ((ctx == NULL) || hash_ctx_complete(ctx)) { 136 i++; 137 continue; 138 } 139 // Resubmit unfinished job 140 i = (uint32_t) (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_sha1_ctx_mgr_flush(mgr, &ctx); 146 if (ret) 147 return 1; 148 while (ctx) { 149 if (hash_ctx_complete(ctx)) { 150 debug_char('-'); 151 ret = isal_sha1_ctx_mgr_flush(mgr, &ctx); 152 if (ret) 153 return 1; 154 continue; 155 } 156 // Resubmit unfinished job 157 i = (uint32_t) (uintptr_t) (ctx->user_data); 158 buf_ptr[i] += UPDATE_SIZE; 159 160 len_done = (uint32_t) ((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_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], len_rem, 165 HASH_LAST); 166 else 167 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 168 UPDATE_SIZE, HASH_UPDATE); 169 if (ret) 170 return 1; 171 172 if (ctx == NULL) { 173 ret = isal_sha1_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 < SHA1_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 %8X <=> %8X", i, j, 185 ctxpool[i].job.result_digest[j], digest_ref[i][j]); 186 } 187 } 188 } 189 putchar('.'); 190 191 // Run tests with random size and number of jobs 192 for (t = 0; t < RANDOMS; t++) { 193 jobs = rand() % (TEST_BUFS); 194 195 for (i = 0; i < jobs; i++) { 196 joblen = rand() % (TEST_LEN); 197 rand_buffer(bufs[i], joblen); 198 lens[i] = joblen; 199 buf_ptr[i] = bufs[i]; 200 sha1_ref(bufs[i], digest_ref[i], lens[i]); 201 } 202 203 ret = isal_sha1_ctx_mgr_init(mgr); 204 if (ret) 205 return 1; 206 207 // Run sha1_sb jobs 208 i = 0; 209 while (i < jobs) { 210 // Submit a new job 211 len_rand = SHA1_BLOCK_SIZE + 212 SHA1_BLOCK_SIZE * (rand() % MAX_RAND_UPDATE_BLOCKS); 213 214 if (lens[i] > len_rand) 215 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 216 len_rand, HASH_FIRST); 217 else 218 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 219 lens[i], HASH_ENTIRE); 220 if (ret) 221 return 1; 222 223 // Returned ctx could be: 224 // - null context (we are just getting started and lanes aren't full yet), 225 // or 226 // - finished already (an ENTIRE we submitted or a previous LAST is 227 // returned), or 228 // - an unfinished ctx, we will resubmit 229 230 if ((ctx == NULL) || hash_ctx_complete(ctx)) { 231 i++; 232 continue; 233 } else { 234 // unfinished ctx returned, choose another random update length and 235 // submit either UPDATE or LAST depending on the amount of buffer 236 // remaining 237 while ((ctx != NULL) && !(hash_ctx_complete(ctx))) { 238 j = (uint32_t) (uintptr_t) (ctx->user_data); // Get index of 239 // the returned 240 // ctx 241 buf_ptr[j] = bufs[j] + ctx->total_length; 242 len_rand = (rand() % SHA1_BLOCK_SIZE) * 243 (rand() % MAX_RAND_UPDATE_BLOCKS); 244 len_rem = lens[j] - (uint32_t) ctx->total_length; 245 246 if (len_rem <= 247 len_rand) // submit the rest of the job as LAST 248 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[j], 249 &ctx, buf_ptr[j], 250 len_rem, HASH_LAST); 251 else // submit the random update length as UPDATE 252 ret = isal_sha1_ctx_mgr_submit( 253 mgr, &ctxpool[j], &ctx, buf_ptr[j], 254 len_rand, HASH_UPDATE); 255 if (ret) 256 return 1; 257 } // Either continue submitting any contexts returned here as 258 // UPDATE/LAST, or 259 // go back to submitting new jobs using the index i. 260 261 i++; 262 } 263 } 264 265 // Start flushing finished jobs, end on last flushed 266 ret = isal_sha1_ctx_mgr_flush(mgr, &ctx); 267 if (ret) 268 return 1; 269 while (ctx) { 270 if (hash_ctx_complete(ctx)) { 271 debug_char('-'); 272 ret = isal_sha1_ctx_mgr_flush(mgr, &ctx); 273 if (ret) 274 return 1; 275 continue; 276 } 277 // Resubmit unfinished job 278 i = (uint32_t) (uintptr_t) (ctx->user_data); 279 buf_ptr[i] = bufs[i] + ctx->total_length; // update buffer pointer 280 len_rem = lens[i] - (uint32_t) ctx->total_length; 281 len_rand = (rand() % SHA1_BLOCK_SIZE) * (rand() % MAX_RAND_UPDATE_BLOCKS); 282 debug_char('+'); 283 if (len_rem <= len_rand) 284 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 285 len_rem, HASH_LAST); 286 else 287 ret = isal_sha1_ctx_mgr_submit(mgr, &ctxpool[i], &ctx, buf_ptr[i], 288 len_rand, HASH_UPDATE); 289 if (ret) 290 return 1; 291 292 if (ctx == NULL) { 293 ret = isal_sha1_ctx_mgr_flush(mgr, &ctx); 294 if (ret) 295 return 1; 296 } 297 } 298 299 // Check result digest 300 for (i = 0; i < jobs; i++) { 301 for (j = 0; j < SHA1_DIGEST_NWORDS; j++) { 302 if (ctxpool[i].job.result_digest[j] != digest_ref[i][j]) { 303 fail++; 304 printf("Test%d, digest%d fail %8X <=> %8X\n", i, j, 305 ctxpool[i].job.result_digest[j], digest_ref[i][j]); 306 } 307 } 308 } 309 if (fail) { 310 printf("Test failed function check %d\n", fail); 311 goto end; 312 } 313 314 putchar('.'); 315 fflush(0); 316 } // random test t 317 318 end: 319 for (i = 0; i < TEST_BUFS; i++) 320 free(bufs[i]); 321 aligned_free(mgr); 322 323 if (fail) 324 printf("Test failed function check %d\n", fail); 325 else 326 printf(" multibinary_sha1_update rand: Pass\n"); 327 328 return fail; 329 } 330