Add missing function EVP_CIPHER_CTX_copy(). Current code uses memcpy() to copy
authorDr. Stephen Henson <steve@openssl.org>
Sun, 7 Feb 2010 13:39:39 +0000 (13:39 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 7 Feb 2010 13:39:39 +0000 (13:39 +0000)
an EVP_CIPHER_CTX structure which may have problems with external ENGINEs
who need to duplicate internal handles etc.

CHANGES
crypto/evp/bio_enc.c
crypto/evp/evp.h
crypto/evp/evp_enc.c
crypto/evp/evp_err.c

diff --git a/CHANGES b/CHANGES
index d4d47db..bad6a9f 100644 (file)
--- 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]
 
 
  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]
 
index afb4d31..3cf75f0 100644 (file)
@@ -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);
index 9064164..78578da 100644 (file)
@@ -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
index 6e582c4..fa78640 100644 (file)
@@ -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;
+       }
+
index f200378..794b86c 100644 (file)
@@ -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"},