Commit 54dbf423 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

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: default avatarRich Salz <rsalz@openssl.org>
parent 1e613922
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
+3 −41
Original line number Diff line number Diff line
@@ -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);
+24 −40
Original line number Diff line number Diff line
@@ -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)
    if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
        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;
        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;
        *pk = ASN1_STRING_data(p8->pkey);
        *ppklen = ASN1_STRING_length(p8->pkey);
    }
    } 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 (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;
}
+1 −2
Original line number Diff line number Diff line
@@ -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"},
+9 −37
Original line number Diff line number Diff line
@@ -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)
Loading