Various enhancements to PKCS#12 code, new

medium level API, improved PKCS12_create
and additional functionality in pkcs12
utility.
This commit is contained in:
Dr. Stephen Henson 2002-10-03 23:53:52 +00:00
parent 230fd6b7b6
commit 9a48b07ee4
6 changed files with 401 additions and 225 deletions

16
CHANGES
View File

@ -4,6 +4,22 @@
Changes between 0.9.7 and 0.9.8 [xx XXX 2002] 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 *) Extend ASN1 encoder to support indefinite length constructed
encoding. This can output sequences tags and octet strings in encoding. This can output sequences tags and octet strings in
this form. Modify pk7_asn1.c to support indefinite length this form. Modify pk7_asn1.c to support indefinite length

View File

@ -2,10 +2,10 @@
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL /* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -164,10 +164,14 @@ int MAIN(int argc, char **argv)
maciter = PKCS12_DEFAULT_ITER; maciter = PKCS12_DEFAULT_ITER;
else if (!strcmp (*args, "-nomaciter")) else if (!strcmp (*args, "-nomaciter"))
maciter = 1; maciter = 1;
else if (!strcmp (*args, "-nomac"))
maciter = -1;
else if (!strcmp (*args, "-nodes")) enc=NULL; else if (!strcmp (*args, "-nodes")) enc=NULL;
else if (!strcmp (*args, "-certpbe")) { else if (!strcmp (*args, "-certpbe")) {
if (args[1]) { if (args[1]) {
args++; args++;
if (!strcmp(*args, "NONE"))
cert_pbe = -1;
cert_pbe=OBJ_txt2nid(*args); cert_pbe=OBJ_txt2nid(*args);
if(cert_pbe == NID_undef) { if(cert_pbe == NID_undef) {
BIO_printf(bio_err, BIO_printf(bio_err,
@ -178,6 +182,9 @@ int MAIN(int argc, char **argv)
} else if (!strcmp (*args, "-keypbe")) { } else if (!strcmp (*args, "-keypbe")) {
if (args[1]) { if (args[1]) {
args++; args++;
if (!strcmp(*args, "NONE"))
key_pbe = -1;
else
key_pbe=OBJ_txt2nid(*args); key_pbe=OBJ_txt2nid(*args);
if(key_pbe == NID_undef) { if(key_pbe == NID_undef) {
BIO_printf(bio_err, BIO_printf(bio_err,
@ -357,24 +364,6 @@ int MAIN(int argc, char **argv)
goto end; 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 #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("write files"); CRYPTO_push_info("write files");
@ -411,25 +400,29 @@ int MAIN(int argc, char **argv)
if (export_cert) { if (export_cert) {
EVP_PKEY *key = NULL; EVP_PKEY *key = NULL;
STACK_OF(PKCS12_SAFEBAG) *bags = NULL; X509 *ucert = NULL, *x = NULL;
STACK_OF(PKCS7) *safes = NULL;
PKCS12_SAFEBAG *bag = NULL;
PKCS8_PRIV_KEY_INFO *p8 = NULL;
PKCS7 *authsafe = NULL;
X509 *ucert = NULL;
STACK_OF(X509) *certs=NULL; STACK_OF(X509) *certs=NULL;
char *catmp = NULL; unsigned char *catmp = NULL;
int i; 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 #ifdef CRYPTO_MDEBUG
CRYPTO_push_info("process -export_cert"); CRYPTO_push_info("process -export_cert");
CRYPTO_push_info("reading private key"); CRYPTO_push_info("reading private key");
#endif #endif
key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1, if (!(options & NOKEYS))
passin, e, "private key"); {
if (!key) { key = load_key(bio_err, keyname ? keyname : infile,
FORMAT_PEM, 1, passin, e, "private key");
if (!key)
goto export_end; goto export_end;
} }
@ -439,9 +432,37 @@ int MAIN(int argc, char **argv)
#endif #endif
/* Load in all certs in input file */ /* Load in all certs in input file */
if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, if(!(options & NOCERTS))
"certificates"))) { {
certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
"certificates");
if (!certs)
goto export_end; goto export_end;
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;
}
}
} }
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
@ -449,17 +470,17 @@ int MAIN(int argc, char **argv)
CRYPTO_push_info("reading certs from input 2"); CRYPTO_push_info("reading certs from input 2");
#endif #endif
for(i = 0; i < sk_X509_num(certs); i++) { /* Add any more certificates asked for */
ucert = sk_X509_value(certs, i); if(certfile)
if(X509_check_private_key(ucert, key)) { {
X509_digest(ucert, EVP_sha1(), keyid, &keyidlen); STACK_OF(X509) *morecerts=NULL;
break; if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
} NULL, e,
} "certificates from certfile")))
if(!keyidlen) {
ucert = NULL;
BIO_printf(bio_err, "No certificate matches private key\n");
goto export_end; goto export_end;
while(sk_X509_num(morecerts) > 0)
sk_X509_push(certs, sk_X509_shift(morecerts));
sk_X509_free(morecerts);
} }
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
@ -467,22 +488,6 @@ int MAIN(int argc, char **argv)
CRYPTO_push_info("reading certs from certfile"); CRYPTO_push_info("reading certs from certfile");
#endif #endif
bags = sk_PKCS12_SAFEBAG_new_null ();
/* Add any more certificates asked for */
if (certfile) {
STACK_OF(X509) *morecerts=NULL;
if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
NULL, e,
"certificates from certfile"))) {
goto export_end;
}
while(sk_X509_num(morecerts) > 0) {
sk_X509_push(certs, sk_X509_shift(morecerts));
}
sk_X509_free(morecerts);
}
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("building chain"); CRYPTO_push_info("building chain");
@ -518,92 +523,43 @@ int MAIN(int argc, char **argv)
} }
} }
#ifdef CRYPTO_MDEBUG /* Add any CA names */
CRYPTO_pop_info();
CRYPTO_push_info("building bags");
#endif
/* We now have loads of certificates: include them all */ for (i = 0; i < sk_num(canames); i++)
for(i = 0; i < sk_X509_num(certs); i++) { {
X509 *cert = NULL; catmp = (unsigned char *)sk_value(canames, i);
cert = sk_X509_value(certs, i); X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
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;
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("encrypting bags"); CRYPTO_push_info("reading password");
#endif #endif
if(!noprompt && if(!noprompt &&
EVP_read_pw_string(pass, 50, "Enter Export Password:", 1)) { EVP_read_pw_string(pass, 50, "Enter Export Password:", 1))
{
BIO_printf (bio_err, "Can't read Password\n"); BIO_printf (bio_err, "Can't read Password\n");
goto export_end; goto export_end;
} }
if (!twopass) strcpy(macpass, pass); 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) { #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
CRYPTO_push_info("creating PKCS#12 structure");
#endif
p12 = PKCS12_create(pass, name, key, ucert, certs,
key_pbe, cert_pbe, iter, -1, keytype);
if (!p12)
{
ERR_print_errors (bio_err); ERR_print_errors (bio_err);
goto export_end; goto export_end;
} }
safes = sk_PKCS7_new_null (); if (maciter != -1)
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");
#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);
#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;
PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL); PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
@ -624,8 +580,7 @@ int MAIN(int argc, char **argv)
if (key) EVP_PKEY_free(key); if (key) EVP_PKEY_free(key);
if (certs) sk_X509_pop_free(certs, X509_free); if (certs) sk_X509_pop_free(certs, X509_free);
if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (ucert) X509_free(ucert);
if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();

