diff options
author | Richard Levitte <levitte@openssl.org> | 2021-01-28 08:56:53 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2021-03-19 16:46:39 +0100 |
commit | 06f6761280285401f3aaa31502614f7c8dd0c4fb (patch) | |
tree | 17234683f7434002c0b9295729b608490845b46f /crypto | |
parent | 65ef000ec26e6ec2fab2c31f74be1b76275bbbe5 (diff) |
PROV: Add type specific SubjectPublicKeyInfo decoding to the DER->key decoders
This makes it possible to use d2i_<TYPE>_PUBKEY instead of the generic
d2i_PUBKEY()
This required adding a number of new d2i_<TYPE>_PUBKEY functions.
These are all kept internal.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14314)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/x509/x_pubkey.c | 261 |
1 files changed, 257 insertions, 4 deletions
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index b1268f22c9..37fe2d3435 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -512,7 +512,7 @@ int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp) RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) { EVP_PKEY *pkey; - RSA *key; + RSA *key = NULL; const unsigned char *q; q = *pp; @@ -549,11 +549,95 @@ int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp) return ret; } +#ifndef OPENSSL_NO_DH +DH *ossl_d2i_DH_PUBKEY(DH **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DH *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + if (EVP_PKEY_id(pkey) == EVP_PKEY_DH) + key = EVP_PKEY_get1_DH(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + DH_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_DH_PUBKEY(const DH *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign_DH(pktmp, (DH *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} + +DH *ossl_d2i_DHx_PUBKEY(DH **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DH *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + if (EVP_PKEY_id(pkey) == EVP_PKEY_DHX) + key = EVP_PKEY_get1_DH(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + DH_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_DHx_PUBKEY(const DH *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign(pktmp, EVP_PKEY_DHX, (DH *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} +#endif + #ifndef OPENSSL_NO_DSA DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) { EVP_PKEY *pkey; - DSA *key; + DSA *key = NULL; const unsigned char *q; q = *pp; @@ -595,14 +679,15 @@ int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp) EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) { EVP_PKEY *pkey; - EC_KEY *key; + EC_KEY *key = NULL; const unsigned char *q; q = *pp; pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); if (pkey == NULL) return NULL; - key = EVP_PKEY_get1_EC_KEY(pkey); + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) + key = EVP_PKEY_get1_EC_KEY(pkey); EVP_PKEY_free(pkey); if (key == NULL) return NULL; @@ -631,6 +716,174 @@ int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp) EVP_PKEY_free(pktmp); return ret; } + +ECX_KEY *ossl_d2i_ED25519_PUBKEY(ECX_KEY **a, + const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + ECX_KEY *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + key = ossl_evp_pkey_get1_ED25519(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + ossl_ecx_key_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_ED25519_PUBKEY(const ECX_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + + if (a == NULL) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED25519, (ECX_KEY *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} + +ECX_KEY *ossl_d2i_ED448_PUBKEY(ECX_KEY **a, + const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + ECX_KEY *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + if (EVP_PKEY_id(pkey) == EVP_PKEY_ED448) + key = ossl_evp_pkey_get1_ED448(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + ossl_ecx_key_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_ED448_PUBKEY(const ECX_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + + if (a == NULL) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED448, (ECX_KEY *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} + +ECX_KEY *ossl_d2i_X25519_PUBKEY(ECX_KEY **a, + const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + ECX_KEY *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + if (EVP_PKEY_id(pkey) == EVP_PKEY_X25519) + key = ossl_evp_pkey_get1_X25519(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + ossl_ecx_key_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_X25519_PUBKEY(const ECX_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + + if (a == NULL) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X25519, (ECX_KEY *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} + +ECX_KEY *ossl_d2i_X448_PUBKEY(ECX_KEY **a, + const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + ECX_KEY *key = NULL; + const unsigned char *q; + + q = *pp; + pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length); + if (pkey == NULL) + return NULL; + if (EVP_PKEY_id(pkey) == EVP_PKEY_X448) + key = ossl_evp_pkey_get1_X448(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) + return NULL; + *pp = q; + if (a != NULL) { + ossl_ecx_key_free(*a); + *a = key; + } + return key; +} + +int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + + if (a == NULL) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X448, (ECX_KEY *)a); + ret = i2d_PUBKEY(pktmp, pp); + pktmp->pkey.ptr = NULL; + EVP_PKEY_free(pktmp); + return ret; +} + #endif int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, |