Make PKCS8_PRIV_KEY_INFO opaque.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 4 Mar 2016 03:48:39 +0000 (03:48 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 7 Mar 2016 17:11:21 +0000 (17:11 +0000)
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 <rsalz@openssl.org>
apps/pkcs12.c
apps/pkcs8.c
crypto/asn1/p8_pkey.c
crypto/evp/evp_err.c
crypto/evp/evp_pkey.c
crypto/include/internal/x509_int.h
crypto/pkcs12/p12_attr.c
crypto/pkcs12/p12_sbag.c
include/openssl/evp.h
include/openssl/x509.h

index b4aabb2b8610528e9d446229702acf2e78a730b7..5ed2122da6aeead020b8e116d0aba49f46a6d565 100644 (file)
@@ -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);
index 0968fef9468ffed6d9d4fecf323da69206c87ab6..8a4d5423d1f957c4d5ee2b9a9221d48225da72d1 100644 (file)
@@ -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);
index 59f1cd167a687712b7e11b8c0beb4cb09c4b247c..1e062a9ee9ae2a1bd31204c8aa101d0a84e190b3 100644 (file)
@@ -60,6 +60,7 @@
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
+#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;
+}
index add74cadd3c01dd9e885ac27b272e72f11dfc8ad..3b77e3b864f4649d40ce2abc222c6b41dacff368 100644 (file)
@@ -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"},
index 530f724033ea89fa10134e2f752e98e837d6ad08..a44d972925ce57dd51695e3ef9dc85ee94988475 100644 (file)
@@ -63,6 +63,7 @@
 #include <openssl/rand.h>
 #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)
index fa51d351d79467a4644fddc6e9d87f631483bc65..e6e7ed141a52c83c21ec49b997749ddada5fe2c6 100644 (file)
@@ -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;
+};
index fba35cd63b8911690fb2b70f53fc03a02aa9a6fc..994f3868d01dba166d7cb2b0427eab1433c183ff 100644 (file)
@@ -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 */
index 57e2bf43df9df53cfc1f9dc51d1fed96fcf9f8b1..ffdf22ded2ea8544a2b9243e4515fbed2302dc65 100644 (file)
@@ -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)
index 1b26bb1f9b2bf209c3229d473c3c8b29f9c67a6c..aef43f411b6bc6ac285287c4901ef105ac4e2667 100644 (file)
@@ -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
index 06fc99ef3039b9f61eae889bdbcffdcf5ee5c598..c5f4ecc5b52f44a2210ab24a46826a0aee156740 100644 (file)
@@ -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);