Add support getting raw private/public keys
authorMatt Caswell <matt@openssl.org>
Fri, 1 Jun 2018 11:22:28 +0000 (12:22 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 8 Jun 2018 09:04:09 +0000 (10:04 +0100)
Only applies to algorithms that support it. Both raw private and public
keys can be obtained for X25519, Ed25519, X448, Ed448. Raw private keys
only can be obtained for HMAC, Poly1305 and SipHash

Fixes #6259

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6394)

crypto/ec/ecx_meth.c
crypto/err/openssl.txt
crypto/evp/evp_err.c
crypto/evp/p_lib.c
crypto/hmac/hm_ameth.c
crypto/include/internal/asn1_int.h
crypto/poly1305/poly1305_ameth.c
crypto/siphash/siphash_ameth.c
include/openssl/evp.h
include/openssl/evperr.h
util/libcrypto.num

index d2aa6dd8709040d3ff99536d249f13364f7b5001..e75e07b05235f238d9bb8d38b2b0605e0ccbe658 100644 (file)
@@ -354,6 +354,47 @@ static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
                       KEY_OP_PUBLIC);
 }
 
+static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
+                            size_t *len)
+{
+    const ECX_KEY *key = pkey->pkey.ecx;
+
+    if (priv == NULL) {
+        *len = KEYLENID(pkey->ameth->pkey_id);
+        return 1;
+    }
+
+    if (key == NULL
+            || key->privkey == NULL
+            || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
+        return 0;
+
+    *len = KEYLENID(pkey->ameth->pkey_id);
+    memcpy(priv, key->privkey, *len);
+
+    return 1;
+}
+
+static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
+                           size_t *len)
+{
+    const ECX_KEY *key = pkey->pkey.ecx;
+
+    if (pub == NULL) {
+        *len = KEYLENID(pkey->ameth->pkey_id);
+        return 1;
+    }
+
+    if (key == NULL
+            || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
+        return 0;
+
+    *len = KEYLENID(pkey->ameth->pkey_id);
+    memcpy(pub, key->pubkey, *len);
+
+    return 1;
+}
+
 const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
     EVP_PKEY_X25519,
     EVP_PKEY_X25519,
@@ -393,6 +434,8 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
 
     ecx_set_priv_key,
     ecx_set_pub_key,
+    ecx_get_priv_key,
+    ecx_get_pub_key,
 };
 
 const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
@@ -434,6 +477,8 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
 
     ecx_set_priv_key,
     ecx_set_pub_key,
+    ecx_get_priv_key,
+    ecx_get_pub_key,
 };
 
 static int ecd_size25519(const EVP_PKEY *pkey)
@@ -547,6 +592,8 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
 
     ecx_set_priv_key,
     ecx_set_pub_key,
+    ecx_get_priv_key,
+    ecx_get_pub_key,
 };
 
 const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
@@ -587,6 +634,8 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
 
     ecx_set_priv_key,
     ecx_set_pub_key,
+    ecx_get_priv_key,
+    ecx_get_pub_key,
 };
 
 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
index afd7e38e3b9b3e7945eb87877f6efe4d8a087fe7..bd54c8bfc2a5305db61fc106954fa8ce5c1f8b49 100644 (file)
@@ -757,6 +757,8 @@ EVP_F_EVP_PKEY_GET0_HMAC:183:EVP_PKEY_get0_hmac
 EVP_F_EVP_PKEY_GET0_POLY1305:184:EVP_PKEY_get0_poly1305
 EVP_F_EVP_PKEY_GET0_RSA:121:EVP_PKEY_get0_RSA
 EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash
+EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY:202:EVP_PKEY_get_raw_private_key
+EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY:203:EVP_PKEY_get_raw_public_key
 EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen
 EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
 EVP_F_EVP_PKEY_METH_ADD0:194:EVP_PKEY_meth_add0
@@ -2199,6 +2201,7 @@ EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
 EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
 EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
 EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
+EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
 EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
 EVP_R_INITIALIZATION_ERROR:134:initialization error
 EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
index 01ed97ed73dc6707a84f098c653783e24d3f2d2a..809adff2888de5d7daf77f27dd7862a09a9dcdac 100644 (file)
@@ -93,6 +93,10 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_RSA, 0), "EVP_PKEY_get0_RSA"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_SIPHASH, 0),
      "EVP_PKEY_get0_siphash"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, 0),
+     "EVP_PKEY_get_raw_private_key"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, 0),
+     "EVP_PKEY_get_raw_public_key"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN, 0), "EVP_PKEY_keygen"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN_INIT, 0),
      "EVP_PKEY_keygen_init"},
@@ -185,6 +189,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "expecting a siphash key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
     "fips mode not supported"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
     "illegal scrypt parameters"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR),
index e4d2bb1835bdc7131ea819cb16cb7a337b39d96c..d78f1d2d841178b08bebf82c3fe4232bdc93086a 100644 (file)
@@ -280,6 +280,40 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
     return NULL;
 }
 
+int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
+                                 size_t *len)
+{
+     if (pkey->ameth->get_priv_key == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return 0;
+    }
+
+    if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
+        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
+                                size_t *len)
+{
+     if (pkey->ameth->get_pub_key == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return 0;
+    }
+
+    if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
+        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
 EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
                                 size_t len, const EVP_CIPHER *cipher)
 {
index b786db07aa2c1d4f2f47f2866f6eadb7a6b34807..fa204e9068e402742fc06d8a9473e835dbbf769e 100644 (file)
@@ -72,6 +72,25 @@ static int hmac_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
     return 1;
 }
 
