Allow PKCS12 export to set arbitrary bag attributes

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19025)
This commit is contained in:
Graham Woodward 2022-08-19 08:46:47 +01:00 committed by Matt Caswell
parent ecc920b327
commit e869c867c1
27 changed files with 500 additions and 24 deletions

View File

@ -24,6 +24,14 @@ OpenSSL 3.1
### Changes between 3.0 and 3.1 [xx XXX xxxx]
* Add the ability to add custom attributes to PKCS12 files. Add a new API
PKCS12_create_ex2, identical to the existing PKCS12_create_ex but allows
for a user specified callback and optional argument.
Added a new PKCS12_SAFEBAG_set0_attr, which allows for a new attr to be
added to the existing STACK_OF attrs.
*Graham Woodward*
* Major refactor of the libssl record layer
*Matt Caswell*

View File

@ -388,3 +388,10 @@ oldcert = $insta::certout # insta.cert.pem
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem
[pkcs12]
certBagAttr = cb_attr
# Uncomment this if you need Java compatible PKCS12 files
[cb_attr]
#jdkTrustedKeyUsage = anyExtendedKeyUsage

View File

@ -388,3 +388,10 @@ oldcert = $insta::certout # insta.cert.pem
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem
[pkcs12]
certBagAttr = cb_attr
# Uncomment this if you need Java compatible PKCS12 files
[cb_attr]
#jdkTrustedKeyUsage = anyExtendedKeyUsage

View File

