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