View File

@ -91,6 +91,14 @@ static X509_CERT_AUX *aux_get(X509 *x)
int X509_alias_set1(X509 *x, unsigned char *name, int len) int X509_alias_set1(X509 *x, unsigned char *name, int len)
{ {
X509_CERT_AUX *aux; 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 = aux_get(x))) return 0;
if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0; if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0;
return ASN1_STRING_set(aux->alias, name, len); 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) int X509_keyid_set1(X509 *x, unsigned char *id, int len)
{ {
X509_CERT_AUX *aux; 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 = aux_get(x))) return 0;
if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0; if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
return ASN1_STRING_set(aux->keyid, id, len); 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; 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) int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj)
{ {
X509_CERT_AUX *aux; X509_CERT_AUX *aux;

View File

@ -1,9 +1,9 @@
/* p12_crt.c */ /* p12_crt.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL /* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -60,105 +60,277 @@
#include "cryptlib.h" #include "cryptlib.h"
#include <openssl/pkcs12.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, 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, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter,
int keytype) int keytype)
{ {
PKCS12 *p12; PKCS12 *p12 = NULL;
STACK_OF(PKCS12_SAFEBAG) *bags; STACK_OF(PKCS7) *safes = NULL;
STACK_OF(PKCS7) *safes; STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
PKCS12_SAFEBAG *bag; PKCS12_SAFEBAG *bag = NULL;
PKCS8_PRIV_KEY_INFO *p8;
PKCS7 *authsafe;
X509 *tcert;
int i; int i;
unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned char keyid[EVP_MAX_MD_SIZE];
unsigned int keyidlen; unsigned int keyidlen = 0;
/* Set defaults */ /* Set defaults */
if(!nid_cert) nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; if (!nid_cert)
if(!nid_key) nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
if(!iter) iter = PKCS12_DEFAULT_ITER; if (!nid_key)
if(!mac_iter) mac_iter = 1; 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); PKCS12err(PKCS12_F_PKCS12_CREATE,PKCS12_R_INVALID_NULL_ARGUMENT);
return NULL; return NULL;
} }
if(!X509_check_private_key(cert, pkey)) return NULL; if (pkey && cert)
{
if(!(bags = sk_PKCS12_SAFEBAG_new_null ())) { if(!X509_check_private_key(cert, pkey))
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
return NULL; return NULL;
X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
} }
/* Add user certificate */ if (cert)
if(!(bag = PKCS12_x5092certbag(cert))) return NULL; {
if(name && !PKCS12_add_friendlyname(bag, name, -1)) return NULL; bag = PKCS12_add_cert(&bags, cert);
X509_digest(cert, EVP_sha1(), keyid, &keyidlen); if(name && !PKCS12_add_friendlyname(bag, name, -1))
if(!PKCS12_add_localkeyid(bag, keyid, keyidlen)) return NULL; goto err;
if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
if(!sk_PKCS12_SAFEBAG_push(bags, bag)) { goto err;
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
return NULL;
} }
/* Add all other certificates */ /* Add all other certificates */
if(ca) { for(i = 0; i < sk_X509_num(ca); i++)
for(i = 0; i < sk_X509_num(ca); i++) { {
tcert = sk_X509_value(ca, i); if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
if(!(bag = PKCS12_x5092certbag(tcert))) return NULL; goto err;
if(!sk_PKCS12_SAFEBAG_push(bags, bag)) {
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
return NULL;
}
}
} }
/* Turn certbags into encrypted authsafe */ if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
authsafe = PKCS12_pack_p7encdata (nid_cert, pass, -1, NULL, 0, goto err;
iter, bags);
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
if (!authsafe) return NULL; if (pkey)
{
if(!(safes = sk_PKCS7_new_null ()) bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
|| !sk_PKCS7_push(safes, authsafe)) { if (!bag)
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); goto err;
return NULL; if(name && !PKCS12_add_friendlyname(bag, name, -1))
goto err;
if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
} }
/* Make a shrouded key bag */ if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
if(!(p8 = EVP_PKEY2PKCS8 (pkey))) return NULL; goto err;
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); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
if(!sk_PKCS7_push(safes, authsafe)) { bags = NULL;
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE);
return NULL;
}
if(!(p12 = PKCS12_init (NID_pkcs7_data))) return NULL; p12 = PKCS12_add_safes(safes, 0);
if(!PKCS12_pack_authsafes (p12, safes)) return NULL;
sk_PKCS7_pop_free(safes, PKCS7_free); sk_PKCS7_pop_free(safes, PKCS7_free);
if(!PKCS12_set_mac (p12, pass, -1, NULL, 0, mac_iter, NULL)) 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; 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)))
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;
}
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;
}
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);
if (!p7)
goto err;
if (!sk_PKCS7_push(*psafes, p7))
goto err;
return 1;
err:
if (free_safes)
{
sk_PKCS7_free(*psafes);
*psafes = NULL;
}
if (p7)
PKCS7_free(p7);
return 0;
}
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 (!sk_PKCS12_SAFEBAG_push(*pbags, bag))
{
if (free_bags)
{
sk_PKCS12_SAFEBAG_free(*pbags);
*pbags = NULL;
}
return 0;
}
return 1;
}
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; return p12;
} }

View File

@ -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, PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
int mac_iter, int keytype); 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_bio(BIO *bp, PKCS12 *p12);
int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);

View File

@ -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_alias_set1(X509 *x, unsigned char *name, int len);
int X509_keyid_set1(X509 *x, unsigned char *id, 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_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_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
int X509_TRUST_set(int *t, int trust); int X509_TRUST_set(int *t, int trust);
int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);