Add appropriate NULL checks in EVP_CIPHER api

The EVP_CIPHER api currently assumes that calls made into several APIs
have already initalized the cipher in a given context via a call to
EVP_CipherInit[_ex[2]].  If that hasnt been done, instead of an error,
the result is typically a SIGSEGV.

Correct that by adding missing NULL checks in the apropriate apis prior
to using ctx->cipher

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22995)
This commit is contained in:
Neil Horman 2023-12-09 13:40:01 -05:00
parent ff78d94b13
commit 6f22bcd631
17 changed files with 149 additions and 30 deletions

View File

@ -593,6 +593,7 @@ int enc_main(int argc, char **argv)
} }
if (hiv != NULL) { if (hiv != NULL) {
int siz = EVP_CIPHER_get_iv_length(cipher); int siz = EVP_CIPHER_get_iv_length(cipher);
if (siz == 0) { if (siz == 0) {
BIO_printf(bio_err, "warning: iv not used by this cipher\n"); BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) { } else if (!set_hex(hiv, iv, siz)) {

View File

@ -95,7 +95,7 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
if (in->nlast_block == -1) if (in->nlast_block == -1)
return 0; return 0;
if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) < 0) if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) == 0)
return 0; return 0;
if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx)) if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx))
return 0; return 0;
@ -111,6 +111,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
const EVP_CIPHER *cipher, ENGINE *impl) const EVP_CIPHER *cipher, ENGINE *impl)
{ {
static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 }; static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 };
int block_len;
/* All zeros means restart */ /* All zeros means restart */
if (!key && !cipher && !impl && keylen == 0) { if (!key && !cipher && !impl && keylen == 0) {
@ -119,7 +120,10 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
return 0; return 0;
if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0; return 0;
memset(ctx->tbl, 0, EVP_CIPHER_CTX_get_block_size(ctx->cctx)); block_len = EVP_CIPHER_CTX_get_block_size(ctx->cctx);
if (block_len == 0)
return 0;
memset(ctx->tbl, 0, block_len);
ctx->nlast_block = 0; ctx->nlast_block = 0;
return 1; return 1;
} }
@ -170,7 +174,7 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
return 0; return 0;
if (dlen == 0) if (dlen == 0)
return 1; return 1;
if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0)
return 0; return 0;
/* Copy into partial block if we need to */ /* Copy into partial block if we need to */
if (ctx->nlast_block > 0) { if (ctx->nlast_block > 0) {
@ -234,7 +238,7 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
if (ctx->nlast_block == -1) if (ctx->nlast_block == -1)
return 0; return 0;
if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0)
return 0; return 0;
if (poutlen != NULL) if (poutlen != NULL)
*poutlen = (size_t)bl; *poutlen = (size_t)bl;

View File

@ -204,6 +204,10 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
unsigned char *tmp; unsigned char *tmp;
int outl, rv = 0; int outl, rv = 0;
if (blocklen == 0)
return 0;
if (inlen < 2 * blocklen) { if (inlen < 2 * blocklen) {
/* too small */ /* too small */
return 0; return 0;
@ -257,6 +261,10 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
size_t olen; size_t olen;
int dummy; int dummy;
if (blocklen == 0)
return 0;
/* /*
* First decide length of output buffer: need header and round up to * First decide length of output buffer: need header and round up to
* multiple of block length. * multiple of block length.

View File

@ -132,6 +132,10 @@ static int enc_read(BIO *b, char *out, int outl)
} }
blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher);
if (blocksize == 0)
return 0;
if (blocksize == 1) if (blocksize == 1)
blocksize = 0; blocksize = 0;

View File

@ -88,7 +88,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
nkey = EVP_CIPHER_get_key_length(type); nkey = EVP_CIPHER_get_key_length(type);
niv = EVP_CIPHER_get_iv_length(type); niv = EVP_CIPHER_get_iv_length(type);
OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH); OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH); OPENSSL_assert(niv >= 0 && niv <= EVP_MAX_IV_LENGTH);
if (data == NULL) if (data == NULL)
return nkey; return nkey;

View File

@ -81,8 +81,12 @@ int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
evp_cipher_aead_asn1_params *asn1_params) evp_cipher_aead_asn1_params *asn1_params)
{ {
int ret = -1; /* Assume the worst */ int ret = -1; /* Assume the worst */
const EVP_CIPHER *cipher = c->cipher; const EVP_CIPHER *cipher;
if (c == NULL || c->cipher == NULL)
goto err;
cipher = c->cipher;
/* /*
* For legacy implementations, we detect custom AlgorithmIdentifier * For legacy implementations, we detect custom AlgorithmIdentifier
* parameter handling by checking if the function pointer * parameter handling by checking if the function pointer
@ -172,8 +176,12 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
evp_cipher_aead_asn1_params *asn1_params) evp_cipher_aead_asn1_params *asn1_params)
{ {
int ret = -1; /* Assume the worst */ int ret = -1; /* Assume the worst */
const EVP_CIPHER *cipher = c->cipher; const EVP_CIPHER *cipher;
if (c == NULL || c->cipher == NULL)
goto err;
cipher = c->cipher;
/* /*
* For legacy implementations, we detect custom AlgorithmIdentifier * For legacy implementations, we detect custom AlgorithmIdentifier
* parameter handling by checking if there the function pointer * parameter handling by checking if there the function pointer
@ -230,6 +238,7 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
ret = -2; ret = -2;
} }
err:
if (ret == -2) if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER); ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
else if (ret <= 0) else if (ret <= 0)
@ -387,7 +396,7 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher)
int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher) int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher)
{ {
return cipher->block_size; return (cipher == NULL) ? 0 : cipher->block_size;
} }
int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx) int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx)
@ -403,6 +412,9 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) const unsigned char *in, unsigned int inl)
{ {
if (ctx == NULL || ctx->cipher == NULL)
return 0;
if (ctx->cipher->prov != NULL) { if (ctx->cipher->prov != NULL) {
/* /*
* If the provided implementation has a ccipher function, we use it, * If the provided implementation has a ccipher function, we use it,
@ -415,6 +427,9 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
size_t outl = 0; size_t outl = 0;
size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx); size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
if (blocksize == 0)
return 0;
if (ctx->cipher->ccipher != NULL) if (ctx->cipher->ccipher != NULL)
ret = ctx->cipher->ccipher(ctx->algctx, out, &outl, ret = ctx->cipher->ccipher(ctx->algctx, out, &outl,
inl + (blocksize == 1 ? 0 : blocksize), inl + (blocksize == 1 ? 0 : blocksize),
@ -454,7 +469,7 @@ EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx)
{ {
EVP_CIPHER *cipher; EVP_CIPHER *cipher;
if (ctx == NULL) if (ctx == NULL || ctx->cipher == NULL)
return NULL; return NULL;
cipher = (EVP_CIPHER *)ctx->cipher; cipher = (EVP_CIPHER *)ctx->cipher;
if (!EVP_CIPHER_up_ref(cipher)) if (!EVP_CIPHER_up_ref(cipher))
@ -469,7 +484,7 @@ int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx)
unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher) unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher)
{ {
return cipher->flags; return cipher == NULL ? 0 : cipher->flags;
} }
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
@ -499,11 +514,14 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher) int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher)
{ {
return cipher->iv_len; return (cipher == NULL) ? 0 : cipher->iv_len;
} }
int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx) int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx)
{ {
if (ctx->cipher == NULL)
return 0;
if (ctx->iv_len < 0) { if (ctx->iv_len < 0) {
int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher);
size_t v = len; size_t v = len;
@ -678,12 +696,12 @@ int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx)
int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher) int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher)
{ {
return cipher->nid; return (cipher == NULL) ? NID_undef : cipher->nid;
} }
int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx) int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx)
{ {
return ctx->cipher->nid; return EVP_CIPHER_get_nid(ctx->cipher);
} }
int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name) int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name)

View File

@ -26,6 +26,7 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
int outlen, i; int outlen, i;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
int max_out_len, mac_len = 0; int max_out_len, mac_len = 0;
int block_size;
if (ctx == NULL) { if (ctx == NULL) {
ERR_raise(ERR_LIB_PKCS12, ERR_R_EVP_LIB); ERR_raise(ERR_LIB_PKCS12, ERR_R_EVP_LIB);
@ -43,7 +44,14 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
* It's appended to encrypted text on encrypting * It's appended to encrypted text on encrypting
* MAC should be processed on decrypting separately from plain text * MAC should be processed on decrypting separately from plain text
*/ */
max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx); block_size = EVP_CIPHER_CTX_get_block_size(ctx);
if (block_size == 0) {
ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
max_out_len = inlen + block_size;
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
& EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) { & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) { if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) {

View File

@ -488,7 +488,9 @@ EVP_CIPHER_free().
Return the NID of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX> Return the NID of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
structure. The actual NID value is an internal value which may not have a structure. The actual NID value is an internal value which may not have a
corresponding OBJECT IDENTIFIER. corresponding OBJECT IDENTIFIER. NID_undef is returned in the event that the
nid is unknown or if the cipher has not been properly initalized via a call to
B<EVP_CipherInit>.
=item EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags() =item EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags()
@ -525,8 +527,10 @@ length to any value other than the fixed value is an error.
=item EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length() =item EVP_CIPHER_get_iv_length() and EVP_CIPHER_CTX_get_iv_length()
Return the IV length of a cipher when passed an B<EVP_CIPHER> or Return the IV length of a cipher when passed an B<EVP_CIPHER> or
B<EVP_CIPHER_CTX>. It will return zero if the cipher does not use an IV. B<EVP_CIPHER_CTX>. It will return zero if the cipher does not use an IV, if
The constant B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers. the cipher has not yet been initalized within the B<EVP_CIPHER_CTX>, or if the
passed cipher is NULL. The constant B<EVP_MAX_IV_LENGTH> is the maximum IV
length for all ciphers.
=item EVP_CIPHER_CTX_get_tag_length() =item EVP_CIPHER_CTX_get_tag_length()
@ -538,7 +542,8 @@ the tag length has not been set.
Return the block size of a cipher when passed an B<EVP_CIPHER> or Return the block size of a cipher when passed an B<EVP_CIPHER> or
B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the B<EVP_CIPHER_CTX> structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the
maximum block length for all ciphers. maximum block length for all ciphers. A value of 0 is returned if the cipher
has not been properly initalized with a call to B<EVP_CipherInit>.
=item EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type() =item EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type()
@ -580,7 +585,7 @@ B<EVP_CIPHER>.
Returns the B<EVP_CIPHER> structure when passed an B<EVP_CIPHER_CTX> structure. Returns the B<EVP_CIPHER> structure when passed an B<EVP_CIPHER_CTX> structure.
EVP_CIPHER_CTX_get1_cipher() is the same except the ownership is passed to EVP_CIPHER_CTX_get1_cipher() is the same except the ownership is passed to
the caller. the caller. Both functions return NULL on error.
=item EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode() =item EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode()
@ -616,7 +621,8 @@ Sets the AlgorithmIdentifier "parameter" based on the passed cipher. This will
typically include any parameters and an IV. The cipher IV (if any) must be set typically include any parameters and an IV. The cipher IV (if any) must be set
when this call is made. This call should be made before the cipher is actually when this call is made. This call should be made before the cipher is actually
"used" (before any EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example). "used" (before any EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example).
This function may fail if the cipher does not have any ASN1 support. This function may fail if the cipher does not have any ASN1 support, or if an
uninitialized cipher is passed to it.
=item EVP_CIPHER_asn1_to_param() =item EVP_CIPHER_asn1_to_param()
@ -1248,8 +1254,9 @@ EVP_DecryptFinal_ex() returns 0 if the decrypt failed or 1 for success.
EVP_CipherInit_ex2() and EVP_CipherUpdate() return 1 for success and 0 for failure. EVP_CipherInit_ex2() and EVP_CipherUpdate() return 1 for success and 0 for failure.
EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success. EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success.
EVP_Cipher() returns 1 on success or 0 on failure, if the flag EVP_Cipher() returns 1 on success and <= 0 on failure, if the flag
B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is not set for the cipher. B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is not set for the cipher, or if the cipher has
not been initalized via a call to B<EVP_CipherInit_ex2>.
EVP_Cipher() returns the number of bytes written to I<out> for encryption / decryption, or EVP_Cipher() returns the number of bytes written to I<out> for encryption / decryption, or
the number of bytes authenticated in a call specifying AAD for an AEAD cipher, if the flag the number of bytes authenticated in a call specifying AAD for an AEAD cipher, if the flag
B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is set for the cipher. B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is set for the cipher.
@ -1262,7 +1269,7 @@ return an B<EVP_CIPHER> structure or NULL on error.
EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid() return a NID. EVP_CIPHER_get_nid() and EVP_CIPHER_CTX_get_nid() return a NID.
EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size() return the EVP_CIPHER_get_block_size() and EVP_CIPHER_CTX_get_block_size() return the
block size. block size, or 0 on error.
EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() return the key EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() return the key
length. length.

View File

@ -416,6 +416,12 @@ static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine,
/* Initialize input block */ /* Initialize input block */
blocksize = EVP_CIPHER_CTX_get_block_size(ctx); blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
if (blocksize == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
ret = 0;
goto out;
}
if (constant_len > blocksize) { if (constant_len > blocksize) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH); ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH);
ret = 0; ret = 0;

View File

@ -119,6 +119,9 @@ static int ssl3_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *inrecs,
l = rec->length; l = rec->length;
bs = EVP_CIPHER_CTX_get_block_size(ds); bs = EVP_CIPHER_CTX_get_block_size(ds);
if (bs == 0)
return 0;
/* COMPRESS */ /* COMPRESS */
if ((bs != 1) && sending && !provided) { if ((bs != 1) && sending && !provided) {

View File

@ -229,6 +229,11 @@ static int tls1_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
bs = EVP_CIPHER_get_block_size(EVP_CIPHER_CTX_get0_cipher(ds)); bs = EVP_CIPHER_get_block_size(EVP_CIPHER_CTX_get0_cipher(ds));
if (bs == 0) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_CIPHER);
return 0;
}
if (n_recs > 1) { if (n_recs > 1) {
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds)) if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
& EVP_CIPH_FLAG_PIPELINE) == 0) { & EVP_CIPH_FLAG_PIPELINE) == 0) {

View File

@ -120,6 +120,7 @@ int ssl3_change_cipher_state(SSL_CONNECTION *s, int which)
md_len = (size_t)mdi; md_len = (size_t)mdi;
key_len = EVP_CIPHER_get_key_length(ciph); key_len = EVP_CIPHER_get_key_length(ciph);
iv_len = EVP_CIPHER_get_iv_length(ciph); iv_len = EVP_CIPHER_get_iv_length(ciph);
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) { (which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
mac_secret = &(p[0]); mac_secret = &(p[0]);

View File

@ -2221,6 +2221,8 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
in = 1; /* padding length byte */ in = 1; /* padding length byte */
out = EVP_CIPHER_get_iv_length(e_ciph); out = EVP_CIPHER_get_iv_length(e_ciph);
blk = EVP_CIPHER_get_block_size(e_ciph); blk = EVP_CIPHER_get_block_size(e_ciph);
if (blk == 0)
return 0;
} }
} }

