static ctr128_f aes_gcm_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, const unsigned char *key, size_t key_len) { #ifdef BSAES_CAPABLE if (BSAES_CAPABLE) { AES_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); return (ctr128_f)bsaes_ctr32_encrypt_blocks; } else #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { vpaes_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt); return NULL; } else #endif (void)0; /* terminate potentially open 'else' */ AES_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); #ifdef AES_CTR_ASM return (ctr128_f)AES_ctr32_encrypt; #else return NULL; #endif }
static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = ctx->cipher_data; if (!iv && !key) return 1; if (key) { do { # ifdef BSAES_CAPABLE if (BSAES_CAPABLE) { AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks; break; } else # endif # ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) vpaes_encrypt); gctx->ctr = NULL; break; } else # endif (void)0; /* terminate potentially open 'else' */ AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); # ifdef AES_CTR_ASM gctx->ctr = (ctr128_f) AES_ctr32_encrypt; # else gctx->ctr = NULL; # endif } while (0); /* * If we have an iv can set it directly, otherwise use saved IV. */ if (iv == NULL && gctx->iv_set) iv = gctx->iv; if (iv) { CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); gctx->iv_set = 1; } gctx->key_set = 1; } else { /* If key set use IV, otherwise copy */ if (gctx->key_set) CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); else memcpy(gctx->iv, iv, gctx->ivlen); gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; }
ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, block128_f *out_block, const uint8_t *key, size_t key_bytes) { if (aesni_capable()) { aesni_set_encrypt_key(key, key_bytes * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt, 1); } if (out_block) { *out_block = (block128_f) aesni_encrypt; } return (ctr128_f)aesni_ctr32_encrypt_blocks; } if (hwaes_capable()) { aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt, 0); } if (out_block) { *out_block = (block128_f) aes_hw_encrypt; } return (ctr128_f)aes_hw_ctr32_encrypt_blocks; } if (bsaes_capable()) { AES_set_encrypt_key(key, key_bytes * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0); } if (out_block) { *out_block = (block128_f) AES_encrypt; } return (ctr128_f)bsaes_ctr32_encrypt_blocks; } if (vpaes_capable()) { vpaes_set_encrypt_key(key, key_bytes * 8, aes_key); if (out_block) { *out_block = (block128_f) vpaes_encrypt; } if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt, 0); } return NULL; } AES_set_encrypt_key(key, key_bytes * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0); } if (out_block) { *out_block = (block128_f) AES_encrypt; } return NULL; }
static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = ctx->cipher_data; if (!iv && !key) return 1; if (key) { aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt); gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks; /* If we have an iv can set it directly, otherwise use * saved IV. */ if (iv == NULL && gctx->iv_set) iv = gctx->iv; if (iv) { CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); gctx->iv_set = 1; } gctx->key_set = 1; } else { /* If key set use IV, otherwise copy */ if (gctx->key_set) CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); else memcpy(gctx->iv, iv, gctx->ivlen); gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; }
static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, int enc) { EVP_AES_GCM_CTX *gctx = ctx->cipher_data; if (!iv && !key) { return 1; } if (key) { aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt, 1); gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks; // If we have an iv can set it directly, otherwise use // saved IV. if (iv == NULL && gctx->iv_set) { iv = gctx->iv; } if (iv) { CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); gctx->iv_set = 1; } gctx->key_set = 1; } else { // If key set use IV, otherwise copy if (gctx->key_set) { CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); } else { OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen); } gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; }
static ctr128_f aes_gcm_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, const uint8_t *key, size_t key_len) { if (bsaes_capable()) { AES_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); return (ctr128_f)bsaes_ctr32_encrypt_blocks; } if (vpaes_capable()) { vpaes_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt); return NULL; } AES_set_encrypt_key(key, key_len * 8, aes_key); CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); return NULL; }
static void benchmark_gcm128(const unsigned char *K, size_t Klen, const unsigned char *IV, size_t IVlen) { #ifdef OPENSSL_CPUID_OBJ GCM128_CONTEXT ctx; AES_KEY key; uint32_t start, gcm_t, ctr_t; union { u64 u; u8 c[1024]; } buf; AES_set_encrypt_key(K, Klen * 8, &key); CRYPTO_gcm128_init(&ctx, &key, (block128_f) AES_encrypt); CRYPTO_gcm128_setiv(&ctx, IV, IVlen); CRYPTO_gcm128_encrypt(&ctx, buf.c, buf.c, sizeof(buf)); start = OPENSSL_rdtsc(); CRYPTO_gcm128_encrypt(&ctx, buf.c, buf.c, sizeof(buf)); gcm_t = OPENSSL_rdtsc() - start; CRYPTO_ctr128_encrypt(buf.c, buf.c, sizeof(buf), &key, ctx.Yi.c, ctx.EKi.c, &ctx.mres, (block128_f) AES_encrypt); start = OPENSSL_rdtsc(); CRYPTO_ctr128_encrypt(buf.c, buf.c, sizeof(buf), &key, ctx.Yi.c, ctx.EKi.c, &ctx.mres, (block128_f) AES_encrypt); ctr_t = OPENSSL_rdtsc() - start; printf("%.2f-%.2f=%.2f\n", gcm_t / (double)sizeof(buf), ctr_t / (double)sizeof(buf), (gcm_t - ctr_t) / (double)sizeof(buf)); # ifdef GHASH { void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], const u8 *inp, size_t len) = ctx.ghash; GHASH((&ctx), buf.c, sizeof(buf)); start = OPENSSL_rdtsc(); for (i = 0; i < 100; ++i) GHASH((&ctx), buf.c, sizeof(buf)); gcm_t = OPENSSL_rdtsc() - start; printf("%.2f\n", gcm_t / (double)sizeof(buf) / (double)i); } # endif #else fprintf(stderr, "Benchmarking of modes isn't available on this platform\n"); #endif }
static int test_gcm128(int idx) { unsigned char out[512]; SIZED_DATA K = gcm128_vectors[idx].K; SIZED_DATA IV = gcm128_vectors[idx].IV; SIZED_DATA A = gcm128_vectors[idx].A; SIZED_DATA P = gcm128_vectors[idx].P; SIZED_DATA C = gcm128_vectors[idx].C; SIZED_DATA T = gcm128_vectors[idx].T; GCM128_CONTEXT ctx; AES_KEY key; /* Size 1 inputs are special-cased to signal NULL. */ if (A.size == 1) A.data = NULL; if (P.size == 1) P.data = NULL; if (C.size == 1) C.data = NULL; AES_set_encrypt_key(K.data, K.size * 8, &key); CRYPTO_gcm128_init(&ctx, &key, (block128_f)AES_encrypt); CRYPTO_gcm128_setiv(&ctx, IV.data, IV.size); memset(out, 0, P.size); if (A.data != NULL) CRYPTO_gcm128_aad(&ctx, A.data, A.size); if (P.data != NULL) CRYPTO_gcm128_encrypt( &ctx, P.data, out, P.size); if (!TEST_false(CRYPTO_gcm128_finish(&ctx, T.data, 16)) || (C.data != NULL && !TEST_mem_eq(out, P.size, C.data, P.size))) return 0; CRYPTO_gcm128_setiv(&ctx, IV.data, IV.size); memset(out, 0, P.size); if (A.data != NULL) CRYPTO_gcm128_aad(&ctx, A.data, A.size); if (C.data != NULL) CRYPTO_gcm128_decrypt(&ctx, C.data, out, P.size); if (!TEST_false(CRYPTO_gcm128_finish(&ctx, T.data, 16)) || (P.data != NULL && !TEST_mem_eq(out, P.size, P.data, P.size))) return 0; return 1; }
static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len, size_t tag_len) { struct aead_aes_gcm_ctx *gcm_ctx; const size_t key_bits = key_len * 8; /* EVP_AEAD_CTX_init should catch this. */ if (key_bits != 128 && key_bits != 256) { EVPerr(EVP_F_AEAD_AES_GCM_INIT, EVP_R_BAD_KEY_LENGTH); return 0; } if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) tag_len = EVP_AEAD_AES_GCM_TAG_LEN; if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) { EVPerr(EVP_F_AEAD_AES_GCM_INIT, EVP_R_TAG_TOO_LARGE); return 0; } gcm_ctx = malloc(sizeof(struct aead_aes_gcm_ctx)); if (gcm_ctx == NULL) return 0; #ifdef AESNI_CAPABLE if (AESNI_CAPABLE) { aesni_set_encrypt_key(key, key_bits, &gcm_ctx->ks.ks); CRYPTO_gcm128_init(&gcm_ctx->gcm, &gcm_ctx->ks.ks, (block128_f)aesni_encrypt); gcm_ctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; } else #endif { gcm_ctx->ctr = aes_gcm_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, key, key_len); } gcm_ctx->tag_len = tag_len; ctx->aead_state = gcm_ctx; return 1; }
static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ret; EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); if (!iv && !key) return 1; if (key) { ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aria_encrypt); if (ret < 0) { EVPerr(EVP_F_ARIA_GCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED); return 0; } /* * If we have an iv can set it directly, otherwise use saved IV. */ if (iv == NULL && gctx->iv_set) iv = gctx->iv; if (iv) { CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); gctx->iv_set = 1; } gctx->key_set = 1; } else { /* If key set use IV, otherwise copy */ if (gctx->key_set) CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); else memcpy(gctx->iv, iv, gctx->ivlen); gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; }
static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len) { struct aead_aes_gcm_ctx *gcm_ctx; const size_t key_bits = key_len * 8; if (key_bits != 128 && key_bits != 256) { OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_init, CIPHER_R_BAD_KEY_LENGTH); return 0; /* EVP_AEAD_CTX_init should catch this. */ } if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) { tag_len = EVP_AEAD_AES_GCM_TAG_LEN; } if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) { OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_init, CIPHER_R_TAG_TOO_LARGE); return 0; } gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx)); if (gcm_ctx == NULL) { return 0; } if (aesni_capable()) { aesni_set_encrypt_key(key, key_len * 8, &gcm_ctx->ks.ks); CRYPTO_gcm128_init(&gcm_ctx->gcm, &gcm_ctx->ks.ks, (block128_f)aesni_encrypt); gcm_ctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks; } else { gcm_ctx->ctr = aes_gcm_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, key, key_len); } gcm_ctx->tag_len = tag_len; ctx->aead_state = gcm_ctx; return 1; }
static int sms4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,ctx); if (!iv && !key) return 1; if (key) { do { (void)0; /* terminate potentially open 'else' */ sms4_set_encrypt_key(&gctx->ks.ks, key); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)sms4_encrypt); gctx->ctr = NULL; } while (0); /* * If we have an iv can set it directly, otherwise use saved IV. */ if (iv == NULL && gctx->iv_set) iv = gctx->iv; if (iv) { CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); gctx->iv_set = 1; } gctx->key_set = 1; } else { /* If key set use IV, otherwise copy */ if (gctx->key_set) CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); else memcpy(gctx->iv, iv, gctx->ivlen); gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; }
static int run_test_case(unsigned test_num, const struct test_case *test) { size_t key_len, plaintext_len, additional_data_len, nonce_len, ciphertext_len, tag_len; uint8_t *key = NULL, *plaintext = NULL, *additional_data = NULL, *nonce = NULL, *ciphertext = NULL, *tag = NULL, *out = NULL; int ret = 0; AES_KEY aes_key; GCM128_CONTEXT ctx; if (!decode_hex(&key, &key_len, test->key, test_num, "key") || !decode_hex(&plaintext, &plaintext_len, test->plaintext, test_num, "plaintext") || !decode_hex(&additional_data, &additional_data_len, test->additional_data, test_num, "additional_data") || !decode_hex(&nonce, &nonce_len, test->nonce, test_num, "nonce") || !decode_hex(&ciphertext, &ciphertext_len, test->ciphertext, test_num, "ciphertext") || !decode_hex(&tag, &tag_len, test->tag, test_num, "tag")) { goto out; } if (plaintext_len != ciphertext_len) { fprintf(stderr, "%u: plaintext and ciphertext have differing lengths.\n", test_num); goto out; } if (key_len != 16 && key_len != 24 && key_len != 32) { fprintf(stderr, "%u: bad key length.\n", test_num); goto out; } if (tag_len != 16) { fprintf(stderr, "%u: bad tag length.\n", test_num); goto out; } out = OPENSSL_malloc(plaintext_len); if (AES_set_encrypt_key(key, key_len*8, &aes_key)) { fprintf(stderr, "%u: AES_set_encrypt_key failed.\n", test_num); goto out; } CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f) AES_encrypt); CRYPTO_gcm128_setiv(&ctx, nonce, nonce_len); memset(out, 0, plaintext_len); if (additional_data) { CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len); } if (plaintext) { CRYPTO_gcm128_encrypt(&ctx, plaintext, out, plaintext_len); } if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len) || (ciphertext && memcmp(out, ciphertext, plaintext_len) != 0)) { fprintf(stderr, "%u: encrypt failed.\n", test_num); hexdump("got ", out, plaintext_len); hexdump("want", ciphertext, plaintext_len); goto out; } CRYPTO_gcm128_setiv(&ctx, nonce, nonce_len); memset(out, 0, plaintext_len); if (additional_data) { CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len); } if (ciphertext) { CRYPTO_gcm128_decrypt(&ctx, ciphertext, out, plaintext_len); } if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len)) { fprintf(stderr, "%u: decrypt failed.\n", test_num); goto out; } if (plaintext && memcmp(out, plaintext, plaintext_len)) { fprintf(stderr, "%u: plaintext doesn't match.\n", test_num); goto out; } ret = 1; out: OPENSSL_free(key); OPENSSL_free(plaintext); OPENSSL_free(additional_data); OPENSSL_free(nonce); OPENSSL_free(ciphertext); OPENSSL_free(tag); OPENSSL_free(out); return ret; }
static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, block128_f *out_block, const uint8_t *key, size_t key_len) { #if defined(AESNI) if (aesni_capable()) { aesni_set_encrypt_key(key, key_len * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt); } if (out_block) { *out_block = (block128_f) aesni_encrypt; } return (ctr128_f)aesni_ctr32_encrypt_blocks; } #endif #if defined(HWAES) if (hwaes_capable()) { aes_v8_set_encrypt_key(key, key_len * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt); } if (out_block) { *out_block = (block128_f) aes_v8_encrypt; } return (ctr128_f)aes_v8_ctr32_encrypt_blocks; } #endif #if defined(BSAES) if (bsaes_capable()) { AES_set_encrypt_key(key, key_len * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); } if (out_block) { *out_block = (block128_f) AES_encrypt; } return (ctr128_f)bsaes_ctr32_encrypt_blocks; } #endif #if defined(VPAES) if (vpaes_capable()) { vpaes_set_encrypt_key(key, key_len * 8, aes_key); if (out_block) { *out_block = (block128_f) vpaes_encrypt; } if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt); } return NULL; } #endif AES_set_encrypt_key(key, key_len * 8, aes_key); if (gcm_ctx != NULL) { CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); } if (out_block) { *out_block = (block128_f) AES_encrypt; } return NULL; }