From c2bf720842d4a38bf00d3fcfdca6864ec82dc6c6 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 7 Feb 2010 13:39:39 +0000 Subject: [PATCH] Add missing function EVP_CIPHER_CTX_copy(). Current code uses memcpy() to copy an EVP_CIPHER_CTX structure which may have problems with external ENGINEs who need to duplicate internal handles etc. --- CHANGES | 7 ++++++- crypto/evp/bio_enc.c | 6 ++++-- crypto/evp/evp.h | 7 ++++++- crypto/evp/evp_enc.c | 35 +++++++++++++++++++++++++++++++++++ crypto/evp/evp_err.c | 1 + 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index d4d47db7fb..bad6a9f4a4 100644 --- a/CHANGES +++ b/CHANGES @@ -5,7 +5,7 @@ Changes between 1.0.0 and 1.1.0 [xx XXX xxxx] *) Experiemental regnegotiation in s_server -www mode. If the client - browsers /reneg connection is renegotiated. If /renegcert it is + browses /reneg connection is renegotiated. If /renegcert it is renegotiated requesting a certificate. [Steve Henson] @@ -49,6 +49,11 @@ Changes between 0.9.8m (?) and 1.0.0 [xx XXX xxxx] + *) Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher + context. The operation can be customised via the ctrl mechanism in + case ENGINEs want to include additional functionality. + [Steve Henson] + *) Tolerate yet another broken PKCS#8 key format: private key value negative. [Steve Henson] diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c index afb4d319ce..3cf75f087e 100644 --- a/crypto/evp/bio_enc.c +++ b/crypto/evp/bio_enc.c @@ -370,8 +370,10 @@ again: case BIO_CTRL_DUP: dbio=(BIO *)ptr; dctx=(BIO_ENC_CTX *)dbio->ptr; - memcpy(&(dctx->cipher),&(ctx->cipher),sizeof(ctx->cipher)); - dbio->init=1; + EVP_CIPHER_CTX_init(&dctx->cipher); + ret = EVP_CIPHER_CTX_copy(&dctx->cipher,&ctx->cipher); + if (ret) + dbio->init=1; break; default: ret=BIO_ctrl(b->next_bio,cmd,num,ptr); diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 9064164941..78578da325 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -340,6 +340,8 @@ struct evp_cipher_st #define EVP_CIPH_NO_PADDING 0x100 /* cipher handles random key generation */ #define EVP_CIPH_RAND_KEY 0x200 +/* cipher has its own additional copying logic */ +#define EVP_CIPH_CUSTOM_COPY 0x200 /* ctrl() values */ @@ -351,6 +353,7 @@ struct evp_cipher_st #define EVP_CTRL_SET_RC5_ROUNDS 0x5 #define EVP_CTRL_RAND_KEY 0x6 #define EVP_CTRL_PBE_PRF_NID 0x7 +#define EVP_CTRL_COPY 0x8 typedef struct evp_cipher_info_st { @@ -449,6 +452,7 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); #define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) @@ -1181,7 +1185,7 @@ void ERR_load_EVP_strings(void); /* Error codes for the EVP functions. */ /* Function codes. */ -#define EVP_F_AESNI_INIT_KEY 163 +#define EVP_F_AESNI_INIT_KEY 165 #define EVP_F_AES_INIT_KEY 133 #define EVP_F_CAMELLIA_INIT_KEY 159 #define EVP_F_D2I_PKEY 100 @@ -1191,6 +1195,7 @@ void ERR_load_EVP_strings(void); #define EVP_F_ECDSA_PKEY2PKCS8 129 #define EVP_F_ECKEY_PKEY2PKCS8 132 #define EVP_F_EVP_CIPHERINIT_EX 123 +#define EVP_F_EVP_CIPHER_CTX_COPY 163 #define EVP_F_EVP_CIPHER_CTX_CTRL 124 #define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 #define EVP_F_EVP_DECRYPTFINAL_EX 101 diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 6e582c458d..fa786406ee 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -566,3 +566,38 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) return 1; } +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) + { + if ((in == NULL) || (in->cipher == NULL)) + { + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY,EVP_R_INPUT_NOT_INITIALIZED); + return 0; + } +#ifndef OPENSSL_NO_ENGINE + /* Make sure it's safe to copy a digest context using an ENGINE */ + if (in->engine && !ENGINE_init(in->engine)) + { + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY,ERR_R_ENGINE_LIB); + return 0; + } +#endif + + EVP_CIPHER_CTX_cleanup(out); + memcpy(out,in,sizeof *out); + + if (in->cipher_data && in->cipher->ctx_size) + { + out->cipher_data=OPENSSL_malloc(in->cipher->ctx_size); + if (!out->cipher_data) + { + 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) + return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out); + return 1; + } + diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index f200378678..794b86c703 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -80,6 +80,7 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_FUNC(EVP_F_ECDSA_PKEY2PKCS8), "ECDSA_PKEY2PKCS8"}, {ERR_FUNC(EVP_F_ECKEY_PKEY2PKCS8), "ECKEY_PKEY2PKCS8"}, {ERR_FUNC(EVP_F_EVP_CIPHERINIT_EX), "EVP_CipherInit_ex"}, +{ERR_FUNC(EVP_F_EVP_CIPHER_CTX_COPY), "EVP_CIPHER_CTX_copy"}, {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_CTRL), "EVP_CIPHER_CTX_ctrl"}, {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH), "EVP_CIPHER_CTX_set_key_length"}, {ERR_FUNC(EVP_F_EVP_DECRYPTFINAL_EX), "EVP_DecryptFinal_ex"}, -- GitLab