View File

@ -3568,6 +3568,10 @@ static int test_evp_iv_aes(int idx)
|| !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len))) || !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len)))
goto err; goto err;
ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
if (!TEST_int_gt(ivlen, 0))
goto err;
if (!TEST_mem_eq(init_iv, ivlen, oiv, ivlen) if (!TEST_mem_eq(init_iv, ivlen, oiv, ivlen)
|| !TEST_mem_eq(ref_iv, ref_len, iv, ivlen)) || !TEST_mem_eq(ref_iv, ref_len, iv, ivlen))
goto err; goto err;
@ -3679,6 +3683,10 @@ static int test_evp_iv_des(int idx)
|| !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len))) || !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len)))
goto err; goto err;
ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
if (!TEST_int_gt(ivlen, 0))
goto err;
if (!TEST_mem_eq(init_iv, ivlen, oiv, ivlen) if (!TEST_mem_eq(init_iv, ivlen, oiv, ivlen)
|| !TEST_mem_eq(ref_iv, ref_len, iv, ivlen)) || !TEST_mem_eq(ref_iv, ref_len, iv, ivlen))
goto err; goto err;
@ -4293,7 +4301,8 @@ static int test_evp_updated_iv(int idx)
errmsg = "CIPHER_CTX_GET_UPDATED_IV"; errmsg = "CIPHER_CTX_GET_UPDATED_IV";
goto err; goto err;
} }
if (!TEST_true(iv_len = EVP_CIPHER_CTX_get_iv_length(ctx))) { iv_len = EVP_CIPHER_CTX_get_iv_length(ctx);
if (!TEST_int_ge(iv_len,0)) {
errmsg = "CIPHER_CTX_GET_IV_LEN"; errmsg = "CIPHER_CTX_GET_IV_LEN";
goto err; goto err;
} }

