From 54dbf42398e23349b59f258a3dd60387bbc5ba13 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 4 Mar 2016 03:48:39 +0000 Subject: [PATCH] Make PKCS8_PRIV_KEY_INFO opaque. Make PKCS8_PRIV_KEY_INFO opaque. Several accessor functions already exist for this structure. Two new ones were added to handle attributes. The old handling of broken formats has been removed and the corresponding structures simplified. Reviewed-by: Rich Salz --- apps/pkcs12.c | 4 +- apps/pkcs8.c | 44 ++------------------ crypto/asn1/p8_pkey.c | 64 +++++++++++------------------- crypto/evp/evp_err.c | 3 +- crypto/evp/evp_pkey.c | 46 +++++---------------- crypto/include/internal/x509_int.h | 9 +++++ crypto/pkcs12/p12_attr.c | 10 ++--- crypto/pkcs12/p12_sbag.c | 2 +- include/openssl/evp.h | 3 +- include/openssl/x509.h | 23 ++--------- 10 files changed, 57 insertions(+), 151 deletions(-) diff --git a/apps/pkcs12.c b/apps/pkcs12.c index b4aabb2b86..5ed2122da6 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -660,7 +660,7 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, p8 = PKCS12_SAFEBAG_get0_p8inf(bag); if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) return 0; - print_attribs(out, p8->attributes, "Key Attributes"); + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); EVP_PKEY_free(pkey); break; @@ -682,7 +682,7 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, PKCS8_PRIV_KEY_INFO_free(p8); return 0; } - print_attribs(out, p8->attributes, "Key Attributes"); + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); PKCS8_PRIV_KEY_INFO_free(p8); PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); EVP_PKEY_free(pkey); diff --git a/apps/pkcs8.c b/apps/pkcs8.c index 0968fef946..8a4d5423d1 100644 --- a/apps/pkcs8.c +++ b/apps/pkcs8.c @@ -67,7 +67,7 @@ typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, - OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, OPT_NOOCT, OPT_NSDB, OPT_EMBED, + OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, #ifndef OPENSSL_NO_SCRYPT OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P, #endif @@ -83,10 +83,6 @@ OPTIONS pkcs8_options[] = { {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, - {"nooct", OPT_NOOCT, '-', "Use (nonstandard) no octet format"}, - {"nsdb", OPT_NSDB, '-', "Use (nonstandard) DSA Netscape DB format"}, - {"embed", OPT_EMBED, '-', - "Use (nonstandard) embedded DSA parameters format"}, {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"}, {"v2prf", OPT_V2PRF, 's'}, @@ -117,7 +113,7 @@ int pkcs8_main(int argc, char **argv) char *passinarg = NULL, *passoutarg = NULL, *prog; char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; OPTION_CHOICE o; - int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER, p8_broken = PKCS8_OK; + int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER; int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; int private = 0; #ifndef OPENSSL_NO_SCRYPT @@ -159,15 +155,6 @@ int pkcs8_main(int argc, char **argv) case OPT_NOCRYPT: nocrypt = 1; break; - case OPT_NOOCT: - p8_broken = PKCS8_NO_OCTET; - break; - case OPT_NSDB: - p8_broken = PKCS8_NS_DB; - break; - case OPT_EMBED: - p8_broken = PKCS8_EMBEDDED_PARAM; - break; case OPT_V2: if (!opt_cipher(opt_arg(), &cipher)) goto opthelp; @@ -249,7 +236,7 @@ int pkcs8_main(int argc, char **argv) pkey = load_key(infile, informat, 1, passin, e, "key"); if (!pkey) goto end; - if ((p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken)) == NULL) { + if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) { BIO_printf(bio_err, "Error converting key\n"); ERR_print_errors(bio_err); goto end; @@ -362,31 +349,6 @@ int pkcs8_main(int argc, char **argv) goto end; } - if (p8inf->broken) { - BIO_printf(bio_err, "Warning: broken key encoding: "); - switch (p8inf->broken) { - case PKCS8_NO_OCTET: - BIO_printf(bio_err, "No Octet String in PrivateKey\n"); - break; - - case PKCS8_EMBEDDED_PARAM: - BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); - break; - - case PKCS8_NS_DB: - BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); - break; - - case PKCS8_NEG_PRIVKEY: - BIO_printf(bio_err, "DSA private key value is negative\n"); - break; - - default: - BIO_printf(bio_err, "Unknown broken type\n"); - break; - } - } - assert(private); if (outformat == FORMAT_PEM) PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c index 59f1cd167a..1e062a9ee9 100644 --- a/crypto/asn1/p8_pkey.c +++ b/crypto/asn1/p8_pkey.c @@ -60,6 +60,7 @@ #include "internal/cryptlib.h" #include #include +#include "internal/x509_int.h" /* Minor tweak to operation: zero private key data */ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, @@ -68,10 +69,8 @@ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ if (operation == ASN1_OP_FREE_PRE) { PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; - if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING - && key->pkey->value.octet_string != NULL) - OPENSSL_cleanse(key->pkey->value.octet_string->data, - key->pkey->value.octet_string->length); + if (key->pkey) + OPENSSL_cleanse(key->pkey->data, key->pkey->length); } return 1; } @@ -79,7 +78,7 @@ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), - ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING), ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) } ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) @@ -89,32 +88,14 @@ int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version, int ptype, void *pval, unsigned char *penc, int penclen) { - unsigned char **ppenc = NULL; if (version >= 0) { if (!ASN1_INTEGER_set(priv->version, version)) return 0; } - if (penc) { - int pmtype; - ASN1_OCTET_STRING *oct; - oct = ASN1_OCTET_STRING_new(); - if (oct == NULL) - return 0; - oct->data = penc; - ppenc = &oct->data; - oct->length = penclen; - if (priv->broken == PKCS8_NO_OCTET) - pmtype = V_ASN1_SEQUENCE; - else - pmtype = V_ASN1_OCTET_STRING; - ASN1_TYPE_set(priv->pkey, pmtype, oct); - } - if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) { - /* If call fails do not swallow 'enc' */ - if (ppenc) - *ppenc = NULL; + if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) return 0; - } + if (penc) + ASN1_STRING_set0(priv->pkey, penc, penclen); return 1; } @@ -124,21 +105,24 @@ int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, { if (ppkalg) *ppkalg = p8->pkeyalg->algorithm; - if (p8->pkey->type == V_ASN1_OCTET_STRING) { - p8->broken = PKCS8_OK; - if (pk) { - *pk = p8->pkey->value.octet_string->data; - *ppklen = p8->pkey->value.octet_string->length; - } - } else if (p8->pkey->type == V_ASN1_SEQUENCE) { - p8->broken = PKCS8_NO_OCTET; - if (pk) { - *pk = p8->pkey->value.sequence->data; - *ppklen = p8->pkey->value.sequence->length; - } - } else - return 0; + if (pk) { + *pk = ASN1_STRING_data(p8->pkey); + *ppklen = ASN1_STRING_length(p8->pkey); + } if (pa) *pa = p8->pkeyalg; return 1; } + +STACK_OF(X509_ATTRIBUTE) *PKCS8_pkey_get0_attrs(PKCS8_PRIV_KEY_INFO *p8) +{ + return p8->attributes; +} + +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL) + return 1; + return 0; +} diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index add74cadd3..3b77e3b864 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -102,8 +102,7 @@ static ERR_STRING_DATA EVP_str_functs[] = { {ERR_FUNC(EVP_F_EVP_PBE_CIPHERINIT), "EVP_PBE_CipherInit"}, {ERR_FUNC(EVP_F_EVP_PBE_SCRYPT), "EVP_PBE_scrypt"}, {ERR_FUNC(EVP_F_EVP_PKCS82PKEY), "EVP_PKCS82PKEY"}, - {ERR_FUNC(EVP_F_EVP_PKCS82PKEY_BROKEN), "EVP_PKCS82PKEY_BROKEN"}, - {ERR_FUNC(EVP_F_EVP_PKEY2PKCS8_BROKEN), "EVP_PKEY2PKCS8_broken"}, + {ERR_FUNC(EVP_F_EVP_PKEY2PKCS8), "EVP_PKEY2PKCS8"}, {ERR_FUNC(EVP_F_EVP_PKEY_COPY_PARAMETERS), "EVP_PKEY_copy_parameters"}, {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL), "EVP_PKEY_CTX_ctrl"}, {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL_STR), "EVP_PKEY_CTX_ctrl_str"}, diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index 530f724033..a44d972925 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -63,6 +63,7 @@ #include #include "internal/asn1_int.h" #include "internal/evp_int.h" +#include "internal/x509_int.h" /* Extract a private key from a PKCS8 structure */ @@ -104,66 +105,37 @@ EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) return NULL; } -PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) -{ - return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK); -} - /* Turn a private key into a PKCS8 structure */ -PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken) +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) { - PKCS8_PRIV_KEY_INFO *p8; - - if ((p8 = PKCS8_PRIV_KEY_INFO_new()) == NULL) { - EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO *p8 = PKCS8_PRIV_KEY_INFO_new(); + if (p8 == NULL) { + EVPerr(EVP_F_EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); return NULL; } - p8->broken = broken; if (pkey->ameth) { if (pkey->ameth->priv_encode) { if (!pkey->ameth->priv_encode(p8, pkey)) { - EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, - EVP_R_PRIVATE_KEY_ENCODE_ERROR); + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_PRIVATE_KEY_ENCODE_ERROR); goto error; } } else { - EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, EVP_R_METHOD_NOT_SUPPORTED); + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_METHOD_NOT_SUPPORTED); goto error; } } else { - EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, - EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); goto error; } - RAND_add(p8->pkey->value.octet_string->data, - p8->pkey->value.octet_string->length, 0.0); + RAND_add(p8->pkey->data, p8->pkey->length, 0.0); return p8; error: PKCS8_PRIV_KEY_INFO_free(p8); return NULL; } -PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) -{ - switch (broken) { - - case PKCS8_OK: - p8->broken = PKCS8_OK; - return p8; - - case PKCS8_NO_OCTET: - p8->broken = PKCS8_NO_OCTET; - p8->pkey->type = V_ASN1_SEQUENCE; - return p8; - - default: - EVPerr(EVP_F_PKCS8_SET_BROKEN, EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); - return NULL; - } -} - /* EVP_PKEY attribute functions */ int EVP_PKEY_get_attr_count(const EVP_PKEY *key) diff --git a/crypto/include/internal/x509_int.h b/crypto/include/internal/x509_int.h index fa51d351d7..e6e7ed141a 100644 --- a/crypto/include/internal/x509_int.h +++ b/crypto/include/internal/x509_int.h @@ -213,3 +213,12 @@ struct x509_st { unsigned char sha1_hash[SHA_DIGEST_LENGTH]; X509_CERT_AUX *aux; } /* X509 */ ; + +/* PKCS#8 private key info structure */ + +struct pkcs8_priv_key_info_st { + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_OCTET_STRING *pkey; + STACK_OF(X509_ATTRIBUTE) *attributes; +}; diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c index fba35cd63b..994f3868d0 100644 --- a/crypto/pkcs12/p12_attr.c +++ b/crypto/pkcs12/p12_attr.c @@ -77,13 +77,9 @@ int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage) { - unsigned char us_val; - us_val = (unsigned char)usage; - if (X509at_add1_attr_by_NID(&p8->attributes, NID_key_usage, - V_ASN1_BIT_STRING, &us_val, 1)) - return 1; - else - return 0; + unsigned char us_val = (unsigned char)usage; + return PKCS8_pkey_add1_attr_by_NID(p8, NID_key_usage, + V_ASN1_BIT_STRING, &us_val, 1); } /* Add a friendlyname to a safebag */ diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c index 57e2bf43df..ffdf22ded2 100644 --- a/crypto/pkcs12/p12_sbag.c +++ b/crypto/pkcs12/p12_sbag.c @@ -69,7 +69,7 @@ ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(PKCS12_SAFEBAG *bag, int attr_nid) ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid) { - return PKCS12_get_attr_gen(p8->attributes, attr_nid); + return PKCS12_get_attr_gen(PKCS8_pkey_get0_attrs(p8), attr_nid); } PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(PKCS12_SAFEBAG *bag) diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 1b26bb1f9b..aef43f411b 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1508,8 +1508,7 @@ void ERR_load_EVP_strings(void); # define EVP_F_EVP_PBE_CIPHERINIT 116 # define EVP_F_EVP_PBE_SCRYPT 181 # define EVP_F_EVP_PKCS82PKEY 111 -# define EVP_F_EVP_PKCS82PKEY_BROKEN 136 -# define EVP_F_EVP_PKEY2PKCS8_BROKEN 113 +# define EVP_F_EVP_PKEY2PKCS8 113 # define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 # define EVP_F_EVP_PKEY_CTX_CTRL 137 # define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 06fc99ef30..c5f4ecc5b5 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -376,23 +376,6 @@ typedef struct PBKDF2PARAM_st { X509_ALGOR *prf; } PBKDF2PARAM; -/* PKCS#8 private key info structure */ - -struct pkcs8_priv_key_info_st { - /* Flag for various broken formats */ - int broken; -# define PKCS8_OK 0 -# define PKCS8_NO_OCTET 1 -# define PKCS8_EMBEDDED_PARAM 2 -# define PKCS8_NS_DB 3 -# define PKCS8_NEG_PRIVKEY 4 - ASN1_INTEGER *version; - X509_ALGOR *pkeyalg; - /* Should be OCTET STRING but some are broken */ - ASN1_TYPE *pkey; - STACK_OF(X509_ATTRIBUTE) *attributes; -}; - #ifdef __cplusplus } #endif @@ -1040,8 +1023,6 @@ DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); -PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken); -PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version, int ptype, void *pval, @@ -1050,6 +1031,10 @@ int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8); +STACK_OF(X509_ATTRIBUTE) *PKCS8_pkey_get0_attrs(PKCS8_PRIV_KEY_INFO *p8); +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len); + int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, int ptype, void *pval, unsigned char *penc, int penclen);