}
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)) {
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;
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) {
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;
}
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) {
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;
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;
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.
}
blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher);
+
+ if (blocksize == 0)
+ return 0;
+
if (blocksize == 1)
blocksize = 0;
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;
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
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
ret = -2;
}
+err:
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
else if (ret <= 0)
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(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,
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),
{
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))
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)
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;
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)
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);
* 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) {
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()
=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()
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()
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()
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()
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.
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.
/* 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;
l = rec->length;
bs = EVP_CIPHER_CTX_get_block_size(ds);
+ if (bs == 0)
+ return 0;
+
/* COMPRESS */
if ((bs != 1) && sending && !provided) {
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) {
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]);
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;
}
}
|| !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;
|| !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;
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;
}
}
#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.
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)
|| !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:
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
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";
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;