diff options
-rw-r--r-- | doc/man3/EVP_EncryptInit.pod | 10 | ||||
-rw-r--r-- | providers/implementations/ciphers/ciphercommon.c | 1 | ||||
-rw-r--r-- | providers/implementations/ciphers/ciphercommon_gcm.c | 9 | ||||
-rw-r--r-- | test/acvp_test.c | 77 | ||||
-rw-r--r-- | util/perl/OpenSSL/paramnames.pm | 1 |
5 files changed, 79 insertions, 19 deletions
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod index 0bad8d4873..8e1e0e9e31 100644 --- a/doc/man3/EVP_EncryptInit.pod +++ b/doc/man3/EVP_EncryptInit.pod @@ -905,6 +905,16 @@ A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. This may be used after calling a cipher final operation such as EVP_EncryptFinal_ex(). It may return 0 if the "encrypt-check" option is set to 0. +=item "iv-generated" (B<OSSL_CIPHER_PARAM_AEAD_IV_GENERATED>) <unsigned integer> + +An indicator that returns 1 if an IV was generated internally during encryption, +or O otherwise. +This may be used by GCM ciphers after calling a cipher final operation such +as EVP_EncryptFinal_ex(). +GCM should generate an IV internally if the IV is not specified during a +cipher initialisation call such as EVP_CipherInit_ex(). +See FIPS 140-3 IG C.H for information related to IV requirements. + =back =head2 Settable EVP_CIPHER_CTX parameters diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c index 7ad3eb0a1f..a0b0f95ede 100644 --- a/providers/implementations/ciphers/ciphercommon.c +++ b/providers/implementations/ciphers/ciphercommon.c @@ -152,6 +152,7 @@ static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, NULL, 0), + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_AEAD_IV_GENERATED, NULL), OSSL_PARAM_END }; const OSSL_PARAM *ossl_cipher_aead_gettable_ctx_params( diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c index fe24b450a5..4be2e1c94d 100644 --- a/providers/implementations/ciphers/ciphercommon_gcm.c +++ b/providers/implementations/ciphers/ciphercommon_gcm.c @@ -236,6 +236,9 @@ int ossl_gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) || !getivgen(ctx, p->data, p->data_size)) return 0; break; + case PIDX_CIPHER_PARAM_AEAD_IV_GENERATED: + if (!OSSL_PARAM_set_uint(p, ctx->iv_gen_rand)) + return 0; } } return 1; @@ -513,9 +516,11 @@ static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, return 0; if (len > 0) memcpy(ctx->iv, iv, len); - if (ctx->enc - && RAND_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len, 0) <= 0) + if (ctx->enc) { + if (RAND_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len, 0) <= 0) return 0; + ctx->iv_gen_rand = 1; + } ctx->iv_gen = 1; ctx->iv_state = IV_STATE_BUFFERED; return 1; diff --git a/test/acvp_test.c b/test/acvp_test.c index 341410ef2b..44f7249505 100644 --- a/test/acvp_test.c +++ b/test/acvp_test.c @@ -829,13 +829,14 @@ static int aes_gcm_enc_dec(const char *alg, const unsigned char *aad, size_t aad_len, const unsigned char *ct, size_t ct_len, const unsigned char *tag, size_t tag_len, - int enc, int pass) + int enc, int pass, + unsigned char *out, int *out_len, + unsigned char *outiv) { int ret = 0; EVP_CIPHER_CTX *ctx; EVP_CIPHER *cipher = NULL; - int out_len, len; - unsigned char out[1024]; + int olen, len; TEST_note("%s : %s : expected to %s", alg, enc ? "encrypt" : "decrypt", pass ? "pass" : "fail"); @@ -853,9 +854,9 @@ static int aes_gcm_enc_dec(const char *alg, goto err; } /* - * For testing purposes the IV it being set here. In a compliant application - * the IV would be generated internally. A fake entropy source could also - * be used to feed in the random IV bytes (see fake_random.c) + * For testing purposes the IV may be passed in here. In a compliant + * application the IV would be generated internally. A fake entropy source + * could also be used to feed in the random IV bytes (see fake_random.c) */ if (!TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) || !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0)) @@ -863,23 +864,41 @@ static int aes_gcm_enc_dec(const char *alg, || !TEST_true(EVP_CipherUpdate(ctx, out, &len, pt, pt_len))) goto err; - if (!TEST_int_eq(EVP_CipherFinal_ex(ctx, out + len, &out_len), pass)) + if (!TEST_int_eq(EVP_CipherFinal_ex(ctx, out + len, &olen), pass)) goto err; if (!pass) { ret = 1; goto err; } - out_len += len; + olen += len; if (enc) { - if (!TEST_mem_eq(out, out_len, ct, ct_len) - || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, - tag_len, out + out_len), 0) - || !TEST_mem_eq(out + out_len, tag_len, tag, tag_len)) - goto err; + if ((ct != NULL && !TEST_mem_eq(out, olen, ct, ct_len)) + || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + tag_len, out + olen), 0) + || (tag != NULL + && !TEST_mem_eq(out + olen, tag_len, tag, tag_len))) + goto err; } else { - if (!TEST_mem_eq(out, out_len, ct, ct_len)) + if (ct != NULL && !TEST_mem_eq(out, olen, ct, ct_len)) + goto err; + } + + { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; + unsigned int iv_generated = -1; + + params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_AEAD_IV_GENERATED, + &iv_generated); + if (outiv != NULL) + params[1] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_IV, + outiv, iv_len); + if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx, params))) + goto err; + if (!TEST_uint_eq(iv_generated, (enc == 0 || iv != NULL ? 0 : 1))) goto err; } + if (out_len != NULL) + *out_len = olen; ret = 1; err: @@ -893,23 +912,45 @@ static int aes_gcm_enc_dec_test(int id) const struct cipher_gcm_st *tst = &aes_gcm_enc_data[id]; int enc = 1; int pass = 1; + unsigned char out[1024]; return aes_gcm_enc_dec(tst->alg, tst->pt, tst->pt_len, tst->key, tst->key_len, tst->iv, tst->iv_len, tst->aad, tst->aad_len, tst->ct, tst->ct_len, tst->tag, tst->tag_len, - enc, pass) + enc, pass, out, NULL, NULL) && aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len, tst->key, tst->key_len, tst->iv, tst->iv_len, tst->aad, tst->aad_len, tst->pt, tst->pt_len, tst->tag, tst->tag_len, - !enc, pass) + !enc, pass, out, NULL, NULL) /* Fail if incorrect tag passed to decrypt */ && aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len, tst->key, tst->key_len, tst->iv, tst->iv_len, tst->aad, tst->aad_len, tst->pt, tst->pt_len, tst->aad, tst->tag_len, - !enc, !pass); + !enc, !pass, out, NULL, NULL); +} + +static int aes_gcm_gen_iv_internal_test(void) +{ + const struct cipher_gcm_st *tst = &aes_gcm_enc_data[0]; + int enc = 1; + int pass = 1; + int out_len = 0; + unsigned char out[1024]; + unsigned char iv[16]; + + return aes_gcm_enc_dec(tst->alg, tst->pt, tst->pt_len, + tst->key, tst->key_len, + NULL, tst->iv_len, tst->aad, tst->aad_len, + NULL, tst->ct_len, NULL, tst->tag_len, + enc, pass, out, &out_len, iv) + && aes_gcm_enc_dec(tst->alg, out, out_len, + tst->key, tst->key_len, + iv, tst->iv_len, tst->aad, tst->aad_len, + tst->pt, tst->pt_len, out + out_len, tst->tag_len, + !enc, pass, out, NULL, NULL); } #ifndef OPENSSL_NO_DH @@ -1492,6 +1533,8 @@ int setup_tests(void) ADD_ALL_TESTS(cipher_enc_dec_test, OSSL_NELEM(cipher_enc_data)); ADD_ALL_TESTS(aes_ccm_enc_dec_test, OSSL_NELEM(aes_ccm_enc_data)); ADD_ALL_TESTS(aes_gcm_enc_dec_test, OSSL_NELEM(aes_gcm_enc_data)); + if (fips_provider_version_ge(libctx, 3, 4, 0)) + ADD_TEST(aes_gcm_gen_iv_internal_test); pass_sig_gen_params = fips_provider_version_ge(libctx, 3, 4, 0); rsa_sign_x931_pad_allowed = fips_provider_version_lt(libctx, 3, 4, 0); diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index 1fadafc7cf..e4edb550be 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -115,6 +115,7 @@ my %params = ( 'CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN' => "tlsivgen", # octet_string 'CIPHER_PARAM_AEAD_TLS1_SET_IV_INV' => "tlsivinv", # octet_string 'CIPHER_PARAM_AEAD_IVLEN' => '*CIPHER_PARAM_IVLEN', + 'CIPHER_PARAM_AEAD_IV_GENERATED' => "iv-generated", # uint 'CIPHER_PARAM_AEAD_TAGLEN' => "taglen", # size_t 'CIPHER_PARAM_AEAD_MAC_KEY' => "mackey", # octet_string 'CIPHER_PARAM_RANDOM_KEY' => "randkey", # octet_string |