@ -14,6 +14,8 @@
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/conf.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/pem.h>
@ -54,6 +56,7 @@ void hex_prin(BIO *out, unsigned char *buf, int len);
static int alg_print(const X509_ALGOR *alg);
int cert_load(BIO *in, STACK_OF(X509) *sk);
static int set_pbe(int *ppbe, const char *str);
static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg);
typedef enum OPTION_choice {
OPT_COMMON,
@ -525,6 +528,11 @@ int pkcs12_main(int argc, char **argv)
EVP_MD *macmd = NULL;
unsigned char *catmp = NULL;
int i;
CONF *conf = NULL;
ASN1_OBJECT *obj = NULL;
STACK_OF(CONF_VALUE) *cb_sk = NULL;
const char *cb_attr = NULL;
const CONF_VALUE *val = NULL;
if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n");
@ -669,9 +677,30 @@ int pkcs12_main(int argc, char **argv)
if (!twopass)
OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
key_pbe, cert_pbe, iter, -1, keytype,
app_get0_libctx(), app_get0_propq());
/* Load the config file */
if ((conf = app_load_config(default_config_file)) == NULL)
goto export_end;
if (!app_load_modules(conf))
goto export_end;
/* Find the cert bag section */
if ((cb_attr = NCONF_get_string(conf, "pkcs12", "certBagAttr")) != NULL) {
if ((cb_sk = NCONF_get_section(conf, cb_attr)) != NULL) {
for (i = 0; i < sk_CONF_VALUE_num(cb_sk); i++) {
val = sk_CONF_VALUE_value(cb_sk, i);
if (strcmp(val->name, "jdkTrustedKeyUsage") == 0)
obj = OBJ_txt2obj(val->value, 0);
}
} else {
ERR_clear_error();
}
} else {
ERR_clear_error();
}
p12 = PKCS12_create_ex2(cpass, name, key, ee_cert, certs,
key_pbe, cert_pbe, iter, -1, keytype,
app_get0_libctx(), app_get0_propq(),
jdk_trust, (void*)obj);
if (p12 == NULL) {
BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
@ -708,7 +737,8 @@ int pkcs12_main(int argc, char **argv)
OSSL_STACK_OF_X509_free(certs);
OSSL_STACK_OF_X509_free(untrusted_certs);
X509_free(ee_cert);
NCONF_free(conf);
ASN1_OBJECT_free(obj);
ERR_print_errors(bio_err);
goto end;
@ -838,6 +868,31 @@ int pkcs12_main(int argc, char **argv)
return ret;
}
static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg)
{
STACK_OF(X509_ATTRIBUTE) *attrs = NULL;
X509_ATTRIBUTE *attr = NULL;
/* Nothing to do */
if (cbarg == NULL)
return 1;
/* Get the current attrs */
attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag);
/* Create a new attr for the JDK Trusted Usage and add it */
attr = X509_ATTRIBUTE_create(NID_oracle_jdk_trustedkeyusage, V_ASN1_OBJECT, (ASN1_OBJECT*)cbarg);
/* Add the new attr, if attrs is NULL, it'll be initialised */
X509at_add1_attr(&attrs, attr);
/* Set the bag attrs */
PKCS12_SAFEBAG_set0_attrs(bag, attrs);
X509_ATTRIBUTE_free(attr);
return 1;
}
int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
int passlen, int options, char *pempass,
const EVP_CIPHER *enc)
@ -1137,6 +1192,8 @@ int cert_load(BIO *in, STACK_OF(X509) *sk)
void print_attribute(BIO *out, const ASN1_TYPE *av)
{
char *value;
const char *ln;
char objbuf[80];
switch (av->type) {
case V_ASN1_BMPSTRING:
@ -1163,6 +1220,15 @@ void print_attribute(BIO *out, const ASN1_TYPE *av)
BIO_printf(out, "\n");
break;
case V_ASN1_OBJECT:
ln = OBJ_nid2ln(OBJ_obj2nid(av->value.object));
if (!ln)
ln = "";
OBJ_obj2txt(objbuf, sizeof(objbuf), av->value.object, 1);
BIO_printf(out, "%s (%s)", ln, objbuf);
BIO_printf(out, "\n");
break;
default:
BIO_printf(out, "<Unsupported tag %d>\n", av->type);
break;

View File

@ -905,6 +905,7 @@ PEM_R_UNSUPPORTED_CIPHER:113:unsupported cipher
PEM_R_UNSUPPORTED_ENCRYPTION:114:unsupported encryption
PEM_R_UNSUPPORTED_KEY_COMPONENTS:126:unsupported key components
PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE:110:unsupported public key type
PKCS12_R_CALLBACK_FAILED:115:callback failed
PKCS12_R_CANT_PACK_STRUCTURE:100:cant pack structure
PKCS12_R_CONTENT_TYPE_NOT_DATA:121:content type not data
PKCS12_R_DECODE_ERROR:101:decode error

View File

@ -10,7 +10,7 @@
*/
/* Serialized OID's */
static const unsigned char so[8326] = {
static const unsigned char so[8345] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
@ -1149,9 +1149,11 @@ static const unsigned char so[8326] = {
0x04,0x00,0x81,0x95,0x32,0x01,0x06, /* [ 8297] OBJ_signedAssertion */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x30, /* [ 8304] OBJ_id_aa_ets_archiveTimestampV2 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11,0x03,0x01, /* [ 8315] OBJ_hmacWithSM3 */
0x60,0x86,0x48,0x01,0x86,0xF9,0x66, /* [ 8325] OBJ_oracle */
0x60,0x86,0x48,0x01,0x86,0xF9,0x66,0xAD,0xCA,0x7B,0x01,0x01, /* [ 8332] OBJ_oracle_jdk_trustedkeyusage */
};
#define NUM_NID 1282
#define NUM_NID 1284
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@ -2435,9 +2437,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"signedAssertion", "signedAssertion", NID_signedAssertion, 7, &so[8297]},
{"id-aa-ets-archiveTimestampV2", "id-aa-ets-archiveTimestampV2", NID_id_aa_ets_archiveTimestampV2, 11, &so[8304]},
{"hmacWithSM3", "hmacWithSM3", NID_hmacWithSM3, 10, &so[8315]},
{"oracle-organization", "Oracle organization", NID_oracle, 7, &so[8325]},
{"oracle-jdk-trustedkeyusage", "Trusted key usage (Oracle)", NID_oracle_jdk_trustedkeyusage, 12, &so[8332]},
};
#define NUM_SN 1273
#define NUM_SN 1275
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@ -3387,6 +3391,8 @@ static const unsigned int sn_objs[NUM_SN] = {
139, /* "nsSGC" */
77, /* "nsSslServerName" */
681, /* "onBasis" */
1283, /* "oracle-jdk-trustedkeyusage" */
1282, /* "oracle-organization" */
1089, /* "organizationIdentifier" */
491, /* "organizationalStatus" */
1141, /* "oscca" */
@ -3714,7 +3720,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
#define NUM_LN 1273
#define NUM_LN 1275
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@ -3864,6 +3870,7 @@ static const unsigned int ln_objs[NUM_LN] = {
180, /* "OCSP Signing" */
1005, /* "OGRN" */
1226, /* "OGRNIP" */
1282, /* "Oracle organization" */
161, /* "PBES2" */
69, /* "PBKDF2" */
162, /* "PBMAC1" */
@ -3910,6 +3917,7 @@ static const unsigned int ln_objs[NUM_LN] = {
129, /* "TLS Web Server Authentication" */
133, /* "Time Stamping" */
375, /* "Trust Root" */
1283, /* "Trusted key usage (Oracle)" */
1034, /* "X25519" */
1035, /* "X448" */
12, /* "X509" */
@ -4991,7 +4999,7 @@ static const unsigned int ln_objs[NUM_LN] = {
125, /* "zlib compression" */
};
#define NUM_OBJ 1144
#define NUM_OBJ 1146
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
@ -5455,6 +5463,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */
508, /* OBJ_id_hex_multipart_message 1 3 6 1 7 1 1 2 */
57, /* OBJ_netscape 2 16 840 1 113730 */
1282, /* OBJ_oracle 2 16 840 1 113894 */
754, /* OBJ_camellia_128_ecb 0 3 4401 5 3 1 9 1 */
766, /* OBJ_camellia_128_ofb128 0 3 4401 5 3 1 9 3 */
757, /* OBJ_camellia_128_cfb128 0 3 4401 5 3 1 9 4 */
@ -6126,6 +6135,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
957, /* OBJ_jurisdictionCountryName 1 3 6 1 4 1 311 60 2 1 3 */
1056, /* OBJ_blake2b512 1 3 6 1 4 1 1722 12 2 1 16 */
1057, /* OBJ_blake2s256 1 3 6 1 4 1 1722 12 2 2 8 */
1283, /* OBJ_oracle_jdk_trustedkeyusage 2 16 840 1 113894 746875 1 1 */
1159, /* OBJ_dstu4145be 1 2 804 2 1 1 1 1 3 1 1 1 1 */
1160, /* OBJ_uacurve0 1 2 804 2 1 1 1 1 3 1 1 2 0 */
1161, /* OBJ_uacurve1 1 2 804 2 1 1 1 1 3 1 1 2 1 */

View File

@ -1279,3 +1279,5 @@ id_aa_ATSHashIndex_v3 1278
signedAssertion 1279
id_aa_ets_archiveTimestampV2 1280
hmacWithSM3 1281
oracle 1282
oracle_jdk_trustedkeyusage 1283

View File

@ -1789,3 +1789,9 @@ dstu4145le 2 9 : uacurve9 : DSTU curve 9
: AES-128-SIV : aes-128-siv
: AES-192-SIV : aes-192-siv
: AES-256-SIV : aes-256-siv
!Cname oracle
joint-iso-itu-t 16 840 1 113894 : oracle-organization : Oracle organization
# Jdk trustedKeyUsage attribute
oracle 746875 1 1 : oracle-jdk-trustedkeyusage : Trusted key usage (Oracle)

View File

@ -119,3 +119,11 @@ PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag)
{
return bag->attrib;
}
void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs)
{
if (bag->attrib != attrs)
sk_X509_ATTRIBUTE_free(bag->attrib);
bag->attrib = (STACK_OF(X509_ATTRIBUTE*))attrs;
}

View File

@ -14,6 +14,8 @@
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag);
static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag);
static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
{
@ -24,16 +26,17 @@ static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
return X509at_add1_attr(&bag->attrib, EVP_PKEY_get_attr(pkey, idx)) != NULL;
}
PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq)
PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq,
PKCS12_create_cb *cb, void *cbarg)
{
PKCS12 *p12 = NULL;
STACK_OF(PKCS7) *safes = NULL;
STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
PKCS12_SAFEBAG *bag = NULL;
int i;
int i, cbret;
unsigned char keyid[EVP_MAX_MD_SIZE];
unsigned int keyidlen = 0;
@ -65,12 +68,30 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
goto err;
if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
if (cb != NULL) {
cbret = cb(bag, cbarg);
if (cbret == -1) {
ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED);
goto err;
} else if (cbret == 0) {
pkcs12_remove_bag(&bags, bag);
}
}
}
/* Add all other certificates */
for (i = 0; i < sk_X509_num(ca); i++) {
if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
if ((bag = PKCS12_add_cert(&bags, sk_X509_value(ca, i))) == NULL)
goto err;
if (cb != NULL) {
cbret = cb(bag, cbarg);
if (cbret == -1) {
ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED);
goto err;
} else if (cbret == 0) {
pkcs12_remove_bag(&bags, bag);
}
}
}
if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass,
@ -96,6 +117,15 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
goto err;
if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
if (cb != NULL) {
cbret = cb(bag, cbarg);
if (cbret == -1) {
ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED);
goto err;
} else if (cbret == 0) {
pkcs12_remove_bag(&bags, bag);
}
}
}
if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
@ -127,6 +157,16 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
}
PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq)
{
return PKCS12_create_ex2(pass, name, pkey, cert, ca, nid_key, nid_cert,
iter, mac_iter, keytype, ctx, propq,
NULL, NULL);
}
PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
int mac_iter, int keytype)
@ -281,6 +321,22 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL);
}
static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag)
{
PKCS12_SAFEBAG *tmp;
if (pbags == NULL || bag == NULL)
return 1;
if ((tmp = sk_PKCS12_SAFEBAG_delete_ptr(*pbags, bag)) == NULL)
return 0;
PKCS12_SAFEBAG_free(tmp);
return 1;
}
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag)
{

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2022 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
@ -15,6 +15,7 @@
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA PKCS12_str_reasons[] = {
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CALLBACK_FAILED), "callback failed"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CANT_PACK_STRUCTURE),
"cant pack structure"},
{ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CONTENT_TYPE_NOT_DATA),

View File

@ -1787,6 +1787,10 @@ DEPEND[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.po
GENERATE[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.pod
DEPEND[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
GENERATE[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
DEPEND[html/man3/PKCS12_SAFEBAG_set0_attrs.html]=man3/PKCS12_SAFEBAG_set0_attrs.pod
GENERATE[html/man3/PKCS12_SAFEBAG_set0_attrs.html]=man3/PKCS12_SAFEBAG_set0_attrs.pod
DEPEND[man/man3/PKCS12_SAFEBAG_set0_attrs.3]=man3/PKCS12_SAFEBAG_set0_attrs.pod
GENERATE[man/man3/PKCS12_SAFEBAG_set0_attrs.3]=man3/PKCS12_SAFEBAG_set0_attrs.pod
DEPEND[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
GENERATE[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
DEPEND[man/man3/PKCS12_add1_attr_by_NID.3]=man3/PKCS12_add1_attr_by_NID.pod
@ -3202,6 +3206,7 @@ html/man3/PKCS12_PBE_keyivgen.html \
html/man3/PKCS12_SAFEBAG_create_cert.html \
html/man3/PKCS12_SAFEBAG_get0_attrs.html \
html/man3/PKCS12_SAFEBAG_get1_cert.html \
html/man3/PKCS12_SAFEBAG_set0_attrs.html \
html/man3/PKCS12_add1_attr_by_NID.html \
html/man3/PKCS12_add_CSPName_asc.html \
html/man3/PKCS12_add_cert.html \
@ -3803,6 +3808,7 @@ man/man3/PKCS12_PBE_keyivgen.3 \
man/man3/PKCS12_SAFEBAG_create_cert.3 \
man/man3/PKCS12_SAFEBAG_get0_attrs.3 \
man/man3/PKCS12_SAFEBAG_get1_cert.3 \
man/man3/PKCS12_SAFEBAG_set0_attrs.3 \
man/man3/PKCS12_add1_attr_by_NID.3 \
man/man3/PKCS12_add_CSPName_asc.3 \
man/man3/PKCS12_add_cert.3 \

View File

@ -0,0 +1,32 @@
=pod
=head1 NAME
PKCS12_SAFEBAG_set0_attrs
- Set attributes for a PKCS#12 safeBag
=head1 SYNOPSIS
#include <openssl/pkcs12.h>
void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs);
=head1 DESCRIPTION
PKCS12_SAFEBAG_set0_attrs() assigns the stack of B<X509_ATTRIBUTE>s to a
PKCS#12 safeBag. I<bag> is the B<PKCS12_SAFEBAG> to assign the attributes to.
=head1 RETURN VALUES
PKCS12_SAFEBAG_set0_attrs() does not return a value.
=head1 COPYRIGHT
Copyright 2019-2022 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
L<https://www.openssl.org/source/license.html>.
=cut

View File

@ -2,7 +2,7 @@
=head1 NAME
PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure
PKCS12_create, PKCS12_create_ex, PKCS12_create_cb, PKCS12_create_ex2 - create a PKCS#12 structure
=head1 SYNOPSIS
@ -16,6 +16,13 @@ PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq);
typedef int PKCS12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg);
PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq,
PKCS12_create_cb *cb, void *cbarg);
=head1 DESCRIPTION
PKCS12_create() creates a PKCS#12 structure.
@ -34,6 +41,14 @@ I<keytype> is the type of key.
PKCS12_create_ex() is identical to PKCS12_create() but allows for a library context
I<ctx> and property query I<propq> to be used to select algorithm implementations.
PKCS12_create_ex2() is identical to PKCS12_create_ex() but allows for a user defined
callback I<cb> of type B<PKCS12_create_cb> to be specified and also allows for an
optional argument I<cbarg> to be passed back to the callback.
The I<cb> if specified will be called for every safebag added to the
PKCS12 structure and allows for optional application processing on the associated
safebag. For example one such use could be to add attributes to the safebag.
=head1 NOTES
The parameters I<nid_key>, I<nid_cert>, I<iter>, I<mac_iter> and I<keytype>
@ -73,6 +88,9 @@ PKCS12_create() makes assumptions regarding the encoding of the given pass
phrase.
See L<passphrase-encoding(7)> for more information.
If I<cb> is specified, then it should return 1 for success and -1 for a fatal error.
A return of 0 is intended to mean to not add the bag after all.
=head1 RETURN VALUES
PKCS12_create() returns a valid B<PKCS12> structure or NULL if an error occurred.
@ -89,6 +107,7 @@ L<passphrase-encoding(7)>
=head1 HISTORY
PKCS12_create_ex() was added in OpenSSL 3.0.
PKCS12_create_ex2() was added in OpenSSL 3.1.
The defaults for encryption algorithms, MAC algorithm, and the MAC key
derivation iteration count were changed in OpenSSL 3.0 to more modern

View File

@ -1145,3 +1145,5 @@ OBJ_id_aa_ATSHashIndex_v3="\x04\x00\x81\x95\x32\x01\x05"
OBJ_signedAssertion="\x04\x00\x81\x95\x32\x01\x06"
OBJ_id_aa_ets_archiveTimestampV2="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x30"
OBJ_hmacWithSM3="\x2A\x81\x1C\xCF\x55\x01\x83\x11\x03\x01"
OBJ_oracle="\x60\x86\x48\x01\x86\xF9\x66"
OBJ_oracle_jdk_trustedkeyusage="\x60\x86\x48\x01\x86\xF9\x66\xAD\xCA\x7B\x01\x01"

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 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

View File

@ -5570,6 +5570,16 @@
#define LN_aes_256_siv "aes-256-siv"
#define NID_aes_256_siv 1200
#define SN_oracle "oracle-organization"
#define LN_oracle "Oracle organization"
#define NID_oracle 1282
#define OBJ_oracle OBJ_joint_iso_itu_t,16L,840L,1L,113894L
#define SN_oracle_jdk_trustedkeyusage "oracle-jdk-trustedkeyusage"
#define LN_oracle_jdk_trustedkeyusage "Trusted key usage (Oracle)"
#define NID_oracle_jdk_trustedkeyusage 1283
#define OBJ_oracle_jdk_trustedkeyusage OBJ_oracle,746875L,1L,1L
#endif /* OPENSSL_OBJ_MAC_H */
#ifndef OPENSSL_NO_DEPRECATED_3_0

View File

@ -199,6 +199,7 @@ ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs,
char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
const STACK_OF(X509_ATTRIBUTE) *
PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag);
void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, const STACK_OF(X509_ATTRIBUTE) *attrs);
unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
const char *pass, int passlen,
const unsigned char *in, int inlen,
@ -286,6 +287,7 @@ DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
void PKCS12_PBE_add(void);
int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
STACK_OF(X509) **ca);
typedef int PKCS12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg);
PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype);
@ -293,6 +295,11 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq);
PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey,
X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
int iter, int mac_iter, int keytype,
OSSL_LIB_CTX *ctx, const char *propq,
PKCS12_create_cb *cb, void *cbarg);
PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2022 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
@ -21,6 +21,7 @@
/*
* PKCS12 reason codes.
*/
# define PKCS12_R_CALLBACK_FAILED 115
# define PKCS12_R_CANT_PACK_STRUCTURE 100
# define PKCS12_R_CONTENT_TYPE_NOT_DATA 121
# define PKCS12_R_DECODE_ERROR 101

View File

@ -338,13 +338,15 @@ err:
* PKCS12 safeBag/attribute builder
*/
static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs)
static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attr)
{
int ret = 0;
int attr_nid;
const PKCS12_ATTR *p_attr = attrs;
const PKCS12_ATTR *p_attr = attr;
STACK_OF(X509_ATTRIBUTE)* attrs = NULL;
X509_ATTRIBUTE *x509_attr = NULL;
if (attrs == NULL)
if (attr == NULL)
return 1;
while (p_attr->oid != NULL) {
@ -358,6 +360,12 @@ static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs)
if (!TEST_true(PKCS12_add_localkeyid(bag, (unsigned char *)p_attr->value,
strlen(p_attr->value))))
goto err;
} else if (attr_nid == NID_oracle_jdk_trustedkeyusage) {
attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag);
x509_attr = X509_ATTRIBUTE_create(attr_nid, V_ASN1_OBJECT, OBJ_txt2obj(p_attr->value, 0));
X509at_add1_attr(&attrs, x509_attr);
PKCS12_SAFEBAG_set0_attrs(bag, attrs);
X509_ATTRIBUTE_free(x509_attr);
} else {
/* Custom attribute values limited to ASCII in these tests */
if (!TEST_true(PKCS12_add1_attr_by_txt(bag, p_attr->oid, MBSTRING_ASC,

View File

@ -82,6 +82,7 @@ void add_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
const PKCS12_ATTR *attrs, const PKCS12_ENC *enc);
void add_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret,
const PKCS12_ATTR *attrs);
void add_extra_attr(PKCS12_BUILDER *pb);
/* Decode/check functions */
void start_check_pkcs12(PKCS12_BUILDER *pb);

View File

@ -94,6 +94,98 @@ err:
return TEST_true(ret);
}
static int pkcs12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg)
{
int cb_ret = *((int*)cbarg);
return cb_ret;
}
static PKCS12 *pkcs12_create_ex2_setup(EVP_PKEY **key, X509 **cert, STACK_OF(X509) **ca)
{
PKCS12 *p12 = NULL;
p12 = PKCS12_load("out6.p12");
if (!TEST_ptr(p12))
goto err;
if (!TEST_true(PKCS12_parse(p12, "", key, cert, ca)))
goto err;
return p12;
err:
PKCS12_free(p12);
return NULL;
}
static int pkcs12_create_ex2_test(int test)
{
int ret = 0, cb_ret = 0;
PKCS12 *ptr = NULL, *p12 = NULL;
EVP_PKEY *key = NULL;
X509 *cert = NULL;
STACK_OF(X509) *ca = NULL;
p12 = pkcs12_create_ex2_setup(&key, &cert, &ca);
if (!TEST_ptr(p12))
goto err;
if (test == 0) {
/* Confirm PKCS12_create_ex2 returns NULL */
ptr = PKCS12_create_ex2(NULL, NULL, NULL,
NULL, NULL, NID_undef, NID_undef,
0, 0, 0,
NULL, NULL,
NULL, NULL);
if (TEST_ptr(ptr))
goto err;
/* Can't proceed without a valid cert at least */
if (!TEST_ptr(cert))
goto err;
/* Specified call back called - return success */
cb_ret = 1;
ptr = PKCS12_create_ex2(NULL, NULL, NULL,
cert, NULL, NID_undef, NID_undef,
0, 0, 0,
NULL, NULL,
pkcs12_create_cb, (void*)&cb_ret);
/* PKCS12 successfully created */
if (!TEST_ptr(ptr))
goto err;
} else if (test == 1) {
/* Specified call back called - return error*/
cb_ret = -1;
ptr = PKCS12_create_ex2(NULL, NULL, NULL,
cert, NULL, NID_undef, NID_undef,
0, 0, 0,
NULL, NULL,
pkcs12_create_cb, (void*)&cb_ret);
/* PKCS12 not created */
if (TEST_ptr(ptr))
goto err;
} else if (test == 2) {
/* Specified call back called - return failure */
cb_ret = 0;
ptr = PKCS12_create_ex2(NULL, NULL, NULL,
cert, NULL, NID_undef, NID_undef,
0, 0, 0,
NULL, NULL,
pkcs12_create_cb, (void*)&cb_ret);
/* PKCS12 successfully created */
if (!TEST_ptr(ptr))
goto err;
}
ret = 1;
err:
PKCS12_free(p12);
PKCS12_free(ptr);
EVP_PKEY_free(key);
X509_free(cert);
OSSL_STACK_OF_X509_free(ca);
return TEST_true(ret);
}
typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
@ -157,7 +249,7 @@ int setup_tests(void)
ADD_TEST(test_null_args);
ADD_TEST(pkcs12_parse_test);
ADD_ALL_TESTS(pkcs12_create_ex2_test, 3);
return 1;
}

