[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Fri Jun 8 09:08:26 UTC 2018


The branch master has been updated
       via  bb5f281ad0eed55ae4ddc7ba0ce953411b64bf32 (commit)
       via  72ff0a540059633b7906a78d5d06087d5ce7b7ad (commit)
       via  edb77a4d0f6032e983c91c1a5fbd4136f9757b1c (commit)
       via  0d124b0a51d3ad8c8807cab280ea18fc68489155 (commit)
      from  c0a58e034d3eff68ca5e0d36d7b4d147425b0599 (commit)


- Log -----------------------------------------------------------------
commit bb5f281ad0eed55ae4ddc7ba0ce953411b64bf32
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 1 15:06:52 2018 +0100

    Add a test for the raw private/public key getters
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6394)

commit 72ff0a540059633b7906a78d5d06087d5ce7b7ad
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 1 14:30:50 2018 +0100

    Add function for setting the EVP_PKEY_ASN1_METHOD raw key getter functions
    
    EVP_PKEY_asn1_set_get_priv_key() and EVP_PKEY_asn1_set_get_pub_key()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6394)

commit edb77a4d0f6032e983c91c1a5fbd4136f9757b1c
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 1 14:14:09 2018 +0100

    Document the raw key getter functions
    
    EVP_PKEY_get_raw_private_key() and EVP_PKEY_get_raw_public_key()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6394)

commit 0d124b0a51d3ad8c8807cab280ea18fc68489155
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 1 12:22:28 2018 +0100

    Add support getting raw private/public keys
    
    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 at openssl.org>
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6394)

-----------------------------------------------------------------------

Summary of changes:
 crypto/asn1/ameth_lib.c            | 16 ++++++++
 crypto/ec/ecx_meth.c               | 49 +++++++++++++++++++++++
 crypto/err/openssl.txt             |  3 ++
 crypto/evp/evp_err.c               |  5 +++
 crypto/evp/p_lib.c                 | 34 ++++++++++++++++
 crypto/hmac/hm_ameth.c             | 21 ++++++++++
 crypto/include/internal/asn1_int.h |  2 +
 crypto/poly1305/poly1305_ameth.c   | 21 ++++++++++
 crypto/siphash/siphash_ameth.c     | 21 ++++++++++
 doc/man3/EVP_PKEY_ASN1_METHOD.pod  | 17 +++++++-
 doc/man3/EVP_PKEY_new.pod          | 49 ++++++++++++++++++-----
 include/openssl/evp.h              | 13 ++++++
 include/openssl/evperr.h           |  3 ++
 test/evp_extra_test.c              | 81 ++++++++++++++++++++++++++++++++++++++
 util/libcrypto.num                 |  4 ++
 15 files changed, 327 insertions(+), 12 deletions(-)

diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
index b5f0293..9b3274b 100644
--- a/crypto/asn1/ameth_lib.c
+++ b/crypto/asn1/ameth_lib.c
@@ -417,3 +417,19 @@ void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
 {
     ameth->set_pub_key = set_pub_key;
 }
+
+void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*get_priv_key) (const EVP_PKEY *pk,
+                                                         unsigned char *priv,
+                                                         size_t *len))
+{
+    ameth->get_priv_key = get_priv_key;
+}
+
+void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                   int (*get_pub_key) (const EVP_PKEY *pk,
+                                                       unsigned char *pub,
+                                                       size_t *len))
+{
+    ameth->get_pub_key = get_pub_key;
+}
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index d2aa6dd..e75e07b 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -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)
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index afd7e38..bd54c8b 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -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
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 01ed97e..809adff 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -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),
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index e4d2bb1..d78f1d2 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -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)
 {
diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c
index b786db0..fa204e9 100644
--- a/crypto/hmac/hm_ameth.c
+++ b/crypto/hmac/hm_ameth.c
@@ -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,
 };
diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h
index 962c3c6..b8a6762 100644
--- a/crypto/include/internal/asn1_int.h
+++ b/crypto/include/internal/asn1_int.h
@@ -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)
diff --git a/crypto/poly1305/poly1305_ameth.c b/crypto/poly1305/poly1305_ameth.c
index ed4115b7..033ee8c 100644
--- a/crypto/poly1305/poly1305_ameth.c
+++ b/crypto/poly1305/poly1305_ameth.c
@@ -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,
 };
diff --git a/crypto/siphash/siphash_ameth.c b/crypto/siphash/siphash_ameth.c
index 6411501..c0ab7ef 100644
--- a/crypto/siphash/siphash_ameth.c
+++ b/crypto/siphash/siphash_ameth.c
@@ -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,
 };
diff --git a/doc/man3/EVP_PKEY_ASN1_METHOD.pod b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
index cb9375a..3c2ffd9 100644
--- a/doc/man3/EVP_PKEY_ASN1_METHOD.pod
+++ b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
@@ -21,6 +21,8 @@ EVP_PKEY_asn1_set_param_check,
 EVP_PKEY_asn1_set_security_bits,
 EVP_PKEY_asn1_set_set_priv_key,
 EVP_PKEY_asn1_set_set_pub_key,
+EVP_PKEY_asn1_set_get_priv_key,
+EVP_PKEY_asn1_set_get_pub_key,
 EVP_PKEY_get0_asn1
 - manipulating and registering EVP_PKEY_ASN1_METHOD structure
 
@@ -125,6 +127,16 @@ EVP_PKEY_get0_asn1
                                                         const unsigned char *pub,
                                                         size_t len));
 
+ void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                     int (*get_priv_key) (const EVP_PKEY *pk,
+                                                          unsigned char *priv,
+                                                          size_t *len));
+
+ void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*get_pub_key) (const EVP_PKEY *pk,
+                                                        unsigned char *pub,
+                                                        size_t *len));
+
  const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey);
 
 =head1 DESCRIPTION
@@ -390,8 +402,9 @@ EVP_PKEY_asn1_set_param(), EVP_PKEY_asn1_set_free(),
 EVP_PKEY_asn1_set_ctrl(), EVP_PKEY_asn1_set_item(),
 EVP_PKEY_asn1_set_siginf(), EVP_PKEY_asn1_set_check(),
 EVP_PKEY_asn1_set_public_check(), EVP_PKEY_asn1_set_param_check(),
-EVP_PKEY_asn1_set_security_bits(), EVP_PKEY_asn1_set_set_priv_key() and
-EVP_PKEY_asn1_set_set_pub_key() set the diverse methods of the given
+EVP_PKEY_asn1_set_security_bits(), EVP_PKEY_asn1_set_set_priv_key(),
+EVP_PKEY_asn1_set_set_pub_key(), EVP_PKEY_asn1_set_get_priv_key() and
+EVP_PKEY_asn1_set_get_pub_key() set the diverse methods of the given
 B<EVP_PKEY_ASN1_METHOD> object.
 
 EVP_PKEY_get0_asn1() finds the B<EVP_PKEY_ASN1_METHOD> associated
diff --git a/doc/man3/EVP_PKEY_new.pod b/doc/man3/EVP_PKEY_new.pod
index 17ffc6b..a3532a3 100644
--- a/doc/man3/EVP_PKEY_new.pod
+++ b/doc/man3/EVP_PKEY_new.pod
@@ -8,8 +8,10 @@ EVP_PKEY_free,
 EVP_PKEY_new_raw_private_key,
 EVP_PKEY_new_raw_public_key,
 EVP_PKEY_new_CMAC_key,
-EVP_PKEY_new_mac_key
-- public/private key allocation functions
+EVP_PKEY_new_mac_key,
+EVP_PKEY_get_raw_private_key,
+EVP_PKEY_get_raw_public_key
+- public/private key allocation and raw key handling functions
 
 =head1 SYNOPSIS
 
@@ -28,10 +30,16 @@ EVP_PKEY_new_mac_key
  EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key,
                                 int keylen);
 
+ 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);
+
 =head1 DESCRIPTION
 
 The EVP_PKEY_new() function allocates an empty B<EVP_PKEY> structure which is
