summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-07-27 18:40:05 +0200
committerPauli <paul.dale@oracle.com>2020-08-01 11:51:19 +1000
commit7c664b1f1b5f60bf896f5fdea5c08c401c541dfe (patch)
tree56b5f9705be72e3139bfadfcfed94eca5ae04ea2
parent3ff8159a8af6ab4e945318c56cd2fffcdd817cf8 (diff)
DESERIALIZER: Add deserializers for the rest of our asymmetric key types
To be able to implement this, there was a need for the standard EVP_PKEY_set1_, EVP_PKEY_get0_ and EVP_PKEY_get1_ functions for ED25519, ED448, X25519 and X448, as well as the corresponding EVP_PKEY_assign_ macros. There was also a need to extend the list of hard coded names that EVP_PKEY_is_a() recognise. Along with this, OSSL_FUNC_keymgmt_load() are implemented for all those key types. The deserializers for these key types are all implemented generically, in providers/implementations/serializers/deserializer_der2key.c. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12544)
-rw-r--r--crypto/err/openssl.txt2
-rw-r--r--crypto/evp/evp_err.c2
-rw-r--r--crypto/evp/p_lib.c61
-rw-r--r--doc/man3/EVP_PKEY_set1_RSA.pod55
-rw-r--r--include/openssl/evp.h21
-rw-r--r--include/openssl/evperr.h2
-rw-r--r--providers/deserializers.inc14
-rw-r--r--providers/implementations/include/prov/implementations.h7
-rw-r--r--providers/implementations/keymgmt/dh_kmgmt.c16
-rw-r--r--providers/implementations/keymgmt/dsa_kmgmt.c16
-rw-r--r--providers/implementations/keymgmt/ec_kmgmt.c16
-rw-r--r--providers/implementations/keymgmt/ecx_kmgmt.c16
-rw-r--r--providers/implementations/serializers/build.info3
-rw-r--r--providers/implementations/serializers/deserialize_der2key.c234
-rw-r--r--providers/implementations/serializers/deserialize_der2rsa.c241
-rw-r--r--test/serdes_test.c346
-rw-r--r--util/libcrypto.num12
-rw-r--r--util/other.syms4
18 files changed, 684 insertions, 384 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 0124d1d3ae..1b4fca9b97 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -875,6 +875,7 @@ EVP_F_EVP_PKEY_ENCRYPT_INIT:139:EVP_PKEY_encrypt_init
EVP_F_EVP_PKEY_ENCRYPT_OLD:152:EVP_PKEY_encrypt_old
EVP_F_EVP_PKEY_GET0_DH:119:EVP_PKEY_get0_DH
EVP_F_EVP_PKEY_GET0_DSA:120:EVP_PKEY_get0_DSA
+EVP_F_EVP_PKEY_GET0_ECX_KEY:222:
EVP_F_EVP_PKEY_GET0_EC_KEY:131:EVP_PKEY_get0_EC_KEY
EVP_F_EVP_PKEY_GET0_HMAC:183:EVP_PKEY_get0_hmac
EVP_F_EVP_PKEY_GET0_POLY1305:184:EVP_PKEY_get0_poly1305
@@ -2532,6 +2533,7 @@ EVP_R_EXPECTING_AN_HMAC_KEY:174:expecting an hmac key
EVP_R_EXPECTING_AN_RSA_KEY:127:expecting an rsa key
EVP_R_EXPECTING_A_DH_KEY:128:expecting a dh key
EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
+EVP_R_EXPECTING_A_ECX_KEY:219:expecting a ecx key
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
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 239efaa51a..d13cd05faa 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -61,6 +61,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "expecting a dh key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY),
"expecting a dsa key"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_ECX_KEY),
+ "expecting a ecx key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_POLY1305_KEY),
"expecting a poly1305 key"},
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index a7fd687dd0..3e3f2118a2 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -34,6 +34,7 @@
#include "crypto/asn1.h"
#include "crypto/evp.h"
+#include "crypto/ecx.h"
#include "internal/evp.h"
#include "internal/provider.h"
#include "evp_local.h"
@@ -855,6 +856,54 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
EC_KEY_up_ref(ret);
return ret;
}
+
+static int EVP_PKEY_set1_ECX_KEY(EVP_PKEY *pkey, int type, ECX_KEY *key)
+{
+ int ret = EVP_PKEY_assign(pkey, type, key);
+ if (ret)
+ ecx_key_up_ref(key);
+ return ret;
+}
+
+static ECX_KEY *EVP_PKEY_get0_ECX_KEY(const EVP_PKEY *pkey, int type)
+{
+ if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
+ return NULL;
+ }
+ if (EVP_PKEY_base_id(pkey) != type) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY);
+ return NULL;
+ }
+ return pkey->pkey.ecx;
+}
+
+static ECX_KEY *EVP_PKEY_get1_ECX_KEY(EVP_PKEY *pkey, int type)
+{
+ ECX_KEY *ret = EVP_PKEY_get0_ECX_KEY(pkey, type);
+ if (ret != NULL)
+ ecx_key_up_ref(ret);
+ return ret;
+}
+
+# define IMPLEMENT_ECX_VARIANT(NAME) \
+ int EVP_PKEY_set1_##NAME(EVP_PKEY *pkey, ECX_KEY *key) \
+ { \
+ return EVP_PKEY_set1_ECX_KEY(pkey, EVP_PKEY_##NAME, key); \
+ } \
+ ECX_KEY *EVP_PKEY_get0_##NAME(const EVP_PKEY *pkey) \
+ { \
+ return EVP_PKEY_get0_ECX_KEY(pkey, EVP_PKEY_##NAME); \
+ } \
+ ECX_KEY *EVP_PKEY_get1_##NAME(EVP_PKEY *pkey) \
+ { \
+ return EVP_PKEY_get1_ECX_KEY(pkey, EVP_PKEY_##NAME); \
+ }
+IMPLEMENT_ECX_VARIANT(X25519)
+IMPLEMENT_ECX_VARIANT(X448)
+IMPLEMENT_ECX_VARIANT(ED25519)
+IMPLEMENT_ECX_VARIANT(ED448)
+
# endif
# ifndef OPENSSL_NO_DH
@@ -940,6 +989,18 @@ int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name)
#ifndef OPENSSL_NO_EC
else if (strcasecmp(name, "EC") == 0)
type = EVP_PKEY_EC;
+ else if (strcasecmp(name, "ED25519") == 0)
+ type = EVP_PKEY_ED25519;
+ else if (strcasecmp(name, "ED448") == 0)
+ type = EVP_PKEY_ED448;
+ else if (strcasecmp(name, "X25519") == 0)
+ type = EVP_PKEY_X25519;
+ else if (strcasecmp(name, "X448") == 0)
+ type = EVP_PKEY_X448;
+#endif
+#ifndef OPENSSL_NO_DH
+ else if (strcasecmp(name, "DH") == 0)
+ type = EVP_PKEY_DH;
#endif
#ifndef OPENSSL_NO_DSA
else if (strcasecmp(name, "DSA") == 0)
diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index 10a8e94661..89737a3c8c 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -3,10 +3,18 @@
=head1 NAME
EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
+EVP_PKEY_set1_ED25519, EVP_PKEY_set1_ED448,
+EVP_PKEY_set1_X25519, EVP_PKEY_set1_X448,
EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
+EVP_PKEY_get1_ED25519, EVP_PKEY_get1_ED448,
+EVP_PKEY_get1_X25519, EVP_PKEY_get1_X448,
EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
+EVP_PKEY_get0_ED25519, EVP_PKEY_get0_ED448,
+EVP_PKEY_get0_X25519, EVP_PKEY_get0_X448,
EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
+EVP_PKEY_assign_ED25519, EVP_PKEY_assign_ED448,
+EVP_PKEY_assign_X25519, EVP_PKEY_assign_X448,
EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id, EVP_PKEY_set_alias_type,
EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
@@ -19,11 +27,19 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
+ int EVP_PKEY_set1_ED25519(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_set1_ED448(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_set1_X25519(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_set1_X448(EVP_PKEY *pkey, ECX_KEY *key);
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get1_ED25519(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get1_ED448(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get1_X25519(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get1_X448(EVP_PKEY *pkey);
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
@@ -32,11 +48,19 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey);
DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get0_ED25519(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get0_ED448(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get0_X25519(EVP_PKEY *pkey);
+ ECX_KEY *EVP_PKEY_get0_X448(EVP_PKEY *pkey);
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
+ int EVP_PKEY_assign_ED25519(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_assign_ED448(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_assign_X25519(EVP_PKEY *pkey, ECX_KEY *key);
+ int EVP_PKEY_assign_X448(EVP_PKEY *pkey, ECX_KEY *key);
int EVP_PKEY_assign_POLY1305(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
int EVP_PKEY_assign_SIPHASH(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
@@ -50,24 +74,31 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
=head1 DESCRIPTION
-EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
-EVP_PKEY_set1_EC_KEY() set the key referenced by I<pkey> to I<key>.
+EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH(),
+EVP_PKEY_set1_EC_KEY(), EVP_PKEY_set1_ED25519(), EVP_PKEY_set1_ED448(),
+EVP_PKEY_set1_X25519() and EVP_PKEY_set1_X448() set the key referenced by
+I<pkey> to I<key>.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
-EVP_PKEY_get1_EC_KEY() return the referenced key in I<pkey> or
-NULL if the key is not of the correct type.
+EVP_PKEY_get1_EC_KEY(), EVP_PKEY_get1_ED25519(), EVP_PKEY_get1_ED448(),
+EVP_PKEY_get1_X25519() and EVP_PKEY_get1_X448() return the referenced key in
+I<pkey> or NULL if the key is not of the correct type. The returned key must
+be freed after use.
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
-EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH()
-and EVP_PKEY_get0_EC_KEY() also return the referenced key in I<pkey> or NULL
-if the key is not of the correct type but the reference count of the
-returned key is B<not> incremented and so must not be freed up after use.
+EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH(),
+EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_ED25519(), EVP_PKEY_get0_ED448(),
+EVP_PKEY_get0_X25519() and EVP_PKEY_get0_X448() return the referenced
+key in I<pkey> or NULL if the key is not of the correct type but the
+reference count of the returned key is B<not> incremented and so must not be
+freed after use.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
-EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() and
-EVP_PKEY_assign_SIPHASH() also set the referenced key to I<key>
-however these use the supplied I<key> internally and so I<key>
-will be freed when the parent I<pkey> is freed.
+EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_ED25519(), EVP_PKEY_assign_ED448(),
+EVP_PKEY_assign_X25519(), EVP_PKEY_assign_X448(), EVP_PKEY_assign_POLY1305() and
+EVP_PKEY_assign_SIPHASH() set the referenced key to I<key> however these use
+the supplied I<key> internally and so I<key> will be freed when the parent
+I<pkey> is freed.
EVP_PKEY_base_id() returns the type of I<pkey>. For example
an RSA key will return B<EVP_PKEY_RSA>.
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 78771ca251..57b6ff1f7c 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -466,6 +466,14 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
# ifndef OPENSSL_NO_EC
# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
(eckey))
+# define EVP_PKEY_assign_X25519(pkey,ecxkey) EVP_PKEY_assign((pkey),EVP_PKEY_X25519,\
+ (ecxkey))
+# define EVP_PKEY_assign_X448(pkey,ecxkey) EVP_PKEY_assign((pkey),EVP_PKEY_X448,\
+ (ecxkey))
+# define EVP_PKEY_assign_ED25519(pkey,ecxkey) EVP_PKEY_assign((pkey),EVP_PKEY_ED25519,\
+ (ecxkey))
+# define EVP_PKEY_assign_ED448(pkey,ecxkey) EVP_PKEY_assign((pkey),EVP_PKEY_ED448,\
+ (ecxkey))
# endif
# ifndef OPENSSL_NO_SIPHASH
# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),\
@@ -1222,6 +1230,19 @@ struct ec_key_st;
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key);
struct ec_key_st *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+struct ecx_key_st;
+int EVP_PKEY_set1_X25519(EVP_PKEY *pkey, struct ecx_key_st *key);
+struct ecx_key_st *EVP_PKEY_get0_X25519(const EVP_PKEY *pkey);
+struct ecx_key_st *EVP_PKEY_get1_X25519(EVP_PKEY *pkey);
+int EVP_PKEY_set1_X448(EVP_PKEY *pkey, struct ecx_key_st *key);
+struct ecx_key_st *EVP_PKEY_get0_X448(const EVP_PKEY *pkey);
+struct ecx_key_st *EVP_PKEY_get1_X448(EVP_PKEY *pkey);
+int EVP_PKEY_set1_ED25519(EVP_PKEY *pkey, struct ecx_key_st *key);
+struct ecx_key_st *EVP_PKEY_get0_ED25519(const EVP_PKEY *pkey);
+struct ecx_key_st *EVP_PKEY_get1_ED25519(EVP_PKEY *pkey);
+int EVP_PKEY_set1_ED448(EVP_PKEY *pkey, struct ecx_key_st *key);
+struct ecx_key_st *EVP_PKEY_get0_ED448(const EVP_PKEY *pkey);
+struct ecx_key_st *EVP_PKEY_get1_ED448(EVP_PKEY *pkey);
# endif
EVP_PKEY *EVP_PKEY_new(void);
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index 6bc106812b..5aa002815a 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -102,6 +102,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_EVP_PKEY_ENCRYPT_OLD 0
# define EVP_F_EVP_PKEY_GET0_DH 0
# define EVP_F_EVP_PKEY_GET0_DSA 0
+# define EVP_F_EVP_PKEY_GET0_ECX_KEY 0
# define EVP_F_EVP_PKEY_GET0_EC_KEY 0
# define EVP_F_EVP_PKEY_GET0_HMAC 0
# define EVP_F_EVP_PKEY_GET0_POLY1305 0
@@ -185,6 +186,7 @@ int ERR_load_EVP_strings(void);
# define EVP_R_EXPECTING_AN_RSA_KEY 127
# define EVP_R_EXPECTING_A_DH_KEY 128
# define EVP_R_EXPECTING_A_DSA_KEY 129
+# define EVP_R_EXPECTING_A_ECX_KEY 219
# define EVP_R_EXPECTING_A_EC_KEY 142
# define EVP_R_EXPECTING_A_POLY1305_KEY 164
# define EVP_R_EXPECTING_A_SIPHASH_KEY 175
diff --git a/providers/deserializers.inc b/providers/deserializers.inc
index bab709d31d..ead1c67878 100644
--- a/providers/deserializers.inc
+++ b/providers/deserializers.inc
@@ -11,6 +11,20 @@
# error Macro DESER undefined
#endif
+#ifndef OPENSSL_NO_DH
+ DESER("DH", "yes", "der", der_to_dh_deserializer_functions),
+#endif
+#ifndef OPENSSL_NO_DSA
+ DESER("DSA", "yes", "der", der_to_dsa_deserializer_functions),
+#endif
+#ifndef OPENSSL_NO_EC
+ DESER("EC", "yes", "der", der_to_ec_deserializer_functions),
+ DESER("ED25519", "yes", "der", der_to_ed25519_deserializer_functions),
+ DESER("ED448", "yes", "der", der_to_ed448_deserializer_functions),
+ DESER("X25519", "yes", "der", der_to_x25519_deserializer_functions),
+ DESER("X448", "yes", "der", der_to_x448_deserializer_functions),
+#endif
DESER("RSA", "yes", "der", der_to_rsa_deserializer_functions),
DESER("RSA-PSS", "yes", "der", der_to_rsapss_deserializer_functions),
+
DESER("DER", "yes", "pem", pem_to_der_deserializer_functions),
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index b02f0c6476..73d4a0225e 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -359,6 +359,13 @@ extern const OSSL_DISPATCH ec_priv_pem_serializer_functions[];
extern const OSSL_DISPATCH ec_pub_pem_serializer_functions[];
extern const OSSL_DISPATCH ec_param_pem_serializer_functions[];
+extern const OSSL_DISPATCH der_to_dh_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_dsa_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_ec_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_x25519_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_x448_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_ed25519_deserializer_functions[];
+extern const OSSL_DISPATCH der_to_ed448_deserializer_functions[];
extern const OSSL_DISPATCH der_to_rsa_deserializer_functions[];
extern const OSSL_DISPATCH der_to_rsapss_deserializer_functions[];
extern const OSSL_DISPATCH pem_to_der_deserializer_functions[];
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index aa4097766d..2a8b7f8521 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -34,6 +34,7 @@ static OSSL_FUNC_keymgmt_gen_set_params_fn dh_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn dh_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn dh_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn dh_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn dh_load;
static OSSL_FUNC_keymgmt_get_params_fn dh_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn dh_gettable_params;
static OSSL_FUNC_keymgmt_set_params_fn dh_set_params;
@@ -644,6 +645,20 @@ static void dh_gen_cleanup(void *genctx)
OPENSSL_free(gctx);
}
+void *dh_load(const void *reference, size_t reference_sz)
+{
+ DH *dh = NULL;
+
+ if (reference_sz == sizeof(dh)) {
+ /* The contents of the reference is the address to our object */
+ dh = *(DH **)reference;
+ /* We grabbed, so we detach it */
+ *(DH **)reference = NULL;
+ return dh;
+ }
+ return NULL;
+}
+
const OSSL_DISPATCH dh_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
@@ -653,6 +668,7 @@ const OSSL_DISPATCH dh_keymgmt_functions[] = {
(void (*)(void))dh_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
index 3d38fea44d..58e9fc564f 100644
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -34,6 +34,7 @@ static OSSL_FUNC_keymgmt_gen_set_params_fn dsa_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn dsa_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn dsa_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn dsa_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn dsa_load;
static OSSL_FUNC_keymgmt_get_params_fn dsa_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn dsa_gettable_params;
static OSSL_FUNC_keymgmt_has_fn dsa_has;
@@ -557,6 +558,20 @@ static void dsa_gen_cleanup(void *genctx)
OPENSSL_free(gctx);
}
+void *dsa_load(const void *reference, size_t reference_sz)
+{
+ DSA *dsa = NULL;
+
+ if (reference_sz == sizeof(dsa)) {
+ /* The contents of the reference is the address to our object */
+ dsa = *(DSA **)reference;
+ /* We grabbed, so we detach it */
+ *(DSA **)reference = NULL;
+ return dsa;
+ }
+ return NULL;
+}
+
const OSSL_DISPATCH dsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init },
@@ -566,6 +581,7 @@ const OSSL_DISPATCH dsa_keymgmt_functions[] = {
(void (*)(void))dsa_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dsa_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dsa_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dsa_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 792b2193e6..4d040a1902 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -33,6 +33,7 @@ static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn ec_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn ec_load;
static OSSL_FUNC_keymgmt_free_fn ec_freedata;
static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
@@ -791,6 +792,20 @@ static void ec_gen_cleanup(void *genctx)
OPENSSL_free(gctx);
}
+void *ec_load(const void *reference, size_t reference_sz)
+{
+ EC_KEY *ec = NULL;
+
+ if (reference_sz == sizeof(ec)) {
+ /* The contents of the reference is the address to our object */
+ ec = *(EC_KEY **)reference;
+ /* We grabbed, so we detach it */
+ *(EC_KEY **)reference = NULL;
+ return ec;
+ }
+ return NULL;
+}
+
const OSSL_DISPATCH ec_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
@@ -801,6 +816,7 @@ const OSSL_DISPATCH ec_keymgmt_functions[] = {
(void (*)(void))ec_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 542592666e..a1e1edbf5a 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -41,6 +41,7 @@ static OSSL_FUNC_keymgmt_gen_fn x448_gen;
static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
+static OSSL_FUNC_keymgmt_load_fn ecx_load;
static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
@@ -589,6 +590,20 @@ static void ecx_gen_cleanup(void *genctx)
OPENSSL_free(gctx);
}
+void *ecx_load(const void *reference, size_t reference_sz)
+{
+ ECX_KEY *key = NULL;
+
+ if (reference_sz == sizeof(key)) {
+ /* The contents of the reference is the address to our object */
+ key = *(ECX_KEY **)reference;
+ /* We grabbed, so we detach it */
+ *(ECX_KEY **)reference = NULL;
+ return key;
+ }
+ return NULL;
+}
+
#define MAKE_KEYMGMT_FUNCTIONS(alg) \
const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
@@ -609,6 +624,7 @@ static void ecx_gen_cleanup(void *genctx)
(void (*)(void))ecx_gen_settable_params }, \
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
+ { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
{ 0, NULL } \
};
diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info
index bcfe9d4d4b..d660385163 100644
--- a/providers/implementations/serializers/build.info
+++ b/providers/implementations/serializers/build.info
@@ -2,6 +2,7 @@
# switch each to the Legacy provider when needed.
$SERIALIZER_GOAL=../../libimplementations.a
+$DESERIALIZER_GOAL=../../libimplementations.a
$RSA_GOAL=../../libimplementations.a
$FFC_GOAL=../../libimplementations.a
$DH_GOAL=../../libimplementations.a
@@ -11,7 +12,7 @@ $EC_GOAL=../../libimplementations.a
SOURCE[$SERIALIZER_GOAL]=serializer_common.c deserialize_common.c
-SOURCE[$RSA_GOAL]=deserialize_der2rsa.c deserialize_pem2der.c
+SOURCE[$RSA_GOAL]=deserialize_der2key.c deserialize_pem2der.c
SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c
DEPEND[serializer_rsa.o]=../../common/include/prov/der_rsa.h
diff --git a/providers/implementations/serializers/deserialize_der2key.c b/providers/implementations/serializers/deserialize_der2key.c
new file mode 100644
index 0000000000..a544d8522c
--- /dev/null
+++ b/providers/implementations/serializers/deserialize_der2key.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/crypto.h>
+#include <openssl/params.h>
+#include <openssl/x509.h>
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "serializer_local.h"
+
+static OSSL_FUNC_deserializer_newctx_fn der2rsa_newctx;
+
+static OSSL_FUNC_deserializer_freectx_fn der2key_freectx;
+static OSSL_FUNC_deserializer_gettable_params_fn der2key_gettable_params;
+static OSSL_FUNC_deserializer_get_params_fn der2key_get_params;
+static OSSL_FUNC_deserializer_deserialize_fn der2key_deserialize;
+static OSSL_FUNC_deserializer_export_object_fn der2key_export_object;
+
+typedef void *(extract_key_fn)(EVP_PKEY *);
+typedef void (free_key_fn)(void *);
+struct keytype_desc_st {
+ int type; /* EVP key type */
+ const char *name; /* Keytype */
+ const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
+
+ /*
+ * These must be the correct EVP_PKEY_get1_{TYPE}() and {TYPE}_free()
+ * function for the key.
+ */
+ extract_key_fn *extract_key;
+ free_key_fn *free_key;
+};
+
+/*
+ * Context used for DER to key deserialization.
+ */
+struct der2key_ctx_st {
+ PROV_CTX *provctx;
+ const struct keytype_desc_st *desc;
+};
+
+static struct der2key_ctx_st *
+der2key_newctx(void *provctx, const struct keytype_desc_st *desc)
+{
+ struct der2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->provctx = provctx;
+ ctx->desc = desc;
+ }
+ return ctx;
+}
+
+static void der2key_freectx(void *vctx)
+{
+ struct der2key_ctx_st *ctx = vctx;
+
+ OPENSSL_free(ctx);
+}
+
+static const OSSL_PARAM *der2key_gettable_params(void)
+{
+ static const OSSL_PARAM gettables[] = {
+ { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
+ OSSL_PARAM_END,
+ };
+
+ return gettables;
+}
+
+static int der2key_get_params(OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "DER"))
+ return 0;
+
+ return 1;
+}
+
+static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
+ OSSL_CALLBACK *data_cb, void *data_cbarg,
+ OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+ struct der2key_ctx_st *ctx = vctx;
+ void *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
+ unsigned char *der = NULL;
+ const unsigned char *derp;
+ long der_len = 0;
+ unsigned char *new_der = NULL;
+ long new_der_len;
+ EVP_PKEY *pkey = NULL;
+ void *key = NULL;
+ int ok = 0;
+
+ if (!ossl_prov_read_der(ctx->provctx, cin, &der, &der_len))
+ return 0;
+
+ /*
+ * Opportunistic attempt to decrypt. If it doesn't work, we try to
+ * decode our input unencrypted.
+ */
+ if (ossl_prov_der_from_p8(&new_der, &new_der_len, der, der_len,
+ pw_cb, pw_cbarg)) {
+ OPENSSL_free(der);
+ der = new_der;
+ der_len = new_der_len;
+ }
+
+ derp = der;
+ pkey = d2i_PrivateKey_ex(ctx->desc->type, NULL, &derp, der_len,
+ libctx, NULL);
+ if (pkey == NULL) {
+ derp = der;
+ pkey = d2i_PUBKEY(NULL, &derp, der_len);
+ }
+
+ if (pkey != NULL) {
+ /*
+ * Tear out the low-level key pointer from the pkey,
+ * but only if it matches the expected key type.
+ *
+ * TODO(3.0): The check should be done with EVP_PKEY_is_a(), but
+ * as long as we still have #legacy internal keys, it's safer to
+ * use the type numbers in side the provider.
+ */
+ if (EVP_PKEY_id(pkey) == ctx->desc->type)
+ key = ctx->desc->extract_key(pkey);
+
+ /*
+ * ctx->desc->extract_key() is expected to have incremented |key|'s
+ * reference count, so it should be safe to free |pkey| now.
+ */
+ EVP_PKEY_free(pkey);
+ }
+
+ OPENSSL_free(der);
+
+ if (key != NULL) {
+ OSSL_PARAM params[3];
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_DESERIALIZER_PARAM_DATA_TYPE,
+ (char *)ctx->desc->name, 0);
+ /* The address of the key becomes the octet string */
+ params[1] =
+ OSSL_PARAM_construct_octet_string(OSSL_DESERIALIZER_PARAM_REFERENCE,
+ &key, sizeof(key));
+ params[2] = OSSL_PARAM_construct_end();
+
+ ok = data_cb(params, data_cbarg);
+ }
+ ctx->desc->free_key(key);
+
+ return ok;
+}
+
+static int der2key_export_object(void *vctx,
+ const void *reference, size_t reference_sz,
+ OSSL_CALLBACK *export_cb, void *export_cbarg)
+{
+ struct der2key_ctx_st *ctx = vctx;
+ OSSL_FUNC_keymgmt_export_fn *export =
+ ossl_prov_get_keymgmt_export(ctx->desc->fns);
+ void *keydata;
+
+ if (reference_sz == sizeof(keydata) && export != NULL) {
+ /* The contents of the reference is the address to our object */
+ keydata = *(void **)reference;
+
+ return export(keydata, OSSL_KEYMGMT_SELECT_ALL,
+ export_cb, export_cbarg);
+ }
+ return 0;
+}
+
+#define IMPLEMENT_NEWCTX(KEYTYPEstr, KEYTYPE, keytype, extract, free) \
+ static const struct keytype_desc_st keytype##_desc = \
+ { EVP_PKEY_##KEYTYPE, KEYTYPEstr, keytype##_keymgmt_functions, \
+ (extract_key_fn *)extract, \
+ (free_key_fn *)free }; \
+ static void *der2##keytype##_newctx(void *provctx) \
+ { \
+ return der2key_newctx(provctx, &keytype##_desc);