View File

@ -205,6 +205,19 @@ static const PKCS12_ATTR ATTRS2[] = {
{ NULL, NULL }
};
static const PKCS12_ATTR ATTRS3[] = {
{ "friendlyName", "wildduk" },
{ "localKeyID", "1122334455" },
{ "oracle-jdk-trustedkeyusage", "anyExtendedKeyUsage" },
{ NULL, NULL }
};
static const PKCS12_ATTR ATTRS4[] = {
{ "friendlyName", "wildduk" },
{ "localKeyID", "1122334455" },
{ NULL, NULL }
};
static const PKCS12_ENC enc_default = {
#ifndef OPENSSL_NO_DES
NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
@ -708,6 +721,84 @@ static int test_multiple_contents(void)
return end_pkcs12_builder(pb);
}
static int test_jdk_trusted_attr(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("jdk_trusted.p12");
/* Generate/encode */
start_pkcs12(pb);
start_contentinfo(pb);
add_certbag(pb, CERT1, sizeof(CERT1), ATTRS3);
end_contentinfo(pb);
end_pkcs12_with_mac(pb, &mac_default);
/* Read/decode */
start_check_pkcs12_with_mac(pb, &mac_default);
start_check_contentinfo(pb);
check_certbag(pb, CERT1, sizeof(CERT1), ATTRS3);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
}
static int test_set0_attrs(void)
{
PKCS12_BUILDER *pb = new_pkcs12_builder("attrs.p12");
PKCS12_SAFEBAG *bag = NULL;
STACK_OF(X509_ATTRIBUTE) *attrs = NULL;
X509_ATTRIBUTE *attr = NULL;
start_pkcs12(pb);
start_contentinfo(pb);
/* Add cert and attrs (name/locakkey only) */
add_certbag(pb, CERT1, sizeof(CERT1), ATTRS4);
bag = sk_PKCS12_SAFEBAG_value(pb->bags, 0);
attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag);
/* Create new attr, add to list and confirm return attrs is not NULL */
attr = X509_ATTRIBUTE_create(NID_oracle_jdk_trustedkeyusage, V_ASN1_OBJECT, OBJ_txt2obj("anyExtendedKeyUsage", 0));
X509at_add1_attr(&attrs, attr);
PKCS12_SAFEBAG_set0_attrs(bag, attrs);
attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag);
X509_ATTRIBUTE_free(attr);
if(!TEST_ptr(attrs)) {
goto err;
}
end_contentinfo(pb);
end_pkcs12(pb);
/* Read/decode */
start_check_pkcs12(pb);
start_check_contentinfo(pb);
/* Use existing check functionality to confirm cert bag attrs identical to ATTRS3 */
check_certbag(pb, CERT1, sizeof(CERT1), ATTRS3);
end_check_contentinfo(pb);
end_check_pkcs12(pb);
return end_pkcs12_builder(pb);
err:
return 0;
}
#ifndef OPENSSL_NO_DES
static int pkcs12_create_test(void)
{
@ -883,6 +974,8 @@ int setup_tests(void)
ADD_TEST(test_cert_key_encrypted_content);
ADD_TEST(test_single_secret_encrypted_content);
ADD_TEST(test_multiple_contents);
ADD_TEST(test_jdk_trusted_attr);
ADD_TEST(test_set0_attrs);
return 1;
}

