1 2 #include <pthread.h> 3 #include <sys/time.h> 4 #include <sys/types.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdbool.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include "isal_multithread_perf.h" 12 13 struct aes_context { 14 int const bits; 15 int (*const preproc)(struct aes_context *pCtx); 16 void (*const processor)(struct aes_context *pCtx, char *plaintext, char *ciphertext, 17 uint64_t len); 18 void (*const postproc)(struct aes_context *pCtx); 19 }; 20 21 #define rounds_buf 2 /* first one is plain text, second is cipher text */ 22 23 static uint64_t 24 aes_thread_func(int32_t id, struct aes_context *pCtx) 25 { 26 uint32_t i = 0, j = 0; 27 char *aes_buf[rounds_buf] = { NULL }; /* aes buf is used to do checksum compute */ 28 char *carry_buf[rounds_buf] = { NULL }; /* carry buf is used to do memory movement */ 29 uint64_t round = -1; 30 struct timeval start_tv, stop_tv; 31 long long secs = run_secs; 32 33 printfv("Thread %i is started\n", id); 34 /* memory allocate */ 35 for (j = 0; j < rounds_buf; j++) { 36 carry_buf[j] = (char *) calloc((size_t) buflen, 1); 37 if (carry_buf[j] == NULL) { 38 printf("calloc failed test aborted\n"); 39 goto out; 40 } 41 42 aes_buf[j] = (char *) calloc((size_t) buflen, 1); 43 if (aes_buf[j] == NULL) { 44 printf("calloc failed test aborted\n"); 45 goto out; 46 } 47 48 /* Create the random data */ 49 for (i = 0; i < buflen; i += 1024) { 50 carry_buf[j][i] = i % 256; 51 aes_buf[j][i] = i % 256; 52 } 53 } 54 55 if (pCtx->preproc(pCtx)) { 56 printf("preproc failed test aborted\n"); 57 goto out; 58 } 59 60 /* Thread sync */ 61 pthread_mutex_lock(&count_lock); 62 count++; 63 if (count == num_threads) { 64 pthread_cond_broadcast(&count_cond); 65 } else { 66 pthread_cond_wait(&count_cond, &count_lock); 67 } 68 pthread_mutex_unlock(&count_lock); 69 70 printfv("Thread %i is ready\n", id); 71 /* hash func starts to run */ 72 round = 0; 73 gettimeofday(&start_tv, 0); 74 gettimeofday(&stop_tv, 0); 75 while (secs > (stop_tv.tv_sec - start_tv.tv_sec)) { 76 /* Pre mem-operation */ 77 if (prememcpy) 78 memcpy(aes_buf[0], carry_buf[0], buflen); 79 80 /* Calculate checksum */ 81 pCtx->processor(pCtx, aes_buf[0], aes_buf[1], buflen); 82 83 /* Post mem-operation */ 84 if (postmemcpy) 85 memcpy(carry_buf[1], aes_buf[1], buflen); 86 87 round++; 88 89 gettimeofday(&stop_tv, 0); 90 } 91 printfv("thread %2i, aes_func rounds %ld\n", id, round); 92 93 out: 94 pCtx->postproc(pCtx); 95 96 for (j = 0; j < rounds_buf; j++) { 97 free(carry_buf[j]); 98 free(aes_buf[j]); 99 } 100 101 return round; 102 } 103 104 /* 105 * facilities for AES-CBC 106 */ 107 static unsigned char const ic[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 108 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; 109 110 void 111 mk_rand_data(uint8_t *data, uint32_t size) 112 { 113 unsigned int i; 114 for (i = 0; i < size; i++) { 115 *data++ = rand(); 116 } 117 } 118 119 /* thread functions for cbc dec */ 120 struct cbc_context { 121 struct aes_context base; 122 uint8_t *iv; 123 uint8_t key[CBC_256_BITS]; 124 struct cbc_key_data *key_data; 125 }; 126 127 static int 128 cbc_dec_pre(struct aes_context *p) 129 { 130 struct cbc_context *pCtx = (struct cbc_context *) p; 131 int ret; 132 133 ret = posix_memalign((void **) &pCtx->iv, 16, (CBC_IV_DATA_LEN)); 134 ret |= posix_memalign((void **) &pCtx->key_data, 16, (sizeof(*pCtx->key_data))); 135 136 if ((0 != ret) || (NULL == pCtx->iv) || (NULL == pCtx->key_data)) 137 return 1; 138 139 mk_rand_data(pCtx->key, sizeof(pCtx->key)); 140 memcpy(pCtx->iv, ic, CBC_IV_DATA_LEN); 141 aes_cbc_precomp(pCtx->key, pCtx->base.bits, pCtx->key_data); 142 143 return 0; 144 } 145 146 static void 147 cbc_dec_post(struct aes_context *p) 148 { 149 struct cbc_context *pCtx = (struct cbc_context *) p; 150 151 free(pCtx->iv); 152 free(pCtx->key_data); 153 154 return; 155 } 156 157 static void 158 cbc_dec_proc(struct aes_context *p, char *plaintext, char *ciphertext, uint64_t len) 159 { 160 struct cbc_context *pCtx = (struct cbc_context *) p; 161 162 if (pCtx->base.bits == 128) 163 aes_cbc_dec_128(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext, len); 164 else if (pCtx->base.bits == 192) 165 aes_cbc_dec_192(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext, len); 166 else if (pCtx->base.bits == 256) 167 aes_cbc_dec_256(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext, len); 168 else { 169 printf("unsupported cbc encryption bits %d\n", pCtx->base.bits); 170 exit(1); 171 } 172 173 return; 174 } 175 176 void * 177 cbc_128_dec_func(void *arg) 178 { 179 int32_t id = *((int *) arg); 180 uint64_t round = -1; 181 182 struct cbc_context ctx = { 183 { 128, cbc_dec_pre, cbc_dec_proc, cbc_dec_post }, NULL, { 0 }, NULL 184 }; 185 186 round = aes_thread_func(id, &ctx.base); 187 188 pthread_exit((void *) round); 189 } 190 191 void * 192 cbc_192_dec_func(void *arg) 193 { 194 int32_t id = *((int *) arg); 195 uint64_t round = -1; 196 197 struct cbc_context ctx = { 198 { 192, cbc_dec_pre, cbc_dec_proc, cbc_dec_post }, NULL, { 0 }, NULL 199 }; 200 201 round = aes_thread_func(id, &ctx.base); 202 203 pthread_exit((void *) round); 204 } 205 206 void * 207 cbc_256_dec_func(void *arg) 208 { 209 int32_t id = *((int *) arg); 210 uint64_t round = -1; 211 212 struct cbc_context ctx = { 213 { 256, cbc_dec_pre, cbc_dec_proc, cbc_dec_post }, NULL, { 0 }, NULL 214 }; 215 216 round = aes_thread_func(id, &ctx.base); 217 218 pthread_exit((void *) round); 219 } 220 221 /* 222 * thread functions for xts enc 223 */ 224 struct xts_content { 225 struct aes_context base; 226 unsigned char key1[16 * 2]; 227 unsigned char key2[16 * 2]; 228 unsigned char tinit[16]; 229 }; 230 231 static int 232 xts_enc_pre(struct aes_context *p) 233 { 234 struct xts_content *pCtx = (struct xts_content *) p; 235 236 mk_rand_data(pCtx->key1, pCtx->base.bits / 8); 237 mk_rand_data(pCtx->key2, pCtx->base.bits / 8); 238 mk_rand_data(pCtx->tinit, sizeof(pCtx->tinit)); 239 240 return 0; 241 } 242 243 static void 244 xts_enc_post(struct aes_context *p) 245 { 246 return; 247 } 248 249 static void 250 xts_enc_proc(struct aes_context *p, char *plaintext, char *ciphertext, uint64_t len) 251 { 252 struct xts_content *pCtx = (struct xts_content *) p; 253 254 if (pCtx->base.bits == 128) 255 XTS_AES_128_enc(pCtx->key2, pCtx->key1, pCtx->tinit, len, plaintext, ciphertext); 256 else if (pCtx->base.bits == 256) 257 XTS_AES_256_enc(pCtx->key2, pCtx->key1, pCtx->tinit, len, plaintext, ciphertext); 258 else { 259 printf("unsupported xts encryption bits %d\n", pCtx->base.bits); 260 exit(1); 261 } 262 263 return; 264 } 265 266 void * 267 xts_128_enc_func(void *arg) 268 { 269 int32_t id = *((int *) arg); 270 uint64_t round = -1; 271 272 struct xts_content ctx = { 273 { 128, xts_enc_pre, xts_enc_proc, xts_enc_post }, { 0 }, { 0 }, { 0 } 274 }; 275 276 round = aes_thread_func(id, &ctx.base); 277 278 pthread_exit((void *) round); 279 } 280 281 void * 282 xts_256_enc_func(void *arg) 283 { 284 int32_t id = *((int *) arg); 285 uint64_t round = -1; 286 287 struct xts_content ctx = { 288 { 256, xts_enc_pre, xts_enc_proc, xts_enc_post }, { 0 }, { 0 }, { 0 } 289 }; 290 291 round = aes_thread_func(id, &ctx.base); 292 293 pthread_exit((void *) round); 294 } 295 296 /* 297 * thread functions for gcm enc 298 */ 299 struct gcm_context { 300 struct aes_context base; 301 uint8_t *key; 302 unsigned char *iv; 303 unsigned char *aad; 304 unsigned char *gcm_tag; 305 struct gcm_key_data gkey; 306 struct gcm_context_data gctx; 307 }; 308 309 static int 310 gcm_enc_pre(struct aes_context *p) 311 { 312 uint8_t const IVend[] = GCM_IV_END_MARK; 313 314 struct gcm_context *pCtx = (struct gcm_context *) p; 315 316 pCtx->key = malloc(pCtx->base.bits / 8); 317 pCtx->iv = malloc(GCM_IV_LEN); 318 pCtx->gcm_tag = malloc(MAX_TAG_LEN); 319 pCtx->aad = malloc(AAD_LENGTH); 320 321 mk_rand_data(pCtx->aad, AAD_LENGTH); 322 323 mk_rand_data(pCtx->iv, GCM_IV_LEN); 324 memcpy(&pCtx->iv[GCM_IV_END_START], IVend, sizeof(IVend)); 325 326 mk_rand_data(pCtx->key, pCtx->base.bits / 8); 327 if (pCtx->base.bits == 128) 328 aes_gcm_pre_128(pCtx->key, &pCtx->gkey); 329 else 330 aes_gcm_pre_256(pCtx->key, &pCtx->gkey); 331 332 return 0; 333 } 334 335 static void 336 gcm_enc_post(struct aes_context *p) 337 { 338 struct gcm_context *pCtx = (struct gcm_context *) p; 339 340 free(pCtx->key); 341 free(pCtx->iv); 342 free(pCtx->gcm_tag); 343 free(pCtx->aad); 344 345 return; 346 } 347 348 static void 349 gcm_enc_proc(struct aes_context *p, char *plaintext, char *ciphertext, uint64_t len) 350 { 351 struct gcm_context *pCtx = (struct gcm_context *) p; 352 353 if (pCtx->base.bits == 128) 354 aes_gcm_enc_128(&pCtx->gkey, &pCtx->gctx, ciphertext, plaintext, len, pCtx->iv, 355 pCtx->aad, AAD_LENGTH, pCtx->gcm_tag, MAX_TAG_LEN); 356 else if (pCtx->base.bits == 256) 357 aes_gcm_enc_256(&pCtx->gkey, &pCtx->gctx, ciphertext, plaintext, len, pCtx->iv, 358 pCtx->aad, AAD_LENGTH, pCtx->gcm_tag, MAX_TAG_LEN); 359 else { 360 printf("unsupported gcm encryption bits %d\n", pCtx->base.bits); 361 exit(1); 362 } 363 364 return; 365 } 366 367 void * 368 gcm_128_enc_func(void *arg) 369 { 370 int32_t id = *((int *) arg); 371 uint64_t round = -1; 372 373 struct gcm_context ctx = { 374 { 128, gcm_enc_pre, gcm_enc_proc, gcm_enc_post }, NULL, NULL, NULL, NULL, { 0 } 375 }; 376 377 round = aes_thread_func(id, &ctx.base); 378 379 pthread_exit((void *) round); 380 } 381 382 void * 383 gcm_256_enc_func(void *arg) 384 { 385 int32_t id = *((int *) arg); 386 uint64_t round = -1; 387 388 struct gcm_context ctx = { 389 { 256, gcm_enc_pre, gcm_enc_proc, gcm_enc_post }, NULL, NULL, NULL, NULL, { 0 } 390 }; 391 392 round = aes_thread_func(id, &ctx.base); 393 394 pthread_exit((void *) round); 395 } 396