-used by OpenSSL to store private keys. The reference count is set to B<1>.
+used by OpenSSL to store public and private keys. The reference count is set to
+B<1>.
 
 EVP_PKEY_up_ref() increments the reference count of B<key>.
 
@@ -63,14 +71,32 @@ creation of a CMAC in the B<cipher> argument.
 EVP_PKEY_new_mac_key() works in the same way as EVP_PKEY_new_raw_private_key().
 New applications should use EVP_PKEY_new_raw_private_key() instead.
 
+EVP_PKEY_get_raw_private_key() fills the buffer provided by B<priv> with raw
+private key data. The number of bytes written is populated in B<*len>. If the
+buffer B<priv> is NULL then B<*len> is populated with the number of bytes
+required to hold the key. The calling application is responsible for ensuring
+that the buffer is large enough to receive the private key data. This function
+only works for algorithms that support raw private keys. Currently this is:
+B<EVP_PKEY_HMAC>, B<EVP_PKEY_POLY1305>, B<EVP_PKEY_SIPHASH>, B<EVP_PKEY_X25519>,
+B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>.
+
+EVP_PKEY_get_raw_public_key() fills the buffer provided by B<pub> with raw
+public key data. The number of bytes written is populated in B<*len>. If the
+buffer B<pub> is NULL then B<*len> is populated with the number of bytes
+required to hold the key. The calling application is responsible for ensuring
+that the buffer is large enough to receive the public key data. This function
+only works for algorithms that support raw public  keys. Currently this is:
+B<EVP_PKEY_X25519>, B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>.
+
 =head1 NOTES
 
 The B<EVP_PKEY> structure is used by various OpenSSL functions which require a
 general private key without reference to any particular algorithm.
 
-The structure returned by EVP_PKEY_new() is empty. To add a private key to this
-empty structure the functions described in L<EVP_PKEY_set1_RSA(3)> should be
-used.
+The structure returned by EVP_PKEY_new() is empty. To add a private or public
+key to this empty structure use the appropriate functions described in
+L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA>, L<EVP_PKEY_set1_DH> or
+L<EVP_PKEY_set1_EC_KEY>.
 
 =head1 RETURN VALUES
 
@@ -78,19 +104,22 @@ EVP_PKEY_new(), EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key(),
 EVP_PKEY_new_CMAC_key() and EVP_PKEY_new_mac_key() return either the newly
 allocated B<EVP_PKEY> structure or B<NULL> if an error occurred.
 
-EVP_PKEY_up_ref() returns 1 for success and 0 for failure.
+EVP_PKEY_up_ref(), EVP_PKEY_get_raw_private_key() and
+EVP_PKEY_get_raw_public_key() return 1 for success and 0 for failure.
 
 =head1 SEE ALSO
 
-L<EVP_PKEY_set1_RSA(3)>
+L<EVP_PKEY_set1_RSA(3)>, L<EVP_PKEY_set1_DSA>, L<EVP_PKEY_set1_DH> or
+L<EVP_PKEY_set1_EC_KEY>
 
 =head1 HISTORY
 
 EVP_PKEY_new() and EVP_PKEY_free() exist in all versions of OpenSSL.
 
 EVP_PKEY_up_ref() was first added to OpenSSL 1.1.0.
-EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key() and
-EVP_PKEY_new_CMAC_key() were first added to OpenSSL 1.1.1.
+EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key(),
+EVP_PKEY_new_CMAC_key(), EVP_PKEY_new_raw_private_key() and
+EVP_PKEY_get_raw_public_key() were first added to OpenSSL 1.1.1.
 
 =head1 COPYRIGHT
 
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 63cba15..33ff674 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1238,6 +1238,14 @@ void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
                                    int (*set_pub_key) (EVP_PKEY *pk,
                                                        const unsigned char *pub,
                                                        size_t len));
