EC_KEY_METHOD copy support
authorDr. Stephen Henson <steve@openssl.org>
Fri, 23 Oct 2015 18:19:57 +0000 (19:19 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 9 Dec 2015 22:09:18 +0000 (22:09 +0000)
Reviewed-by: Richard Levitte <levitte@openssl.org>
crypto/ec/ec_key.c
crypto/ec/ec_kmeth.c
crypto/ec/ec_lcl.h

index e2681c9..1b941b4 100644 (file)
@@ -132,6 +132,15 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
         ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
         return NULL;
     }
+    if (src->meth != dest->meth) {
+        if (dest->meth->finish)
+            dest->meth->finish(dest);
+#ifndef OPENSSL_NO_ENGINE
+        if (dest->engine && ENGINE_finish(dest->engine) == 0)
+            return 0;
+        dest->engine = NULL;
+#endif
+    }
     /* copy the parameters */
     if (src->group) {
         const EC_METHOD *meth = EC_GROUP_method_of(src->group);
@@ -182,12 +191,24 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
     dest->version = src->version;
     dest->flags = src->flags;
 
+    if (src->meth != dest->meth) {
+#ifndef OPENSSL_NO_ENGINE
+        if (src->engine && ENGINE_init(src->engine) == 0)
+            return 0;
+        dest->engine = src->engine;
+#endif
+        dest->meth = src->meth;
+    }
+
+    if (src->meth->copy && src->meth->copy(dest, src) == 0)
+        return 0;
+
     return dest;
 }
 
 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
 {
-    EC_KEY *ret = EC_KEY_new();
+    EC_KEY *ret = EC_KEY_new_method(ec_key->engine);
     if (ret == NULL)
         return NULL;
     if (EC_KEY_copy(ret, ec_key) == NULL) {
index 77b4443..4581880 100644 (file)
@@ -63,7 +63,7 @@
 static const EC_KEY_METHOD openssl_ec_key_method = {
     "OpenSSL EC_KEY method",
     0,
-    0,0,
+    0,0,0,
     ossl_ec_key_gen,
     ossl_ecdh_compute_key
 };
index 3aaee31..2db8779 100644 (file)
@@ -562,6 +562,7 @@ struct ec_key_method_st {
     int32_t flags;
     int (*init)(EC_KEY *key);
     void (*finish)(EC_KEY *key);
+    int (*copy)(EC_KEY *dest, const EC_KEY *src);
     int (*keygen)(EC_KEY *key);
     int (*compute_key)(void *out, size_t outlen, const EC_POINT *pub_key,
                        EC_KEY *ecdh,