Add functions to create an EVP_PKEY from raw private/public key data
authorMatt Caswell <matt@openssl.org>
Mon, 5 Mar 2018 14:06:41 +0000 (14:06 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 15 Mar 2018 12:47:27 +0000 (12:47 +0000)
Not all algorithms will support this, since their keys are not a simple
block of data. But many can.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5520)

crypto/err/openssl.txt
crypto/evp/evp_err.c
crypto/evp/p_lib.c
crypto/include/internal/asn1_int.h
include/openssl/evp.h
include/openssl/evperr.h
util/libcrypto.num

index 3f6169e..f33e961 100644 (file)
@@ -703,6 +703,8 @@ EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash
 EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen
 EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
 EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
+EVP_F_EVP_PKEY_NEW_PRIVATE_KEY:191:EVP_PKEY_new_private_key
+EVP_F_EVP_PKEY_NEW_PUBLIC_KEY:192:EVP_PKEY_new_public_key
 EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen
 EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init
 EVP_F_EVP_PKEY_PARAM_CHECK:189:EVP_PKEY_param_check
index a43de74..d45f2b9 100644 (file)
@@ -93,6 +93,10 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN_INIT, 0),
      "EVP_PKEY_keygen_init"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW, 0), "EVP_PKEY_new"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_PRIVATE_KEY, 0),
+     "EVP_PKEY_new_private_key"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_PUBLIC_KEY, 0),
+     "EVP_PKEY_new_public_key"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN, 0), "EVP_PKEY_paramgen"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN_INIT, 0),
      "EVP_PKEY_paramgen_init"},
index 6177e04..7ec1dd7 100644 (file)
@@ -174,10 +174,12 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
  * is NULL just return 1 or 0 if the algorithm exists.
  */
 
-static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
+static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
+                         int len)
 {
     const EVP_PKEY_ASN1_METHOD *ameth;
-    ENGINE *e = NULL;
+    ENGINE **eptr = (e == NULL) ? &e :  NULL;
+
     if (pkey) {
         if (pkey->pkey.ptr)
             EVP_PKEY_free_it(pkey);
@@ -196,11 +198,11 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
 #endif
     }
     if (str)
-        ameth = EVP_PKEY_asn1_find_str(&e, str, len);
+        ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
     else
-        ameth = EVP_PKEY_asn1_find(&e, type);
+        ameth = EVP_PKEY_asn1_find(eptr, type);
 #ifndef OPENSSL_NO_ENGINE
-    if (pkey == NULL)
+    if (pkey == NULL && eptr != NULL)
         ENGINE_finish(e);
 #endif
     if (ameth == NULL) {
@@ -217,14 +219,73 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
     return 1;
 }
 
+EVP_PKEY *EVP_PKEY_new_private_key(int type, ENGINE *e, unsigned char *priv,
+                                   size_t len)
+{
+    EVP_PKEY *ret = EVP_PKEY_new();
+
+    if (ret == NULL
+            || !pkey_set_type(ret, e, type, NULL, -1)) {
+        /* EVPerr already called */
+        goto err;
+    }
+
+    if (ret->ameth->set_priv_key == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_NEW_PRIVATE_KEY,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        goto err;
+    }
+
+    if (!ret->ameth->set_priv_key(ret, priv, len)) {
+        /* We assume the method function calls EVPerr */
+        goto err;
+    }
+
+    return ret;
+
+ err:
+    EVP_PKEY_free(ret);
+    return NULL;
+}
+
+EVP_PKEY *EVP_PKEY_new_public_key(int type, ENGINE *e, unsigned char *pub,
+                                  size_t len)
+{
+    EVP_PKEY *ret = EVP_PKEY_new();
+
+    if (ret == NULL
+            || !pkey_set_type(ret, e, type, NULL, -1)) {
+        /* EVPerr already called */
+        goto err;
+    }
+
+    if (ret->ameth->set_pub_key == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_NEW_PUBLIC_KEY,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        goto err;
+    }
+
+    if (!ret->ameth->set_pub_key(ret, pub, len)) {
+        /* We assume the method function calls EVPerr */
+        goto err;
+    }
+
+    return ret;
+
+ err:
+    EVP_PKEY_free(ret);
+    return NULL;
+}
+
+
 int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
 {
-    return pkey_set_type(pkey, type, NULL, -1);
+    return pkey_set_type(pkey, NULL, type, NULL, -1);
 }
 
 int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
 {
-    return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
+    return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
 }
 #ifndef OPENSSL_NO_ENGINE
 int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
index 664d4d6..90673ab 100644 (file)
@@ -58,6 +58,9 @@ struct evp_pkey_asn1_method_st {
     int (*pkey_check) (const EVP_PKEY *pk);
     int (*pkey_public_check) (const EVP_PKEY *pk);
     int (*pkey_param_check) (const EVP_PKEY *pk);
+    /* Get/set raw private/public key data */
+    int (*set_priv_key) (EVP_PKEY *pk, const unsigned char *priv, size_t len);
+    int (*set_pub_key) (EVP_PKEY *pk, const unsigned char *pub, size_t len);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
index 9727e9d..0479763 100644 (file)
@@ -1337,6 +1337,10 @@ void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
 
 EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
                                const unsigned char *key, int keylen);
+EVP_PKEY *EVP_PKEY_new_private_key(int type, ENGINE *e, unsigned char *priv,
+                                   size_t len);
+EVP_PKEY *EVP_PKEY_new_public_key(int type, ENGINE *e, unsigned char *pub,
+                                  size_t len);
 
 void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
index 45e9fcf..83dcd05 100644 (file)
@@ -78,6 +78,8 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PKEY_KEYGEN                            146
 # define EVP_F_EVP_PKEY_KEYGEN_INIT                       147
 # define EVP_F_EVP_PKEY_NEW                               106
+# define EVP_F_EVP_PKEY_NEW_PRIVATE_KEY                   191
+# define EVP_F_EVP_PKEY_NEW_PUBLIC_KEY                    192
 # define EVP_F_EVP_PKEY_PARAMGEN                          148
 # define EVP_F_EVP_PKEY_PARAMGEN_INIT                     149
 # define EVP_F_EVP_PKEY_PARAM_CHECK                       189
index a96bd2f..401d9fd 100644 (file)
@@ -4522,3 +4522,5 @@ OSSL_STORE_LOADER_set_find              4463      1_1_1   EXIST::FUNCTION:
 OSSL_STORE_SEARCH_free                  4464   1_1_1   EXIST::FUNCTION:
 OSSL_STORE_SEARCH_get0_digest           4465   1_1_1   EXIST::FUNCTION:
 RAND_DRBG_set_reseed_defaults           4466   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_new_private_key                4467   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_new_public_key                 4468   1_1_1   EXIST::FUNCTION: