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 | |
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')
-rw-r--r-- | providers/decoders.inc | 31 | ||||
-rw-r--r-- | providers/encoders.inc | 48 | ||||
-rw-r--r-- | providers/implementations/encode_decode/build.info | 2 | ||||
-rw-r--r-- | providers/implementations/encode_decode/decode_der2key.c | 89 | ||||
-rw-r--r-- | providers/implementations/encode_decode/decode_epki2pki.c | 153 | ||||
-rw-r--r-- | providers/implementations/encode_decode/decode_pem2der.c | 4 | ||||
-rw-r--r-- | providers/implementations/encode_decode/encode_key2any.c | 228 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 67 |
8 files changed, 411 insertions, 211 deletions
diff --git a/providers/decoders.inc b/providers/decoders.inc index a92abe03e2..02b2b32c3f 100644 --- a/providers/decoders.inc +++ b/providers/decoders.inc @@ -15,7 +15,8 @@ #define DECODER_STRUCTURE_type_specific_params "type-specific" #define DECODER_STRUCTURE_type_specific "type-specific" #define DECODER_STRUCTURE_type_specific_no_pub "type-specific" -#define DECODER_STRUCTURE_PKCS8 "pkcs8" +#define DECODER_STRUCTURE_EncryptedPrivateKeyInfo "EncryptedPrivateKeyInfo" +#define DECODER_STRUCTURE_PrivateKeyInfo "PrivateKeyInfo" #define DECODER_STRUCTURE_SubjectPublicKeyInfo "SubjectPublicKeyInfo" #define DECODER_STRUCTURE_DH "dh" #define DECODER_STRUCTURE_DHX "dhx" @@ -35,17 +36,17 @@ (ossl_##_structure##_##_input##_to_##_output##_decoder_functions) } #ifndef OPENSSL_NO_DH -DECODER_w_structure("DH", der, PKCS8, dh, yes), +DECODER_w_structure("DH", der, PrivateKeyInfo, dh, yes), DECODER_w_structure("DH", der, SubjectPublicKeyInfo, dh, yes), DECODER_w_structure("DH", der, type_specific_params, dh, yes), DECODER_w_structure("DH", der, DH, dh, yes), -DECODER_w_structure("DHX", der, PKCS8, dhx, yes), +DECODER_w_structure("DHX", der, PrivateKeyInfo, dhx, yes), DECODER_w_structure("DHX", der, SubjectPublicKeyInfo, dhx, yes), DECODER_w_structure("DHX", der, type_specific_params, dhx, yes), DECODER_w_structure("DHX", der, DHX, dhx, yes), #endif #ifndef OPENSSL_NO_DSA -DECODER_w_structure("DSA", der, PKCS8, dsa, yes), +DECODER_w_structure("DSA", der, PrivateKeyInfo, dsa, yes), DECODER_w_structure("DSA", der, SubjectPublicKeyInfo, dsa, yes), DECODER_w_structure("DSA", der, type_specific, dsa, yes), DECODER_w_structure("DSA", der, DSA, dsa, yes), @@ -53,30 +54,36 @@ DECODER("DSA", msblob, dsa, yes), DECODER("DSA", pvk, dsa, yes), #endif #ifndef OPENSSL_NO_EC -DECODER_w_structure("EC", der, PKCS8, ec, yes), +DECODER_w_structure("EC", der, PrivateKeyInfo, ec, yes), DECODER_w_structure("EC", der, SubjectPublicKeyInfo, ec, yes), DECODER_w_structure("EC", der, type_specific_no_pub, ec, yes), DECODER_w_structure("EC", der, EC, ec, yes), -DECODER_w_structure("ED25519", der, PKCS8, ed25519, yes), +DECODER_w_structure("ED25519", der, PrivateKeyInfo, ed25519, yes), DECODER_w_structure("ED25519", der, SubjectPublicKeyInfo, ed25519, yes), -DECODER_w_structure("ED448", der, PKCS8, ed448, yes), +DECODER_w_structure("ED448", der, PrivateKeyInfo, ed448, yes), DECODER_w_structure("ED448", der, SubjectPublicKeyInfo, ed448, yes), -DECODER_w_structure("X25519", der, PKCS8, x25519, yes), +DECODER_w_structure("X25519", der, PrivateKeyInfo, x25519, yes), DECODER_w_structure("X25519", der, SubjectPublicKeyInfo, x25519, yes), -DECODER_w_structure("X448", der, PKCS8, x448, yes), +DECODER_w_structure("X448", der, PrivateKeyInfo, x448, yes), DECODER_w_structure("X448", der, SubjectPublicKeyInfo, x448, yes), # ifndef OPENSSL_NO_SM2 -DECODER_w_structure("SM2", der, PKCS8, sm2, yes), +DECODER_w_structure("SM2", der, PrivateKeyInfo, sm2, yes), DECODER_w_structure("SM2", der, SubjectPublicKeyInfo, sm2, yes), # endif #endif -DECODER_w_structure("RSA", der, PKCS8, rsa, yes), +DECODER_w_structure("RSA", der, PrivateKeyInfo, rsa, yes), DECODER_w_structure("RSA", der, SubjectPublicKeyInfo, rsa, yes), DECODER_w_structure("RSA", der, type_specific_keypair, rsa, yes), DECODER_w_structure("RSA", der, RSA, rsa, yes), -DECODER_w_structure("RSA-PSS", der, PKCS8, rsapss, yes), +DECODER_w_structure("RSA-PSS", der, PrivateKeyInfo, rsapss, yes), DECODER_w_structure("RSA-PSS", der, SubjectPublicKeyInfo, rsapss, yes), DECODER("RSA", msblob, rsa, yes), DECODER("RSA", pvk, rsa, yes), DECODER("DER", pem, der, yes), +/* + * A decoder that recognises PKCS#8 EncryptedPrivateKeyInfo structure + * and decrypts it, passing on the unencrypted PrivateKeyInfo in DER + * form to the next decoder. + */ +DECODER_w_structure("DER", der, EncryptedPrivateKeyInfo, der, yes), diff --git a/providers/encoders.inc b/providers/encoders.inc index 71f4f13848..a1034f45de 100644 --- a/providers/encoders.inc +++ b/providers/encoders.inc @@ -15,7 +15,7 @@ #define ENCODER_STRUCTURE_type_specific_params "type-specific" #define ENCODER_STRUCTURE_type_specific "type-specific" #define ENCODER_STRUCTURE_type_specific_no_pub "type-specific" -#define ENCODER_STRUCTURE_PKCS8 "pkcs8" +#define ENCODER_STRUCTURE_PrivateKeyInfo "PrivateKeyInfo" #define ENCODER_STRUCTURE_SubjectPublicKeyInfo "SubjectPublicKeyInfo" #define ENCODER_STRUCTURE_DH "dh" #define ENCODER_STRUCTURE_DHX "dhx" @@ -127,70 +127,70 @@ ENCODER("DSA", dsa, yes, pvk), #endif /* - * Entries for PKCS#8 and SubjectPublicKeyInfo. + * Entries for PKCS#8 (PrivateKeyInfo) and SubjectPublicKeyInfo. * The "der" ones are added convenience for any user that wants to use * OSSL_ENCODER directly. * The "pem" ones also support PEM_write_bio_PrivateKey() and * PEM_write_bio_PUBKEY(). */ -ENCODER_w_structure("RSA", rsa, yes, der, PKCS8), -ENCODER_w_structure("RSA", rsa, yes, pem, PKCS8), +ENCODER_w_structure("RSA", rsa, yes, der, PrivateKeyInfo), +ENCODER_w_structure("RSA", rsa, yes, pem, PrivateKeyInfo), ENCODER_w_structure("RSA", rsa, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("RSA", rsa, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("RSA-PSS", rsapss, yes, der, PKCS8), -ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, PKCS8), +ENCODER_w_structure("RSA-PSS", rsapss, yes, der, PrivateKeyInfo), +ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, PrivateKeyInfo), ENCODER_w_structure("RSA-PSS", rsapss, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("RSA-PSS", rsapss, yes, pem, SubjectPublicKeyInfo), #ifndef OPENSSL_NO_DH -ENCODER_w_structure("DH", dh, yes, der, PKCS8), -ENCODER_w_structure("DH", dh, yes, pem, PKCS8), +ENCODER_w_structure("DH", dh, yes, der, PrivateKeyInfo), +ENCODER_w_structure("DH", dh, yes, pem, PrivateKeyInfo), ENCODER_w_structure("DH", dh, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("DH", dh, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("DHX", dhx, yes, der, PKCS8), -ENCODER_w_structure("DHX", dhx, yes, pem, PKCS8), +ENCODER_w_structure("DHX", dhx, yes, der, PrivateKeyInfo), +ENCODER_w_structure("DHX", dhx, yes, pem, PrivateKeyInfo), ENCODER_w_structure("DHX", dhx, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("DHX", dhx, yes, pem, SubjectPublicKeyInfo), #endif #ifndef OPENSSL_NO_DSA -ENCODER_w_structure("DSA", dsa, yes, der, PKCS8), -ENCODER_w_structure("DSA", dsa, yes, pem, PKCS8), +ENCODER_w_structure("DSA", dsa, yes, der, PrivateKeyInfo), +ENCODER_w_structure("DSA", dsa, yes, pem, PrivateKeyInfo), ENCODER_w_structure("DSA", dsa, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("DSA", dsa, yes, pem, SubjectPublicKeyInfo), #endif #ifndef OPENSSL_NO_EC -ENCODER_w_structure("EC", ec, yes, der, PKCS8), -ENCODER_w_structure("EC", ec, yes, pem, PKCS8), +ENCODER_w_structure("EC", ec, yes, der, PrivateKeyInfo), +ENCODER_w_structure("EC", ec, yes, pem, PrivateKeyInfo), ENCODER_w_structure("EC", ec, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("EC", ec, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("X25519", x25519, yes, der, PKCS8), -ENCODER_w_structure("X25519", x25519, yes, pem, PKCS8), +ENCODER_w_structure("X25519", x25519, yes, der, PrivateKeyInfo), +ENCODER_w_structure("X25519", x25519, yes, pem, PrivateKeyInfo), ENCODER_w_structure("X25519", x25519, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("X25519", x25519, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("X448", x448, yes, der, PKCS8), -ENCODER_w_structure("X448", x448, yes, pem, PKCS8), +ENCODER_w_structure("X448", x448, yes, der, PrivateKeyInfo), +ENCODER_w_structure("X448", x448, yes, pem, PrivateKeyInfo), ENCODER_w_structure("X448", x448, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("X448", x448, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("ED25519", ed25519, yes, der, PKCS8), -ENCODER_w_structure("ED25519", ed25519, yes, pem, PKCS8), +ENCODER_w_structure("ED25519", ed25519, yes, der, PrivateKeyInfo), +ENCODER_w_structure("ED25519", ed25519, yes, pem, PrivateKeyInfo), ENCODER_w_structure("ED25519", ed25519, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("ED25519", ed25519, yes, pem, SubjectPublicKeyInfo), -ENCODER_w_structure("ED448", ed448, yes, der, PKCS8), -ENCODER_w_structure("ED448", ed448, yes, pem, PKCS8), +ENCODER_w_structure("ED448", ed448, yes, der, PrivateKeyInfo), +ENCODER_w_structure("ED448", ed448, yes, pem, PrivateKeyInfo), ENCODER_w_structure("ED448", ed448, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("ED448", ed448, yes, pem, SubjectPublicKeyInfo), # ifndef OPENSSL_NO_SM2 -ENCODER_w_structure("SM2", sm2, yes, der, PKCS8), -ENCODER_w_structure("SM2", sm2, yes, pem, PKCS8), +ENCODER_w_structure("SM2", sm2, yes, der, PrivateKeyInfo), +ENCODER_w_structure("SM2", sm2, yes, pem, PrivateKeyInfo), ENCODER_w_structure("SM2", sm2, yes, der, SubjectPublicKeyInfo), ENCODER_w_structure("SM2", sm2, yes, pem, SubjectPublicKeyInfo), # endif 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_d |