+void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*get_priv_key) (const EVP_PKEY *pk,
+                                                         unsigned char *priv,
+                                                         size_t *len));
+void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
+                                   int (*get_pub_key) (const EVP_PKEY *pk,
+                                                       unsigned char *pub,
+                                                       size_t *len));
 
 void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
                                      int (*pkey_security_bits) (const EVP_PKEY
@@ -1352,6 +1360,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);
 
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index 84f2951..a8f79c7 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -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
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index e63d683..fd461c9 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -9,6 +9,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <openssl/bio.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
@@ -476,6 +477,85 @@ static int test_EVP_PKCS82PKEY(void)
 }
 #endif
 
+static struct keys_st {
+    int type;
+    char *priv;
+    char *pub;
+} keys[] = {
+    {
+        EVP_PKEY_HMAC, "0123456789", NULL
+    }, {
+        EVP_PKEY_POLY1305, "01234567890123456789012345678901", NULL
+    }, {
+        EVP_PKEY_SIPHASH, "0123456789012345", NULL
+    }, {
+        EVP_PKEY_X25519, "01234567890123456789012345678901",
+        "abcdefghijklmnopqrstuvwxyzabcdef"
+    }, {
+        EVP_PKEY_ED25519, "01234567890123456789012345678901",
+        "abcdefghijklmnopqrstuvwxyzabcdef"
+    }, {
+        EVP_PKEY_X448,
+        "01234567890123456789012345678901234567890123456789012345",
+        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+    }, {
+        EVP_PKEY_ED448,
+        "012345678901234567890123456789012345678901234567890123456",
+        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde"
+    }
+};
+
+static int test_set_get_raw_keys_int(int tst, int pub)
+{
+    int ret = 0;
+    unsigned char buf[80];
+    unsigned char *in;
+    size_t inlen, len = 0;
+    EVP_PKEY *pkey;
+
+    /* Check if this algorithm supports public keys */
+    if (keys[tst].pub == NULL)
+        return 1;
+
+    memset(buf, 0, sizeof(buf));
+
+    if (pub) {
+        inlen = strlen(keys[tst].pub);
+        in = (unsigned char *)keys[tst].pub;
+        pkey = EVP_PKEY_new_raw_public_key(keys[tst].type,
+                                           NULL,
+                                           in,
+                                           inlen);
+    } else {
+        inlen = strlen(keys[tst].priv);
+        in = (unsigned char *)keys[tst].priv;
+        pkey = EVP_PKEY_new_raw_private_key(keys[tst].type,
+                                            NULL,
+                                            in,
+                                            inlen);
+    }
+
+    if (!TEST_ptr(pkey)
+            || (!pub && !TEST_true(EVP_PKEY_get_raw_private_key(pkey, NULL, &len)))
+            || (pub && !TEST_true(EVP_PKEY_get_raw_public_key(pkey, NULL, &len)))
+            || !TEST_true(len == inlen)
+            || (!pub && !TEST_true(EVP_PKEY_get_raw_private_key(pkey, buf, &len)))
+            || (pub && !TEST_true(EVP_PKEY_get_raw_public_key(pkey, buf, &len)))
+            || !TEST_mem_eq(in, inlen, buf, len))
+        goto done;
+
+    ret = 1;
+ done:
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
+static int test_set_get_raw_keys(int tst)
+{
+    return test_set_get_raw_keys_int(tst, 0)
+           && test_set_get_raw_keys_int(tst, 1);
+}
+
 static int pkey_custom_check(EVP_PKEY *pkey)
 {
     return 0xbeef;
@@ -581,6 +661,7 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_EC
     ADD_TEST(test_EVP_PKCS82PKEY);
 #endif
+    ADD_ALL_TESTS(test_set_get_raw_keys, OSSL_NELEM(keys));
     custom_pmeth = EVP_PKEY_meth_new(0xdefaced, 0);
     if (!TEST_ptr(custom_pmeth))
         return 0;
diff --git a/util/libcrypto.num b/util/libcrypto.num
index a810755..a25f65f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4563,3 +4563,7 @@ 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:
+EVP_PKEY_asn1_set_get_priv_key          4520	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_asn1_set_get_pub_key           4521	1_1_1	EXIST::FUNCTION:


More information about the openssl-commits mailing list