summaryrefslogtreecommitdiffstats
path: root/crypto/x509
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-02-12 18:58:15 +0100
committerRichard Levitte <levitte@openssl.org>2020-02-14 14:17:22 +0100
commitcdb16632636c4a1a439449d110f94cad15d2e9fe (patch)
tree2f37613d27a46a39a39e9e369c2081fab9c0f1d3 /crypto/x509
parent3e686afd04a99e64b70a7c2ef488459ed10ad392 (diff)
Adapt i2d_PUBKEY for provider only keys
It uses EVP_PKEY serializers to get the desired results. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11078)
Diffstat (limited to 'crypto/x509')
-rw-r--r--crypto/x509/x_pubkey.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index f74c156652..f79a57cb7d 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -253,21 +253,52 @@ EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
{
- X509_PUBKEY *xpk = NULL;
int ret = -1;
if (a == NULL)
return 0;
- if ((xpk = X509_PUBKEY_new()) == NULL)
- return -1;
- if (a->ameth != NULL && a->ameth->pub_encode != NULL
- && !a->ameth->pub_encode(xpk, a))
- goto error;
- xpk->pkey = (EVP_PKEY *)a;
- ret = i2d_X509_PUBKEY(xpk, pp);
- xpk->pkey = NULL;
- error:
- X509_PUBKEY_free(xpk);
+ if (a->ameth != NULL) {
+ X509_PUBKEY *xpk = NULL;
+
+ if ((xpk = X509_PUBKEY_new()) == NULL)
+ return -1;
+
+ /* pub_encode() only encode parameters, not the key itself */
+ if (a->ameth->pub_encode != NULL && a->ameth->pub_encode(xpk, a)) {
+ xpk->pkey = (EVP_PKEY *)a;
+ ret = i2d_X509_PUBKEY(xpk, pp);
+ xpk->pkey = NULL;
+ }
+ X509_PUBKEY_free(xpk);
+ } else if (a->pkeys[0].keymgmt != NULL) {
+ const char *serprop = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
+ OSSL_SERIALIZER_CTX *ctx =
+ OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(a, serprop);
+ BIO *out = BIO_new(BIO_s_mem());
+ BUF_MEM *buf = NULL;
+
+ if (ctx != NULL
+ && out != NULL
+ && OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL
+ && OSSL_SERIALIZER_to_bio(ctx, out)
+ && BIO_get_mem_ptr(out, &buf) > 0) {
+ ret = buf->length;
+
+ if (pp != NULL) {
+ if (*pp == NULL) {
+ *pp = (unsigned char *)buf->data;
+ buf->length = 0;
+ buf->data = NULL;
+ } else {
+ memcpy(*pp, buf->data, ret);
+ *pp += ret;
+ }
+ }
+ }
+ BIO_free(out);
+ OSSL_SERIALIZER_CTX_free(ctx);
+ }
+
return ret;
}