View File

@ -71,6 +71,37 @@ static const char *getname(int id)
} }
#endif #endif
static int test_evp_cipher_api_safety(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx = NULL;
ctx = EVP_CIPHER_CTX_new();
if (!TEST_ptr(ctx))
goto err;
/*
* Ensure that EVP_CIPHER_get_block_size returns 0
* if we haven't initalized the cipher in this context
*/
if (!TEST_int_eq(EVP_CIPHER_CTX_get_block_size(ctx), 0))
goto err_free;
/*
* Ensure that EVP_CIPHER_get_iv_length returns 0
* if we haven't initalized the cipher in this context
*/
if (!TEST_int_eq(EVP_CIPHER_CTX_get_iv_length(ctx), 0))
goto err_free;
ret = 1;
err_free:
EVP_CIPHER_CTX_free(ctx);
err:
return ret;
}
/* /*
* We're using some DH specific values in this test, so we skip compilation if * We're using some DH specific values in this test, so we skip compilation if
* we're in a no-dh build. * we're in a no-dh build.
@ -438,7 +469,11 @@ static int test_cipher_reinit_partialupdate(int test_id)
if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL))) if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL)))
goto err; goto err;
in_len = EVP_CIPHER_get_block_size(cipher) / 2; in_len = EVP_CIPHER_get_block_size(cipher);
if (!TEST_int_gt(in_len, 0))
goto err;
if (in_len > 1)
in_len /= 2;
/* skip any ciphers that don't allow partial updates */ /* skip any ciphers that don't allow partial updates */
if (((EVP_CIPHER_get_flags(cipher) if (((EVP_CIPHER_get_flags(cipher)
@ -456,16 +491,18 @@ static int test_cipher_reinit_partialupdate(int test_id)
|| !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len))) || !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len)))
goto err; goto err;
if (!TEST_mem_eq(out1, out1_len, out2, out2_len)) if (EVP_CIPHER_get_iv_length(cipher) != 0)
goto err; if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
goto err;
if (EVP_CIPHER_get_mode(cipher) != EVP_CIPH_SIV_MODE) { if (EVP_CIPHER_get_mode(cipher) != EVP_CIPH_SIV_MODE) {
if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv)) if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
|| !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len))) || !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len)))
goto err; goto err;
if (!TEST_mem_eq(out1, out1_len, out3, out3_len)) if (EVP_CIPHER_get_iv_length(cipher) != 0)
goto err; if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
goto err;
} }
ret = 1; ret = 1;
err: err:
@ -725,6 +762,8 @@ int setup_tests(void)
if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name)) if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
return 0; return 0;
ADD_TEST(test_evp_cipher_api_safety);
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH) #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3); ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
#endif #endif

