Add missing function EVP_CIPHER_CTX_copy(). Current code uses memcpy() to copy
authorDr. Stephen Henson <steve@openssl.org>
Sun, 7 Feb 2010 13:41:23 +0000 (13:41 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 7 Feb 2010 13:41:23 +0000 (13:41 +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 42c3b9e01abca69c3a0356b5cc454af0e95b204b..2f7f79e526debd7fdb6f6e6d980f08c4c7d6ae6c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,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]
 
index f6ac94c6e1bba4464a6f6c7239cd42bde6fb9dfc..b6efb5fbc4b1f3288e3e6b14f3cbbd238fc45e6d 100644 (file)
@@ -361,8 +361,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 35e7847342529d546518ab4a363511850c940f18..26acd646cad40dbe5ff22a7ba015a59dcf4d06e0 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))
@@ -1190,6 +1194,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 6e582c458de55b5fc7b230d3d3c546fc42cbbb43..fa786406ee533a54f27acf9e1b0b4dea0de99718 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 d4bdf513842fa29f0c68d81f51b8da862783d70e..d8bfec0959053b9796452fcad9877a0c25653c61 100644 (file)
@@ -79,6 +79,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"},