+static int hmac_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
+                             size_t *len)
+{
+    ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
+
+    if (priv == NULL) {
+        *len = ASN1_STRING_length(os);
+        return 1;
+    }
+
+    if (os == NULL || *len < (size_t)ASN1_STRING_length(os))
+        return 0;
+
+    *len = ASN1_STRING_length(os);
+    memcpy(priv, ASN1_STRING_get0_data(os), *len);
+
+    return 1;
+}
+
 const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
     EVP_PKEY_HMAC,
     EVP_PKEY_HMAC,
@@ -103,4 +122,6 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
 
     hmac_set_priv_key,
     NULL,
+    hmac_get_priv_key,
+    NULL,
 };
index 962c3c630267d541ec4c1001a02c42ff0e0ee1ce..b8a6762aa1581a45ea84e8d3a5b75081138b416f 100644 (file)
@@ -61,6 +61,8 @@ struct evp_pkey_asn1_method_st {
     /* 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);
+    int (*get_priv_key) (const EVP_PKEY *pk, unsigned char *priv, size_t *len);
+    int (*get_pub_key) (const EVP_PKEY *pk, unsigned char *pub, size_t *len);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
index ed4115b718cba5c5f296b392d1091f8f749f5231..033ee8cd9699738705c1c06d3908e79fa67e37ba 100644 (file)
@@ -67,6 +67,25 @@ static int poly1305_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
     return 1;
 }
 
+static int poly1305_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
+                                 size_t *len)
+{
+    ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
+
+    if (priv == NULL) {
+        *len = POLY1305_KEY_SIZE;
+        return 1;
+    }
+
+    if (os == NULL || *len < POLY1305_KEY_SIZE)
+        return 0;
+
+    memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os));
+    *len = POLY1305_KEY_SIZE;
+
+    return 1;
+}
+
 const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth = {
     EVP_PKEY_POLY1305,
     EVP_PKEY_POLY1305,
@@ -98,4 +117,6 @@ const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth = {
 
     poly1305_set_priv_key,
     NULL,
+    poly1305_get_priv_key,
+    NULL,
 };
index 6411501bc00de0141d4bbd3a7b7c341b7bfcd13a..c0ab7efae4b6d36bb17148c7ce69fa05991ab818 100644 (file)
@@ -68,6 +68,25 @@ static int siphash_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
     return 1;
 }
 
+static int siphash_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
+                                size_t *len)
+{
+    ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
+
+    if (priv == NULL) {
+        *len = SIPHASH_KEY_SIZE;
+        return 1;
+    }
+
+    if (os == NULL || *len < SIPHASH_KEY_SIZE)
+        return 0;
+
+    memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os));
+    *len = SIPHASH_KEY_SIZE;
+
+    return 1;
+}
+
 const EVP_PKEY_ASN1_METHOD siphash_asn1_meth = {
     EVP_PKEY_SIPHASH,
     EVP_PKEY_SIPHASH,
@@ -99,4 +118,6 @@ const EVP_PKEY_ASN1_METHOD siphash_asn1_meth = {
 
     siphash_set_priv_key,
     NULL,
+    siphash_get_priv_key,
+    NULL,
 };
index 63cba15a6fa0cfae5b3fa60dcc7d097dc4a1ebdc..8e4e3fe2277e018ec83d9ba8f428f854e1e09447 100644 (file)
@@ -1352,6 +1352,11 @@ EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
 EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
                                       const unsigned char *pub,
                                       size_t len);
+int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
+                                 size_t *len);
+int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
+                                size_t *len);
+
 EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
                                 size_t len, const EVP_CIPHER *cipher);
 
index 84f29518b0e970ea2e9cd96534f6ed8a6769ba30..a8f79c74a9e710dccb75b7370895b45f446eb342 100644 (file)
@@ -79,6 +79,8 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PKEY_GET0_POLY1305                     184
 # define EVP_F_EVP_PKEY_GET0_RSA                          121
 # define EVP_F_EVP_PKEY_GET0_SIPHASH                      172
+# define EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY               202
+# define EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY                203
 # define EVP_F_EVP_PKEY_KEYGEN                            146
 # define EVP_F_EVP_PKEY_KEYGEN_INIT                       147
 # define EVP_F_EVP_PKEY_METH_ADD0                         194
@@ -139,6 +141,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_EXPECTING_A_POLY1305_KEY                   164
 # define EVP_R_EXPECTING_A_SIPHASH_KEY                    175
 # define EVP_R_FIPS_MODE_NOT_SUPPORTED                    167
+# define EVP_R_GET_RAW_KEY_FAILED                         182
 # define EVP_R_ILLEGAL_SCRYPT_PARAMETERS                  171
 # define EVP_R_INITIALIZATION_ERROR                       134
 # define EVP_R_INPUT_NOT_INITIALIZED                      111
index a8107555a05ddf1bbf745489d1c90a167d948ae5..50dcd36a37b1506386dde23a0184d485e6ae910a 100644 (file)
@@ -4563,3 +4563,5 @@ X509_OBJECT_set1_X509                   4514      1_1_0i  EXIST::FUNCTION:
 X509_LOOKUP_meth_get_get_by_issuer_serial 4515 1_1_0i  EXIST::FUNCTION:
 X509_LOOKUP_meth_set_init               4516   1_1_0i  EXIST::FUNCTION:
 X509_OBJECT_set1_X509_CRL               4517   1_1_0i  EXIST::FUNCTION:
+EVP_PKEY_get_raw_public_key             4518   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_get_raw_private_key            4519   1_1_1   EXIST::FUNCTION: