mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 12:39:28 +00:00
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
363 lines
12 KiB
C
363 lines
12 KiB
C
/* Provenance: openssl/openssl evp_cipher_init_internal (fixed).
|
|
* repo: openssl/openssl
|
|
* commit: 0df40630850fb2740e6be6890bb905d3fc623b2d
|
|
* parent: 23d21359e35536a4ee8f7be0b245ddbfac909bff
|
|
* commit_url: https://github.com/openssl/openssl/commit/0df40630850fb2740e6be6890bb905d3fc623b2d
|
|
* cve: CVE-2023-5363
|
|
* license: Apache-2.0
|
|
* function: evp_cipher_init_internal
|
|
* relpath: crypto/evp/evp_enc.c
|
|
*/
|
|
|
|
static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
|
|
const EVP_CIPHER *cipher,
|
|
ENGINE *impl, const unsigned char *key,
|
|
const unsigned char *iv, int enc,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
int n;
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
|
ENGINE *tmpimpl = NULL;
|
|
#endif
|
|
|
|
ctx->iv_len = -1;
|
|
|
|
/*
|
|
* enc == 1 means we are encrypting.
|
|
* enc == 0 means we are decrypting.
|
|
* enc == -1 means, use the previously initialised value for encrypt/decrypt
|
|
*/
|
|
if (enc == -1) {
|
|
enc = ctx->encrypt;
|
|
} else {
|
|
if (enc)
|
|
enc = 1;
|
|
ctx->encrypt = enc;
|
|
}
|
|
|
|
if (cipher == NULL && ctx->cipher == NULL) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
|
return 0;
|
|
}
|
|
|
|
/* Code below to be removed when legacy support is dropped. */
|
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
|
/*
|
|
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
|
|
* this context may already have an ENGINE! Try to avoid releasing the
|
|
* previous handle, re-querying for an ENGINE, and having a
|
|
* reinitialisation, when it may all be unnecessary.
|
|
*/
|
|
if (ctx->engine && ctx->cipher
|
|
&& (cipher == NULL || cipher->nid == ctx->cipher->nid))
|
|
goto skip_to_init;
|
|
|
|
if (cipher != NULL && impl == NULL) {
|
|
/* Ask if an ENGINE is reserved for this job */
|
|
tmpimpl = ENGINE_get_cipher_engine(cipher->nid);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* If there are engines involved then we should use legacy handling for now.
|
|
*/
|
|
if (ctx->engine != NULL
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
|
|| tmpimpl != NULL
|
|
#endif
|
|
|| impl != NULL
|
|
|| (cipher != NULL && cipher->origin == EVP_ORIG_METH)
|
|
|| (cipher == NULL && ctx->cipher != NULL
|
|
&& ctx->cipher->origin == EVP_ORIG_METH)) {
|
|
if (ctx->cipher == ctx->fetched_cipher)
|
|
ctx->cipher = NULL;
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
|
ctx->fetched_cipher = NULL;
|
|
goto legacy;
|
|
}
|
|
/*
|
|
* Ensure a context left lying around from last time is cleared
|
|
* (legacy code)
|
|
*/
|
|
if (cipher != NULL && ctx->cipher != NULL) {
|
|
if (ctx->cipher->cleanup != NULL && !ctx->cipher->cleanup(ctx))
|
|
return 0;
|
|
OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
|
|
ctx->cipher_data = NULL;
|
|
}
|
|
|
|
/* Start of non-legacy code below */
|
|
|
|
/* Ensure a context left lying around from last time is cleared */
|
|
if (cipher != NULL && ctx->cipher != NULL) {
|
|
unsigned long flags = ctx->flags;
|
|
|
|
EVP_CIPHER_CTX_reset(ctx);
|
|
/* Restore encrypt and flags */
|
|
ctx->encrypt = enc;
|
|
ctx->flags = flags;
|
|
}
|
|
|
|
if (cipher == NULL)
|
|
cipher = ctx->cipher;
|
|
|
|
if (cipher->prov == NULL) {
|
|
#ifdef FIPS_MODULE
|
|
/* We only do explicit fetches inside the FIPS module */
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
#else
|
|
EVP_CIPHER *provciph =
|
|
EVP_CIPHER_fetch(NULL,
|
|
cipher->nid == NID_undef ? "NULL"
|
|
: OBJ_nid2sn(cipher->nid),
|
|
"");
|
|
|
|
if (provciph == NULL)
|
|
return 0;
|
|
cipher = provciph;
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
|
ctx->fetched_cipher = provciph;
|
|
#endif
|
|
}
|
|
|
|
if (!ossl_assert(cipher->prov != NULL)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
|
|
if (cipher != ctx->fetched_cipher) {
|
|
if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
|
ctx->fetched_cipher = (EVP_CIPHER *)cipher;
|
|
}
|
|
ctx->cipher = cipher;
|
|
if (ctx->algctx == NULL) {
|
|
ctx->algctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
|
|
if (ctx->algctx == NULL) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
|
|
/*
|
|
* If this ctx was already set up for no padding then we need to tell
|
|
* the new cipher about it.
|
|
*/
|
|
if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
|
|
return 0;
|
|
}
|
|
|
|
#ifndef FIPS_MODULE
|
|
/*
|
|
* Fix for CVE-2023-5363
|
|
* Passing in a size as part of the init call takes effect late
|
|
* so, force such to occur before the initialisation.
|
|
*
|
|
* The FIPS provider's internal library context is used in a manner
|
|
* such that this is not an issue.
|
|
*/
|
|
if (params != NULL) {
|
|
OSSL_PARAM param_lens[3] = { OSSL_PARAM_END, OSSL_PARAM_END,
|
|
OSSL_PARAM_END };
|
|
OSSL_PARAM *q = param_lens;
|
|
const OSSL_PARAM *p;
|
|
|
|
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
|
|
if (p != NULL)
|
|
memcpy(q++, p, sizeof(*q));
|
|
|
|
/*
|
|
* Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for
|
|
* OSSL_CIPHER_PARAM_IVLEN so both are covered here.
|
|
*/
|
|
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
|
|
if (p != NULL)
|
|
memcpy(q++, p, sizeof(*q));
|
|
|
|
if (q != param_lens) {
|
|
if (!EVP_CIPHER_CTX_set_params(ctx, param_lens)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (enc) {
|
|
if (ctx->cipher->einit == NULL) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
|
|
return ctx->cipher->einit(ctx->algctx,
|
|
key,
|
|
key == NULL ? 0
|
|
: EVP_CIPHER_CTX_get_key_length(ctx),
|
|
iv,
|
|
iv == NULL ? 0
|
|
: EVP_CIPHER_CTX_get_iv_length(ctx),
|
|
params);
|
|
}
|
|
|
|
if (ctx->cipher->dinit == NULL) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
|
|
return ctx->cipher->dinit(ctx->algctx,
|
|
key,
|
|
key == NULL ? 0
|
|
: EVP_CIPHER_CTX_get_key_length(ctx),
|
|
iv,
|
|
iv == NULL ? 0
|
|
: EVP_CIPHER_CTX_get_iv_length(ctx),
|
|
params);
|
|
|
|
/* Code below to be removed when legacy support is dropped. */
|
|
legacy:
|
|
|
|
if (cipher != NULL) {
|
|
/*
|
|
* Ensure a context left lying around from last time is cleared (we
|
|
* previously attempted to avoid this if the same ENGINE and
|
|
* EVP_CIPHER could be used).
|
|
*/
|
|
if (ctx->cipher) {
|
|
unsigned long flags = ctx->flags;
|
|
EVP_CIPHER_CTX_reset(ctx);
|
|
/* Restore encrypt and flags */
|
|
ctx->encrypt = enc;
|
|
ctx->flags = flags;
|
|
}
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
|
if (impl != NULL) {
|
|
if (!ENGINE_init(impl)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
} else {
|
|
impl = tmpimpl;
|
|
}
|
|
if (impl != NULL) {
|
|
/* There's an ENGINE for this job ... (apparently) */
|
|
const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
|
|
|
|
if (c == NULL) {
|
|
/*
|
|
* One positive side-effect of US's export control history,
|
|
* is that we should at least be able to avoid using US
|
|
* misspellings of "initialisation"?
|
|
*/
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
/* We'll use the ENGINE's private cipher definition */
|
|
cipher = c;
|
|
/*
|
|
* Store the ENGINE functional reference so we know 'cipher' came
|
|
* from an ENGINE and we need to release it when done.
|
|
*/
|
|
ctx->engine = impl;
|
|
} else {
|
|
ctx->engine = NULL;
|
|
}
|
|
#endif
|
|
|
|
ctx->cipher = cipher;
|
|
if (ctx->cipher->ctx_size) {
|
|
ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);
|
|
if (ctx->cipher_data == NULL) {
|
|
ctx->cipher = NULL;
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
|
return 0;
|
|
}
|
|
} else {
|
|
ctx->cipher_data = NULL;
|
|
}
|
|
ctx->key_len = cipher->key_len;
|
|
/* Preserve wrap enable flag, zero everything else */
|
|
ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
|
|
if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
|
|
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL) <= 0) {
|
|
ctx->cipher = NULL;
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
|
skip_to_init:
|
|
#endif
|
|
if (ctx->cipher == NULL)
|
|
return 0;
|
|
|
|
/* we assume block size is a power of 2 in *cryptUpdate */
|
|
OPENSSL_assert(ctx->cipher->block_size == 1
|
|
|| ctx->cipher->block_size == 8
|
|
|| ctx->cipher->block_size == 16);
|
|
|
|
if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW)
|
|
&& EVP_CIPHER_CTX_get_mode(ctx) == EVP_CIPH_WRAP_MODE) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_WRAP_MODE_NOT_ALLOWED);
|
|
return 0;
|
|
}
|
|
|
|
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
|
|
& EVP_CIPH_CUSTOM_IV) == 0) {
|
|
switch (EVP_CIPHER_CTX_get_mode(ctx)) {
|
|
|
|
case EVP_CIPH_STREAM_CIPHER:
|
|
case EVP_CIPH_ECB_MODE:
|
|
break;
|
|
|
|
case EVP_CIPH_CFB_MODE:
|
|
case EVP_CIPH_OFB_MODE:
|
|
|
|
ctx->num = 0;
|
|
/* fall-through */
|
|
|
|
case EVP_CIPH_CBC_MODE:
|
|
n = EVP_CIPHER_CTX_get_iv_length(ctx);
|
|
if (n < 0 || n > (int)sizeof(ctx->iv)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
|
|
return 0;
|
|
}
|
|
if (iv != NULL)
|
|
memcpy(ctx->oiv, iv, n);
|
|
memcpy(ctx->iv, ctx->oiv, n);
|
|
break;
|
|
|
|
case EVP_CIPH_CTR_MODE:
|
|
ctx->num = 0;
|
|
/* Don't reuse IV for CTR mode */
|
|
if (iv != NULL) {
|
|
n = EVP_CIPHER_CTX_get_iv_length(ctx);
|
|
if (n <= 0 || n > (int)sizeof(ctx->iv)) {
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
|
|
return 0;
|
|
}
|
|
memcpy(ctx->iv, iv, n);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (key != NULL || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
|
|
if (!ctx->cipher->init(ctx, key, iv, enc))
|
|
return 0;
|
|
}
|
|
ctx->buf_len = 0;
|
|
ctx->final_used = 0;
|
|
ctx->block_mask = ctx->cipher->block_size - 1;
|
|
return 1;
|
|
}
|