static int crypto_rfc4309_encrypt(struct aead_request *req) { req = crypto_rfc4309_crypt(req); return crypto_aead_encrypt(req); }
static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct lrw_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .table_ctx = &ctx->lrw_table, .crypt_ctx = aes_ctx(ctx->raw_aes_ctx), .crypt_fn = lrw_xts_encrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = lrw_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct lrw_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .table_ctx = &ctx->lrw_table, .crypt_ctx = aes_ctx(ctx->raw_aes_ctx), .crypt_fn = lrw_xts_decrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = lrw_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm); u32 *flags = &tfm->crt_flags; int err; /* key consists of keys of equal size concatenated, therefore * the length must be even */ if (keylen % 2) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } /* first half of xts-key is for crypt */ err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2); if (err) return err; /* second half of xts-key is for tweak */ return aes_set_key_common(tfm, ctx->raw_tweak_ctx, key + keylen / 2, keylen / 2); } static void aesni_xts_tweak(void *ctx, u8 *out, const u8 *in) { aesni_enc(ctx, out, in); } static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_encrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = xts_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_decrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = xts_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } #ifdef CONFIG_X86_64 static int rfc4106_init(struct crypto_tfm *tfm) { struct cryptd_aead *cryptd_tfm; struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *) PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN); struct crypto_aead *cryptd_child; struct aesni_rfc4106_gcm_ctx *child_ctx; cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0); if (IS_ERR(cryptd_tfm)) return PTR_ERR(cryptd_tfm); cryptd_child = cryptd_aead_child(cryptd_tfm); child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); memcpy(child_ctx, ctx, sizeof(*ctx)); ctx->cryptd_tfm = cryptd_tfm; tfm->crt_aead.reqsize = sizeof(struct aead_request) + crypto_aead_reqsize(&cryptd_tfm->base); return 0; } static void rfc4106_exit(struct crypto_tfm *tfm) { struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *) PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN); if (!IS_ERR(ctx->cryptd_tfm)) cryptd_free_aead(ctx->cryptd_tfm); return; } static void rfc4106_set_hash_subkey_done(struct crypto_async_request *req, int err) { struct aesni_gcm_set_hash_subkey_result *result = req->data; if (err == -EINPROGRESS) return; result->err = err; complete(&result->completion); } static int rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len) { struct crypto_ablkcipher *ctr_tfm; struct ablkcipher_request *req; int ret = -EINVAL; struct aesni_hash_subkey_req_data *req_data; ctr_tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, 0); if (IS_ERR(ctr_tfm)) return PTR_ERR(ctr_tfm); crypto_ablkcipher_clear_flags(ctr_tfm, ~0); ret = crypto_ablkcipher_setkey(ctr_tfm, key, key_len); if (ret) goto out_free_ablkcipher; ret = -ENOMEM; req = ablkcipher_request_alloc(ctr_tfm, GFP_KERNEL); if (!req) goto out_free_ablkcipher; req_data = kmalloc(sizeof(*req_data), GFP_KERNEL); if (!req_data) goto out_free_request; memset(req_data->iv, 0, sizeof(req_data->iv)); /* Clear the data in the hash sub key container to zero.*/ /* We want to cipher all zeros to create the hash sub key. */ memset(hash_subkey, 0, RFC4106_HASH_SUBKEY_SIZE); init_completion(&req_data->result.completion); sg_init_one(&req_data->sg, hash_subkey, RFC4106_HASH_SUBKEY_SIZE); ablkcipher_request_set_tfm(req, ctr_tfm); ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, rfc4106_set_hash_subkey_done, &req_data->result); ablkcipher_request_set_crypt(req, &req_data->sg, &req_data->sg, RFC4106_HASH_SUBKEY_SIZE, req_data->iv); ret = crypto_ablkcipher_encrypt(req); if (ret == -EINPROGRESS || ret == -EBUSY) { ret = wait_for_completion_interruptible (&req_data->result.completion); if (!ret) ret = req_data->result.err; } kfree(req_data); out_free_request: ablkcipher_request_free(req); out_free_ablkcipher: crypto_free_ablkcipher(ctr_tfm); return ret; } static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, unsigned int key_len) { int ret = 0; struct crypto_tfm *tfm = crypto_aead_tfm(parent); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); struct aesni_rfc4106_gcm_ctx *child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); u8 *new_key_align, *new_key_mem = NULL; if (key_len < 4) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } /*Account for 4 byte nonce at the end.*/ key_len -= 4; if (key_len != AES_KEYSIZE_128) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } memcpy(ctx->nonce, key + key_len, sizeof(ctx->nonce)); /*This must be on a 16 byte boundary!*/ if ((unsigned long)(&(ctx->aes_key_expanded.key_enc[0])) % AESNI_ALIGN) return -EINVAL; if ((unsigned long)key % AESNI_ALIGN) { /*key is not aligned: use an auxuliar aligned pointer*/ new_key_mem = kmalloc(key_len+AESNI_ALIGN, GFP_KERNEL); if (!new_key_mem) return -ENOMEM; new_key_align = PTR_ALIGN(new_key_mem, AESNI_ALIGN); memcpy(new_key_align, key, key_len); key = new_key_align; } if (!irq_fpu_usable()) ret = crypto_aes_expand_key(&(ctx->aes_key_expanded), key, key_len); else { kernel_fpu_begin(); ret = aesni_set_key(&(ctx->aes_key_expanded), key, key_len); kernel_fpu_end(); } /*This must be on a 16 byte boundary!*/ if ((unsigned long)(&(ctx->hash_subkey[0])) % AESNI_ALIGN) { ret = -EINVAL; goto exit; } ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len); memcpy(child_ctx, ctx, sizeof(*ctx)); exit: kfree(new_key_mem); return ret; } /* This is the Integrity Check Value (aka the authentication tag length and can * be 8, 12 or 16 bytes long. */ static int rfc4106_set_authsize(struct crypto_aead *parent, unsigned int authsize) { struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); switch (authsize) { case 8: case 12: case 16: break; default: return -EINVAL; } crypto_aead_crt(parent)->authsize = authsize; crypto_aead_crt(cryptd_child)->authsize = authsize; return 0; } static int rfc4106_encrypt(struct aead_request *req) { int ret; struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); if (!irq_fpu_usable()) { struct aead_request *cryptd_req = (struct aead_request *) aead_request_ctx(req); memcpy(cryptd_req, req, sizeof(*req)); aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); return crypto_aead_encrypt(cryptd_req); } else { struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); kernel_fpu_begin(); ret = cryptd_child->base.crt_aead.encrypt(req); kernel_fpu_end(); return ret; } } static int rfc4106_decrypt(struct aead_request *req) { int ret; struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); if (!irq_fpu_usable()) { struct aead_request *cryptd_req = (struct aead_request *) aead_request_ctx(req); memcpy(cryptd_req, req, sizeof(*req)); aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); return crypto_aead_decrypt(cryptd_req); } else { struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); kernel_fpu_begin(); ret = cryptd_child->base.crt_aead.decrypt(req); kernel_fpu_end(); return ret; } }
static int tls_enc_record(struct aead_request *aead_req, struct crypto_aead *aead, char *aad, char *iv, __be64 rcd_sn, struct scatter_walk *in, struct scatter_walk *out, int *in_len) { unsigned char buf[TLS_HEADER_SIZE + TLS_CIPHER_AES_GCM_128_IV_SIZE]; struct scatterlist sg_in[3]; struct scatterlist sg_out[3]; u16 len; int rc; len = min_t(int, *in_len, ARRAY_SIZE(buf)); scatterwalk_copychunks(buf, in, len, 0); scatterwalk_copychunks(buf, out, len, 1); *in_len -= len; if (!*in_len) return 0; scatterwalk_pagedone(in, 0, 1); scatterwalk_pagedone(out, 1, 1); len = buf[4] | (buf[3] << 8); len -= TLS_CIPHER_AES_GCM_128_IV_SIZE; tls_make_aad(aad, len - TLS_CIPHER_AES_GCM_128_TAG_SIZE, (char *)&rcd_sn, sizeof(rcd_sn), buf[0]); memcpy(iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, buf + TLS_HEADER_SIZE, TLS_CIPHER_AES_GCM_128_IV_SIZE); sg_init_table(sg_in, ARRAY_SIZE(sg_in)); sg_init_table(sg_out, ARRAY_SIZE(sg_out)); sg_set_buf(sg_in, aad, TLS_AAD_SPACE_SIZE); sg_set_buf(sg_out, aad, TLS_AAD_SPACE_SIZE); chain_to_walk(sg_in + 1, in); chain_to_walk(sg_out + 1, out); *in_len -= len; if (*in_len < 0) { *in_len += TLS_CIPHER_AES_GCM_128_TAG_SIZE; /* the input buffer doesn't contain the entire record. * trim len accordingly. The resulting authentication tag * will contain garbage, but we don't care, so we won't * include any of it in the output skb * Note that we assume the output buffer length * is larger then input buffer length + tag size */ if (*in_len < 0) len += *in_len; *in_len = 0; } if (*in_len) { scatterwalk_copychunks(NULL, in, len, 2); scatterwalk_pagedone(in, 0, 1); scatterwalk_copychunks(NULL, out, len, 2); scatterwalk_pagedone(out, 1, 1); } len -= TLS_CIPHER_AES_GCM_128_TAG_SIZE; aead_request_set_crypt(aead_req, sg_in, sg_out, len, iv); rc = crypto_aead_encrypt(aead_req); return rc; }
int genKAT(unsigned long long plaintext_length, unsigned long long ad_length) { if((plaintext_length > (1<<31)) || (ad_length> (1<<31))) return 1; Init(); //For generating plaintext unsigned char *key = (unsigned char*)malloc(crypto_aead_KEYBYTES); unsigned char *nonce = (unsigned char*)malloc(crypto_aead_NPUBBYTES); unsigned char *ciphertext; unsigned long long ciphertext_length; unsigned long long decrypted_length; unsigned char *plaintext = (unsigned char*)malloc((size_t)plaintext_length); unsigned char *plaintext_decrypted = (unsigned char*)malloc((size_t)plaintext_length); plaintext_length = (size_t)plaintext_length; if(plaintext==NULL || plaintext_decrypted==NULL) return 1; unsigned char *associated_data = (unsigned char*)malloc((size_t)ad_length); if(associated_data==NULL) { free(plaintext); free(plaintext_decrypted); return 1; } //Plaintext initialization unsigned char StateIn[64]; memset(StateIn,0,64); unsigned char StateOut[64]; int counter= (int)plaintext_length; unsigned char *dest_pointer = plaintext; while(counter>0) { FPerm(StateIn,StateOut); unsigned to_copy = (counter<64)?counter:64; memcpy(dest_pointer,StateOut,to_copy); dest_pointer += to_copy; (*((unsigned*)StateIn))++; counter-= to_copy; } //AD initialization counter= (int) ad_length; dest_pointer = associated_data; while(counter>0) { FPerm(StateIn,StateOut); unsigned to_copy = (counter<64)?counter:64; memcpy(dest_pointer,StateOut,to_copy); dest_pointer += to_copy; (*((unsigned*)StateIn))++; counter-= to_copy; } //Key setting FPerm(StateIn,StateOut); memcpy(key,StateOut,crypto_aead_KEYBYTES); (*((unsigned*)StateIn))++; //Nonce setting FPerm(StateIn,StateOut); memcpy(nonce,StateOut,crypto_aead_NPUBBYTES); (*((unsigned*)StateIn))++; //Ciphertext memory allocation ciphertext = (unsigned char*)malloc((size_t)(plaintext_length+crypto_aead_ABYTES)); if(ciphertext==NULL) { free(plaintext); free(plaintext_decrypted); free(associated_data); return 1; } //Writing input FILE *fp=fopen("out.log","w+"); fprintf(fp, "PLAINTEXT (%llu bytes):\n",plaintext_length); for(unsigned i=0; i<plaintext_length; ++i) { fprintf(fp, "0x%.02x ",plaintext[i]); if(i%20==19) fprintf(fp, "\n"); } fprintf(fp, "\nASSOCIATED DATA (%llu bytes):\n", ad_length); for(unsigned i=0; i<ad_length; ++i) { fprintf(fp, "0x%.02x ",associated_data[i]); if(i%20==19) fprintf(fp, "\n"); } fprintf(fp, "\n"); fprintf(fp, "\nKEY (%d bytes):\n", crypto_aead_KEYBYTES); for(unsigned i=0; i<crypto_aead_KEYBYTES; ++i) fprintf(fp, "0x%.02x ",key[i]); fprintf(fp, "\n"); //Encryption and decryption #ifdef EXTRANONCE //ExtraNonce crypto_aead_encrypt_no_nonce(ciphertext,&ciphertext_length,plaintext,plaintext_length,associated_data, ad_length,NULL,nonce,key); int result = crypto_aead_decrypt(plaintext_decrypted,&decrypted_length,NULL,ciphertext,ciphertext_length,associated_data, ad_length,nonce,key); #else //Normal nonce crypto_aead_encrypt(ciphertext,&ciphertext_length,plaintext,plaintext_length,associated_data, ad_length,NULL,nonce,key); int result = crypto_aead_decrypt(plaintext_decrypted,&decrypted_length,NULL,ciphertext,ciphertext_length,associated_data, ad_length,nonce,key); #endif if(decrypted_length != plaintext_length) printf("Plaintext length mismatch\n"); //Writing outputs fprintf(fp, "\nNONCE (%d bytes):\n", crypto_aead_NPUBBYTES); for(unsigned i=0; i<crypto_aead_NPUBBYTES; ++i) fprintf(fp, "0x%.02x ",nonce[i]); fprintf(fp, ".\n"); printf("Decryption result: %d\n",result); fprintf(fp, "\nCIPHERTEXT (%llu bytes):\n", ciphertext_length); for(unsigned i=0; i<ciphertext_length; ++i) { fprintf(fp, "0x%.02x ",ciphertext[i]); if(i%20==19) fprintf(fp, "\n"); if(i == ciphertext_length - crypto_aead_ABYTES-1) fprintf(fp, " || "); } fprintf(fp, ".\n"); fprintf(fp, "\nDECRYPTED PLAINTEXT (%llu bytes):\n", decrypted_length); for(unsigned i=0; i<decrypted_length; ++i) { fprintf(fp, "0x%.02x ",plaintext_decrypted[i]); if(i%20==19) fprintf(fp, "\n"); } fprintf(fp, ".\n"); fclose(fp); free(plaintext); free(ciphertext); free(plaintext_decrypted); free(associated_data); return 0; }
static int aead_null_givencrypt(struct aead_givcrypt_request *req) { return crypto_aead_encrypt(&req->areq); }
static int seqiv_aead_encrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; u8 *info; unsigned int ivsize = 8; int err; if (req->cryptlen < ivsize) return -EINVAL; aead_request_set_tfm(subreq, ctx->child); compl = req->base.complete; data = req->base.data; info = req->iv; if (req->src != req->dst) { SKCIPHER_REQUEST_ON_STACK(nreq, ctx->sknull); skcipher_request_set_tfm(nreq, ctx->sknull); skcipher_request_set_callback(nreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(nreq, req->src, req->dst, req->assoclen + req->cryptlen, NULL); err = crypto_skcipher_encrypt(nreq); if (err) return err; } if (unlikely(!IS_ALIGNED((unsigned long)info, crypto_aead_alignmask(geniv) + 1))) { info = kmalloc(ivsize, req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: GFP_ATOMIC); if (!info) return -ENOMEM; memcpy(info, req->iv, ivsize); compl = seqiv_aead_encrypt_complete; data = req; } aead_request_set_callback(subreq, req->base.flags, compl, data); aead_request_set_crypt(subreq, req->dst, req->dst, req->cryptlen - ivsize, info); aead_request_set_ad(subreq, req->assoclen + ivsize); crypto_xor(info, ctx->salt, ivsize); scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); err = crypto_aead_encrypt(subreq); if (unlikely(info != req->iv)) seqiv_aead_encrypt_complete2(req, err); return err; }
int benchmark(unsigned long long plaintext_length, unsigned long long ad_length) { if ((plaintext_length >(1 << 31)) || (ad_length> (1 << 31))) return 1; Init(); //For generating plaintext unsigned char *key = (unsigned char*)malloc(key_bytes); unsigned char *nonce = (unsigned char*)malloc(nonce_bytes); unsigned char *ciphertext; unsigned long long ciphertext_length; unsigned long long decrypted_length; unsigned char *plaintext = (unsigned char*)malloc((size_t)plaintext_length); unsigned char *plaintext_decrypted = (unsigned char*)malloc((size_t)plaintext_length); plaintext_length = (size_t)plaintext_length; if (plaintext == NULL || plaintext_decrypted == NULL) return 1; unsigned char *associated_data = (unsigned char*)malloc((size_t)ad_length); if (associated_data == NULL) { free(plaintext); free(plaintext_decrypted); return 1; } //Plaintext initialization unsigned char StateIn[64]; memset(StateIn, 0, 64); unsigned char StateOut[64]; int counter = (int)plaintext_length; unsigned char *dest_pointer = plaintext; while (counter>0) { FPerm(StateIn, StateOut); unsigned to_copy = (counter<64) ? counter : 64; memcpy(dest_pointer, StateOut, to_copy); dest_pointer += to_copy; (*((unsigned*)StateIn))++; counter -= to_copy; } //AD initialization counter = (int) ad_length; dest_pointer = associated_data; while (counter>0) { FPerm(StateIn, StateOut); unsigned to_copy = (counter<64) ? counter : 64; memcpy(dest_pointer, StateOut, to_copy); dest_pointer += to_copy; (*((unsigned*)StateIn))++; counter -= to_copy; } //Key setting FPerm(StateIn, StateOut); memcpy(key, StateOut, key_bytes); (*((unsigned*)StateIn))++; //Nonce setting FPerm(StateIn, StateOut); memcpy(nonce, StateOut, nonce_bytes); (*((unsigned*)StateIn))++; //Ciphertext memory allocation ciphertext = (unsigned char*)malloc((size_t)(plaintext_length + tag_bytes)); if (ciphertext == NULL) { free(plaintext); free(plaintext_decrypted); free(associated_data); return 1; } uint64_t start_time, mid_time, end_time; uint32_t start_ptr, mid_ptr, end_ptr; start_time = __rdtscp(&start_ptr); #ifdef EXTRANONCE //ExtraNonce crypto_aead_encrypt_no_nonce(ciphertext, &ciphertext_length, plaintext, plaintext_length, associated_data, ad_length, NULL, nonce, key); #else crypto_aead_encrypt(ciphertext, &ciphertext_length, plaintext, plaintext_length, associated_data, ad_length, NULL, nonce, key); #endif mid_time = __rdtscp(&mid_ptr); float speed = (float)(mid_time - start_time) / (plaintext_length + ad_length); printf("PAEQ-128: %d bytes encrypted, %2.2f cpb\n", (uint32_t)(plaintext_length + ad_length), speed); mid_time = __rdtscp(&mid_ptr); int result = crypto_aead_decrypt(plaintext_decrypted, &decrypted_length, NULL, ciphertext, ciphertext_length, associated_data, ad_length, nonce, key); end_time = __rdtscp(&end_ptr); speed = (float)(end_time - mid_time) / (plaintext_length + ad_length); printf("PAEQ-128: %d bytes decrypted, %2.2f cpb\n", (uint32_t)(plaintext_length + ad_length), speed); if (decrypted_length != plaintext_length) printf("Plaintext length mismatch\n"); if (result!=0) printf("Decryption result: %d\n", result); free(ciphertext); free(plaintext_decrypted); free(associated_data); return 0; }
int main() { const unsigned char key[16] = {0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70}; unsigned char nonce[16] = {0x09,0xf9,0x11,0x02,0x9d,0x74,0xe3,0x5b,0xd8,0x41,0x56,0xc5,0x63,0x56,0x88,0xc0}; unsigned char in[4096], out[4096],adata[4096]; unsigned long long tag[16]; //asm volatile ("mcr p15, 0, %0, c15, c9, 0\n" : : "r" (1)); int i, j, k, l=100; // srand(time(NULL)); for (i=0; i<16*BLOCKS*l; i++) in[i] = (unsigned char)rand(); uint32_t overhead = rdtsc32(); overhead = rdtsc32() - overhead; uint32_t t0,t1; uint32_t tMin = 0xFFFFFFFF; /* big number to start */ printf("Cycles for calibrate: %d\n", overhead); for (j=0;j<1000;j++) crypto_aead_encrypt(out,tag,in,4096,0,0,0,nonce,key); printf("\nEncryption: \nWithout Adata\n"); for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,64,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(64)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,128,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(128)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,256,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(256))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,512,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(512))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,1024,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(1024))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,2048,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(2048))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,4096,0,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(4096))); tMin = 0xFFFFFFFF; /* big number to start */ printf("Cycles for calibrate: %d\n", overhead); for (j=0;j<1000;j++) crypto_aead_encrypt(out,tag,in,4096,0,0,0,nonce,key); printf("\nEncryption: \nWith Adata\n"); for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,64,adata,64,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(64)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,128,adata,128,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(128)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,256,adata,256,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(256))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,512,adata,512,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(512))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,1024,adata,1024,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(1024))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,2048,adata,2048,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(2048))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_encrypt(out,tag,in,4096,adata,4096,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(4096))); tMin = 0xFFFFFFFF; /* big number to start */ printf("\ndecryption: \nWithout Adata\n"); for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,64,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(64)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,128,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(128)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,256,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(256))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,512,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(512))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,1024,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(1024))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,2048,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(2048))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,4096,0,0,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(4096))); tMin = 0xFFFFFFFF; /* big number to start */ for (j=0;j<1000;j++) crypto_aead_decrypt(out,tag,0,in,4096,0,0,nonce,key); printf("\nDecryption: \nWith Adata\n"); for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,64,adata,64,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(64)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,128,adata,128,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/(((double)(128)))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,256,adata,256,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(256))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,512,adata,512,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(512))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,1024,adata,1024,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(1024))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,2048,adata,2048,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(2048))); tMin = 0xFFFFFFFF; /* big number to start */ for (k=0;k < TIMER_SAMPLE_CNT;k++) { t0 = rdtsc32(); crypto_aead_decrypt(out,tag,0,in,4096,adata,4096,nonce,key); t1 = rdtsc32(); if (tMin > t1-t0 - overhead) tMin = t1-t0 - overhead; } printf("Cycles for AEGIS: %d\n", tMin); printf("Cycles per byte: %f\n", tMin/((double)(4096))); return 0; }
static int echainiv_encrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; u8 *info; unsigned int ivsize = crypto_aead_ivsize(geniv); int err; if (req->cryptlen < ivsize) return -EINVAL; aead_request_set_tfm(subreq, ctx->child); compl = echainiv_encrypt_complete; data = req; info = req->iv; if (req->src != req->dst) { struct blkcipher_desc desc = { .tfm = ctx->null, }; err = crypto_blkcipher_encrypt( &desc, req->dst, req->src, req->assoclen + req->cryptlen); if (err) return err; } if (unlikely(!IS_ALIGNED((unsigned long)info, crypto_aead_alignmask(geniv) + 1))) { info = kmalloc(ivsize, req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: GFP_ATOMIC); if (!info) return -ENOMEM; memcpy(info, req->iv, ivsize); } aead_request_set_callback(subreq, req->base.flags, compl, data); aead_request_set_crypt(subreq, req->dst, req->dst, req->cryptlen, info); aead_request_set_ad(subreq, req->assoclen); crypto_xor(info, ctx->salt, ivsize); scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); echainiv_read_iv(info, ivsize); err = crypto_aead_encrypt(subreq); echainiv_encrypt_complete2(req, err); return err; } static int echainiv_decrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; unsigned int ivsize = crypto_aead_ivsize(geniv); if (req->cryptlen < ivsize) return -EINVAL; aead_request_set_tfm(subreq, ctx->child); compl = req->base.complete; data = req->base.data; aead_request_set_callback(subreq, req->base.flags, compl, data); aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen - ivsize, req->iv); aead_request_set_ad(subreq, req->assoclen + ivsize); scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); return crypto_aead_decrypt(subreq); } static int echainiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb) { struct aead_instance *inst; struct crypto_aead_spawn *spawn; struct aead_alg *alg; int err; inst = aead_geniv_alloc(tmpl, tb, 0, 0); if (IS_ERR(inst)) return PTR_ERR(inst); spawn = aead_instance_ctx(inst); alg = crypto_spawn_aead_alg(spawn); err = -EINVAL; if (inst->alg.ivsize & (sizeof(u32) - 1) || inst->alg.ivsize > MAX_IV_SIZE) goto free_inst; inst->alg.encrypt = echainiv_encrypt; inst->alg.decrypt = echainiv_decrypt; inst->alg.init = aead_init_geniv; inst->alg.exit = aead_exit_geniv; inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); inst->alg.base.cra_ctxsize += inst->alg.ivsize; inst->free = aead_geniv_free; err = aead_register_instance(tmpl, inst); if (err) goto free_inst; out: return err; free_inst: aead_geniv_free(inst); goto out; } static void echainiv_free(struct crypto_instance *inst) { aead_geniv_free(aead_instance(inst)); }