summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/man3/EVP_EncryptInit.pod10
-rw-r--r--providers/implementations/ciphers/ciphercommon.c1
-rw-r--r--providers/implementations/ciphers/ciphercommon_gcm.c9
-rw-r--r--test/acvp_test.c77
-rw-r--r--util/perl/OpenSSL/paramnames.pm1
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