summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGraham Woodward <graham.woodward@ibm.com>2022-08-19 08:46:47 +0100
committerMatt Caswell <matt@openssl.org>2022-09-23 17:40:02 +0100
commite869c867c1c405de3b6538586f17b67937556a4b (patch)
tree21feab85e639e54c1e2a8a6d1a68a807f2e7dae4
parentecc920b3277311e859282b6d400ba8566d7ea8c1 (diff)
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)
-rw-r--r--CHANGES.md8
-rw-r--r--apps/openssl-vms.cnf7
-rw-r--r--apps/openssl.cnf7
-rw-r--r--apps/pkcs12.c74
-rw-r--r--crypto/err/openssl.txt1
-rw-r--r--crypto/objects/obj_dat.h20
-rw-r--r--crypto/objects/obj_mac.num2
-rw-r--r--crypto/objects/objects.txt6
-rw-r--r--crypto/pkcs12/p12_attr.c8
-rw-r--r--crypto/pkcs12/p12_crt.c68
-rw-r--r--crypto/pkcs12/pk12err.c3
-rw-r--r--doc/build.info6
-rw-r--r--doc/man3/PKCS12_SAFEBAG_set0_attrs.pod32
-rw-r--r--doc/man3/PKCS12_create.pod21
-rw-r--r--fuzz/oids.txt2
-rw-r--r--include/crypto/pkcs12err.h2
-rw-r--r--include/openssl/obj_mac.h10
-rw-r--r--include/openssl/pkcs12.h.in7
-rw-r--r--include/openssl/pkcs12err.h3
-rw-r--r--test/helpers/pkcs12.c14
-rw-r--r--test/helpers/pkcs12.h1
-rw-r--r--test/pkcs12_api_test.c94
-rw-r--r--test/pkcs12_format_test.c93
-rw-r--r--test/recipes/80-test_pkcs12.t24
-rw-r--r--test/recipes/80-test_pkcs12_data/jdk_trusted.cnf8
-rw-r--r--util/libcrypto.num2
-rw-r--r--util/other.syms1
27 files changed, 500 insertions, 24 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 9bc1a91c94..fb71df56a4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -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*
diff --git a/apps/openssl-vms.cnf b/apps/openssl-vms.cnf
index c141010e8a..7eaab9457a 100644
--- a/apps/openssl-vms.cnf
+++ b/apps/openssl-vms.cnf
@@ -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
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 1933f9ebe8..ff45f9a5aa 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -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
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 0338ff30d6..f4aef816dd 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -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;
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index dbb2daa350..96f49c8c7c 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -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
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index eaecb61a51..5d13a73ac4 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -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 */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 0a92288d1c..e56d96336c 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1279,3 +1279,5 @@ id_aa_ATSHashIndex_v3 1278
signedAssertion 1279
id_aa_ets_archiveTimestampV2 1280
hmacWithSM3 1281
+oracle 1282
+oracle_jdk_trustedkeyusage 1283
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index f413d27400..6c831141cd 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -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)
diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c
index 568a32a55e..d9b2db9aaf 100644
--- a/crypto/pkcs12/p12_attr.c
+++ b/crypto/pkcs12/p12_attr.c
@@ -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;
+}
diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c
index 7889842b6f..3246fbb7e8 100644
--- a/crypto/pkcs12/p12_crt.c
+++ b/crypto/pkcs12/p12_crt.c
@@ -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)
{
diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c
index 6e3ec78cd6..b53b0e0d09 100644
--- a/crypto/pkcs12/pk12err.c
+++ b/crypto/pkcs12/pk12err.c
@@ -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),
diff --git a/doc/build.info b/doc/build.info
index 8b55bcdbc7..068082df32 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -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 \
diff --git a/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod b/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod
new file mode 100644
index 0000000000..98e212a9b7
--- /dev/null
+++ b/doc/man3/PKCS12_SAFEBAG_set0_attrs.pod
@@ -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
diff --git a/doc/man3/PKCS12_create.pod b/doc/man3/PKCS12_create.pod
index dc0f06d9d3..8a61e2c76b 100644
--- a/doc/man3/PKCS12_create.pod
+++ b/doc/man3/PKCS12_create.pod
@@ -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
diff --git a/fuzz/oids.txt b/fuzz/oids.txt
index 05c40eb79a..57be5f1674 100644
--- a/fuzz/oids.txt
+++ b/fuzz/oids.txt
@@ -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"
diff --git a/include/crypto/pkcs12err.h b/include/crypto/pkcs12err.h
index 662f412e97..114971c607 100644
--- a/include/crypto/pkcs12err.h
+++ b/include/crypto/pkcs12err.h
@@ -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
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index f329fdfbb1..e8c18b077f 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -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
diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in
index 7d8b751bbc..f3a72bb0ef 100644
--- a/include/openssl/pkcs12.h.in
+++ b/include/openssl/pkcs12.h.in
@@ -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,
diff --git a/include/openssl/pkcs12err.h b/include/openssl/pkcs12err.h
index 933c83299a..abce373628 100644
--- a/