View File

@ -1131,7 +1131,7 @@ static int cipher_test_run(EVP_TEST *t)
t->err = "NO_KEY"; t->err = "NO_KEY";
return 0; return 0;
} }
if (!cdat->iv && EVP_CIPHER_get_iv_length(cdat->cipher)) { if (!cdat->iv && EVP_CIPHER_get_iv_length(cdat->cipher) > 0) {
/* IV is optional and usually omitted in wrap mode */ /* IV is optional and usually omitted in wrap mode */
if (EVP_CIPHER_get_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) { if (EVP_CIPHER_get_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) {
t->err = "NO_IV"; t->err = "NO_IV";

View File

@ -326,6 +326,10 @@ static int test_tls13_encryption(void)
for (ctr = 0; ctr < OSSL_NELEM(refdata); ctr++) { for (ctr = 0; ctr < OSSL_NELEM(refdata); ctr++) {
/* Load the record */ /* Load the record */
ivlen = EVP_CIPHER_get_iv_length(ciph); ivlen = EVP_CIPHER_get_iv_length(ciph);
if (TEST_int_eq((int)ivlen, -1)) {
TEST_error("IV length undefined");
goto err;
}
if (!load_record(&rec, &refdata[ctr], &key, iv, ivlen, seqbuf)) { if (!load_record(&rec, &refdata[ctr], &key, iv, ivlen, seqbuf)) {
TEST_error("Failed loading key into EVP_CIPHER_CTX"); TEST_error("Failed loading key into EVP_CIPHER_CTX");
goto err; goto err;