diff options
-rw-r--r-- | crypto/err/openssl.txt | 2 | ||||
-rw-r--r-- | crypto/evp/evp_err.c | 2 | ||||
-rw-r--r-- | crypto/evp/p_lib.c | 61 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_set1_RSA.pod | 55 | ||||
-rw-r--r-- | include/openssl/evp.h | 21 | ||||
-rw-r--r-- | include/openssl/evperr.h | 2 | ||||
-rw-r--r-- | providers/deserializers.inc | 14 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 7 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dh_kmgmt.c | 16 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dsa_kmgmt.c | 16 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ec_kmgmt.c | 16 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ecx_kmgmt.c | 16 | ||||
-rw-r--r-- | providers/implementations/serializers/build.info | 3 | ||||
-rw-r--r-- | providers/implementations/serializers/deserialize_der2key.c | 234 | ||||
-rw-r--r-- | providers/implementations/serializers/deserialize_der2rsa.c | 241 | ||||
-rw-r--r-- | test/serdes_test.c | 346 | ||||
-rw-r--r-- | util/libcrypto.num | 12 | ||||
-rw-r--r-- | util/other.syms | 4 |
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); \ + } \ + const OSSL_DISPATCH der_to_##keytype##_deserializer_functions[] = { \ + { OSSL_FUNC_DESERIALIZER_NEWCTX, \ + (void (*)(void))der2##keytype##_newctx }, \ + { OSSL_FUNC_DESERIALIZER_FREECTX, \ + (void (*)(void))der2key_freectx }, \ + { OSSL_FUNC_DESERIALIZER_GET |