2016-05-18 02:24:46 +08:00
|
|
|
/*
|
2021-02-18 22:57:13 +08:00
|
|
|
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
1998-12-21 18:52:47 +08:00
|
|
|
*
|
2018-12-06 20:40:06 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 02:24:46 +08:00
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
1998-12-21 18:52:47 +08:00
|
|
|
*/
|
|
|
|
|
2020-07-14 07:40:29 +08:00
|
|
|
/* We need to use some engine deprecated APIs */
|
|
|
|
#define OPENSSL_SUPPRESS_DEPRECATED
|
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
#include <stdio.h>
|
2021-02-03 01:17:23 +08:00
|
|
|
#include <limits.h>
|
2016-06-17 19:55:01 +08:00
|
|
|
#include <assert.h>
|
2015-05-14 22:56:48 +08:00
|
|
|
#include "internal/cryptlib.h"
|
1999-04-24 06:13:45 +08:00
|
|
|
#include <openssl/evp.h>
|
2000-05-27 07:51:35 +08:00
|
|
|
#include <openssl/err.h>
|
2004-04-20 01:46:04 +08:00
|
|
|
#include <openssl/rand.h>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/engine.h>
|
2019-04-03 22:38:07 +08:00
|
|
|
#include <openssl/params.h>
|
|
|
|
#include <openssl/core_names.h>
|
2019-09-28 06:45:33 +08:00
|
|
|
#include "crypto/evp.h"
|
2019-04-03 22:38:07 +08:00
|
|
|
#include "internal/provider.h"
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "evp_local.h"
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2019-04-03 22:38:07 +08:00
|
|
|
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-04-03 22:38:07 +08:00
|
|
|
if (ctx == NULL)
|
2015-12-13 23:03:02 +08:00
|
|
|
return 1;
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
|
|
|
goto legacy;
|
|
|
|
|
|
|
|
if (ctx->provctx != NULL) {
|
|
|
|
if (ctx->cipher->freectx != NULL)
|
|
|
|
ctx->cipher->freectx(ctx->provctx);
|
|
|
|
ctx->provctx = NULL;
|
|
|
|
}
|
|
|
|
if (ctx->fetched_cipher != NULL)
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
2019-04-03 22:38:07 +08:00
|
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
|
|
|
if (ctx->cipher != NULL) {
|
|
|
|
if (ctx->cipher->cleanup && !ctx->cipher->cleanup(ctx))
|
2015-12-13 23:03:02 +08:00
|
|
|
return 0;
|
|
|
|
/* Cleanse cipher context data */
|
2019-04-03 22:38:07 +08:00
|
|
|
if (ctx->cipher_data && ctx->cipher->ctx_size)
|
|
|
|
OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
|
2015-12-13 23:03:02 +08:00
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
OPENSSL_free(ctx->cipher_data);
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2019-04-03 22:38:07 +08:00
|
|
|
ENGINE_finish(ctx->engine);
|
2015-12-13 23:03:02 +08:00
|
|
|
#endif
|
2019-04-03 22:38:07 +08:00
|
|
|
memset(ctx, 0, sizeof(*ctx));
|
2015-12-13 23:03:02 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2005-12-02 21:46:39 +08:00
|
|
|
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-12-13 23:03:02 +08:00
|
|
|
return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX));
|
|
|
|
}
|
|
|
|
|
|
|
|
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
|
|
|
|
{
|
|
|
|
EVP_CIPHER_CTX_reset(ctx);
|
|
|
|
OPENSSL_free(ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-10-17 08:37:12 +08:00
|
|
|
|
2000-05-28 20:44:46 +08:00
|
|
|
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *key, const unsigned char *iv, int enc)
|
|
|
|
{
|
2017-10-29 22:13:43 +08:00
|
|
|
if (cipher != NULL)
|
|
|
|
EVP_CIPHER_CTX_reset(ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
|
|
|
ENGINE *impl, const unsigned char *key,
|
|
|
|
const unsigned char *iv, int enc)
|
|
|
|
{
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2019-04-03 22:38:07 +08:00
|
|
|
ENGINE *tmpimpl = NULL;
|
2019-05-13 13:41:06 +08:00
|
|
|
#endif
|
2019-04-03 22:38:07 +08:00
|
|
|
/*
|
|
|
|
* 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) {
|
2015-01-22 11:40:55 +08:00
|
|
|
enc = ctx->encrypt;
|
2019-04-03 22:38:07 +08:00
|
|
|
} else {
|
2015-01-22 11:40:55 +08:00
|
|
|
if (enc)
|
|
|
|
enc = 1;
|
|
|
|
ctx->encrypt = enc;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (cipher == NULL && ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO(3.0): Legacy work around code below. Remove this */
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
|
|
|
* 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
|
2016-02-06 04:23:54 +08:00
|
|
|
* reinitialisation, when it may all be unnecessary.
|
2015-01-22 11:40:55 +08:00
|
|
|
*/
|
2015-12-10 04:18:00 +08:00
|
|
|
if (ctx->engine && ctx->cipher
|
2016-05-16 21:56:53 +08:00
|
|
|
&& (cipher == NULL || cipher->nid == ctx->cipher->nid))
|
2015-01-22 11:40:55 +08:00
|
|
|
goto skip_to_init;
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (cipher != NULL && impl == NULL) {
|
|
|
|
/* Ask if an ENGINE is reserved for this job */
|
|
|
|
tmpimpl = ENGINE_get_cipher_engine(cipher->nid);
|
|
|
|
}
|
2003-01-31 01:39:26 +08:00
|
|
|
#endif
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are engines involved then we should use legacy handling for now.
|
|
|
|
*/
|
|
|
|
if (ctx->engine != NULL
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2019-05-13 13:41:06 +08:00
|
|
|
|| tmpimpl != NULL
|
|
|
|
#endif
|
|
|
|
|| impl != NULL) {
|
2019-04-03 22:38:07 +08:00
|
|
|
if (ctx->cipher == ctx->fetched_cipher)
|
|
|
|
ctx->cipher = NULL;
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
2019-04-03 22:38:07 +08:00
|
|
|
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) {
|
|
|
|
OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
|
|
|
|
ctx->cipher_data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* TODO(3.0): 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;
|
|
|
|
}
|
|
|
|
|
2019-08-05 20:37:05 +08:00
|
|
|
if (cipher == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
cipher = ctx->cipher;
|
|
|
|
|
|
|
|
if (cipher->prov == NULL) {
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifdef FIPS_MODULE
|
2019-12-01 07:18:47 +08:00
|
|
|
/* We only do explicit fetches inside the FIPS module */
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2019-05-13 13:41:06 +08:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
EVP_CIPHER *provciph =
|
2020-01-09 00:16:22 +08:00
|
|
|
EVP_CIPHER_fetch(NULL,
|
|
|
|
cipher->nid == NID_undef ? "NULL"
|
|
|
|
: OBJ_nid2sn(cipher->nid),
|
|
|
|
"");
|
2019-05-13 13:41:06 +08:00
|
|
|
|
2020-08-29 15:46:24 +08:00
|
|
|
if (provciph == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
cipher = provciph;
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER_free(ctx->fetched_cipher);
|
2019-04-03 22:38:07 +08:00
|
|
|
ctx->fetched_cipher = provciph;
|
2019-05-13 13:41:06 +08:00
|
|
|
#endif
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
|
2021-02-08 09:38:21 +08:00
|
|
|
if (cipher->prov != NULL) {
|
|
|
|
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;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
ctx->cipher = cipher;
|
|
|
|
if (ctx->provctx == NULL) {
|
2019-04-30 19:41:51 +08:00
|
|
|
ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
|
2019-04-03 22:38:07 +08:00
|
|
|
if (ctx->provctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
2019-04-03 22:38:07 +08:00
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc) {
|
|
|
|
if (ctx->cipher->einit == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-10 20:23:58 +08:00
|
|
|
return ctx->cipher->einit(ctx->provctx,
|
|
|
|
key,
|
2019-04-19 23:48:09 +08:00
|
|
|
key == NULL ? 0
|
|
|
|
: EVP_CIPHER_CTX_key_length(ctx),
|
2019-04-10 20:23:58 +08:00
|
|
|
iv,
|
2019-04-19 23:48:09 +08:00
|
|
|
iv == NULL ? 0
|
|
|
|
: EVP_CIPHER_CTX_iv_length(ctx));
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->cipher->dinit == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-10 20:23:58 +08:00
|
|
|
return ctx->cipher->dinit(ctx->provctx,
|
|
|
|
key,
|
2019-04-19 23:48:09 +08:00
|
|
|
key == NULL ? 0
|
|
|
|
: EVP_CIPHER_CTX_key_length(ctx),
|
2019-04-10 20:23:58 +08:00
|
|
|
iv,
|
2019-04-19 23:48:09 +08:00
|
|
|
iv == NULL ? 0
|
|
|
|
: EVP_CIPHER_CTX_iv_length(ctx));
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
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
|
2015-01-22 11:40:55 +08:00
|
|
|
* EVP_CIPHER could be used).
|
|
|
|
*/
|
|
|
|
if (ctx->cipher) {
|
|
|
|
unsigned long flags = ctx->flags;
|
2015-12-14 04:36:33 +08:00
|
|
|
EVP_CIPHER_CTX_reset(ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
/* Restore encrypt and flags */
|
|
|
|
ctx->encrypt = enc;
|
|
|
|
ctx->flags = flags;
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2019-04-03 22:38:07 +08:00
|
|
|
if (impl != NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!ENGINE_init(impl)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
} else {
|
|
|
|
impl = tmpimpl;
|
|
|
|
}
|
|
|
|
if (impl != NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
/* There's an ENGINE for this job ... (apparently) */
|
|
|
|
const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (c == NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
|
|
|
* One positive side-effect of US's export control history,
|
|
|
|
* is that we should at least be able to avoid using US
|
2016-02-06 04:23:54 +08:00
|
|
|
* misspellings of "initialisation"?
|
2015-01-22 11:40:55 +08:00
|
|
|
*/
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2015-01-22 11:40:55 +08:00
|
|
|
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;
|
2019-04-03 22:38:07 +08:00
|
|
|
} else {
|
2015-01-22 11:40:55 +08:00
|
|
|
ctx->engine = NULL;
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
2003-01-31 01:39:26 +08:00
|
|
|
#endif
|
2002-05-16 02:49:25 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
ctx->cipher = cipher;
|
|
|
|
if (ctx->cipher->ctx_size) {
|
2015-08-26 01:25:58 +08:00
|
|
|
ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);
|
2015-10-30 19:12:26 +08:00
|
|
|
if (ctx->cipher_data == NULL) {
|
2017-02-06 20:37:42 +08:00
|
|
|
ctx->cipher = NULL;
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
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)) {
|
2017-02-06 20:37:42 +08:00
|
|
|
ctx->cipher = NULL;
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2015-01-22 11:40:55 +08:00
|
|
|
skip_to_init:
|
2003-01-31 01:39:26 +08:00
|
|
|
#endif
|
2019-05-07 09:04:37 +08:00
|
|
|
if (ctx->cipher == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/* 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_mode(ctx) == EVP_CIPH_WRAP_MODE) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_WRAP_MODE_NOT_ALLOWED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-12-18 22:06:30 +08:00
|
|
|
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_CUSTOM_IV)) {
|
2015-01-22 11:40:55 +08:00
|
|
|
switch (EVP_CIPHER_CTX_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:
|
|
|
|
|
|
|
|
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
|
|
|
|
(int)sizeof(ctx->iv));
|
|
|
|
if (iv)
|
|
|
|
memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
|
|
|
|
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EVP_CIPH_CTR_MODE:
|
|
|
|
ctx->num = 0;
|
|
|
|
/* Don't reuse IV for CTR mode */
|
|
|
|
if (iv)
|
|
|
|
memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key || (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;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2000-05-27 20:38:43 +08:00
|
|
|
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *in, int inl)
|
|
|
|
{
|
|
|
|
if (ctx->encrypt)
|
|
|
|
return EVP_EncryptUpdate(ctx, out, outl, in, inl);
|
|
|
|
else
|
|
|
|
return EVP_DecryptUpdate(ctx, out, outl, in, inl);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2001-10-17 08:37:12 +08:00
|
|
|
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (ctx->encrypt)
|
|
|
|
return EVP_EncryptFinal_ex(ctx, out, outl);
|
|
|
|
else
|
|
|
|
return EVP_DecryptFinal_ex(ctx, out, outl);
|
|
|
|
}
|
2001-10-17 08:37:12 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (ctx->encrypt)
|
|
|
|
return EVP_EncryptFinal(ctx, out, outl);
|
|
|
|
else
|
|
|
|
return EVP_DecryptFinal(ctx, out, outl);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2000-05-27 20:38:43 +08:00
|
|
|
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *key, const unsigned char *iv)
|
|
|
|
{
|
|
|
|
return EVP_CipherInit(ctx, cipher, key, iv, 1);
|
|
|
|
}
|
2001-10-09 01:24:10 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
|
|
|
ENGINE *impl, const unsigned char *key,
|
|
|
|
const unsigned char *iv)
|
|
|
|
{
|
|
|
|
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2000-05-27 20:38:43 +08:00
|
|
|
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *key, const unsigned char *iv)
|
|
|
|
{
|
|
|
|
return EVP_CipherInit(ctx, cipher, key, iv, 0);
|
|
|
|
}
|
2001-10-09 01:24:10 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
|
|
|
ENGINE *impl, const unsigned char *key,
|
|
|
|
const unsigned char *iv)
|
|
|
|
{
|
|
|
|
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2016-06-17 19:55:01 +08:00
|
|
|
/*
|
|
|
|
* According to the letter of standard difference between pointers
|
|
|
|
* is specified to be valid only within same object. This makes
|
|
|
|
* it formally challenging to determine if input and output buffers
|
|
|
|
* are not partially overlapping with standard pointer arithmetic.
|
|
|
|
*/
|
|
|
|
#ifdef PTRDIFF_T
|
|
|
|
# undef PTRDIFF_T
|
|
|
|
#endif
|
|
|
|
#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE==64
|
|
|
|
/*
|
|
|
|
* Then we have VMS that distinguishes itself by adhering to
|
2016-06-20 17:11:25 +08:00
|
|
|
* sizeof(size_t)==4 even in 64-bit builds, which means that
|
|
|
|
* difference between two pointers might be truncated to 32 bits.
|
|
|
|
* In the context one can even wonder how comparison for
|
|
|
|
* equality is implemented. To be on the safe side we adhere to
|
|
|
|
* PTRDIFF_T even for comparison for equality.
|
2016-06-17 19:55:01 +08:00
|
|
|
*/
|
|
|
|
# define PTRDIFF_T uint64_t
|
|
|
|
#else
|
|
|
|
# define PTRDIFF_T size_t
|
|
|
|
#endif
|
|
|
|
|
2017-01-24 20:57:34 +08:00
|
|
|
int is_partially_overlapping(const void *ptr1, const void *ptr2, int len)
|
2016-06-17 19:55:01 +08:00
|
|
|
{
|
|
|
|
PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2;
|
|
|
|
/*
|
|
|
|
* Check for partially overlapping buffers. [Binary logical
|
|
|
|
* operations are used instead of boolean to minimize number
|
|
|
|
* of conditional branches.]
|
|
|
|
*/
|
2016-07-25 21:02:26 +08:00
|
|
|
int overlapped = (len > 0) & (diff != 0) & ((diff < (PTRDIFF_T)len) |
|
|
|
|
(diff > (0 - (PTRDIFF_T)len)));
|
2017-01-25 23:01:43 +08:00
|
|
|
|
2016-07-25 21:02:26 +08:00
|
|
|
return overlapped;
|
2016-06-17 19:55:01 +08:00
|
|
|
}
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
|
|
|
|
unsigned char *out, int *outl,
|
|
|
|
const unsigned char *in, int inl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2016-11-17 17:31:39 +08:00
|
|
|
int i, j, bl, cmpl = inl;
|
|
|
|
|
|
|
|
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
|
|
|
|
cmpl = (cmpl + 7) / 8;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2017-01-24 20:57:34 +08:00
|
|
|
bl = ctx->cipher->block_size;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
2017-01-24 20:57:34 +08:00
|
|
|
/* If block size > 1 then the cipher will have to do this check */
|
2016-11-17 17:31:39 +08:00
|
|
|
if (bl == 1 && is_partially_overlapping(out, in, cmpl)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
|
2016-06-20 17:11:25 +08:00
|
|
|
return 0;
|
2016-07-25 21:02:26 +08:00
|
|
|
}
|
2016-06-20 17:11:25 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
i = ctx->cipher->do_cipher(ctx, out, in, inl);
|
|
|
|
if (i < 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
*outl = i;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-05-21 16:31:32 +08:00
|
|
|
if (inl <= 0) {
|
|
|
|
*outl = 0;
|
|
|
|
return inl == 0;
|
|
|
|
}
|
2016-11-17 17:31:39 +08:00
|
|
|
if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
|
2016-06-20 17:11:25 +08:00
|
|
|
return 0;
|
2016-07-25 21:02:26 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (ctx->buf_len == 0 && (inl & (ctx->block_mask)) == 0) {
|
|
|
|
if (ctx->cipher->do_cipher(ctx, out, in, inl)) {
|
|
|
|
*outl = inl;
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
*outl = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i = ctx->buf_len;
|
|
|
|
OPENSSL_assert(bl <= (int)sizeof(ctx->buf));
|
|
|
|
if (i != 0) {
|
2016-03-04 07:36:23 +08:00
|
|
|
if (bl - i > inl) {
|
2015-01-22 11:40:55 +08:00
|
|
|
memcpy(&(ctx->buf[i]), in, inl);
|
|
|
|
ctx->buf_len += inl;
|
|
|
|
*outl = 0;
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
j = bl - i;
|
2021-02-03 01:17:23 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Once we've processed the first j bytes from in, the amount of
|
|
|
|
* data left that is a multiple of the block length is:
|
|
|
|
* (inl - j) & ~(bl - 1)
|
|
|
|
* We must ensure that this amount of data, plus the one block that
|
|
|
|
* we process from ctx->buf does not exceed INT_MAX
|
|
|
|
*/
|
|
|
|
if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
memcpy(&(ctx->buf[i]), in, j);
|
|
|
|
inl -= j;
|
|
|
|
in += j;
|
2016-06-20 17:11:25 +08:00
|
|
|
if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
out += bl;
|
|
|
|
*outl = bl;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
*outl = 0;
|
|
|
|
i = inl & (bl - 1);
|
|
|
|
inl -= i;
|
|
|
|
if (inl > 0) {
|
|
|
|
if (!ctx->cipher->do_cipher(ctx, out, in, inl))
|
|
|
|
return 0;
|
|
|
|
*outl += inl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i != 0)
|
|
|
|
memcpy(ctx->buf, &(in[inl]), i);
|
|
|
|
ctx->buf_len = i;
|
|
|
|
return 1;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
|
|
|
|
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
|
|
|
const unsigned char *in, int inl)
|
|
|
|
{
|
2019-04-03 22:38:07 +08:00
|
|
|
int ret;
|
|
|
|
size_t soutl;
|
2019-04-10 20:43:45 +08:00
|
|
|
int blocksize;
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2020-10-30 02:05:19 +08:00
|
|
|
if (outl != NULL) {
|
|
|
|
*outl = 0;
|
|
|
|
} else {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
2020-10-30 02:05:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of decryption context when encrypting */
|
|
|
|
if (!ctx->encrypt) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
2018-12-09 21:18:50 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:35:04 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2019-05-25 05:35:04 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->cipher->prov == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2020-12-24 00:30:36 +08:00
|
|
|
blocksize = ctx->cipher->block_size;
|
2019-04-10 20:43:45 +08:00
|
|
|
|
|
|
|
if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2019-04-10 20:43:45 +08:00
|
|
|
ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
|
|
|
|
inl + (blocksize == 1 ? 0 : blocksize), in,
|
|
|
|
(size_t)inl);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2019-05-03 21:44:38 +08:00
|
|
|
if (ret) {
|
|
|
|
if (soutl > INT_MAX) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
2019-05-03 21:44:38 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = soutl;
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
2019-05-03 21:44:38 +08:00
|
|
|
|
2019-04-03 22:38:07 +08:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
|
|
|
|
}
|
|
|
|
|
2000-05-27 20:38:43 +08:00
|
|
|
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
ret = EVP_EncryptFinal_ex(ctx, out, outl);
|
|
|
|
return ret;
|
|
|
|
}
|
2001-10-17 08:37:12 +08:00
|
|
|
|
|
|
|
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int n, ret;
|
|
|
|
unsigned int i, b, bl;
|
2019-04-03 22:38:07 +08:00
|
|
|
size_t soutl;
|
2019-04-10 20:43:45 +08:00
|
|
|
int blocksize;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2020-10-30 02:05:19 +08:00
|
|
|
if (outl != NULL) {
|
|
|
|
*outl = 0;
|
|
|
|
} else {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
2020-10-30 02:05:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of decryption context when encrypting */
|
|
|
|
if (!ctx->encrypt) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
2018-12-09 21:18:50 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-07 08:18:29 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2019-05-07 08:18:29 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ctx->cipher->prov == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-04-10 20:43:45 +08:00
|
|
|
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
|
|
|
|
|
|
|
if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-10 20:43:45 +08:00
|
|
|
ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
|
|
|
|
blocksize == 1 ? 0 : blocksize);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2019-05-03 21:44:38 +08:00
|
|
|
if (ret) {
|
|
|
|
if (soutl > INT_MAX) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
|
2019-05-03 21:44:38 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = soutl;
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
|
|
|
ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
|
|
|
|
if (ret < 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
*outl = ret;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = ctx->cipher->block_size;
|
2017-12-08 02:39:34 +08:00
|
|
|
OPENSSL_assert(b <= sizeof(ctx->buf));
|
2015-01-22 11:40:55 +08:00
|
|
|
if (b == 1) {
|
|
|
|
*outl = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
bl = ctx->buf_len;
|
|
|
|
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
|
|
|
if (bl) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = b - bl;
|
|
|
|
for (i = bl; i < b; i++)
|
|
|
|
ctx->buf[i] = n;
|
|
|
|
ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
*outl = b;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2000-05-27 20:38:43 +08:00
|
|
|
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *in, int inl)
|
|
|
|
{
|
2019-04-03 22:38:07 +08:00
|
|
|
int fix_len, cmpl = inl, ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned int b;
|
2019-04-03 22:38:07 +08:00
|
|
|
size_t soutl;
|
2019-04-10 20:43:45 +08:00
|
|
|
int blocksize;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2020-10-30 02:05:19 +08:00
|
|
|
if (outl != NULL) {
|
|
|
|
*outl = 0;
|
|
|
|
} else {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
2020-10-30 02:05:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of encryption context when decrypting */
|
|
|
|
if (ctx->encrypt) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
2018-12-09 21:18:50 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-07 08:48:42 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2019-05-07 08:48:42 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ctx->cipher->prov == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-04-10 20:43:45 +08:00
|
|
|
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
|
|
|
|
|
|
|
if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2019-04-10 20:43:45 +08:00
|
|
|
ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
|
|
|
|
inl + (blocksize == 1 ? 0 : blocksize), in,
|
|
|
|
(size_t)inl);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
if (soutl > INT_MAX) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = soutl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2017-01-24 20:57:34 +08:00
|
|
|
b = ctx->cipher->block_size;
|
|
|
|
|
2016-11-17 17:31:39 +08:00
|
|
|
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
|
|
|
|
cmpl = (cmpl + 7) / 8;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
2016-11-17 17:31:39 +08:00
|
|
|
if (b == 1 && is_partially_overlapping(out, in, cmpl)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
|
2016-06-20 17:11:25 +08:00
|
|
|
return 0;
|
2016-07-25 21:02:26 +08:00
|
|
|
}
|
2016-06-20 17:11:25 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
fix_len = ctx->cipher->do_cipher(ctx, out, in, inl);
|
|
|
|
if (fix_len < 0) {
|
|
|
|
*outl = 0;
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
*outl = fix_len;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-05-21 16:31:32 +08:00
|
|
|
if (inl <= 0) {
|
|
|
|
*outl = 0;
|
|
|
|
return inl == 0;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->flags & EVP_CIPH_NO_PADDING)
|
2018-12-09 21:18:50 +08:00
|
|
|
return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2017-12-08 02:39:34 +08:00
|
|
|
OPENSSL_assert(b <= sizeof(ctx->final));
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (ctx->final_used) {
|
2016-06-20 17:11:25 +08:00
|
|
|
/* see comment about PTRDIFF_T comparison above */
|
|
|
|
if (((PTRDIFF_T)out == (PTRDIFF_T)in)
|
2016-07-25 21:02:26 +08:00
|
|
|
|| is_partially_overlapping(out, in, b)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
|
2016-06-20 17:11:25 +08:00
|
|
|
return 0;
|
2016-07-25 21:02:26 +08:00
|
|
|
}
|
2021-02-03 01:17:23 +08:00
|
|
|
/*
|
|
|
|
* final_used is only ever set if buf_len is 0. Therefore the maximum
|
|
|
|
* length output we will ever see from evp_EncryptDecryptUpdate is
|
|
|
|
* the maximum multiple of the block length that is <= inl, or just:
|
|
|
|
* inl & ~(b - 1)
|
|
|
|
* Since final_used has been set then the final output length is:
|
|
|
|
* (inl & ~(b - 1)) + b
|
|
|
|
* This must never exceed INT_MAX
|
|
|
|
*/
|
|
|
|
if ((inl & ~(b - 1)) > INT_MAX - b) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
memcpy(out, ctx->final, b);
|
|
|
|
out += b;
|
|
|
|
fix_len = 1;
|
|
|
|
} else
|
|
|
|
fix_len = 0;
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
if (!evp_EncryptDecryptUpdate(ctx, out, outl, in, inl))
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if we have 'decrypted' a multiple of block size, make sure we have a
|
|
|
|
* copy of this last block
|
|
|
|
*/
|
|
|
|
if (b > 1 && !ctx->buf_len) {
|
|
|
|
*outl -= b;
|
|
|
|
ctx->final_used = 1;
|
|
|
|
memcpy(ctx->final, &out[*outl], b);
|
|
|
|
} else
|
|
|
|
ctx->final_used = 0;
|
|
|
|
|
|
|
|
if (fix_len)
|
|
|
|
*outl += b;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
ret = EVP_DecryptFinal_ex(ctx, out, outl);
|
|
|
|
return ret;
|
|
|
|
}
|
2001-10-17 08:37:12 +08:00
|
|
|
|
|
|
|
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i, n;
|
|
|
|
unsigned int b;
|
2019-04-03 22:38:07 +08:00
|
|
|
size_t soutl;
|
|
|
|
int ret;
|
2019-04-10 20:43:45 +08:00
|
|
|
int blocksize;
|
2018-12-09 21:18:50 +08:00
|
|
|
|
2020-10-30 02:05:19 +08:00
|
|
|
if (outl != NULL) {
|
|
|
|
*outl = 0;
|
|
|
|
} else {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
2020-10-30 02:05:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of encryption context when decrypting */
|
|
|
|
if (ctx->encrypt) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
2018-12-09 21:18:50 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:35:04 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2019-05-25 05:35:04 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->cipher->prov == NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-04-10 20:43:45 +08:00
|
|
|
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
|
|
|
|
|
|
|
if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-10 20:43:45 +08:00
|
|
|
ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
|
|
|
|
blocksize == 1 ? 0 : blocksize);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
if (soutl > INT_MAX) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = soutl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
*outl = 0;
|
|
|
|
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
|
|
|
i = ctx->cipher->do_cipher(ctx, out, NULL, 0);
|
|
|
|
if (i < 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
*outl = i;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
b = ctx->cipher->block_size;
|
|
|
|
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
|
|
|
if (ctx->buf_len) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (b > 1) {
|
|
|
|
if (ctx->buf_len || !ctx->final_used) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_WRONG_FINAL_BLOCK_LENGTH);
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2017-12-08 02:39:34 +08:00
|
|
|
OPENSSL_assert(b <= sizeof(ctx->final));
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The following assumes that the ciphertext has been authenticated.
|
|
|
|
* Otherwise it provides a padding oracle.
|
|
|
|
*/
|
|
|
|
n = ctx->final[b - 1];
|
|
|
|
if (n == 0 || n > (int)b) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_BAD_DECRYPT);
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
if (ctx->final[--b] != n) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_BAD_DECRYPT);
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n = ctx->cipher->block_size - n;
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
out[i] = ctx->final[i];
|
|
|
|
*outl = n;
|
|
|
|
} else
|
|
|
|
*outl = 0;
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2008-11-12 11:58:08 +08:00
|
|
|
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-11-15 00:05:19 +08:00
|
|
|
if (c->cipher->prov != NULL) {
|
|
|
|
int ok;
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
size_t len = keylen;
|
2019-07-16 07:46:14 +08:00
|
|
|
|
2019-11-15 00:05:19 +08:00
|
|
|
if (EVP_CIPHER_CTX_key_length(c) == keylen)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Check the cipher actually understands this parameter */
|
|
|
|
if (OSSL_PARAM_locate_const(EVP_CIPHER_settable_ctx_params(c->cipher),
|
|
|
|
OSSL_CIPHER_PARAM_KEYLEN) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
|
|
|
|
ok = evp_do_ciph_ctx_setparams(c->cipher, c->provctx, params);
|
2019-07-09 13:32:16 +08:00
|
|
|
|
2019-11-15 00:05:19 +08:00
|
|
|
return ok > 0 ? 1 : 0;
|
|
|
|
}
|
2019-07-09 13:32:16 +08:00
|
|
|
|
|
|
|
/* TODO(3.0) legacy code follows */
|
2019-11-15 00:05:19 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Note there have never been any built-in ciphers that define this flag
|
|
|
|
* since it was first introduced.
|
|
|
|
*/
|
2015-01-22 11:40:55 +08:00
|
|
|
if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
|
|
|
|
return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
|
2019-04-03 22:38:07 +08:00
|
|
|
if (EVP_CIPHER_CTX_key_length(c) == keylen)
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
|
|
|
|
c->key_len = keylen;
|
|
|
|
return 1;
|
|
|
|
}
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2000-05-31 02:26:22 +08:00
|
|
|
|
2001-02-14 10:11:52 +08:00
|
|
|
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-07-09 13:32:16 +08:00
|
|
|
int ok;
|
2019-07-16 07:46:14 +08:00
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
2019-09-05 09:23:57 +08:00
|
|
|
unsigned int pd = pad;
|
2019-07-09 13:32:16 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (pad)
|
|
|
|
ctx->flags &= ~EVP_CIPH_NO_PADDING;
|
|
|
|
else
|
|
|
|
ctx->flags |= EVP_CIPH_NO_PADDING;
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2020-11-18 17:49:19 +08:00
|
|
|
if (ctx->cipher != NULL && ctx->cipher->prov == NULL)
|
|
|
|
return 1;
|
2019-09-05 09:23:57 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_PADDING, &pd);
|
2019-07-16 07:46:14 +08:00
|
|
|
ok = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
|
2019-07-09 13:32:16 +08:00
|
|
|
return ok != 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-02-14 10:11:52 +08:00
|
|
|
|
2000-05-31 02:26:22 +08:00
|
|
|
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
|
|
|
|
{
|
2019-07-31 18:34:26 +08:00
|
|
|
int ret = EVP_CTRL_RET_UNSUPPORTED;
|
2019-07-16 07:46:14 +08:00
|
|
|
int set_params = 1;
|
2019-09-05 09:23:57 +08:00
|
|
|
size_t sz = arg;
|
2019-10-03 14:05:49 +08:00
|
|
|
unsigned int i;
|
2020-01-06 11:02:16 +08:00
|
|
|
OSSL_PARAM params[4] = {
|
|
|
|
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
|
|
|
|
};
|
2017-11-05 21:37:15 +08:00
|
|
|
|
2019-07-16 07:46:14 +08:00
|
|
|
if (ctx == NULL || ctx->cipher == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-09 13:32:16 +08:00
|
|
|
if (ctx->cipher->prov == NULL)
|
|
|
|
goto legacy;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case EVP_CTRL_SET_KEY_LENGTH:
|
2019-09-05 09:23:57 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz);
|
2019-07-09 13:32:16 +08:00
|
|
|
break;
|
|
|
|
case EVP_CTRL_RAND_KEY: /* Used by DES */
|
2019-08-26 15:05:08 +08:00
|
|
|
set_params = 0;
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY,
|
2019-09-05 09:23:57 +08:00
|
|
|
ptr, sz);
|
2019-08-26 15:05:08 +08:00
|
|
|
break;
|
|
|
|
|
2019-10-15 22:45:12 +08:00
|
|
|
case EVP_CTRL_INIT:
|
|
|
|
/*
|
|
|
|
* TODO(3.0) EVP_CTRL_INIT is purely legacy, no provider counterpart
|
|
|
|
* As a matter of fact, this should be dead code, but some caller
|
|
|
|
* might still do a direct control call with this command, so...
|
|
|
|
* Legacy methods return 1 except for exceptional circumstances, so
|
|
|
|
* we do the same here to not be disruptive.
|
|
|
|
*/
|
|
|
|
return 1;
|
2019-07-09 13:32:16 +08:00
|
|
|
case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: /* Used by DASYNC */
|
2019-07-16 07:46:14 +08:00
|
|
|
default:
|
2019-10-13 19:00:46 +08:00
|
|
|
goto end;
|
2019-07-16 07:46:14 +08:00
|
|
|
case EVP_CTRL_AEAD_SET_IVLEN:
|
|
|
|
if (arg < 0)
|
|
|
|
return 0;
|
2019-09-05 09:23:57 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz);
|
2019-07-09 13:32:16 +08:00
|
|
|
break;
|
2019-10-14 18:59:31 +08:00
|
|
|
case EVP_CTRL_AEAD_SET_IV_FIXED:
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, ptr, sz);
|
|
|
|
break;
|
|
|
|
case EVP_CTRL_GCM_IV_GEN:
|
|
|
|
set_params = 0;
|
|
|
|
if (arg < 0)
|
|
|
|
sz = 0; /* special case that uses the iv length */
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, ptr, sz);
|
|
|
|
break;
|
|
|
|
case EVP_CTRL_GCM_SET_IV_INV:
|
|
|
|
if (arg < 0)
|
|
|
|
return 0;
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, ptr, sz);
|
2019-07-16 07:46:14 +08:00
|
|
|
break;
|
2019-10-03 14:05:49 +08:00
|
|
|
case EVP_CTRL_GET_RC5_ROUNDS:
|
|
|
|
set_params = 0; /* Fall thru */
|
|
|
|
case EVP_CTRL_SET_RC5_ROUNDS:
|
|
|
|
if (arg < 0)
|
|
|
|
return 0;
|
|
|
|
i = (unsigned int)arg;
|
|
|
|
params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_ROUNDS, &i);
|
|
|
|
break;
|
2019-11-08 10:14:44 +08:00
|
|
|
case EVP_CTRL_SET_SPEED:
|
|
|
|
if (arg < 0)
|
|
|
|
return 0;
|
|
|
|
i = (unsigned int)arg;
|
|
|
|
params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_SPEED, &i);
|
|
|
|
break;
|
2019-07-16 07:46:14 +08:00
|
|
|
case EVP_CTRL_AEAD_GET_TAG:
|
2019-09-05 09:23:57 +08:00
|
|
|
set_params = 0; /* Fall thru */
|
|
|
|
case EVP_CTRL_AEAD_SET_TAG:
|
2019-07-16 07:46:14 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
|
2019-09-05 09:23:57 +08:00
|
|
|
ptr, sz);
|
2019-07-16 07:46:14 +08:00
|
|
|
break;
|
|
|
|
case EVP_CTRL_AEAD_TLS1_AAD:
|
2020-01-06 11:02:16 +08:00
|
|
|
/* This one does a set and a get - since it returns a size */
|
2019-07-16 07:46:14 +08:00
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD,
|
2019-09-05 09:23:57 +08:00
|
|
|
ptr, sz);
|
2019-07-16 07:46:14 +08:00
|
|
|
ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
2019-10-13 19:00:46 +08:00
|
|
|
goto end;
|
2019-07-16 07:46:14 +08:00
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, &sz);
|
|
|
|
ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
2019-10-13 19:00:46 +08:00
|
|
|
goto end;
|
2019-07-16 07:46:14 +08:00
|
|
|
return sz;
|
2019-10-08 14:42:28 +08:00
|
|
|
#ifndef OPENSSL_NO_RC2
|
|
|
|
case EVP_CTRL_GET_RC2_KEY_BITS:
|
|
|
|
set_params = 0; /* Fall thru */
|
|
|
|
case EVP_CTRL_SET_RC2_KEY_BITS:
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, &sz);
|
|
|
|
break;
|
|
|
|
#endif /* OPENSSL_NO_RC2 */
|
2020-01-06 11:02:16 +08:00
|
|
|
#if !defined(OPENSSL_NO_MULTIBLOCK)
|
|
|
|
case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE:
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, &sz);
|
|
|
|
ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, &sz);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return 0;
|
|
|
|
return sz;
|
|
|
|
case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: {
|
|
|
|
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *p =
|
|
|
|
(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *)ptr;
|
|
|
|
|
|
|
|
if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, (void*)p->inp, p->len);
|
|
|
|
params[1] = OSSL_PARAM_construct_uint(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
|
|
|
|
ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
/* Retrieve the return values changed by the set */
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, &sz);
|
|
|
|
params[1] = OSSL_PARAM_construct_uint(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
|
|
|
|
params[2] = OSSL_PARAM_construct_end();
|
|
|
|
ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return 0;
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: {
|
|
|
|
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *p =
|
|
|
|
(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *)ptr;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, p->out, p->len);
|
|
|
|
|
|
|
|
params[1] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, (void*)p->inp,
|
|
|
|
p->len);
|
|
|
|
params[2] = OSSL_PARAM_construct_uint(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, &p->interleave);
|
|
|
|
ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(
|
|
|
|
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, &sz);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
if (ret <= 0)
|
|
|
|
return 0;
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
#endif /* OPENSSL_NO_MULTIBLOCK */
|
|
|
|
case EVP_CTRL_AEAD_SET_MAC_KEY:
|
|
|
|
if (arg < 0)
|
|
|
|
return -1;
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
OSSL_CIPHER_PARAM_AEAD_MAC_KEY, ptr, sz);
|
|
|
|
break;
|
2019-07-09 13:32:16 +08:00
|
|
|
}
|
2019-07-16 07:46:14 +08:00
|
|
|
|
|
|
|
if (set_params)
|
|
|
|
ret = evp_do_ciph_ctx_setparams(ctx->cipher, ctx->provctx, params);
|
|
|
|
else
|
|
|
|
ret = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);
|
2019-10-13 19:00:46 +08:00
|
|
|
goto end;
|
2019-07-09 13:32:16 +08:00
|
|
|
|
2019-07-16 07:46:14 +08:00
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
if (ctx->cipher->ctrl == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
|
2019-10-06 16:45:17 +08:00
|
|
|
|
2019-10-13 19:00:46 +08:00
|
|
|
end:
|
2019-07-31 18:34:26 +08:00
|
|
|
if (ret == EVP_CTRL_RET_UNSUPPORTED) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return ret;
|
2000-05-31 02:26:22 +08:00
|
|
|
}
|
2004-03-29 01:38:00 +08:00
|
|
|
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[])
|
|
|
|
{
|
|
|
|
if (cipher != NULL && cipher->get_params != NULL)
|
|
|
|
return cipher->get_params(params);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[])
|
|
|
|
{
|
2019-08-16 15:04:29 +08:00
|
|
|
if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL)
|
|
|
|
return ctx->cipher->set_ctx_params(ctx->provctx, params);
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[])
|
|
|
|
{
|
2019-08-16 15:04:29 +08:00
|
|
|
if (ctx->cipher != NULL && ctx->cipher->get_ctx_params != NULL)
|
|
|
|
return ctx->cipher->get_ctx_params(ctx->provctx, params);
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const OSSL_PARAM *EVP_CIPHER_gettable_params(const EVP_CIPHER *cipher)
|
|
|
|
{
|
|
|
|
if (cipher != NULL && cipher->gettable_params != NULL)
|
2020-08-05 11:23:16 +08:00
|
|
|
return cipher->gettable_params(
|
|
|
|
ossl_provider_ctx(EVP_CIPHER_provider(cipher)));
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-27 14:35:45 +08:00
|
|
|
const OSSL_PARAM *EVP_CIPHER_settable_ctx_params(const EVP_CIPHER *cipher)
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
{
|
|
|
|
if (cipher != NULL && cipher->settable_ctx_params != NULL)
|
2020-08-05 11:23:16 +08:00
|
|
|
return cipher->settable_ctx_params(
|
|
|
|
ossl_provider_ctx(EVP_CIPHER_provider(cipher)));
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-27 14:35:45 +08:00
|
|
|
const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher)
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
{
|
|
|
|
if (cipher != NULL && cipher->gettable_ctx_params != NULL)
|
2020-08-05 11:23:16 +08:00
|
|
|
return cipher->gettable_ctx_params(
|
|
|
|
ossl_provider_ctx(EVP_CIPHER_provider(cipher)));
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-07-26 15:26:43 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-10-15 17:55:50 +08:00
|
|
|
static OSSL_LIB_CTX *EVP_CIPHER_CTX_get_libctx(EVP_CIPHER_CTX *ctx)
|
2020-07-26 15:26:43 +08:00
|
|
|
{
|
|
|
|
const EVP_CIPHER *cipher = ctx->cipher;
|
|
|
|
const OSSL_PROVIDER *prov;
|
|
|
|
|
|
|
|
if (cipher == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
prov = EVP_CIPHER_provider(cipher);
|
2020-10-15 17:55:50 +08:00
|
|
|
return ossl_provider_libctx(prov);
|
2020-07-26 15:26:43 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-03-29 01:38:00 +08:00
|
|
|
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
|
|
|
|
return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
|
2019-08-26 15:05:08 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifdef FIPS_MODULE
|
2019-08-26 15:05:08 +08:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
int kl;
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx = EVP_CIPHER_CTX_get_libctx(ctx);
|
2019-08-26 15:05:08 +08:00
|
|
|
|
|
|
|
kl = EVP_CIPHER_CTX_key_length(ctx);
|
2020-07-26 15:26:43 +08:00
|
|
|
if (kl <= 0 || RAND_priv_bytes_ex(libctx, key, kl) <= 0)
|
2019-08-26 15:05:08 +08:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#endif /* FIPS_MODULE */
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2004-03-29 01:38:00 +08:00
|
|
|
|
2010-02-07 21:39:39 +08:00
|
|
|
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if ((in == NULL) || (in->cipher == NULL)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INPUT_NOT_INITIALIZED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (in->cipher->prov == NULL)
|
|
|
|
goto legacy;
|
|
|
|
|
|
|
|
if (in->cipher->dupctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EVP_CIPHER_CTX_reset(out);
|
|
|
|
|
|
|
|
*out = *in;
|
|
|
|
out->provctx = NULL;
|
|
|
|
|
2019-06-25 00:38:01 +08:00
|
|
|
if (in->fetched_cipher != NULL && !EVP_CIPHER_up_ref(in->fetched_cipher)) {
|
2019-04-03 22:38:07 +08:00
|
|
|
out->fetched_cipher = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
out->provctx = in->cipher->dupctx(in->provctx);
|
|
|
|
if (out->provctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
2019-04-03 22:38:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|
2015-01-22 11:40:55 +08:00
|
|
|
/* Make sure it's safe to copy a cipher context using an ENGINE */
|
|
|
|
if (in->engine && !ENGINE_init(in->engine)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2010-02-07 21:39:39 +08:00
|
|
|
#endif
|
|
|
|
|
2015-12-14 04:36:33 +08:00
|
|
|
EVP_CIPHER_CTX_reset(out);
|
2015-05-02 11:10:31 +08:00
|
|
|
memcpy(out, in, sizeof(*out));
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (in->cipher_data && in->cipher->ctx_size) {
|
|
|
|
out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
|
2015-10-30 19:12:26 +08:00
|
|
|
if (out->cipher_data == NULL) {
|
2017-02-06 20:37:42 +08:00
|
|
|
out->cipher = NULL;
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY)
|
2017-02-06 20:37:42 +08:00
|
|
|
if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) {
|
|
|
|
out->cipher = NULL;
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
2017-02-06 20:37:42 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER *evp_cipher_new(void)
|
|
|
|
{
|
|
|
|
EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
|
|
|
|
|
|
|
|
if (cipher != NULL) {
|
|
|
|
cipher->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
if (cipher->lock == NULL) {
|
|
|
|
OPENSSL_free(cipher);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cipher->refcnt = 1;
|
|
|
|
}
|
|
|
|
return cipher;
|
|
|
|
}
|
|
|
|
|
2019-09-22 02:57:51 +08:00
|
|
|
/*
|
|
|
|
* FIPS module note: since internal fetches will be entirely
|
|
|
|
* provider based, we know that none of its code depends on legacy
|
|
|
|
* NIDs or any functionality that use them.
|
|
|
|
*/
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2019-09-22 02:57:51 +08:00
|
|
|
/* TODO(3.x) get rid of the need for legacy NIDs */
|
|
|
|
static void set_legacy_nid(const char *name, void *vlegacy_nid)
|
|
|
|
{
|
|
|
|
int nid;
|
|
|
|
int *legacy_nid = vlegacy_nid;
|
2019-05-23 09:27:37 +08:00
|
|
|
/*
|
|
|
|
* We use lowest level function to get the associated method, because
|
|
|
|
* higher level functions such as EVP_get_cipherbyname() have changed
|
|
|
|
* to look at providers too.
|
|
|
|
*/
|
|
|
|
const void *legacy_method = OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
|
2019-09-22 02:57:51 +08:00
|
|
|
|
|
|
|
if (*legacy_nid == -1) /* We found a clash already */
|
|
|
|
return;
|
2019-05-23 09:27:37 +08:00
|
|
|
if (legacy_method == NULL)
|
2019-09-22 02:57:51 +08:00
|
|
|
return;
|
2019-05-23 09:27:37 +08:00
|
|
|
nid = EVP_CIPHER_nid(legacy_method);
|
2019-09-22 02:57:51 +08:00
|
|
|
if (*legacy_nid != NID_undef && *legacy_nid != nid) {
|
|
|
|
*legacy_nid = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*legacy_nid = nid;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
static void *evp_cipher_from_dispatch(const int name_id,
|
2019-07-11 04:22:16 +08:00
|
|
|
const OSSL_DISPATCH *fns,
|
2019-10-31 19:10:01 +08:00
|
|
|
OSSL_PROVIDER *prov)
|
2019-04-03 22:38:07 +08:00
|
|
|
{
|
|
|
|
EVP_CIPHER *cipher = NULL;
|
|
|
|
int fnciphcnt = 0, fnctxcnt = 0;
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
if ((cipher = evp_cipher_new()) == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
2019-04-03 22:38:07 +08:00
|
|
|
return NULL;
|
2019-07-11 04:22:16 +08:00
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2019-09-22 02:57:51 +08:00
|
|
|
/* TODO(3.x) get rid of the need for legacy NIDs */
|
|
|
|
cipher->nid = NID_undef;
|
2021-02-20 01:03:43 +08:00
|
|
|
if (!evp_names_do_all(prov, name_id, set_legacy_nid, &cipher->nid)
|
|
|
|
|| cipher->nid == -1) {
|
2019-09-22 02:57:51 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
EVP_CIPHER_free(cipher);
|
|
|
|
return NULL;
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
}
|
2019-08-15 01:09:28 +08:00
|
|
|
#endif
|
|
|
|
|
2019-09-22 02:57:51 +08:00
|
|
|
cipher->name_id = name_id;
|
|
|
|
|
2019-04-03 22:38:07 +08:00
|
|
|
for (; fns->function_id != 0; fns++) {
|
|
|
|
switch (fns->function_id) {
|
|
|
|
case OSSL_FUNC_CIPHER_NEWCTX:
|
|
|
|
if (cipher->newctx != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->newctx = OSSL_FUNC_cipher_newctx(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnctxcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_ENCRYPT_INIT:
|
|
|
|
if (cipher->einit != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->einit = OSSL_FUNC_cipher_encrypt_init(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_DECRYPT_INIT:
|
|
|
|
if (cipher->dinit != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->dinit = OSSL_FUNC_cipher_decrypt_init(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_UPDATE:
|
|
|
|
if (cipher->cupdate != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->cupdate = OSSL_FUNC_cipher_update(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_FINAL:
|
|
|
|
if (cipher->cfinal != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->cfinal = OSSL_FUNC_cipher_final(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
2019-04-04 01:01:21 +08:00
|
|
|
case OSSL_FUNC_CIPHER_CIPHER:
|
|
|
|
if (cipher->ccipher != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->ccipher = OSSL_FUNC_cipher_cipher(fns);
|
2019-04-04 01:01:21 +08:00
|
|
|
break;
|
2019-04-03 22:38:07 +08:00
|
|
|
case OSSL_FUNC_CIPHER_FREECTX:
|
|
|
|
if (cipher->freectx != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->freectx = OSSL_FUNC_cipher_freectx(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
fnctxcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_DUPCTX:
|
|
|
|
if (cipher->dupctx != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->dupctx = OSSL_FUNC_cipher_dupctx(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_GET_PARAMS:
|
|
|
|
if (cipher->get_params != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->get_params = OSSL_FUNC_cipher_get_params(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
break;
|
2019-08-16 15:04:29 +08:00
|
|
|
case OSSL_FUNC_CIPHER_GET_CTX_PARAMS:
|
|
|
|
if (cipher->get_ctx_params != NULL)
|
2019-04-04 01:01:21 +08:00
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->get_ctx_params = OSSL_FUNC_cipher_get_ctx_params(fns);
|
2019-04-04 01:01:21 +08:00
|
|
|
break;
|
2019-08-16 15:04:29 +08:00
|
|
|
case OSSL_FUNC_CIPHER_SET_CTX_PARAMS:
|
|
|
|
if (cipher->set_ctx_params != NULL)
|
2019-04-03 22:38:07 +08:00
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->set_ctx_params = OSSL_FUNC_cipher_set_ctx_params(fns);
|
2019-04-03 22:38:07 +08:00
|
|
|
break;
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
case OSSL_FUNC_CIPHER_GETTABLE_PARAMS:
|
|
|
|
if (cipher->gettable_params != NULL)
|
|
|
|
break;
|
2020-06-21 07:19:16 +08:00
|
|
|
cipher->gettable_params = OSSL_FUNC_cipher_gettable_params(fns);
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS:
|
|
|
|
if (cipher->gettable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
cipher->gettable_ctx_params =
|
2020-06-21 07:19:16 +08:00
|
|
|
OSSL_FUNC_cipher_gettable_ctx_params(fns);
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS:
|
|
|
|
if (cipher->settable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
cipher->settable_ctx_params =
|
2020-06-21 07:19:16 +08:00
|
|
|
OSSL_FUNC_cipher_settable_ctx_params(fns);
|
Add missing EVP param utility functions
These functions were missing for a completes API:
EVP_MD_get_params(), EVP_CIPHER_get_params(), EVP_CIPHER_CTX_set_params(),
and EVP_CIPHER_CTX_get_params
Additionally, we also add all the corresponding parameter descriptor
returning functions, along the correspoding provider dispatches:
EVP_MD_gettable_params(), EVP_MD_CTX_settable_params(),
EVP_MD_CTX_gettable_params(), EVP_CIPHER_gettable_params(),
EVP_CIPHER_CTX_settable_params(), and EVP_CIPHER_CTX_gettable_params()
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9576)
2019-08-12 20:56:18 +08:00
|
|
|
break;
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
}
|
2019-04-04 01:01:21 +08:00
|
|
|
if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
|
|
|
|
|| (fnciphcnt == 0 && cipher->ccipher == NULL)
|
2019-07-09 13:32:16 +08:00
|
|
|
|| fnctxcnt != 2) {
|
2019-04-03 22:38:07 +08:00
|
|
|
/*
|
|
|
|
* In order to be a consistent set of functions we must have at least
|
|
|
|
* a complete set of "encrypt" functions, or a complete set of "decrypt"
|
2019-07-25 18:55:00 +08:00
|
|
|
* functions, or a single "cipher" function. In all cases we need both
|
|
|
|
* the "newctx" and "freectx" functions.
|
2019-04-03 22:38:07 +08:00
|
|
|
*/
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER_free(cipher);
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
|
2019-04-03 22:38:07 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cipher->prov = prov;
|
|
|
|
if (prov != NULL)
|
2019-07-02 20:57:36 +08:00
|
|
|
ossl_provider_up_ref(prov);
|
2019-04-03 22:38:07 +08:00
|
|
|
|
2020-12-22 19:54:16 +08:00
|
|
|
if (!evp_cipher_cache_constants(cipher)) {
|
|
|
|
EVP_CIPHER_free(cipher);
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED);
|
|
|
|
cipher = NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-03 22:38:07 +08:00
|
|
|
return cipher;
|
|
|
|
}
|
|
|
|
|
2019-06-25 00:38:01 +08:00
|
|
|
static int evp_cipher_up_ref(void *cipher)
|
2019-04-03 22:38:07 +08:00
|
|
|
{
|
2019-06-25 00:38:01 +08:00
|
|
|
return EVP_CIPHER_up_ref(cipher);
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void evp_cipher_free(void *cipher)
|
|
|
|
{
|
2019-09-04 00:11:49 +08:00
|
|
|
EVP_CIPHER_free(cipher);
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
|
2019-04-03 22:38:07 +08:00
|
|
|
const char *properties)
|
|
|
|
{
|
2019-05-08 20:00:31 +08:00
|
|
|
EVP_CIPHER *cipher =
|
|
|
|
evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
|
2019-10-31 19:10:01 +08:00
|
|
|
evp_cipher_from_dispatch, evp_cipher_up_ref,
|
2019-05-08 20:00:31 +08:00
|
|
|
evp_cipher_free);
|
|
|
|
|
|
|
|
return cipher;
|
2019-04-03 22:38:07 +08:00
|
|
|
}
|
2019-07-13 13:02:54 +08:00
|
|
|
|
2019-09-04 00:11:49 +08:00
|
|
|
int EVP_CIPHER_up_ref(EVP_CIPHER *cipher)
|
|
|
|
{
|
|
|
|
int ref = 0;
|
|
|
|
|
|
|
|
CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EVP_CIPHER_free(EVP_CIPHER *cipher)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cipher == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
ossl_provider_free(cipher->prov);
|
|
|
|
CRYPTO_THREAD_lock_free(cipher->lock);
|
|
|
|
OPENSSL_free(cipher);
|
|
|
|
}
|
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
|
EVP: add missing common functionality
This adds the missing functions that should be common for all
fetchable EVP sub-APIs:
EVP_KEYMGMT_is_a(), EVP_KEYMGMT_do_all_provided(), EVP_KEYEXCH_is_a(),
EVP_KEYEXCH_do_all_provided(), EVP_KDF_is_a(), EVP_MD_is_a(),
EVP_SIGNATURE_do_all_provided(), EVP_SIGNATURE_is_a().
This also renames EVP_MD_do_all_ex(), EVP_CIPHER_do_all_ex(),
EVP_KDF_do_all_ex(), EVP_MAC_do_all_ex() to change '_ex'
to '_provided'.
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/9979)
2019-09-23 16:33:26 +08:00
|
|
|
void (*fn)(EVP_CIPHER *mac, void *arg),
|
|
|
|
void *arg)
|
2019-07-13 13:02:54 +08:00
|
|
|
{
|
|
|
|
evp_generic_do_all(libctx, OSSL_OP_CIPHER,
|
|
|
|
(void (*)(void *, void *))fn, arg,
|
2019-10-31 19:10:01 +08:00
|
|
|
evp_cipher_from_dispatch, evp_cipher_free);
|
2019-07-13 13:02:54 +08:00
|
|
|
}
|