diff options
author | Richard Levitte <levitte@openssl.org> | 2021-05-27 12:34:03 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2021-06-09 17:00:10 +0200 |
commit | 6a2b8ff392a304bbb106528653397b864acc53fa (patch) | |
tree | 75bd836ad9cec6eec65f270fd4db4b893f73b939 /providers/implementations | |
parent | 320fc032b98cc452c5dc96600b16da40b155123b (diff) |
Decoding PKCS#8: separate decoding of encrypted and unencrypted PKCS#8
This has us switch from the 'structure' "pkcs8" to "PrivateKeyInfo",
which is sensible considering we already have "SubjectPublicKeyInfo".
We also add "EncryptedPrivateKeyInfo", and use it for a special decoder
that detects and decrypts an EncryptedPrivateKeyInfo structured DER
blob into a PrivateKeyInfo structured DER blob and passes that on to
the next decoder implementation.
The result of this change is that PKCS#8 decryption should only happen
once per decoding instead of once for every expected key type.
Furthermore, this new decoder implementation sets the data type to the
OID of the algorithmIdentifier field, thus reducing how many decoder
implementations are tentativaly run further down the call chain.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15498)
Diffstat (limited to 'providers/implementations')
6 files changed, 368 insertions, 175 deletions
diff --git a/providers/implementations/encode_decode/build.info b/providers/implementations/encode_decode/build.info index 537d393261..22f11cbceb 100644 --- a/providers/implementations/encode_decode/build.info +++ b/providers/implementations/encode_decode/build.info @@ -6,7 +6,7 @@ $DECODER_GOAL=../../libdefault.a SOURCE[$ENCODER_GOAL]=endecoder_common.c -SOURCE[$DECODER_GOAL]=decode_der2key.c decode_pem2der.c \ +SOURCE[$DECODER_GOAL]=decode_der2key.c decode_epki2pki.c decode_pem2der.c \ decode_msblob2key.c decode_pvk2key.c SOURCE[$ENCODER_GOAL]=encode_key2any.c encode_key2text.c encode_key2ms.c diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c index 22ee075b19..7de44ed75d 100644 --- a/providers/implementations/encode_decode/decode_der2key.c +++ b/providers/implementations/encode_decode/decode_der2key.c @@ -41,8 +41,7 @@ typedef int check_key_fn(void *, struct der2key_ctx_st *ctx); typedef void adjust_key_fn(void *, struct der2key_ctx_st *ctx); typedef void free_key_fn(void *); typedef void *d2i_PKCS8_fn(void **, const unsigned char **, long, - struct der2key_ctx_st *, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg); + struct der2key_ctx_st *); struct keytype_desc_st { const char *keytype_name; const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */ @@ -65,7 +64,7 @@ struct keytype_desc_st { d2i_of_void *d2i_private_key; /* From type-specific DER */ d2i_of_void *d2i_public_key; /* From type-specific DER */ d2i_of_void *d2i_key_params; /* From type-specific DER */ - d2i_PKCS8_fn *d2i_PKCS8; /* Wrapped in a PKCS#8, possibly encrypted */ + d2i_PKCS8_fn *d2i_PKCS8; /* Wrapped in a PrivateKeyInfo */ d2i_of_void *d2i_PUBKEY; /* Wrapped in a SubjectPublicKeyInfo */ /* @@ -114,36 +113,13 @@ typedef void *key_from_pkcs8_t(const PKCS8_PRIV_KEY_INFO *p8inf, OSSL_LIB_CTX *libctx, const char *propq); static void *der2key_decode_p8(const unsigned char **input_der, long input_der_len, struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg, key_from_pkcs8_t *key_from_pkcs8) { - X509_SIG *p8 = NULL; PKCS8_PRIV_KEY_INFO *p8inf = NULL; const X509_ALGOR *alg = NULL; void *key = NULL; - ctx->flag_fatal = 0; - - ERR_set_mark(); - if ((p8 = d2i_X509_SIG(NULL, input_der, input_der_len)) != NULL) { - char pbuf[PEM_BUFSIZE]; - size_t plen = 0; - - ERR_clear_last_mark(); - - if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) - ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE); - else - p8inf = PKCS8_decrypt_ex(p8, pbuf, plen, PROV_LIBCTX_OF(ctx->provctx), NULL); - if (p8inf == NULL) - ctx->flag_fatal = 1; - X509_SIG_free(p8); - } else { - /* Pop any errors that might have been raised by d2i_X509_SIG. */ - ERR_pop_to_mark(); - p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, input_der, input_der_len); - } - if (p8inf != NULL + if ((p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, input_der, input_der_len)) != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf) && OBJ_obj2nid(alg->algorithm) == ctx->desc->evp_type) key = key_from_pkcs8(p8inf, PROV_LIBCTX_OF(ctx->provctx), NULL); @@ -247,8 +223,7 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { derp = der; if (ctx->desc->d2i_PKCS8 != NULL) { - key = ctx->desc->d2i_PKCS8(NULL, &derp, der_len, ctx, - pw_cb, pw_cbarg); + key = ctx->desc->d2i_PKCS8(NULL, &derp, der_len, ctx); if (ctx->flag_fatal) goto end; } else if (ctx->desc->d2i_private_key != NULL) { @@ -360,10 +335,9 @@ static int der2key_export_object(void *vctx, # define dh_d2i_key_params (d2i_of_void *)d2i_DHparams static void *dh_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_dh_key_from_pkcs8); } @@ -396,10 +370,9 @@ static void dh_adjust(void *key, struct der2key_ctx_st *ctx) # define dsa_d2i_key_params (d2i_of_void *)d2i_DSAparams static void *dsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_dsa_key_from_pkcs8); } @@ -422,10 +395,9 @@ static void dsa_adjust(void *key, struct der2key_ctx_st *ctx) # define ec_d2i_key_params (d2i_of_void *)d2i_ECParameters static void *ec_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8); } @@ -452,10 +424,9 @@ static void ec_adjust(void *key, struct der2key_ctx_st *ctx) */ static void *ecx_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_ecx_key_from_pkcs8); } @@ -511,10 +482,9 @@ static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx) # define sm2_d2i_key_params (d2i_of_void *)d2i_ECParameters static void *sm2_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8); } @@ -533,10 +503,9 @@ static void *sm2_d2i_PKCS8(void **key, const unsigned char **der, long der_len, #define rsa_d2i_key_params NULL static void *rsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len, - struct der2key_ctx_st *ctx, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) + struct der2key_ctx_st *ctx) { - return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg, + return der2key_decode_p8(der, der_len, ctx, (key_from_pkcs8_t *)ossl_rsa_key_from_pkcs8); } @@ -650,8 +619,8 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx) keytype##_adjust, \ keytype##_free -#define DO_PKCS8(keytype) \ - "pkcs8", keytype##_evp_type, \ +#define DO_PrivateKeyInfo(keytype) \ + "PrivateKeyInfo", keytype##_evp_type, \ ( OSSL_KEYMGMT_SELECT_PRIVATE_KEY ), \ NULL, \ NULL, \ @@ -785,42 +754,42 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx) } #ifndef OPENSSL_NO_DH -MAKE_DECODER("DH", dh, dh, PKCS8); +MAKE_DECODER("DH", dh, dh, PrivateKeyInfo); MAKE_DECODER("DH", dh, dh, SubjectPublicKeyInfo); MAKE_DECODER("DH", dh, dh, type_specific_params); MAKE_DECODER("DH", dh, dh, DH); -MAKE_DECODER("DHX", dhx, dhx, PKCS8); +MAKE_DECODER("DHX", dhx, dhx, PrivateKeyInfo); MAKE_DECODER("DHX", dhx, dhx, SubjectPublicKeyInfo); MAKE_DECODER("DHX", dhx, dhx, type_specific_params); MAKE_DECODER("DHX", dhx, dhx, DHX); #endif #ifndef OPENSSL_NO_DSA -MAKE_DECODER("DSA", dsa, dsa, PKCS8); +MAKE_DECODER("DSA", dsa, dsa, PrivateKeyInfo); MAKE_DECODER("DSA", dsa, dsa, SubjectPublicKeyInfo); MAKE_DECODER("DSA", dsa, dsa, type_specific); MAKE_DECODER("DSA", dsa, dsa, DSA); #endif #ifndef OPENSSL_NO_EC -MAKE_DECODER("EC", ec, ec, PKCS8); +MAKE_DECODER("EC", ec, ec, PrivateKeyInfo); MAKE_DECODER("EC", ec, ec, SubjectPublicKeyInfo); MAKE_DECODER("EC", ec, ec, type_specific_no_pub); MAKE_DECODER("EC", ec, ec, EC); -MAKE_DECODER("X25519", x25519, ecx, PKCS8); +MAKE_DECODER("X25519", x25519, ecx, PrivateKeyInfo); MAKE_DECODER("X25519", x25519, ecx, SubjectPublicKeyInfo); -MAKE_DECODER("X448", x448, ecx, PKCS8); +MAKE_DECODER("X448", x448, ecx, PrivateKeyInfo); MAKE_DECODER("X448", x448, ecx, SubjectPublicKeyInfo); -MAKE_DECODER("ED25519", ed25519, ecx, PKCS8); +MAKE_DECODER("ED25519", ed25519, ecx, PrivateKeyInfo); MAKE_DECODER("ED25519", ed25519, ecx, SubjectPublicKeyInfo); -MAKE_DECODER("ED448", ed448, ecx, PKCS8); +MAKE_DECODER("ED448", ed448, ecx, PrivateKeyInfo); MAKE_DECODER("ED448", ed448, ecx, SubjectPublicKeyInfo); # ifndef OPENSSL_NO_SM2 -MAKE_DECODER("SM2", sm2, ec, PKCS8); +MAKE_DECODER("SM2", sm2, ec, PrivateKeyInfo); MAKE_DECODER("SM2", sm2, ec, SubjectPublicKeyInfo); # endif #endif -MAKE_DECODER("RSA", rsa, rsa, PKCS8); +MAKE_DECODER("RSA", rsa, rsa, PrivateKeyInfo); MAKE_DECODER("RSA", rsa, rsa, SubjectPublicKeyInfo); MAKE_DECODER("RSA", rsa, rsa, type_specific_keypair); MAKE_DECODER("RSA", rsa, rsa, RSA); -MAKE_DECODER("RSA-PSS", rsapss, rsapss, PKCS8); +MAKE_DECODER("RSA-PSS", rsapss, rsapss, PrivateKeyInfo); MAKE_DECODER("RSA-PSS", rsapss, rsapss, SubjectPublicKeyInfo); diff --git a/providers/implementations/encode_decode/decode_epki2pki.c b/providers/implementations/encode_decode/decode_epki2pki.c new file mode 100644 index 0000000000..c0d014aef1 --- /dev/null +++ b/providers/implementations/encode_decode/decode_epki2pki.c @@ -0,0 +1,153 @@ +/* + * Copyright 2020-2021 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 + */ + +#include <openssl/core.h> +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +#include <openssl/core_object.h> +#include <openssl/asn1.h> +#include <openssl/err.h> +#include <openssl/objects.h> +#include <openssl/pkcs12.h> +#include <openssl/x509.h> +#include <openssl/proverr.h> +#include "internal/asn1.h" +#include "internal/sizes.h" +#include "prov/bio.h" +#include "prov/implementations.h" +#include "endecoder_local.h" + +static OSSL_FUNC_decoder_newctx_fn epki2pki_newctx; +static OSSL_FUNC_decoder_freectx_fn epki2pki_freectx; +static OSSL_FUNC_decoder_decode_fn epki2pki_decode; + +/* + * Context used for EncryptedPrivateKeyInfo to PrivateKeyInfo decoding. + */ +struct epki2pki_ctx_st { + PROV_CTX *provctx; +}; + +static void *epki2pki_newctx(void *provctx) +{ + struct epki2pki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + ctx->provctx = provctx; + return ctx; +} + +static void epki2pki_freectx(void *vctx) +{ + struct epki2pki_ctx_st *ctx = vctx; + + OPENSSL_free(ctx); +} + +/* + * The selection parameter in epki2pki_decode() is not used by this function + * because it's not relevant just to decode EncryptedPrivateKeyInfo to + * PrivateKeyInfo. + */ +static int epki2pki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, + OSSL_CALLBACK *data_cb, void *data_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + struct epki2pki_ctx_st *ctx = vctx; + BUF_MEM *mem = NULL; + unsigned char *der = NULL; + const unsigned char *pder = NULL; + long der_len = 0; + X509_SIG *p8 = NULL; + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + const X509_ALGOR *alg = NULL; + BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); + int ok = (asn1_d2i_read_bio(in, &mem) >= 0); + + BIO_free(in); + + /* We return "empty handed". This is not an error. */ + if (!ok) + return 1; + + pder = der = (unsigned char *)mem->data; + der_len = (long)mem->length; + OPENSSL_free(mem); + + ok = 1; /* Assume good */ + ERR_set_mark(); + if ((p8 = d2i_X509_SIG(NULL, &pder, der_len)) != NULL) { + char pbuf[1024]; + size_t plen = 0; + + ERR_clear_last_mark(); + + if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) { + ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE); + } else { + const ASN1_OCTET_STRING *oct; + unsigned char *new_der = NULL; + int new_der_len = 0; + + X509_SIG_get0(p8, &alg, &oct); + if (!PKCS12_pbe_crypt_ex(alg, pbuf, plen, + oct->data, oct->length, + &new_der, &new_der_len, 0, + PROV_LIBCTX_OF(ctx->provctx), NULL)) { + ok = 0; + } else { + OPENSSL_free(der); + der = new_der; + der_len = new_der_len; + } + alg = NULL; + } + X509_SIG_free(p8); + } else { + ERR_pop_to_mark(); + } + + ERR_set_mark(); + pder = der; + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pder, der_len); + ERR_pop_to_mark(); + + if (p8inf != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)) { + /* + * We have something and recognised it as PrivateKeyInfo, so let's + * pass all the applicable data to the callback. + */ + char keytype[OSSL_MAX_NAME_SIZE]; + OSSL_PARAM params[5], *p = params; + int objtype = OSSL_OBJECT_PKEY; + + OBJ_obj2txt(keytype, sizeof(keytype), alg->algorithm, 0); + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, + keytype, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + "PrivateKeyInfo", 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, + der, der_len); + *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); + *p = OSSL_PARAM_construct_end(); + + ok = data_cb(params, data_cbarg); + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + OPENSSL_free(der); + return ok; +} + +const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[] = { + { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))epki2pki_newctx }, + { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))epki2pki_freectx }, + { OSSL_FUNC_DECODER_DECODE, (void (*)(void))epki2pki_decode }, + { 0, NULL } +}; diff --git a/providers/implementations/encode_decode/decode_pem2der.c b/providers/implementations/encode_decode/decode_pem2der.c index 318efcc6af..16f3322354 100644 --- a/providers/implementations/encode_decode/decode_pem2der.c +++ b/providers/implementations/encode_decode/decode_pem2der.c @@ -101,8 +101,8 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, * These entries should be in longest to shortest order to avoid * mixups. */ - { "ENCRYPTED PRIVATE KEY", "pkcs8" }, - { "PRIVATE KEY", "pkcs8" }, + { "ENCRYPTED PRIVATE KEY", "EncryptedPrivateKeyInfo" }, + { "PRIVATE KEY", "PrivateKeyInfo" }, { "PUBLIC KEY", "SubjectPublicKeyInfo" }, { "PARAMETERS", NULL } diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c index f986ec124e..855866cbfe 100644 --- a/providers/implementations/encode_decode/encode_key2any.c +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -128,12 +128,14 @@ static X509_SIG *key_to_encp8(const void *key, int key_nid, { PKCS8_PRIV_KEY_INFO *p8info = key_to_p8info(key, key_nid, params, params_type, k2d); - X509_SIG *p8 = p8info_to_encp8(p8info, ctx); + X509_SIG *p8 = NULL; - if (p8info == NULL) + if (p8info == NULL) { free_asn1_data(params_type, params); - - PKCS8_PRIV_KEY_INFO_free(p8info); + } else { + p8 = p8info_to_encp8(p8info, ctx); + PKCS8_PRIV_KEY_INFO_free(p8info); + } return p8; } @@ -162,81 +164,141 @@ static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid, } /* - * key_to_pkcs8_* produce encoded output with the key data pkcs8 - * in a structure. For private keys, that structure is PKCS#8, and for - * public keys, it's X.509 SubjectPublicKeyInfo. Parameters don't have - * any defined envelopment of that kind. + * key_to_epki_* produce encoded output with the private key data in a + * EncryptedPrivateKeyInfo structure (defined by PKCS#8). They require + * that there's an intent to encrypt, anything else is an error. + * They are currently only called from the corresponding key_to_pki_ function. + * + * key_to_pki_* primarly produce encoded output with the private key data + * in a PrivateKeyInfo structure (also defined by PKCS#8). However, if + * there is an intent to encrypt the data, the corresponding key_to_epki_* + * function is used instead. + * + * key_to_spki_* produce encoded output with the public key data in an + * X.509 SubjectPublicKeyInfo. + * + * Key parameters don't have any defined envelopment of this kind, but are + * included in some manner in the output from the functions described above, + * either in the AlgorithmIdentifier's parameter field, or as part of the + * key data itself. */ -static int key_to_pkcs8_der_priv_bio(BIO *out, const void *key, - int key_nid, - ossl_unused const char *pemname, - key_to_paramstring_fn *p2s, - i2d_of_void *k2d, - struct key2any_ctx_st *ctx) + +static int key_to_epki_der_priv_bio(BIO *out, const void *key, + int key_nid, + ossl_unused const char *pemname, + key_to_paramstring_fn *p2s, + i2d_of_void *k2d, + struct key2any_ctx_st *ctx) { int ret = 0; void *str = NULL; int strtype = V_ASN1_UNDEF; + X509_SIG *p8; + + if (!ctx->cipher_intent) + return 0; if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters, &str, &strtype)) return 0; - if (ctx->cipher_intent) { - X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + if (p8 != NULL) + ret = i2d_PKCS8_bio(out, p8); - if (p8 != NULL) - ret = i2d_PKCS8_bio(out, p8); + X509_SIG_free(p8); - X509_SIG_free(p8); - } else { - PKCS8_PRIV_KEY_INFO *p8info = - key_to_p8info(key, key_nid, str, strtype, k2d); + return ret; +} - if (p8info != NULL) - ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info); - else - free_asn1_data(strtype, str); +static int key_to_epki_pem_priv_bio(BIO *out, const void *key, + int key_nid, + ossl_unused const char *pemname, + key_to_paramstring_fn *p2s, + i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + X509_SIG *p8; - PKCS8_PRIV_KEY_INFO_free(p8info); - } + if (!ctx->cipher_intent) + return 0; + + if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters, + &str, &strtype)) + return 0; + + p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + if (p8 != NULL) + ret = PEM_write_bio_PKCS8(out, p8); + + X509_SIG_free(p8); return ret; } -static int key_to_pkcs8_pem_priv_bio(BIO *out, const void *key, - int key_nid, - ossl_unused const char *pemname, - key_to_paramstring_fn *p2s, - i2d_of_void *k2d, - struct key2any_ctx_st *ctx) +static int key_to_pki_der_priv_bio(BIO *out, const void *key, + int key_nid, + ossl_unused const char *pemname, + key_to_paramstring_fn *p2s, + i2d_of_void *k2d, + struct key2any_ctx_st *ctx) { int ret = 0; void *str = NULL; int strtype = V_ASN1_UNDEF; + PKCS8_PRIV_KEY_INFO *p8info; + + if (ctx->cipher_intent) + return key_to_epki_der_priv_bio(out, key, key_nid, pemname, + p2s, k2d, ctx); if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters, &str, &strtype)) return 0; - if (ctx->cipher_intent) { - X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + p8info = key_to_p8info(key, key_nid, str, strtype, k2d); - if (p8 != NULL) - ret = PEM_write_bio_PKCS8(out, p8); + if (p8info != NULL) + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info); + else + free_asn1_data(strtype, str); - X509_SIG_free(p8); - } else { - PKCS8_PRIV_KEY_INFO *p8info = - key_to_p8info(key, key_nid, str, strtype, k2d); + PKCS8_PRIV_KEY_INFO_free(p8info); - if (p8info != NULL) - ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info); - else - free_asn1_data(strtype, str); + return ret; +} - PKCS8_PRIV_KEY_INFO_free(p8info); - } +static int key_to_pki_pem_priv_bio(BIO *out, const void *key, + int key_nid, + ossl_unused const char *pemname, + key_to_paramstring_fn *p2s, + i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + PKCS8_PRIV_KEY_INFO *p8info; + + if (ctx->cipher_intent) + return key_to_epki_pem_priv_bio(out, key, key_nid, pemname, + p2s, k2d, ctx); + + if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters, + &str, &strtype)) + return 0; + + p8info = key_to_p8info(key, key_nid, str, strtype, k2d); + + if (p8info != NULL) + ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info); + else + free_asn1_data(strtype, str); + + PKCS8_PRIV_KEY_INFO_free(p8info); return ret; } @@ -427,7 +489,7 @@ static int dh_spki_pub_to_der(const void *dh, unsigned char **pder) return ret; } -static int dh_pkcs8_priv_to_der(const void *dh, unsigned char **pder) +static int dh_pki_priv_to_der(const void *dh, unsigned char **pder) { const BIGNUM *bn = NULL; ASN1_INTEGER *priv_key = NULL; @@ -540,7 +602,7 @@ static int dsa_spki_pub_to_der(const void *dsa, unsigned char **pder) return ret; } -static int dsa_pkcs8_priv_to_der(const void *dsa, unsigned char **pder) +static int dsa_pki_priv_to_der(const void *dsa, unsigned char **pder) { const BIGNUM *bn = NULL; ASN1_INTEGER *priv_key = NULL; @@ -639,7 +701,7 @@ static int ec_spki_pub_to_der(const void *eckey, unsigned char **pder) return i2o_ECPublicKey(eckey, pder); } -static int ec_pkcs8_priv_to_der(const void *veckey, unsigned char **pder) +static int ec_pki_priv_to_der(const void *veckey, unsigned char **pder) { EC_KEY *eckey = (EC_KEY *)veckey; unsigned int old_flags; @@ -700,7 +762,7 @@ static int ecx_spki_pub_to_der(const void *vecxkey, unsigned char **pder) return ecxkey->keylen; } -static int ecx_pkcs8_priv_to_der(const void *vecxkey, unsigned char **pder) +static int ecx_pki_priv_to_der(const void *vecxkey, unsigned char **pder) { const ECX_KEY *ecxkey = vecxkey; ASN1_OCTET_STRING oct; @@ -826,7 +888,7 @@ static int prepare_rsa_params(const void *rsa, int nid, int save, * RSA is extremely simple, as PKCS#1 is used for the PKCS#8 |privateKey| * field as well as the SubjectPublicKeyInfo |subjectPublicKey| field. */ -#define rsa_pkcs8_priv_to_der rsa_type_specific_priv_to_der +#define rsa_pki_priv_to_der rsa_type_specific_priv_to_der #define rsa_spki_pub_to_der rsa_type_specific_pub_to_der #define rsa_type_specific_priv_to_der (i2d_of_void *)i2d_RSAPrivateKey #define rsa_type_specific_pub_to_der (i2d_of_void *)i2d_RSAPublicKey @@ -1041,10 +1103,18 @@ static int key2any_encode(struct key2any_ctx_st *ctx, OSSL_CORE_BIO *cout, * the same. */ -/* PKCS#8 is a structure for private keys only */ -#define DO_PKCS8_selection_mask DO_PRIVATE_KEY_selection_mask -#define DO_PKCS8(impl, type, output) \ - DO_PRIVATE_KEY(impl, type, pkcs8, output) +/* + * PKCS#8 defines two structures for private keys only: + * - PrivateKeyInfo (raw unencrypted form) + * - EncryptedPrivateKeyInfo (encrypted wrapping) + * + * To allow a certain amount of flexibility, we allow the routines + * for PrivateKeyInfo to also produce EncryptedPrivateKeyInfo if a + * passphrase callback has been passed to them. + */ +#define DO_PrivateKeyInfo_selection_mask DO_PRIVATE_KEY_selection_mask +#define DO_PrivateKeyInfo(impl, type, output) \ + DO_PRIVATE_KEY(impl, type, pki, output) /* SubjectPublicKeyInfo is a structure for public keys only */ #define DO_SubjectPublicKeyInfo_selection_mask DO_PUBLIC_KEY_selection_mask @@ -1258,55 +1328,55 @@ MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, type_specific_no_pub, pem); * For PEM, these are expected to be used by PEM_write_bio_PrivateKey(), * PEM_write_bio_PUBKEY() and PEM_write_bio_Parameters(). */ -MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS8, der); -MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS8, pem); +MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, der); +MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, pem); MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, der); MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, pem); -MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS8, der); -MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS8, pem); +MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, der); +MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, pem); MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, der); MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, pem); #ifndef OPENSSL_NO_DH -MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS8, der); -MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS8, pem); +MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, der); +MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, pem); MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, der); MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, pem); -MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PKCS8, der); -MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PKCS8, pem); +MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, der); +MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, pem); MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, der); MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, pem); #endif #ifndef OPENSSL_NO_DSA -MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PKCS8, der); -MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PKCS8, pem); +MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, der); +MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, pem); MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, der); MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, pem); #endif #ifndef OPENSSL_NO_EC -MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PKCS8, der); -MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PKCS8, pem); +MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, der); +MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, pem); MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der); MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem); # ifndef OPENSSL_NO_SM2 -MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PKCS8, der); -MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PKCS8, pem); +MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, der); +MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, pem); MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der); MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem); # endif -MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PKCS8, der); -MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PKCS8, pem); +MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, der); +MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, pem); MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, der); MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, pem); -MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PKCS8, der); -MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PKCS8, pem); +MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der); +MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem); MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der); MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem); -MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PKCS8, der); -MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PKCS8, pem); +MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, der); +MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, pem); MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, der); MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, pem); -MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PKCS8, der); -MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PKCS8, pem); +MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der); +MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem); MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der); MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem); #endif diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index ae09ccd506..7b59e7308d 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -323,8 +323,8 @@ extern const OSSL_DISPATCH ossl_rsa_asym_kem_functions[]; /* Encoders */ extern const OSSL_DISPATCH ossl_rsa_to_PKCS1_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsa_to_PKCS1_pem_encoder_functions[]; -extern const OSSL_DISPATCH ossl_rsa_to_PKCS8_der_encoder_functions[]; -extern const OSSL_DISPATCH ossl_rsa_to_PKCS8_pem_encoder_functions[]; +extern const OSSL_DISPATCH ossl_rsa_to_PrivateKeyInfo_der_encoder_functions[]; +extern const OSSL_DISPATCH ossl_rsa_to_PrivateKeyInfo_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsa_to_RSA_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsa_to_RSA_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsa_to_SubjectPublicKeyInfo_der_encoder_functions[]; @@ -337,8 +337,8 @@ extern const OSSL_DISPATCH ossl_rsa_to_type_specific_keypair_pem_encoder_functio extern const OSSL_DISPATCH ossl_rsapss_to_PKCS1_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsapss_to_PKCS1_pem_encoder_functions[]; -extern const OSSL_DISPATCH ossl_rsapss_to_PKCS8_der_encoder_functions[]; -extern const OSSL_DISPATCH ossl_rsapss_to_PKCS8_pem_encoder_functions[]; +extern const OSSL_DISPATCH ossl_rsapss_to_PrivateKeyInfo_der_encoder_functions[]; +extern const OSSL_DISPATCH ossl_rsapss_to_PrivateKeyInfo_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsapss_to_SubjectPublicKeyInfo_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsapss_to_SubjectPublicKeyInfo_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_rsapss_to_text_encoder_functions[]; @@ -347,8 +347,8 @@ extern const OSSL_DISPATCH ossl_dh_to_DH_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_DH_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_PKCS3_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_PKCS3_pem_encoder_functions[]; -extern const OSSL_DISPATCH ossl_dh_to_PKCS8_der_encoder_functions[]; -extern const OSSL_DISPATCH ossl_dh_to_PKCS8_pem_encoder_functions[]; +extern const OSSL_DISPATCH ossl_dh_to_PrivateKeyInfo_der_encoder_functions[]; +extern const OSSL_DISPATCH ossl_dh_to_PrivateKeyInfo_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_SubjectPublicKeyInfo_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_SubjectPublicKeyInfo_pem_encoder_functions[]; extern const OSSL_DISPATCH ossl_dh_to_type_specific_params_der_encoder_functions[]; @@ -357,8 +357,8 @@ extern const OSSL_DISPATCH ossl_dh_to_text_encoder_functions[]; extern const OSSL_DISPATCH ossl_dhx_to_DHX_der_encoder_functions[]; extern const OSSL_DISPATCH ossl_dhx_to_DHX_pem_encoder_functions[]; -extern const OSSL_DISPATCH ossl_dhx_to_PKCS8_der_encoder_functions[]; -extern const OSSL_DISPATCH ossl_dhx_to_PKCS8_pem_encoder_functions[]; +extern const OSSL_DISPATCH ossl_dhx_to_PrivateKeyInfo_der_encoder_functions[]; +extern const OSSL_DISPATCH ossl_dhx_to_PrivateKeyInfo_pem_encoder_functions[]; |