2016-05-18 02:24:46 +08:00
|
|
|
/*
|
2019-07-31 19:55:16 +08:00
|
|
|
* Copyright 1995-2019 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
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.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>
|
2018-03-06 06:45:44 +08:00
|
|
|
#include <openssl/rand_drbg.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);
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
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)
|
|
|
|
{
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
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
|
|
|
const EVP_CIPHER *tmpcipher;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO(3.0): Legacy work around code below. Remove this */
|
|
|
|
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
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
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
|
|
|
|| 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpcipher = (cipher == NULL) ? ctx->cipher : cipher;
|
|
|
|
|
|
|
|
if (tmpcipher->prov == NULL) {
|
|
|
|
switch(tmpcipher->nid) {
|
2019-04-03 22:34:08 +08:00
|
|
|
case NID_aes_256_ecb:
|
2019-04-03 23:53:22 +08:00
|
|
|
case NID_aes_192_ecb:
|
|
|
|
case NID_aes_128_ecb:
|
2019-04-04 01:01:21 +08:00
|
|
|
case NID_aes_256_cbc:
|
|
|
|
case NID_aes_192_cbc:
|
|
|
|
case NID_aes_128_cbc:
|
2019-04-08 23:55:34 +08:00
|
|
|
case NID_aes_256_ofb128:
|
|
|
|
case NID_aes_192_ofb128:
|
|
|
|
case NID_aes_128_ofb128:
|
2019-04-09 00:13:01 +08:00
|
|
|
case NID_aes_256_cfb128:
|
|
|
|
case NID_aes_192_cfb128:
|
|
|
|
case NID_aes_128_cfb128:
|
|
|
|
case NID_aes_256_cfb1:
|
|
|
|
case NID_aes_192_cfb1:
|
|
|
|
case NID_aes_128_cfb1:
|
|
|
|
case NID_aes_256_cfb8:
|
|
|
|
case NID_aes_192_cfb8:
|
|
|
|
case NID_aes_128_cfb8:
|
2019-04-09 00:19:59 +08:00
|
|
|
case NID_aes_256_ctr:
|
|
|
|
case NID_aes_192_ctr:
|
|
|
|
case NID_aes_128_ctr:
|
2019-09-14 07:27:49 +08:00
|
|
|
case NID_aes_128_xts:
|
|
|
|
case NID_aes_256_xts:
|
2019-09-19 18:10:25 +08:00
|
|
|
case NID_aes_256_ocb:
|
|
|
|
case NID_aes_192_ocb:
|
|
|
|
case NID_aes_128_ocb:
|
2019-07-31 19:55:16 +08:00
|
|
|
case NID_aes_256_gcm:
|
|
|
|
case NID_aes_192_gcm:
|
|
|
|
case NID_aes_128_gcm:
|
2019-07-10 09:42:03 +08:00
|
|
|
case NID_id_aes256_wrap:
|
|
|
|
case NID_id_aes256_wrap_pad:
|
|
|
|
case NID_id_aes192_wrap:
|
|
|
|
case NID_id_aes192_wrap_pad:
|
|
|
|
case NID_id_aes128_wrap:
|
|
|
|
case NID_id_aes128_wrap_pad:
|
2019-07-31 19:55:16 +08:00
|
|
|
case NID_aria_256_gcm:
|
|
|
|
case NID_aria_192_gcm:
|
|
|
|
case NID_aria_128_gcm:
|
2019-08-20 06:54:41 +08:00
|
|
|
case NID_aes_256_ccm:
|
|
|
|
case NID_aes_192_ccm:
|
|
|
|
case NID_aes_128_ccm:
|
|
|
|
case NID_aria_256_ccm:
|
|
|
|
case NID_aria_192_ccm:
|
|
|
|
case NID_aria_128_ccm:
|
2019-08-22 09:42:54 +08:00
|
|
|
case NID_aria_256_ecb:
|
|
|
|
case NID_aria_192_ecb:
|
|
|
|
case NID_aria_128_ecb:
|
|
|
|
case NID_aria_256_cbc:
|
|
|
|
case NID_aria_192_cbc:
|
|
|
|
case NID_aria_128_cbc:
|
|
|
|
case NID_aria_256_ofb128:
|
|
|
|
case NID_aria_192_ofb128:
|
|
|
|
case NID_aria_128_ofb128:
|
|
|
|
case NID_aria_256_cfb128:
|
|
|
|
case NID_aria_192_cfb128:
|
|
|
|
case NID_aria_128_cfb128:
|
|
|
|
case NID_aria_256_cfb1:
|
|
|
|
case NID_aria_192_cfb1:
|
|
|
|
case NID_aria_128_cfb1:
|
|
|
|
case NID_aria_256_cfb8:
|
|
|
|
case NID_aria_192_cfb8:
|
|
|
|
case NID_aria_128_cfb8:
|
|
|
|
case NID_aria_256_ctr:
|
|
|
|
case NID_aria_192_ctr:
|
|
|
|
case NID_aria_128_ctr:
|
|
|
|
case NID_camellia_256_ecb:
|
|
|
|
case NID_camellia_192_ecb:
|
|
|
|
case NID_camellia_128_ecb:
|
|
|
|
case NID_camellia_256_cbc:
|
|
|
|
case NID_camellia_192_cbc:
|
|
|
|
case NID_camellia_128_cbc:
|
|
|
|
case NID_camellia_256_ofb128:
|
|
|
|
case NID_camellia_192_ofb128:
|
|
|
|
case NID_camellia_128_ofb128:
|
|
|
|
case NID_camellia_256_cfb128:
|
|
|
|
case NID_camellia_192_cfb128:
|
|
|
|
case NID_camellia_128_cfb128:
|
|
|
|
case NID_camellia_256_cfb1:
|
|
|
|
case NID_camellia_192_cfb1:
|
|
|
|
case NID_camellia_128_cfb1:
|
|
|
|
case NID_camellia_256_cfb8:
|
|
|
|
case NID_camellia_192_cfb8:
|
|
|
|
case NID_camellia_128_cfb8:
|
|
|
|
case NID_camellia_256_ctr:
|
|
|
|
case NID_camellia_192_ctr:
|
|
|
|
case NID_camellia_128_ctr:
|
2019-08-26 15:05:08 +08:00
|
|
|
case NID_des_ede3_cbc:
|
|
|
|
case NID_des_ede3_ecb:
|
|
|
|
case NID_des_ede3_ofb64:
|
|
|
|
case NID_des_ede3_cfb64:
|
|
|
|
case NID_des_ede3_cfb8:
|
|
|
|
case NID_des_ede3_cfb1:
|
|
|
|
case NID_des_ede_cbc:
|
|
|
|
case NID_des_ede_ecb:
|
|
|
|
case NID_des_ede_ofb64:
|
|
|
|
case NID_des_ede_cfb64:
|
|
|
|
case NID_desx_cbc:
|
2019-09-23 12:35:16 +08:00
|
|
|
case NID_des_cbc:
|
|
|
|
case NID_des_ecb:
|
|
|
|
case NID_des_cfb1:
|
|
|
|
case NID_des_cfb8:
|
|
|
|
case NID_des_cfb64:
|
|
|
|
case NID_des_ofb64:
|
2019-08-26 15:05:08 +08:00
|
|
|
case NID_id_smime_alg_CMS3DESwrap:
|
2019-09-15 18:06:28 +08:00
|
|
|
case NID_bf_cbc:
|
|
|
|
case NID_bf_ecb:
|
|
|
|
case NID_bf_cfb64:
|
|
|
|
case NID_bf_ofb64:
|
2019-09-18 13:57:08 +08:00
|
|
|
case NID_idea_cbc:
|
|
|
|
case NID_idea_ecb:
|
|
|
|
case NID_idea_cfb64:
|
|
|
|
case NID_idea_ofb64:
|
2019-09-18 16:55:11 +08:00
|
|
|
case NID_cast5_cbc:
|
|
|
|
case NID_cast5_ecb:
|
|
|
|
case NID_cast5_cfb64:
|
|
|
|
case NID_cast5_ofb64:
|
2019-09-18 20:13:59 +08:00
|
|
|
case NID_seed_cbc:
|
|
|
|
case NID_seed_ecb:
|
|
|
|
case NID_seed_cfb128:
|
|
|
|
case NID_seed_ofb128:
|
2019-09-19 13:38:51 +08:00
|
|
|
case NID_sm4_cbc:
|
|
|
|
case NID_sm4_ecb:
|
|
|
|
case NID_sm4_ctr:
|
|
|
|
case NID_sm4_cfb128:
|
|
|
|
case NID_sm4_ofb128:
|
2019-09-25 08:46:39 +08:00
|
|
|
case NID_rc4:
|
|
|
|
case NID_rc4_40:
|
2019-10-03 14:05:49 +08:00
|
|
|
case NID_rc5_cbc:
|
|
|
|
case NID_rc5_ecb:
|
|
|
|
case NID_rc5_cfb64:
|
|
|
|
case NID_rc5_ofb64:
|
2019-10-08 14:42:28 +08:00
|
|
|
case NID_rc2_cbc:
|
|
|
|
case NID_rc2_40_cbc:
|
|
|
|
case NID_rc2_64_cbc:
|
|
|
|
case NID_rc2_cfb64:
|
|
|
|
case NID_rc2_ofb64:
|
2019-10-16 14:18:42 +08:00
|
|
|
case NID_chacha20:
|
|
|
|
case NID_chacha20_poly1305:
|
2019-10-03 14:05:49 +08:00
|
|
|
break;
|
2019-04-03 22:38:07 +08:00
|
|
|
default:
|
|
|
|
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) {
|
2019-05-13 13:41:06 +08:00
|
|
|
#ifdef FIPS_MODE
|
|
|
|
/* We only do explict fetches inside the FIPS module */
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
EVP_CIPHER *provciph =
|
|
|
|
EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
|
|
|
|
|
2019-04-03 22:38:07 +08:00
|
|
|
if (provciph == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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;
|
|
|
|
}
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
2019-04-03 22:38:07 +08:00
|
|
|
if (impl != NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!ENGINE_init(impl)) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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
|
|
|
*/
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, 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;
|
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;
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, 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)) {
|
2017-02-06 20:37:42 +08:00
|
|
|
ctx->cipher = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_WRAP_MODE_NOT_ALLOWED);
|
|
|
|
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)) {
|
2018-12-09 21:18:50 +08:00
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 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)) {
|
2018-12-09 21:18:50 +08:00
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 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;
|
|
|
|
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
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of decryption context when encrypting */
|
|
|
|
if (!ctx->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_INVALID_OPERATION);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:35:04 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_NO_CIPHER_SET);
|
|
|
|
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) {
|
2019-04-03 22:38:07 +08:00
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
|
|
|
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
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of decryption context when encrypting */
|
|
|
|
if (!ctx->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_INVALID_OPERATION);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-07 08:18:29 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
|
|
|
|
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) {
|
2019-04-03 22:38:07 +08:00
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX,
|
|
|
|
EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
|
|
|
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
|
|
|
|
2018-12-09 21:18:50 +08:00
|
|
|
/* Prevent accidental use of encryption context when decrypting */
|
|
|
|
if (ctx->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_INVALID_OPERATION);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-07 08:48:42 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_NO_CIPHER_SET);
|
|
|
|
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) {
|
2019-04-03 22:38:07 +08:00
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
|
|
|
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)) {
|
2016-07-25 21:02:26 +08:00
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, 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)) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTUPDATE, 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
|
|
|
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
|
|
|
|
|
|
|
/* Prevent accidental use of encryption context when decrypting */
|
|
|
|
if (ctx->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_INVALID_OPERATION);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:35:04 +08:00
|
|
|
if (ctx->cipher == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
|
|
|
|
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) {
|
2019-04-03 22:38:07 +08:00
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,
|
|
|
|
EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*outl = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (b > 1) {
|
|
|
|
if (ctx->buf_len || !ctx->final_used) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, 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) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, 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) {
|
|
|
|
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, 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-07-16 07:46:14 +08:00
|
|
|
int ok;
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
2019-09-05 09:23:57 +08:00
|
|
|
size_t len = keylen;
|
2019-07-16 07:46:14 +08:00
|
|
|
|
2019-09-05 09:23:57 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
|
2019-07-16 07:46:14 +08:00
|
|
|
ok = evp_do_ciph_ctx_setparams(c->cipher, c->provctx, params);
|
2019-07-09 13:32:16 +08:00
|
|
|
|
2019-07-31 18:34:26 +08:00
|
|
|
if (ok != EVP_CTRL_RET_UNSUPPORTED)
|
2019-07-09 13:32:16 +08:00
|
|
|
return ok;
|
|
|
|
|
|
|
|
/* TODO(3.0) legacy code follows */
|
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;
|
|
|
|
}
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, EVP_R_INVALID_KEY_LENGTH);
|
|
|
|
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
|
|
|
|
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;
|
2019-07-16 07:46:14 +08:00
|
|
|
OSSL_PARAM params[2] = { 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) {
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
|
|
|
|
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-07-09 13:32:16 +08:00
|
|
|
case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: /* Used by DASYNC */
|
|
|
|
case EVP_CTRL_INIT: /* TODO(3.0) Purely legacy, no provider counterpart */
|
2019-07-16 07:46:14 +08:00
|
|
|
default:
|
2019-07-31 18:34:26 +08:00
|
|
|
return EVP_CTRL_RET_UNSUPPORTED;
|
2019-07-16 07:46:14 +08:00
|
|
|
case EVP_CTRL_GET_IV:
|
|
|
|
set_params = 0;
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_IV,
|
2019-09-05 09:23:57 +08:00
|
|
|
ptr, sz);
|
2019-07-16 07:46:14 +08:00
|
|
|
break;
|
|
|
|
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-07-16 07:46:14 +08:00
|
|
|
case EVP_CTRL_GCM_SET_IV_FIXED:
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED,
|
2019-09-05 09:23:57 +08:00
|
|
|
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-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;
|
2019-10-16 14:18:42 +08:00
|
|
|
case EVP_CTRL_AEAD_SET_MAC_KEY:
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_MAC_KEY,
|
|
|
|
ptr, sz);
|
|
|
|
break;
|
2019-07-16 07:46:14 +08:00
|
|
|
case EVP_CTRL_AEAD_TLS1_AAD:
|
|
|
|
/* This one does a set and a get - since it returns a padding size */
|
|
|
|
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)
|
|
|
|
return ret;
|
|
|
|
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)
|
|
|
|
return 0;
|
|
|
|
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 */
|
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-06 16:45:17 +08:00
|
|
|
goto conclude;
|
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) {
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
|
2019-10-06 16:45:17 +08:00
|
|
|
|
|
|
|
conclude:
|
2019-07-31 18:34:26 +08:00
|
|
|
if (ret == EVP_CTRL_RET_UNSUPPORTED) {
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL,
|
|
|
|
EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
|
|
|
|
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)
|
|
|
|
return cipher->gettable_params();
|
|
|
|
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)
|
|
|
|
return cipher->settable_ctx_params();
|
|
|
|
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)
|
|
|
|
return cipher->gettable_ctx_params();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
#ifdef FIPS_MODE
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
int kl;
|
|
|
|
|
|
|
|
kl = EVP_CIPHER_CTX_key_length(ctx);
|
|
|
|
if (kl <= 0 || RAND_priv_bytes(key, kl) <= 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif /* FIPS_MODE */
|
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)) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED);
|
|
|
|
return 0;
|
|
|
|
}
|
2019-04-03 22:38:07 +08:00
|
|
|
|
|
|
|
if (in->cipher->prov == NULL)
|
|
|
|
goto legacy;
|
|
|
|
|
|
|
|
if (in->cipher->dupctx == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
|
|
|
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) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* TODO(3.0): Remove legacy code below */
|
|
|
|
legacy:
|
|
|
|
|
2019-05-13 13:41:06 +08:00
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
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)) {
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB);
|
|
|
|
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;
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_MALLOC_FAILURE);
|
|
|
|
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;
|
|
|
|
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
#ifndef FIPS_MODE
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
if (*legacy_nid == -1) /* We found a clash already */
|
|
|
|
return;
|
|
|
|
if ((nid = OBJ_sn2nid(name)) == NID_undef
|
|
|
|
&& (nid = OBJ_ln2nid(name)) == NID_undef)
|
|
|
|
return;
|
|
|
|
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-08-23 20:03:28 +08:00
|
|
|
OSSL_PROVIDER *prov,
|
|
|
|
void *unused)
|
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) {
|
2019-07-11 04:22:16 +08:00
|
|
|
EVPerr(0, 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
|
|
|
|
2019-08-15 01:09:28 +08:00
|
|
|
#ifndef FIPS_MODE
|
2019-09-22 02:57:51 +08:00
|
|
|
/* TODO(3.x) get rid of the need for legacy NIDs */
|
|
|
|
cipher->nid = NID_undef;
|
|
|
|
evp_doall_names(prov, name_id, set_legacy_nid, &cipher->nid);
|
|
|
|
if (cipher->nid == -1) {
|
|
|
|
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;
|
|
|
|
cipher->newctx = OSSL_get_OP_cipher_newctx(fns);
|
|
|
|
fnctxcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_ENCRYPT_INIT:
|
|
|
|
if (cipher->einit != NULL)
|
|
|
|
break;
|
|
|
|
cipher->einit = OSSL_get_OP_cipher_encrypt_init(fns);
|
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_DECRYPT_INIT:
|
|
|
|
if (cipher->dinit != NULL)
|
|
|
|
break;
|
|
|
|
cipher->dinit = OSSL_get_OP_cipher_decrypt_init(fns);
|
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_UPDATE:
|
|
|
|
if (cipher->cupdate != NULL)
|
|
|
|
break;
|
|
|
|
cipher->cupdate = OSSL_get_OP_cipher_update(fns);
|
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_FINAL:
|
|
|
|
if (cipher->cfinal != NULL)
|
|
|
|
break;
|
|
|
|
cipher->cfinal = OSSL_get_OP_cipher_final(fns);
|
|
|
|
fnciphcnt++;
|
|
|
|
break;
|
2019-04-04 01:01:21 +08:00
|
|
|
case OSSL_FUNC_CIPHER_CIPHER:
|
|
|
|
if (cipher->ccipher != NULL)
|
|
|
|
break;
|
|
|
|
cipher->ccipher = OSSL_get_OP_cipher_cipher(fns);
|
|
|
|
break;
|
2019-04-03 22:38:07 +08:00
|
|
|
case OSSL_FUNC_CIPHER_FREECTX:
|
|
|
|
if (cipher->freectx != NULL)
|
|
|
|
break;
|
|
|
|
cipher->freectx = OSSL_get_OP_cipher_freectx(fns);
|
|
|
|
fnctxcnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_DUPCTX:
|
|
|
|
if (cipher->dupctx != NULL)
|
|
|
|
break;
|
|
|
|
cipher->dupctx = OSSL_get_OP_cipher_dupctx(fns);
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_GET_PARAMS:
|
|
|
|
if (cipher->get_params != NULL)
|
|
|
|
break;
|
|
|
|
cipher->get_params = OSSL_get_OP_cipher_get_params(fns);
|
|
|
|
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;
|
2019-08-16 15:04:29 +08:00
|
|
|
cipher->get_ctx_params = OSSL_get_OP_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;
|
2019-08-16 15:04:29 +08:00
|
|
|
cipher->set_ctx_params = OSSL_get_OP_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;
|
|
|
|
cipher->gettable_params = OSSL_get_OP_cipher_gettable_params(fns);
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS:
|
|
|
|
if (cipher->gettable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
cipher->gettable_ctx_params =
|
|
|
|
OSSL_get_OP_cipher_gettable_ctx_params(fns);
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS:
|
|
|
|
if (cipher->settable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
cipher->settable_ctx_params =
|
|
|
|
OSSL_get_OP_cipher_settable_ctx_params(fns);
|
|
|
|
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);
|
2019-04-03 22:38:07 +08:00
|
|
|
EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);
|
|
|
|
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
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
|
|
|
const char *properties)
|
|
|
|
{
|
2019-05-08 20:00:31 +08:00
|
|
|
EVP_CIPHER *cipher =
|
|
|
|
evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
|
2019-08-23 20:03:28 +08:00
|
|
|
evp_cipher_from_dispatch, NULL, 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);
|
|
|
|
}
|
|
|
|
|
2019-07-13 13:02:54 +08:00
|
|
|
void EVP_CIPHER_do_all_ex(OPENSSL_CTX *libctx,
|
|
|
|
void (*fn)(EVP_CIPHER *mac, void *arg),
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
evp_generic_do_all(libctx, OSSL_OP_CIPHER,
|
|
|
|
(void (*)(void *, void *))fn, arg,
|
2019-08-23 20:03:28 +08:00
|
|
|
evp_cipher_from_dispatch, NULL, evp_cipher_free);
|
2019-07-13 13:02:54 +08:00
|
|
|
}
|