aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2002-10-03 23:53:52 +0000
committerDr. Stephen Henson <steve@openssl.org>2002-10-03 23:53:52 +0000
commit9a48b07ee40b9d4f0f00f0a0822b1296fefb10eb (patch)
tree72d37d95bd0218dd763d0e760673af4936a921fc
parent230fd6b7b66f0b72b1cf7fc300652a1adf94ba1a (diff)
downloadopenssl-9a48b07ee40b9d4f0f00f0a0822b1296fefb10eb.tar.gz
Various enhancements to PKCS#12 code, new
medium level API, improved PKCS12_create and additional functionality in pkcs12 utility.
-rw-r--r--CHANGES16
-rw-r--r--apps/pkcs12.c233
-rw-r--r--crypto/asn1/x_x509a.c23
-rw-r--r--crypto/pkcs12/p12_crt.c316
-rw-r--r--crypto/pkcs12/pkcs12.h9
-rw-r--r--crypto/x509/x509.h1
6 files changed, 387 insertions, 211 deletions
diff --git a/CHANGES b/CHANGES
index ef7d1b55dd..54fb8daecd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,22 @@
Changes between 0.9.7 and 0.9.8 [xx XXX 2002]
+ *) Add new 'medium level' PKCS#12 API. Certificates and keys
+ can be added using this API to created arbitrary PKCS#12
+ files while avoiding the low level API.
+
+ New options to PKCS12_create(), key or cert can be NULL and
+ will then be omitted from the output file. The encryption
+ algorithm NIDs can be set to -1 for no encryption, the mac
+ iteration count can be set to 0 to omit the mac.
+
+ Enhance pkcs12 utility by making the -nokeys and -nocerts
+ options work when creating a PKCS#12 file. New option -nomac
+ to omit the mac, NONE can be set for an encryption algorithm.
+ New code is modified to use the enhanced PKCS12_create()
+ instead of the low level API.
+ [Steve Henson]
+
*) Extend ASN1 encoder to support indefinite length constructed
encoding. This can output sequences tags and octet strings in
this form. Modify pk7_asn1.c to support indefinite length
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 1697f6157f..0d7bf3e6a8 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -2,10 +2,10 @@
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
*/
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -164,10 +164,14 @@ int MAIN(int argc, char **argv)
maciter = PKCS12_DEFAULT_ITER;
else if (!strcmp (*args, "-nomaciter"))
maciter = 1;
+ else if (!strcmp (*args, "-nomac"))
+ maciter = -1;
else if (!strcmp (*args, "-nodes")) enc=NULL;
else if (!strcmp (*args, "-certpbe")) {
if (args[1]) {
args++;
+ if (!strcmp(*args, "NONE"))
+ cert_pbe = -1;
cert_pbe=OBJ_txt2nid(*args);
if(cert_pbe == NID_undef) {
BIO_printf(bio_err,
@@ -178,7 +182,10 @@ int MAIN(int argc, char **argv)
} else if (!strcmp (*args, "-keypbe")) {
if (args[1]) {
args++;
- key_pbe=OBJ_txt2nid(*args);
+ if (!strcmp(*args, "NONE"))
+ key_pbe = -1;
+ else
+ key_pbe=OBJ_txt2nid(*args);
if(key_pbe == NID_undef) {
BIO_printf(bio_err,
"Unknown PBE algorithm %s\n", *args);
@@ -357,24 +364,6 @@ int MAIN(int argc, char **argv)
goto end;
}
-#if 0
- if (certfile) {
- if(!(certsin = BIO_new_file(certfile, "r"))) {
- BIO_printf(bio_err, "Can't open certificate file %s\n", certfile);
- perror (certfile);
- goto end;
- }
- }
-
- if (keyname) {
- if(!(inkey = BIO_new_file(keyname, "r"))) {
- BIO_printf(bio_err, "Can't key certificate file %s\n", keyname);
- perror (keyname);
- goto end;
- }
- }
-#endif
-
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
CRYPTO_push_info("write files");
@@ -411,27 +400,31 @@ int MAIN(int argc, char **argv)
if (export_cert) {
EVP_PKEY *key = NULL;
- STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
- STACK_OF(PKCS7) *safes = NULL;
- PKCS12_SAFEBAG *bag = NULL;
- PKCS8_PRIV_KEY_INFO *p8 = NULL;
- PKCS7 *authsafe = NULL;
- X509 *ucert = NULL;
+ X509 *ucert = NULL, *x = NULL;
STACK_OF(X509) *certs=NULL;
- char *catmp = NULL;
+ unsigned char *catmp = NULL;
int i;
- unsigned char keyid[EVP_MAX_MD_SIZE];
- unsigned int keyidlen = 0;
+
+ if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS))
+ {
+ BIO_printf(bio_err, "Nothing to do!\n");
+ goto export_end;
+ }
+
+ if (options & NOCERTS)
+ chain = 0;
#ifdef CRYPTO_MDEBUG
CRYPTO_push_info("process -export_cert");
CRYPTO_push_info("reading private key");
#endif
- key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1,
- passin, e, "private key");
- if (!key) {
- goto export_end;
- }
+ if (!(options & NOKEYS))
+ {
+ key = load_key(bio_err, keyname ? keyname : infile,
+ FORMAT_PEM, 1, passin, e, "private key");
+ if (!key)
+ goto export_end;
+ }
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
@@ -439,49 +432,61 @@ int MAIN(int argc, char **argv)
#endif
/* Load in all certs in input file */
- if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
- "certificates"))) {
- goto export_end;
- }
+ if(!(options & NOCERTS))
+ {
+ certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
+ "certificates");
+ if (!certs)
+ goto export_end;
-#ifdef CRYPTO_MDEBUG
- CRYPTO_pop_info();
- CRYPTO_push_info("reading certs from input 2");
-#endif
+ if (key)
+ {
+ /* Look for matching private key */
+ for(i = 0; i < sk_X509_num(certs); i++)
+ {
+ x = sk_X509_value(certs, i);
+ if(X509_check_private_key(x, key))
+ {
+ ucert = x;
+ /* Zero keyid and alias */
+ X509_keyid_set1(ucert, NULL, 0);
+ X509_alias_set1(ucert, NULL, 0);
+ /* Remove from list */
+ sk_X509_delete(certs, i);
+ break;
+ }
+ }
+ if (!ucert)
+ {
+ BIO_printf(bio_err, "No certificate matches private key\n");
+ goto export_end;
+ }
+ }
- for(i = 0; i < sk_X509_num(certs); i++) {
- ucert = sk_X509_value(certs, i);
- if(X509_check_private_key(ucert, key)) {
- X509_digest(ucert, EVP_sha1(), keyid, &keyidlen);
- break;
}
- }
- if(!keyidlen) {
- ucert = NULL;
- BIO_printf(bio_err, "No certificate matches private key\n");
- goto export_end;
- }
-
+
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
- CRYPTO_push_info("reading certs from certfile");
+ CRYPTO_push_info("reading certs from input 2");
#endif
- bags = sk_PKCS12_SAFEBAG_new_null ();
-
/* Add any more certificates asked for */
- if (certfile) {
+ if(certfile)
+ {
STACK_OF(X509) *morecerts=NULL;
if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
NULL, e,
- "certificates from certfile"))) {
+ "certificates from certfile")))
goto export_end;
- }
- while(sk_X509_num(morecerts) > 0) {
+ while(sk_X509_num(morecerts) > 0)
sk_X509_push(certs, sk_X509_shift(morecerts));
- }
sk_X509_free(morecerts);
- }
+ }
+
+#ifdef CRYPTO_MDEBUG
+ CRYPTO_pop_info();
+ CRYPTO_push_info("reading certs from certfile");
+#endif
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
@@ -518,100 +523,51 @@ int MAIN(int argc, char **argv)
}
}
-#ifdef CRYPTO_MDEBUG
- CRYPTO_pop_info();
- CRYPTO_push_info("building bags");
-#endif
+ /* Add any CA names */
- /* We now have loads of certificates: include them all */
- for(i = 0; i < sk_X509_num(certs); i++) {
- X509 *cert = NULL;
- cert = sk_X509_value(certs, i);
- bag = PKCS12_x5092certbag(cert);
- /* If it matches private key set id */
- if(cert == ucert) {
- if(name) PKCS12_add_friendlyname(bag, name, -1);
- PKCS12_add_localkeyid(bag, keyid, keyidlen);
- } else if((catmp = sk_shift(canames)))
- PKCS12_add_friendlyname(bag, catmp, -1);
- sk_PKCS12_SAFEBAG_push(bags, bag);
- }
- sk_X509_pop_free(certs, X509_free);
- certs = NULL;
+ for (i = 0; i < sk_num(canames); i++)
+ {
+ catmp = (unsigned char *)sk_value(canames, i);
+ X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
+ }
+
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
- CRYPTO_push_info("encrypting bags");
+ CRYPTO_push_info("reading password");
#endif
if(!noprompt &&
- EVP_read_pw_string(pass, 50, "Enter Export Password:", 1)) {
- BIO_printf (bio_err, "Can't read Password\n");
- goto export_end;
- }
+ EVP_read_pw_string(pass, 50, "Enter Export Password:", 1))
+ {
+ BIO_printf (bio_err, "Can't read Password\n");
+ goto export_end;
+ }
if (!twopass) strcpy(macpass, pass);
- /* Turn certbags into encrypted authsafe */
- authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0,
- iter, bags);
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- bags = NULL;
-
- if (!authsafe) {
- ERR_print_errors (bio_err);
- goto export_end;
- }
-
- safes = sk_PKCS7_new_null ();
- sk_PKCS7_push (safes, authsafe);
-
-#ifdef CRYPTO_MDEBUG
- CRYPTO_pop_info();
- CRYPTO_push_info("building shrouded key bag");
-#endif
-
- /* Make a shrouded key bag */
- p8 = EVP_PKEY2PKCS8 (key);
- if(keytype) PKCS8_add_keyusage(p8, keytype);
- bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- p8 = NULL;
- if (name) PKCS12_add_friendlyname (bag, name, -1);
- if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1);
- PKCS12_add_localkeyid (bag, keyid, keyidlen);
- bags = sk_PKCS12_SAFEBAG_new_null();
- sk_PKCS12_SAFEBAG_push (bags, bag);
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
- CRYPTO_push_info("encrypting shrouded key bag");
+ CRYPTO_push_info("creating PKCS#12 structure");
#endif
- /* Turn it into unencrypted safe bag */
- authsafe = PKCS12_pack_p7data (bags);
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- bags = NULL;
- sk_PKCS7_push (safes, authsafe);
+ p12 = PKCS12_create(pass, name, key, ucert, certs,
+ key_pbe, cert_pbe, iter, -1, keytype);
-#ifdef CRYPTO_MDEBUG
- CRYPTO_pop_info();
- CRYPTO_push_info("building pkcs12");
-#endif
-
- p12 = PKCS12_init(NID_pkcs7_data);
-
- PKCS12_pack_authsafes(p12, safes);
-
- sk_PKCS7_pop_free(safes, PKCS7_free);
- safes = NULL;
+ if (!p12)
+ {
+ ERR_print_errors (bio_err);
+ goto export_end;
+ }
- PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL);
+ if (maciter != -1)
+ PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
CRYPTO_push_info("writing pkcs12");
#endif
- i2d_PKCS12_bio (out, p12);
+ i2d_PKCS12_bio(out, p12);
ret = 0;
@@ -624,8 +580,7 @@ int MAIN(int argc, char **argv)
if (key) EVP_PKEY_free(key);
if (certs) sk_X509_pop_free(certs, X509_free);
- if (safes) sk_PKCS7_pop_free(safes, PKCS7_free);
- if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ if (ucert) X509_free(ucert);
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
diff --git a/crypto/asn1/x_x509a.c b/crypto/asn1/x_x509a.c
index f244768b7e..0c9aa4fd0c 100644
--- a/crypto/asn1/x_x509a.c
+++ b/crypto/asn1/x_x509a.c
@@ -91,6 +91,14 @@ static X509_CERT_AUX *aux_get(X509 *x)
int X509_alias_set1(X509 *x, unsigned char *name, int len)
{
X509_CERT_AUX *aux;
+ if (!name)
+ {
+ if (!x || !x->aux || !x->aux->alias)
+ return 1;
+ ASN1_UTF8STRING_free(x->aux->alias);
+ x->aux->alias = NULL;
+ return 1;
+ }
if(!(aux = aux_get(x))) return 0;
if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0;
return ASN1_STRING_set(aux->alias, name, len);
@@ -99,6 +107,14 @@ int X509_alias_set1(X509 *x, unsigned char *name, int len)
int X509_keyid_set1(X509 *x, unsigned char *id, int len)
{
X509_CERT_AUX *aux;
+ if (!id)
+ {
+ if (!x || !x->aux || !x->aux->keyid)
+ return 1;
+ ASN1_OCTET_STRING_free(x->aux->keyid);
+ x->aux->keyid = NULL;
+ return 1;
+ }
if(!(aux = aux_get(x))) return 0;
if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
return ASN1_STRING_set(aux->keyid, id, len);
@@ -111,6 +127,13 @@ unsigned char *X509_alias_get0(X509 *x, int *len)
return x->aux->alias->data;
}
+unsigned char *X509_keyid_get0(X509 *x, int *len)
+{
+ if(!x->aux || !x->aux->keyid) return NULL;
+ if(len) *len = x->aux->keyid->length;
+ return x->aux->keyid->data;
+}
+
int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c
index 4c36c643ce..77b5845ea9 100644
--- a/crypto/pkcs12/p12_crt.c
+++ b/crypto/pkcs12/p12_crt.c
@@ -1,9 +1,9 @@
/* p12_crt.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
*/
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,105 +60,277 @@
#include "cryptlib.h"
#include <openssl/pkcs12.h>
+
+static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag);
+
PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter,
int keytype)
{
- PKCS12 *p12;
- STACK_OF(PKCS12_SAFEBAG) *bags;
- STACK_OF(PKCS7) *safes;
- PKCS12_SAFEBAG *bag;
- PKCS8_PRIV_KEY_INFO *p8;
- PKCS7 *authsafe;
- X509 *tcert;
+ PKCS12 *p12 = NULL;
+ STACK_OF(PKCS7) *safes = NULL;
+ STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
+ PKCS12_SAFEBAG *bag = NULL;
int i;
unsigned char keyid[EVP_MAX_MD_SIZE];
- unsigned int keyidlen;
+ unsigned int keyidlen = 0;
/* Set defaults */
- if(!nid_cert) nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
- if(!nid_key) nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
- if(!iter) iter = PKCS12_DEFAULT_ITER;
- if(!mac_iter) mac_iter = 1;
+ if (!nid_cert)
+ nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
+ if (!nid_key)
+ nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ if (!iter)
+ iter = PKCS12_DEFAULT_ITER;
+ if (!mac_iter)
+ mac_iter = 1;
- if(!pkey || !cert) {
+ if(!pkey && !cert && !ca)
+ {
PKCS12err(PKCS12_F_PKCS12_CREATE,PKCS12_R_INVALID_NULL_ARGUMENT);
return NULL;
- }
+ }
- if(!X509_check_private_key(cert, pkey)) return NULL;
+ if (pkey && cert)
+ {
+ if(!X509_check_private_key(cert, pkey))
+ return NULL;
+ X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
+ }
- if(!(bags = sk_PKCS12_SAFEBAG_new_null ())) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ if (cert)
+ {
+ bag = PKCS12_add_cert(&bags, cert);
+ if(name && !PKCS12_add_friendlyname(bag, name, -1))
+ goto err;
+ if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+ goto err;
+ }
+
+ /* Add all other certificates */
+ for(i = 0; i < sk_X509_num(ca); i++)
+ {
+ if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
+ goto err;
+ }
+
+ if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
+ goto err;
+
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ bags = NULL;
+
+ if (pkey)
+ {
+ bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
+ if (!bag)
+ goto err;
+ if(name && !PKCS12_add_friendlyname(bag, name, -1))
+ goto err;
+ if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+ goto err;
+ }
+
+ if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
+ goto err;
+
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ bags = NULL;
+
+ p12 = PKCS12_add_safes(safes, 0);
+
+ sk_PKCS7_pop_free(safes, PKCS7_free);
+
+ safes = NULL;
+
+ if ((mac_iter != -1) &&
+ !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
+ goto err;
+
+ return p12;
+
+ err:
+
+ if (p12)
+ PKCS12_free(p12);
+ if (safes)
+ sk_PKCS7_pop_free(safes, PKCS7_free);
+ if (bags)
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ return NULL;
+
+}
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+ {
+ PKCS12_SAFEBAG *bag = NULL;
+ char *name;
+ int namelen = -1;
+ unsigned char *keyid;
+ int keyidlen = -1;
/* Add user certificate */
- if(!(bag = PKCS12_x5092certbag(cert))) return NULL;
- if(name && !PKCS12_add_friendlyname(bag, name, -1)) return NULL;
- X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
- if(!PKCS12_add_localkeyid(bag, keyid, keyidlen)) return NULL;
+ if(!(bag = PKCS12_x5092certbag(cert)))
+ goto err;
+
+ /* Use friendlyName and localKeyID in certificate.
+ * (if present)
+ */
+
+ name = (char *)X509_alias_get0(cert, &namelen);
+
+ if(name && !PKCS12_add_friendlyname(bag, name, namelen))
+ goto err;
+
+ keyid = X509_keyid_get0(cert, &keyidlen);
+
+ if(keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+ goto err;
+
+ if (!pkcs12_add_bag(pbags, bag))
+ goto err;
+
+ return bag;
+
+ err:
+
+ if (bag)
+ PKCS12_SAFEBAG_free(bag);
+
+ return NULL;
- if(!sk_PKCS12_SAFEBAG_push(bags, bag)) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
}
-
- /* Add all other certificates */
- if(ca) {
- for(i = 0; i < sk_X509_num(ca); i++) {
- tcert = sk_X509_value(ca, i);
- if(!(bag = PKCS12_x5092certbag(tcert))) return NULL;
- if(!sk_PKCS12_SAFEBAG_push(bags, bag)) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
+ int key_usage, int iter,
+ int nid_key, char *pass)
+ {
+
+ PKCS12_SAFEBAG *bag = NULL;
+ PKCS8_PRIV_KEY_INFO *p8 = NULL;
+
+ /* Make a PKCS#8 structure */
+ if(!(p8 = EVP_PKEY2PKCS8(key)))
+ goto err;
+ if(key_usage && !PKCS8_add_keyusage(p8, key_usage))
+ goto err;
+ if (nid_key != -1)
+ {
+ bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, iter, p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
}
+ else
+ bag = PKCS12_MAKE_KEYBAG(p8);
+
+ if(!bag)
+ goto err;
+
+ if (!pkcs12_add_bag(pbags, bag))
+ goto err;
+
+ return bag;
+
+ err:
+
+ if (bag)
+ PKCS12_SAFEBAG_free(bag);
+
+ return NULL;
+
}
- /* Turn certbags into encrypted authsafe */
- authsafe = PKCS12_pack_p7encdata (nid_cert, pass, -1, NULL, 0,
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int nid_safe, int iter, char *pass)
+ {
+ PKCS7 *p7 = NULL;
+ int free_safes = 0;
+
+ if (!*psafes)
+ {
+ *psafes = sk_PKCS7_new_null();
+ if (!*psafes)
+ return 0;
+ free_safes = 1;
+ }
+ else
+ free_safes = 0;
+
+ if (nid_safe == 0)
+ nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
+
+ if (nid_safe == -1)
+ p7 = PKCS12_pack_p7data(bags);
+ else
+ p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0,
iter, bags);
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ if (!p7)
+ goto err;
- if (!authsafe) return NULL;
+ if (!sk_PKCS7_push(*psafes, p7))
+ goto err;
- if(!(safes = sk_PKCS7_new_null ())
- || !sk_PKCS7_push(safes, authsafe)) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
+ return 1;
+
+ err:
+ if (free_safes)
+ {
+ sk_PKCS7_free(*psafes);
+ *psafes = NULL;
+ }
+
+ if (p7)
+ PKCS7_free(p7);
+
+ return 0;
- /* Make a shrouded key bag */
- if(!(p8 = EVP_PKEY2PKCS8 (pkey))) return NULL;
- if(keytype && !PKCS8_add_keyusage(p8, keytype)) return NULL;
- bag = PKCS12_MAKE_SHKEYBAG (nid_key, pass, -1, NULL, 0, iter, p8);
- if(!bag) return NULL;
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (name && !PKCS12_add_friendlyname (bag, name, -1)) return NULL;
- if(!PKCS12_add_localkeyid (bag, keyid, keyidlen)) return NULL;
- if(!(bags = sk_PKCS12_SAFEBAG_new_null())
- || !sk_PKCS12_SAFEBAG_push (bags, bag)) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- /* Turn it into unencrypted safe bag */
- if(!(authsafe = PKCS12_pack_p7data (bags))) return NULL;
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- if(!sk_PKCS7_push(safes, authsafe)) {
- PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
- return NULL;
}
- if(!(p12 = PKCS12_init (NID_pkcs7_data))) return NULL;
+static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag)
+ {
+ int free_bags;
+ if (!pbags)
+ return 1;
+ if (!*pbags)
+ {
+ *pbags = sk_PKCS12_SAFEBAG_new_null();
+ if (!*pbags)
+ return 0;
+ free_bags = 1;
+ }
+ else
+ free_bags = 0;
- if(!PKCS12_pack_authsafes (p12, safes)) return NULL;
+ if (!sk_PKCS12_SAFEBAG_push(*pbags, bag))
+ {
+ if (free_bags)
+ {
+ sk_PKCS12_SAFEBAG_free(*pbags);
+ *pbags = NULL;
+ }
+ return 0;
+ }
- sk_PKCS7_pop_free(safes, PKCS7_free);
+ return 1;
- if(!PKCS12_set_mac (p12, pass, -1, NULL, 0, mac_iter, NULL))
- return NULL;
+ }
+
+
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+ {
+ PKCS12 *p12;
+ if (nid_p7 <= 0)
+ nid_p7 = NID_pkcs7_data;
+ p12 = PKCS12_init(nid_p7);
+
+ if (!p12)
+ return NULL;
+
+ if(!PKCS12_pack_authsafes(p12, safes))
+ {
+ PKCS12_free(p12);
+ return NULL;
+ }
return p12;
-}
+ }
diff --git a/crypto/pkcs12/pkcs12.h b/crypto/pkcs12/pkcs12.h
index dd338f266c..5c8b492816 100644
--- a/crypto/pkcs12/pkcs12.h
+++ b/crypto/pkcs12/pkcs12.h
@@ -249,6 +249,15 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
int mac_iter, int keytype);
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
+ int key_usage, int iter,
+ int key_nid, char *pass);
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, char *pass);
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+
int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 96d3b69888..7a2c8db1b0 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -929,6 +929,7 @@ X509 * d2i_X509_AUX(X509 **a,unsigned char **pp,long length);
int X509_alias_set1(X509 *x, unsigned char *name, int len);
int X509_keyid_set1(X509 *x, unsigned char *id, int len);
unsigned char * X509_alias_get0(X509 *x, int *len);
+unsigned char * X509_keyid_get0(X509 *x, int *len);
int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
int X509_TRUST_set(int *t, int trust);
int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);