p12_crt.c revision 264331
155714Skris/* p12_crt.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3160814Ssimon * project. 455714Skris */ 555714Skris/* ==================================================================== 6160814Ssimon * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. 755714Skris * 855714Skris * Redistribution and use in source and binary forms, with or without 955714Skris * modification, are permitted provided that the following conditions 1055714Skris * are met: 1155714Skris * 1255714Skris * 1. Redistributions of source code must retain the above copyright 1355714Skris * notice, this list of conditions and the following disclaimer. 1455714Skris * 1555714Skris * 2. Redistributions in binary form must reproduce the above copyright 1655714Skris * notice, this list of conditions and the following disclaimer in 1755714Skris * the documentation and/or other materials provided with the 1855714Skris * distribution. 1955714Skris * 2055714Skris * 3. All advertising materials mentioning features or use of this 2155714Skris * software must display the following acknowledgment: 2255714Skris * "This product includes software developed by the OpenSSL Project 2355714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2455714Skris * 2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2655714Skris * endorse or promote products derived from this software without 2755714Skris * prior written permission. For written permission, please contact 2855714Skris * licensing@OpenSSL.org. 2955714Skris * 3055714Skris * 5. Products derived from this software may not be called "OpenSSL" 3155714Skris * nor may "OpenSSL" appear in their names without prior written 3255714Skris * permission of the OpenSSL Project. 3355714Skris * 3455714Skris * 6. Redistributions of any form whatsoever must retain the following 3555714Skris * acknowledgment: 3655714Skris * "This product includes software developed by the OpenSSL Project 3755714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3855714Skris * 3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4255714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5155714Skris * ==================================================================== 5255714Skris * 5355714Skris * This product includes cryptographic software written by Eric Young 5455714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5555714Skris * Hudson (tjh@cryptsoft.com). 5655714Skris * 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/pkcs12.h> 6255714Skris 63160814Ssimon 64160814Ssimonstatic int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag); 65160814Ssimon 66194206Ssimonstatic int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) 67194206Ssimon { 68194206Ssimon int idx; 69194206Ssimon X509_ATTRIBUTE *attr; 70194206Ssimon idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1); 71194206Ssimon if (idx < 0) 72194206Ssimon return 1; 73194206Ssimon attr = EVP_PKEY_get_attr(pkey, idx); 74194206Ssimon if (!X509at_add1_attr(&bag->attrib, attr)) 75194206Ssimon return 0; 76194206Ssimon return 1; 77194206Ssimon } 78194206Ssimon 7955714SkrisPKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, 8059191Skris STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, 8155714Skris int keytype) 8255714Skris{ 83160814Ssimon PKCS12 *p12 = NULL; 84160814Ssimon STACK_OF(PKCS7) *safes = NULL; 85160814Ssimon STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 86160814Ssimon PKCS12_SAFEBAG *bag = NULL; 8755714Skris int i; 8855714Skris unsigned char keyid[EVP_MAX_MD_SIZE]; 89160814Ssimon unsigned int keyidlen = 0; 9055714Skris 9155714Skris /* Set defaults */ 92160814Ssimon if (!nid_cert) 93264331Sjkim { 94264331Sjkim#ifdef OPENSSL_FIPS 95264331Sjkim if (FIPS_mode()) 96264331Sjkim nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 97264331Sjkim else 98264331Sjkim#endif 99160814Ssimon nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; 100264331Sjkim } 101160814Ssimon if (!nid_key) 102160814Ssimon nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 103160814Ssimon if (!iter) 104160814Ssimon iter = PKCS12_DEFAULT_ITER; 105160814Ssimon if (!mac_iter) 106160814Ssimon mac_iter = 1; 10755714Skris 108160814Ssimon if(!pkey && !cert && !ca) 109160814Ssimon { 11055714Skris PKCS12err(PKCS12_F_PKCS12_CREATE,PKCS12_R_INVALID_NULL_ARGUMENT); 11155714Skris return NULL; 112160814Ssimon } 11355714Skris 114160814Ssimon if (pkey && cert) 115160814Ssimon { 116160814Ssimon if(!X509_check_private_key(cert, pkey)) 117160814Ssimon return NULL; 118160814Ssimon X509_digest(cert, EVP_sha1(), keyid, &keyidlen); 119160814Ssimon } 12068651Skris 121160814Ssimon if (cert) 122160814Ssimon { 123160814Ssimon bag = PKCS12_add_cert(&bags, cert); 124160814Ssimon if(name && !PKCS12_add_friendlyname(bag, name, -1)) 125160814Ssimon goto err; 126160814Ssimon if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 127160814Ssimon goto err; 128160814Ssimon } 12955714Skris 130160814Ssimon /* Add all other certificates */ 131160814Ssimon for(i = 0; i < sk_X509_num(ca); i++) 132160814Ssimon { 133160814Ssimon if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i))) 134160814Ssimon goto err; 135160814Ssimon } 136160814Ssimon 137160814Ssimon if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass)) 138160814Ssimon goto err; 139160814Ssimon 140160814Ssimon sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 141160814Ssimon bags = NULL; 142160814Ssimon 143160814Ssimon if (pkey) 144160814Ssimon { 145160814Ssimon bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass); 146160814Ssimon 147160814Ssimon if (!bag) 148160814Ssimon goto err; 149160814Ssimon 150194206Ssimon if (!copy_bag_attr(bag, pkey, NID_ms_csp_name)) 151194206Ssimon goto err; 152194206Ssimon if (!copy_bag_attr(bag, pkey, NID_LocalKeySet)) 153194206Ssimon goto err; 154160814Ssimon 155160814Ssimon if(name && !PKCS12_add_friendlyname(bag, name, -1)) 156160814Ssimon goto err; 157160814Ssimon if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 158160814Ssimon goto err; 159160814Ssimon } 160160814Ssimon 161160814Ssimon if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL)) 162160814Ssimon goto err; 163160814Ssimon 164160814Ssimon sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 165160814Ssimon bags = NULL; 166160814Ssimon 167160814Ssimon p12 = PKCS12_add_safes(safes, 0); 168160814Ssimon 169194206Ssimon if (!p12) 170194206Ssimon goto err; 171194206Ssimon 172160814Ssimon sk_PKCS7_pop_free(safes, PKCS7_free); 173160814Ssimon 174160814Ssimon safes = NULL; 175160814Ssimon 176160814Ssimon if ((mac_iter != -1) && 177160814Ssimon !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL)) 178160814Ssimon goto err; 179160814Ssimon 180160814Ssimon return p12; 181160814Ssimon 182160814Ssimon err: 183160814Ssimon 184160814Ssimon if (p12) 185160814Ssimon PKCS12_free(p12); 186160814Ssimon if (safes) 187160814Ssimon sk_PKCS7_pop_free(safes, PKCS7_free); 188160814Ssimon if (bags) 189160814Ssimon sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 190160814Ssimon return NULL; 191160814Ssimon 192160814Ssimon} 193160814Ssimon 194160814SsimonPKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) 195160814Ssimon { 196160814Ssimon PKCS12_SAFEBAG *bag = NULL; 197160814Ssimon char *name; 198160814Ssimon int namelen = -1; 199160814Ssimon unsigned char *keyid; 200160814Ssimon int keyidlen = -1; 201160814Ssimon 20255714Skris /* Add user certificate */ 203160814Ssimon if(!(bag = PKCS12_x5092certbag(cert))) 204160814Ssimon goto err; 20555714Skris 206160814Ssimon /* Use friendlyName and localKeyID in certificate. 207160814Ssimon * (if present) 208160814Ssimon */ 209160814Ssimon 210160814Ssimon name = (char *)X509_alias_get0(cert, &namelen); 211160814Ssimon 212160814Ssimon if(name && !PKCS12_add_friendlyname(bag, name, namelen)) 213160814Ssimon goto err; 214160814Ssimon 215160814Ssimon keyid = X509_keyid_get0(cert, &keyidlen); 216160814Ssimon 217160814Ssimon if(keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 218160814Ssimon goto err; 219160814Ssimon 220160814Ssimon if (!pkcs12_add_bag(pbags, bag)) 221160814Ssimon goto err; 222160814Ssimon 223160814Ssimon return bag; 224160814Ssimon 225160814Ssimon err: 226160814Ssimon 227160814Ssimon if (bag) 228160814Ssimon PKCS12_SAFEBAG_free(bag); 229160814Ssimon 230160814Ssimon return NULL; 231160814Ssimon 23255714Skris } 233160814Ssimon 234160814SsimonPKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key, 235160814Ssimon int key_usage, int iter, 236160814Ssimon int nid_key, char *pass) 237160814Ssimon { 238160814Ssimon 239160814Ssimon PKCS12_SAFEBAG *bag = NULL; 240160814Ssimon PKCS8_PRIV_KEY_INFO *p8 = NULL; 241160814Ssimon 242160814Ssimon /* Make a PKCS#8 structure */ 243160814Ssimon if(!(p8 = EVP_PKEY2PKCS8(key))) 244160814Ssimon goto err; 245160814Ssimon if(key_usage && !PKCS8_add_keyusage(p8, key_usage)) 246160814Ssimon goto err; 247160814Ssimon if (nid_key != -1) 248160814Ssimon { 249160814Ssimon bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, iter, p8); 250160814Ssimon PKCS8_PRIV_KEY_INFO_free(p8); 25155714Skris } 252160814Ssimon else 253160814Ssimon bag = PKCS12_MAKE_KEYBAG(p8); 254160814Ssimon 255160814Ssimon if(!bag) 256160814Ssimon goto err; 257160814Ssimon 258160814Ssimon if (!pkcs12_add_bag(pbags, bag)) 259160814Ssimon goto err; 260160814Ssimon 261160814Ssimon return bag; 262160814Ssimon 263160814Ssimon err: 264160814Ssimon 265160814Ssimon if (bag) 266160814Ssimon PKCS12_SAFEBAG_free(bag); 267160814Ssimon 268160814Ssimon return NULL; 269160814Ssimon 27055714Skris } 27155714Skris 272160814Ssimonint PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, 273160814Ssimon int nid_safe, int iter, char *pass) 274160814Ssimon { 275160814Ssimon PKCS7 *p7 = NULL; 276160814Ssimon int free_safes = 0; 277160814Ssimon 278160814Ssimon if (!*psafes) 279160814Ssimon { 280160814Ssimon *psafes = sk_PKCS7_new_null(); 281160814Ssimon if (!*psafes) 282160814Ssimon return 0; 283160814Ssimon free_safes = 1; 284160814Ssimon } 285160814Ssimon else 286160814Ssimon free_safes = 0; 287160814Ssimon 288160814Ssimon if (nid_safe == 0) 289160814Ssimon nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC; 290160814Ssimon 291160814Ssimon if (nid_safe == -1) 292160814Ssimon p7 = PKCS12_pack_p7data(bags); 293160814Ssimon else 294160814Ssimon p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0, 29555714Skris iter, bags); 296160814Ssimon if (!p7) 297160814Ssimon goto err; 29855714Skris 299160814Ssimon if (!sk_PKCS7_push(*psafes, p7)) 300160814Ssimon goto err; 30155714Skris 302160814Ssimon return 1; 303160814Ssimon 304160814Ssimon err: 305160814Ssimon if (free_safes) 306160814Ssimon { 307160814Ssimon sk_PKCS7_free(*psafes); 308160814Ssimon *psafes = NULL; 309160814Ssimon } 310160814Ssimon 311160814Ssimon if (p7) 312160814Ssimon PKCS7_free(p7); 313160814Ssimon 314160814Ssimon return 0; 315160814Ssimon 31655714Skris } 31755714Skris 318160814Ssimonstatic int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag) 319160814Ssimon { 320160814Ssimon int free_bags; 321160814Ssimon if (!pbags) 322160814Ssimon return 1; 323160814Ssimon if (!*pbags) 324160814Ssimon { 325160814Ssimon *pbags = sk_PKCS12_SAFEBAG_new_null(); 326160814Ssimon if (!*pbags) 327160814Ssimon return 0; 328160814Ssimon free_bags = 1; 329160814Ssimon } 330160814Ssimon else 331160814Ssimon free_bags = 0; 332160814Ssimon 333160814Ssimon if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) 334160814Ssimon { 335160814Ssimon if (free_bags) 336160814Ssimon { 337160814Ssimon sk_PKCS12_SAFEBAG_free(*pbags); 338160814Ssimon *pbags = NULL; 339160814Ssimon } 340160814Ssimon return 0; 341160814Ssimon } 342160814Ssimon 343160814Ssimon return 1; 344160814Ssimon 34555714Skris } 346160814Ssimon 34755714Skris 348160814SsimonPKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7) 349160814Ssimon { 350160814Ssimon PKCS12 *p12; 351160814Ssimon if (nid_p7 <= 0) 352160814Ssimon nid_p7 = NID_pkcs7_data; 353160814Ssimon p12 = PKCS12_init(nid_p7); 35455714Skris 355160814Ssimon if (!p12) 356160814Ssimon return NULL; 35755714Skris 358160814Ssimon if(!PKCS12_pack_authsafes(p12, safes)) 359160814Ssimon { 360160814Ssimon PKCS12_free(p12); 361160814Ssimon return NULL; 362160814Ssimon } 36355714Skris 36455714Skris return p12; 36555714Skris 366160814Ssimon } 367