summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2018-06-01 12:22:28 +0100
committerMatt Caswell <matt@openssl.org>2018-06-08 10:04:09 +0100
commit0d124b0a51d3ad8c8807cab280ea18fc68489155 (patch)
tree0a77711f66e26da760c452c867999b024806bad6 /crypto
parentc0a58e034d3eff68ca5e0d36d7b4d147425b0599 (diff)
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@openssl.org> Reviewed-by: Tim Hudson <tjh@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6394)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ec/ecx_meth.c49
-rw-r--r--crypto/err/openssl.txt3
-rw-r--r--crypto/evp/evp_err.c5
-rw-r--r--crypto/evp/p_lib.c34
-rw-r--r--crypto/hmac/hm_ameth.c21
-rw-r--r--crypto/include/internal/asn1_int.h2
-rw-r--r--crypto/poly1305/poly1305_ameth.c21
-rw-r--r--crypto/siphash/siphash_ameth.c21
8 files changed, 156 insertions, 0 deletions
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index d2aa6dd870..e75e07b052 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 afd7e38e3b..bd54c8bfc2 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 01ed97ed73..809adff288 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 e4d2bb1835..d78f1d2d84 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 b786db07aa..fa204e9068 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 962c3c6302..b8a6762aa1 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 ed4115b718..033ee8cd96 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 6411501bc0..c0ab7efae4 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,
};