1 /* 2 * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 1999. 4 */ 5 /* 6 * ==================================================================== 7 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60 /* 61 * Copyright 2002, 2003 Sun Microsystems, Inc. All rights reserved. 62 * Use is subject to license terms. 63 */ 64 65 #pragma ident "%Z%%M% %I% %E% SMI" 66 67 #include <stdio.h> 68 #include <strings.h> 69 70 #include <openssl/crypto.h> 71 #include <openssl/err.h> 72 #include <openssl/x509.h> 73 74 #include <openssl/pkcs12.h> 75 #include <p12aux.h> 76 #include <auxutil.h> 77 #include <p12err.h> 78 79 /* 80 * sunw_PKCS12_create() creates a pkcs#12 structure and given component parts. 81 * 82 * Given one or more of user private key, user cert and/or other (CA) certs, 83 * return an encrypted PKCS12 structure containing them. 84 * 85 * Arguments: 86 * pass - Pass phrase for the pkcs12 structure and private key (possibly 87 * empty) or NULL if there is none. It will be used to encrypt 88 * both the private key(s) and as the pass phrase for the whole 89 * pkcs12 wad. 90 * pkeys - Points to stack of private keys. 91 * certs - Points to stack of client (public ke) certs 92 * cacerts - Points to stack of 'certificate authority' certs (or trust 93 * anchors). 94 * 95 * Note that any of these may be NULL. 96 * 97 * Returns: 98 * NULL - An error occurred. 99 * != NULL - Address of PKCS12 structure. The user is responsible for 100 * freeing the memory when done. 101 */ 102 PKCS12 * 103 sunw_PKCS12_create(const char *pass, STACK_OF(EVP_PKEY) *pkeys, 104 STACK_OF(X509) *certs, STACK_OF(X509) *cacerts) 105 { 106 int nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; 107 int nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 108 STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 109 STACK_OF(PKCS7) *safes = NULL; 110 PKCS12_SAFEBAG *bag = NULL; 111 PKCS8_PRIV_KEY_INFO *p8 = NULL; 112 EVP_PKEY *pkey = NULL; 113 PKCS12 *ret_p12 = NULL; 114 PKCS12 *p12 = NULL; 115 PKCS7 *authsafe = NULL; 116 X509 *cert = NULL; 117 uchar_t *str = NULL; 118 int certs_there = 0; 119 int keys_there = 0; 120 int len; 121 int i; 122 123 if ((safes = sk_PKCS7_new_null()) == NULL) { 124 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 125 return (NULL); 126 } 127 128 if ((bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) { 129 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 130 goto err_ret; 131 } 132 133 if (certs != NULL && sk_X509_num(certs) > 0) { 134 135 for (i = 0; i < sk_X509_num(certs); i++) { 136 cert = sk_X509_value(certs, i); 137 138 /* Add user certificate */ 139 if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) { 140 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 141 goto err_ret; 142 } 143 if (cert->aux != NULL && cert->aux->alias != NULL && 144 cert->aux->alias->type == V_ASN1_UTF8STRING) { 145 str = utf82ascstr(cert->aux->alias); 146 if (str == NULL) { 147 /* 148 * Error already on stack 149 */ 150 goto err_ret; 151 } 152 if (PKCS12_add_friendlyname_asc(bag, 153 (char const *) str, 154 strlen((char const *) str)) == 0) { 155 SUNWerr(SUNW_F_PKCS12_CREATE, 156 SUNW_R_ADD_ATTR_ERR); 157 goto err_ret; 158 } 159 } 160 if (cert->aux != NULL && cert->aux->keyid != NULL && 161 cert->aux->keyid->type == V_ASN1_OCTET_STRING) { 162 str = cert->aux->keyid->data; 163 len = cert->aux->keyid->length; 164 165 if (str != NULL && 166 PKCS12_add_localkeyid(bag, str, len) == 0) { 167 SUNWerr(SUNW_F_PKCS12_CREATE, 168 SUNW_R_ADD_ATTR_ERR); 169 goto err_ret; 170 } 171 } 172 if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 173 SUNWerr(SUNW_F_PKCS12_CREATE, 174 SUNW_R_MEMORY_FAILURE); 175 goto err_ret; 176 } 177 certs_there++; 178 bag = NULL; 179 } 180 } 181 182 if (cacerts != NULL && sk_X509_num(cacerts) > 0) { 183 184 /* Put all certs in structure */ 185 for (i = 0; i < sk_X509_num(cacerts); i++) { 186 cert = sk_X509_value(cacerts, i); 187 if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) { 188 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 189 goto err_ret; 190 } 191 192 if (cert->aux != NULL && cert->aux->alias != NULL && 193 cert->aux->alias->type == V_ASN1_UTF8STRING) { 194 str = utf82ascstr(cert->aux->alias); 195 if (str == NULL) { 196 /* 197 * Error already on stack 198 */ 199 goto err_ret; 200 } 201 if (PKCS12_add_friendlyname_asc( 202 bag, (char const *) str, 203 strlen((char const *) str)) == 0) { 204 SUNWerr(SUNW_F_PKCS12_CREATE, 205 SUNW_R_ADD_ATTR_ERR); 206 goto err_ret; 207 } 208 } 209 if (cert->aux != NULL && cert->aux->keyid != NULL && 210 cert->aux->keyid->type == V_ASN1_OCTET_STRING) { 211 str = cert->aux->keyid->data; 212 len = cert->aux->keyid->length; 213 214 if (str != NULL && 215 PKCS12_add_localkeyid(bag, str, len) == 0) { 216 SUNWerr(SUNW_F_PKCS12_CREATE, 217 SUNW_R_ADD_ATTR_ERR); 218 goto err_ret; 219 } 220 } 221 if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 222 SUNWerr(SUNW_F_PKCS12_CREATE, 223 SUNW_R_MEMORY_FAILURE); 224 goto err_ret; 225 } 226 certs_there++; 227 bag = NULL; 228 } 229 } 230 231 if (certs != NULL || cacerts != NULL && certs_there) { 232 /* Turn certbags into encrypted authsafe */ 233 authsafe = PKCS12_pack_p7encdata(nid_cert, pass, -1, 234 NULL, 0, PKCS12_DEFAULT_ITER, bags); 235 if (authsafe == NULL) { 236 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 237 goto err_ret; 238 } 239 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 240 bags = NULL; 241 242 if (sk_PKCS7_push(safes, authsafe) == 0) { 243 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 244 goto err_ret; 245 } 246 authsafe = NULL; 247 } 248 249 if (pkeys != NULL && sk_EVP_PKEY_num(pkeys) > 0) { 250 251 if (bags == NULL && 252 (bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) { 253 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 254 goto err_ret; 255 } 256 257 for (i = 0; i < sk_EVP_PKEY_num(pkeys); i++) { 258 259 pkey = sk_EVP_PKEY_value(pkeys, i); 260 261 /* Make a shrouded key bag */ 262 if ((p8 = EVP_PKEY2PKCS8(pkey)) == NULL) { 263 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKEY_ERR); 264 goto err_ret; 265 } 266 267 bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, 268 PKCS12_DEFAULT_ITER, p8); 269 if (bag == NULL) { 270 SUNWerr(SUNW_F_PKCS12_CREATE, 271 SUNW_R_MAKE_BAG_ERR); 272 goto err_ret; 273 } 274 PKCS8_PRIV_KEY_INFO_free(p8); 275 p8 = NULL; 276 277 len = sunw_get_pkey_fname(GETDO_COPY, pkey, 278 (char **)&str); 279 if (str != NULL) { 280 if (PKCS12_add_friendlyname_asc(bag, 281 (const char *)str, len) == 0) { 282 SUNWerr(SUNW_F_PKCS12_CREATE, 283 SUNW_R_ADD_ATTR_ERR); 284 goto err_ret; 285 } 286 } 287 str = NULL; 288 289 len = sunw_get_pkey_localkeyid(GETDO_COPY, pkey, 290 (char **)&str, &len); 291 if (str != NULL) { 292 if (PKCS12_add_localkeyid(bag, str, len) == 0) { 293 SUNWerr(SUNW_F_PKCS12_CREATE, 294 SUNW_R_ADD_ATTR_ERR); 295 goto err_ret; 296 } 297 } 298 str = NULL; 299 300 if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 301 SUNWerr(SUNW_F_PKCS12_CREATE, 302 SUNW_R_MEMORY_FAILURE); 303 goto err_ret; 304 } 305 keys_there++; 306 bag = NULL; 307 } 308 309 if (keys_there) { 310 /* Turn into unencrypted authsafe */ 311 authsafe = PKCS12_pack_p7data(bags); 312 if (authsafe == NULL) { 313 SUNWerr(SUNW_F_PKCS12_CREATE, 314 SUNW_R_PKCS12_CREATE_ERR); 315 goto err_ret; 316 } 317 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 318 bags = NULL; 319 320 if (sk_PKCS7_push(safes, authsafe) == 0) { 321 SUNWerr(SUNW_F_PKCS12_CREATE, 322 SUNW_R_MEMORY_FAILURE); 323 } 324 authsafe = NULL; 325 } 326 } 327 328 if (certs_there == 0 && keys_there == 0) { 329 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_EMPTY_ERR); 330 goto err_ret; 331 } 332 333 if ((p12 = PKCS12_init(NID_pkcs7_data)) == NULL) { 334 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR); 335 goto err_ret; 336 } 337 338 /* 339 * Note that safes is copied by the following. Therefore, it needs 340 * to be freed whether or not the following succeeds. 341 */ 342 if (M_PKCS12_pack_authsafes(p12, safes) == 0) { 343 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR); 344 goto err_ret; 345 } 346 if (PKCS12_set_mac(p12, pass, -1, NULL, 0, 2048, NULL) == 0) { 347 SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MAC_CREATE_FAILURE); 348 goto err_ret; 349 } 350 351 ret_p12 = p12; 352 p12 = NULL; 353 354 /* Fallthrough is intentional */ 355 356 err_ret: 357 358 if (str != NULL) 359 free(str); 360 361 if (p8 != NULL) 362 PKCS8_PRIV_KEY_INFO_free(p8); 363 364 if (bag != NULL) 365 PKCS12_SAFEBAG_free(bag); 366 if (bags != NULL) 367 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 368 if (authsafe != NULL) 369 PKCS7_free(authsafe); 370 if (safes != NULL) 371 sk_PKCS7_pop_free(safes, PKCS7_free); 372 if (p12 != NULL) 373 PKCS12_free(p12); 374 375 return (ret_p12); 376 } 377