Skip to content

Commit

Permalink
EVP_SKEY strawman implementation
Browse files Browse the repository at this point in the history
EVP_CipherInit_skey basically calls evp_cipher_init_skey_internal
which, in turn, is a evp_cipher_init_internal without any legacy stuff
  • Loading branch information
beldmit committed Nov 8, 2024
1 parent e4e0de3 commit 239f8d2
Show file tree
Hide file tree
Showing 2 changed files with 268 additions and 0 deletions.
181 changes: 181 additions & 0 deletions crypto/evp/evp_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,187 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
return 1;
}

static int evp_cipher_init_skey_internal(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher,
const EVP_SKEY *key,
const unsigned char *iv, int enc,
const OSSL_PARAM params[])
{
/*
* 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;
}

/*
* If there are engines involved then we throw an error
*/
if (ctx->engine != NULL
|| (cipher != NULL && cipher->origin == EVP_ORIG_METH)
|| (cipher == NULL && ctx->cipher != NULL
&& ctx->cipher->origin == EVP_ORIG_METH)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
/*
* 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;
}

/* 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);
/* Coverity false positive, the reference counting is confusing it */
/* coverity[use_after_free] */
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 synonym 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_opaque == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}

return ctx->cipher->einit_opaque(ctx->algctx,
key->params,
iv,
iv == NULL ? 0
: EVP_CIPHER_CTX_get_iv_length(ctx),
params);
}

if (ctx->cipher->dinit_opaque == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}

return ctx->cipher->dinit_opaque(ctx->algctx,
key->params,
iv,
iv == NULL ? 0
: EVP_CIPHER_CTX_get_iv_length(ctx),
params);
}

int EVP_CipherInit_skey(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const EVP_SKEY *key, const unsigned char *iv,
int enc, const OSSL_PARAM params[])
{
return evp_cipher_init_skey_internal(ctx, cipher, key, iv, enc, params);
}

int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv,
int enc, const OSSL_PARAM params[])
Expand Down
87 changes: 87 additions & 0 deletions crypto/evp/p_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2495,3 +2495,90 @@ int EVP_PKEY_get_field_type(const EVP_PKEY *pkey)
return 0;
}
#endif

/*- All methods below can also be used in FIPS_MODULE */

EVP_SKEY *EVP_SKEY_new(void)
{
EVP_SKEY *ret = OPENSSL_zalloc(sizeof(*ret));

if (ret == NULL)
return NULL;

if (!CRYPTO_NEW_REF(&ret->references, 1))
goto err;

ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
goto err;
}

return ret;

err:
CRYPTO_FREE_REF(&ret->references);
CRYPTO_THREAD_lock_free(ret->lock);
OPENSSL_free(ret);
return NULL;
}

int EVP_SKEY_up_ref(EVP_SKEY *pkey)
{
int i;

if (CRYPTO_UP_REF(&pkey->references, &i) <= 0)
return 0;

REF_PRINT_COUNT("EVP_SKEY", pkey);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}

static void evp_skey_free_it(EVP_SKEY *x)
{
OSSL_PARAM_free(x->params);
x->params = NULL;
}

void EVP_SKEY_free(EVP_SKEY *x)
{
int i;

if (x == NULL)
return;

CRYPTO_DOWN_REF(&x->references, &i);
REF_PRINT_COUNT("EVP_SKEY", x);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
evp_skey_free_it(x);

CRYPTO_THREAD_lock_free(x->lock);
CRYPTO_FREE_REF(&x->references);
OPENSSL_free(x);
}

/*Passing ownership*/
int EVP_SKEY_assign(EVP_SKEY *x, OSSL_PARAM *params)
{
if (x->params != NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
return 0;
}

x->params = params;
return 1;
}

int EVP_SKEY_todata(const EVP_SKEY *x, OSSL_PARAM **params)
{
if (x->params == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
return 0;
}

*params = OSSL_PARAM_dup(x->params);
return (*params != NULL) ? 1 : 0;
}

0 comments on commit 239f8d2

Please sign in to comment.