Add appropriate NULL checks in EVP_CIPHER api
authorNeil Horman <nhorman@openssl.org>
Sat, 9 Dec 2023 18:40:01 +0000 (13:40 -0500)
committerNeil Horman <nhorman@openssl.org>
Thu, 25 Jan 2024 13:27:53 +0000 (08:27 -0500)
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)

17 files changed:
apps/enc.c
crypto/cmac/cmac.c
crypto/cms/cms_pwri.c
crypto/evp/bio_enc.c
crypto/evp/evp_key.c
crypto/evp/evp_lib.c
crypto/pkcs12/p12_decr.c
doc/man3/EVP_EncryptInit.pod
providers/implementations/kdfs/krb5kdf.c
ssl/record/methods/ssl3_meth.c
ssl/record/methods/tls1_meth.c
ssl/s3_enc.c
ssl/ssl_ciph.c
test/evp_extra_test.c
test/evp_libctx_test.c
test/evp_test.c
test/tls13encryptiontest.c

index d94f5236d7bbee617230f1382369876132cf5f11..5b53929c55110fc8a339d6ae749d2be786065256 100644 (file)
@@ -593,6 +593,7 @@ int enc_main(int argc, char **argv)
         }
         if (hiv != NULL) {
             int siz = EVP_CIPHER_get_iv_length(cipher);
+
             if (siz == 0) {
                 BIO_printf(bio_err, "warning: iv not used by this cipher\n");
             } else if (!set_hex(hiv, iv, siz)) {
index 50c8511ba7dd51d3a0783f7a0ed13ab1dea88e7e..95e531f68b43007c6d11d43f722193067e643b09 100644 (file)
@@ -95,7 +95,7 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
 
     if (in->nlast_block == -1)
         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;
     if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx))
         return 0;
@@ -111,6 +111,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
               const EVP_CIPHER *cipher, ENGINE *impl)
 {
     static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 };
+    int block_len;
 
     /* All zeros means restart */
     if (!key && !cipher && !impl && keylen == 0) {
@@ -119,7 +120,10 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
             return 0;
         if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
             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;
         return 1;
     }
@@ -170,7 +174,7 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
         return 0;
     if (dlen == 0)
         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;
     /* Copy into partial block if we need to */
     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)
         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;
     if (poutlen != NULL)
         *poutlen = (size_t)bl;
index 8b5beb21577dc6fef2a4eb92b0ef95caf768a087..a028c5842cf7ba5b9ca33abfc3e558579615660e 100644 (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);
     unsigned char *tmp;
     int outl, rv = 0;
+
+    if (blocklen == 0)
+        return 0;
+
     if (inlen < 2 * blocklen) {
         /* too small */
         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 olen;
     int dummy;
+
+    if (blocklen == 0)
+        return 0;
+
     /*
      * First decide length of output buffer: need header and round up to
      * multiple of block length.
index ece3f6d57f070581f2c5b49cd59b66b3f0db7a0b..fc6eec7764cb371f86741547a24459c07200511f 100644 (file)
@@ -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;
 
index 607d45ee23406d350cef56ccf685980b29de5b6e..a4ba76cd838ac676c56bc32ac6b440338ab8f1f2 100644 (file)
@@ -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;
index f29d592e0fbcd0536e278b934aed3c1b43835d36..e539a76a78e80ea3e348e905cfed2e07a30a07f3 100644 (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)
 {
     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)
index b916db0ab1bfebd8276ec3dce94758317f75beca..498632a0bc443a20e4c8d7d40ee6a55ead12dea2 100644 (file)
@@ -26,6 +26,7 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
     int outlen, i;
     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
     int max_out_len, mac_len = 0;
+    int block_size;
 
     if (ctx == NULL) {
         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
      * 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))
                 & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
         if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) {
index 955340b94d4a05fd3c936f9c391a875ffd97b58d..fef8d1aa1f3d538e19f46f2d437ad7ea9bc42d18 100644 (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>
 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()
 
@@ -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()
 
 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.
-The constant B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers.
+B<EVP_CIPHER_CTX>. It will return zero if the cipher does not use an IV, if
+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()
 
@@ -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
 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()
 
@@ -580,7 +585,7 @@ B<EVP_CIPHER>.
 
 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
-the caller.
+the caller. Both functions return NULL on error.
 
 =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
 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).
-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()
 
@@ -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_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
-B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is not set for the cipher.
+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, 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
 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.
@@ -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_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
 length.
index b6cf0e3a2bcf3e649334ee46009fe97b0fc62b85..19dcd83835965580ad88d41fe65319d73b020838 100644 (file)
@@ -416,6 +416,12 @@ static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine,
     /* Initialize input block */
     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) {
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH);
         ret = 0;
