diff options
author | Neil Horman <nhorman@openssl.org> | 2023-12-09 13:40:01 -0500 |
---|---|---|
committer | Neil Horman <nhorman@openssl.org> | 2024-01-25 08:27:53 -0500 |
commit | 6f22bcd631ab622c2436bc5b299ba2677c388375 (patch) | |
tree | e62244a2a0e8f491ab3e3b582928dbc6383f7abf /crypto/evp | |
parent | ff78d94b131d7bb3b761509d3ce0dd864b1420e3 (diff) |
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)
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/bio_enc.c | 4 | ||||
-rw-r--r-- | crypto/evp/evp_key.c | 2 | ||||
-rw-r--r-- | crypto/evp/evp_lib.c | 34 |
3 files changed, 31 insertions, 9 deletions
diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c index ece3f6d57f..fc6eec7764 100644 --- a/crypto/evp/bio_enc.c +++ b/crypto/evp/bio_enc.c @@ -132,6 +132,10 @@ static int enc_read(BIO *b, char *out, int outl) } blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); + + if (blocksize == 0) + return 0; + if (blocksize == 1) blocksize = 0; diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c index 607d45ee23..a4ba76cd83 100644 --- a/crypto/evp/evp_key.c +++ b/crypto/evp/evp_key.c @@ -88,7 +88,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, nkey = EVP_CIPHER_get_key_length(type); niv = EVP_CIPHER_get_iv_length(type); 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) return nkey; diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index f29d592e0f..e539a76a78 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -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) { 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 * 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) { 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 * 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; } +err: if (ret == -2) ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER); 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) { - return cipher->block_size; + return (cipher == NULL) ? 0 : cipher->block_size; } 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, const unsigned char *in, unsigned int inl) { + if (ctx == NULL || ctx->cipher == NULL) + return 0; + if (ctx->cipher->prov != NULL) { /* * 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 blocksize = EVP_CIPHER_CTX_get_block_size(ctx); + if (blocksize == 0) + return 0; + if (ctx->cipher->ccipher != NULL) ret = ctx->cipher->ccipher(ctx->algctx, out, &outl, inl + (blocksize == 1 ? 0 : blocksize), @@ -454,7 +469,7 @@ EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx) { EVP_CIPHER *cipher; - if (ctx == NULL) + if (ctx == NULL || ctx->cipher == NULL) return NULL; cipher = (EVP_CIPHER *)ctx->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) { - return cipher->flags; + return cipher == NULL ? 0 : cipher->flags; } 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) { - return cipher->iv_len; + return (cipher == NULL) ? 0 : cipher->iv_len; } int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx) { + if (ctx->cipher == NULL) + return 0; + if (ctx->iv_len < 0) { int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); 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) { - return cipher->nid; + return (cipher == NULL) ? NID_undef : cipher->nid; } 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) |