提交 9a48b07e 编写于 作者: D Dr. Stephen Henson

Various enhancements to PKCS#12 code, new
medium level API, improved PKCS12_create
and additional functionality in pkcs12
utility.
上级 230fd6b7
...@@ -4,6 +4,22 @@ ...@@ -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
......
...@@ -2,10 +2,10 @@ ...@@ -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) ...@@ -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,7 +182,10 @@ int MAIN(int argc, char **argv) ...@@ -178,7 +182,10 @@ int MAIN(int argc, char **argv)
} else if (!strcmp (*args, "-keypbe")) { } else if (!strcmp (*args, "-keypbe")) {
if (args[1]) { if (args[1]) {
args++; args++;
key_pbe=OBJ_txt2nid(*args); if (!strcmp(*args, "NONE"))
key_pbe = -1;
else
key_pbe=OBJ_txt2nid(*args);
if(key_pbe == NID_undef) { if(key_pbe == NID_undef) {
BIO_printf(bio_err, BIO_printf(bio_err,
"Unknown PBE algorithm %s\n", *args); "Unknown PBE algorithm %s\n", *args);
...@@ -357,24 +364,6 @@ int MAIN(int argc, char **argv) ...@@ -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,27 +400,31 @@ int MAIN(int argc, char **argv) ...@@ -411,27 +400,31 @@ 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,
goto export_end; FORMAT_PEM, 1, passin, e, "private key");
} if (!key)
goto export_end;
}
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
...@@ -439,49 +432,61 @@ int MAIN(int argc, char **argv) ...@@ -439,49 +432,61 @@ 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"))) { {
goto export_end; certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
} "certificates");
if (!certs)
goto export_end;
#ifdef CRYPTO_MDEBUG if (key)
CRYPTO_pop_info(); {
CRYPTO_push_info("reading certs from input 2"); /* Look for matching private key */
#endif 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 #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("reading certs from certfile"); CRYPTO_push_info("reading certs from input 2");
#endif #endif
bags = sk_PKCS12_SAFEBAG_new_null ();
/* Add any more certificates asked for */ /* Add any more certificates asked for */
if (certfile) { if(certfile)
{
STACK_OF(X509) *morecerts=NULL; STACK_OF(X509) *morecerts=NULL;
if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
NULL, e, NULL, e,
"certificates from certfile"))) { "certificates from certfile")))
goto export_end; 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_push(certs, sk_X509_shift(morecerts));
}
sk_X509_free(morecerts); sk_X509_free(morecerts);
} }
#ifdef CRYPTO_MDEBUG
CRYPTO_pop_info();
CRYPTO_push_info("reading certs from certfile");
#endif
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
...@@ -518,100 +523,51 @@ int MAIN(int argc, char **argv) ...@@ -518,100 +523,51 @@ 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"); {
goto export_end; BIO_printf (bio_err, "Can't read Password\n");
} 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) {
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 #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("encrypting shrouded key bag"); CRYPTO_push_info("creating PKCS#12 structure");
#endif #endif
/* Turn it into unencrypted safe bag */ p12 = PKCS12_create(pass, name, key, ucert, certs,
authsafe = PKCS12_pack_p7data (bags); key_pbe, cert_pbe, iter, -1, keytype);
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
bags = NULL;
sk_PKCS7_push (safes, authsafe);
#ifdef CRYPTO_MDEBUG if (!p12)
CRYPTO_pop_info(); {
CRYPTO_push_info("building pkcs12"); ERR_print_errors (bio_err);
#endif goto export_end;
}
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); if (maciter != -1)
PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL);
#ifdef CRYPTO_MDEBUG #ifdef CRYPTO_MDEBUG
CRYPTO_pop_info(); CRYPTO_pop_info();
CRYPTO_push_info("writing pkcs12"); CRYPTO_push_info("writing pkcs12");
#endif #endif
i2d_PKCS12_bio (out, p12); i2d_PKCS12_bio(out, p12);
ret = 0; ret = 0;
...@@ -624,8 +580,7 @@ int MAIN(int argc, char **argv) ...@@ -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();
......
...@@ -91,6 +91,14 @@ static X509_CERT_AUX *aux_get(X509 *x) ...@@ -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) ...@@ -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) ...@@ -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;
......
/* 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 @@ ...@@ -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(!X509_check_private_key(cert, pkey))
return NULL;
X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
}
if(!(bags = sk_PKCS12_SAFEBAG_new_null ())) { if (cert)
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); {
return NULL; 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 */ /* Add user certificate */
if(!(bag = PKCS12_x5092certbag(cert))) return NULL; if(!(bag = PKCS12_x5092certbag(cert)))
if(name && !PKCS12_add_friendlyname(bag, name, -1)) return NULL; goto err;
X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
if(!PKCS12_add_localkeyid(bag, keyid, keyidlen)) return NULL; /* 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 */ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
if(ca) { int key_usage, int iter,
for(i = 0; i < sk_X509_num(ca); i++) { int nid_key, char *pass)
tcert = sk_X509_value(ca, i); {
if(!(bag = PKCS12_x5092certbag(tcert))) return NULL;
if(!sk_PKCS12_SAFEBAG_push(bags, bag)) { PKCS12_SAFEBAG *bag = NULL;
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); PKCS8_PRIV_KEY_INFO *p8 = NULL;
return 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 */ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
authsafe = PKCS12_pack_p7encdata (nid_cert, pass, -1, NULL, 0, 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); 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 ()) return 1;
|| !sk_PKCS7_push(safes, authsafe)) {
PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); err:
return NULL; 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; return p12;
} }
...@@ -249,6 +249,15 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, ...@@ -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);
......
...@@ -929,6 +929,7 @@ X509 * d2i_X509_AUX(X509 **a,unsigned char **pp,long length); ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册