index 810dc0716bc9ec729bdf4ef535cbbe2c1b88ce1d..145dccf0d911b6482e4804a686bca9c5753d4fea 100644 (file)
@@ -119,6 +119,9 @@ static int ssl3_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *inrecs,
     l = rec->length;
     bs = EVP_CIPHER_CTX_get_block_size(ds);
 
+    if (bs == 0)
+        return 0;
+
     /* COMPRESS */
 
     if ((bs != 1) && sending && !provided) {
index f13d530a05d9c33c39e2101cf3a4cede5a905dc0..f820803b8dab27c8f072ff866627d9f4c4015d17 100644 (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));
 
+    if (bs == 0) {
+        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_CIPHER);
+        return 0;
+    }
+
     if (n_recs > 1) {
         if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
                  & EVP_CIPH_FLAG_PIPELINE) == 0) {
index 54c47dd3f9bc811209949f0cc312e62162c7aed7..d63ea56c3316fe77a0f4df4296f24153961b44e2 100644 (file)
@@ -120,6 +120,7 @@ int ssl3_change_cipher_state(SSL_CONNECTION *s, int which)
     md_len = (size_t)mdi;
     key_len = EVP_CIPHER_get_key_length(ciph);
     iv_len = EVP_CIPHER_get_iv_length(ciph);
+
     if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
         (which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
         mac_secret = &(p[0]);
index 31c0d5af1dd57f3526bef89f6dce2159f21ebf95..6e49d6b40079a0cba81d3b546217e33cc40e7235 100644 (file)
@@ -2221,6 +2221,8 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
             in = 1; /* padding length byte */
             out = EVP_CIPHER_get_iv_length(e_ciph);
             blk = EVP_CIPHER_get_block_size(e_ciph);
+            if (blk == 0)
+                return 0;
         }
     }
 
index 32624a4b59789e3164e5b5b47041941755303511..03252136e641c6f6907fe5d814e8c93a440bc33a 100644 (file)
@@ -3568,6 +3568,10 @@ static int test_evp_iv_aes(int idx)
             || !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len)))
         goto err;
     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)
             || !TEST_mem_eq(ref_iv, ref_len, iv, ivlen))
         goto err;
@@ -3679,6 +3683,10 @@ static int test_evp_iv_des(int idx)
             || !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len)))
         goto err;
     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)
             || !TEST_mem_eq(ref_iv, ref_len, iv, ivlen))
         goto err;
@@ -4293,7 +4301,8 @@ static int test_evp_updated_iv(int idx)
         errmsg = "CIPHER_CTX_GET_UPDATED_IV";
         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";
         goto err;
     }
index 2448c35a149f60892d238e51a7b97857ed8b8628..224e16b398af9f3d715eeca8d1c71fdf4ff2ef31 100644 (file)
@@ -71,6 +71,37 @@ static const char *getname(int id)
 }
 #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 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)))
         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 */
     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)))
         goto err;
 
-    if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
-        goto err;
+    if (EVP_CIPHER_get_iv_length(cipher) != 0)
+        if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+            goto err;
 
     if (EVP_CIPHER_get_mode(cipher) != EVP_CIPH_SIV_MODE) {
         if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
             || !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len)))
             goto err;
 
-        if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
-            goto err;
+        if (EVP_CIPHER_get_iv_length(cipher) != 0)
+            if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
+                goto err;
     }
     ret = 1;
 err:
@@ -725,6 +762,8 @@ int setup_tests(void)
     if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
         return 0;
 
+    ADD_TEST(test_evp_cipher_api_safety);
+
 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
     ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
 #endif
index ecc7f7fe209c2f28c8f0b605fd6a68edb1e73780..aa6f7ee5a19b8115191112095e87fe345c8db137 100644 (file)
@@ -1131,7 +1131,7 @@ static int cipher_test_run(EVP_TEST *t)
         t->err = "NO_KEY";
         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 */
         if (EVP_CIPHER_get_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) {
             t->err = "NO_IV";
index f1e6490f9f900b810bd19642d3e7e5cd2c191f48..c696e62d2ecdb6191b09ef05076de8666de3f95d 100644 (file)
@@ -326,6 +326,10 @@ static int test_tls13_encryption(void)
     for (ctr = 0; ctr < OSSL_NELEM(refdata); ctr++) {
         /* Load the record */
         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)) {
             TEST_error("Failed loading key into EVP_CIPHER_CTX");
             goto err;