View File

@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) {
}
$ENV{OPENSSL_WIN32_UTF8}=1;
plan tests => 21;
plan tests => 24;
# Test different PKCS#12 formats
ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats");
@ -81,6 +81,7 @@ my $outfile3 = "out3.p12";
my $outfile4 = "out4.p12";
my $outfile5 = "out5.p12";
my $outfile6 = "out6.p12";
my $outfile7 = "out7.p12";
# Test the -chain option with -untrusted
ok(run(app(["openssl", "pkcs12", "-export", "-chain",
@ -146,9 +147,14 @@ my @pkcs12info = run(app(["openssl", "pkcs12", "-info", "-in", $outfile5,
# Test that with one input certificate, we get one output certificate
ok(grep(/subject=CN\s*=\s*server.example/, @pkcs12info) == 1,
"test one cert in output");
# Test that the expected friendly name is present in the output
ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output");
# Test there's no Oracle Trusted Key Usage bag attribute
ok(grep(/Trusted key usage (Oracle)/, @pkcs12info) == 0,
"test no oracle trusted key usage");
# Test export of PEM file with both cert and key, without password.
# -nomac necessary to avoid legacy provider requirement
{
@ -164,6 +170,22 @@ ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output");
ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr6_empty");
}
# Test with Oracle Trusted Key Usage specified in openssl.cnf
{
$ENV{OPENSSL_CONF} = srctop_file("test", "recipes", "80-test_pkcs12_data", "jdk_trusted.cnf");
ok(run(app(["openssl", "pkcs12", "-export", "-out", $outfile7,
"-in", srctop_file(@path, "ee-cert.pem"),
"-nokeys", "-passout", "pass:", "-certpbe", "NONE"])),
"test nokeys single cert");
my @pkcs12info = run(app(["openssl", "pkcs12", "-info", "-in", $outfile7,
"-passin", "pass:"]), capture => 1);
ok(grep(/Trusted key usage \(Oracle\): Any Extended Key Usage \(2.5.29.37.0\)/, @pkcs12info) == 1,
"test oracle trusted key usage is set");
delete $ENV{OPENSSL_CONF}
}
# Tests for pkcs12_parse
ok(run(test(["pkcs12_api_test",
"-in", $outfile1,

View File

@ -0,0 +1,8 @@
#
[pkcs12]
certBagAttr = cb_attr
# Uncomment this if you need Java compatible PKCS12 files
[cb_attr]
jdkTrustedKeyUsage = anyExtendedKeyUsage

View File

@ -5463,3 +5463,5 @@ BIO_s_dgram_pair ? 3_1_0 EXIST::FUNCTION:DGRAM
BIO_new_bio_dgram_pair ? 3_1_0 EXIST::FUNCTION:DGRAM
EVP_PKEY_auth_encapsulate_init ? 3_1_0 EXIST::FUNCTION:
EVP_PKEY_auth_decapsulate_init ? 3_1_0 EXIST::FUNCTION:
PKCS12_SAFEBAG_set0_attrs ? 3_1_0 EXIST::FUNCTION:
PKCS12_create_ex2 ? 3_1_0 EXIST::FUNCTION:

View File

@ -139,6 +139,7 @@ pem_password_cb datatype
ssl_ct_validation_cb datatype
ASYNC_stack_alloc_fn datatype
ASYNC_stack_free_fn datatype
PKCS12_create_cb datatype
#
ASN1_BIT_STRING_digest define
BIO_IS_ERRNO define