1*00e52b80Stb /* $OpenBSD: p12_kiss.c,v 1.28 2025/01/06 23:35:25 tb Exp $ */ 2e6841c1dSdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 37695d5a3Sbeck * project 1999. 47695d5a3Sbeck */ 57695d5a3Sbeck /* ==================================================================== 67695d5a3Sbeck * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 77695d5a3Sbeck * 87695d5a3Sbeck * Redistribution and use in source and binary forms, with or without 97695d5a3Sbeck * modification, are permitted provided that the following conditions 107695d5a3Sbeck * are met: 117695d5a3Sbeck * 127695d5a3Sbeck * 1. Redistributions of source code must retain the above copyright 137695d5a3Sbeck * notice, this list of conditions and the following disclaimer. 147695d5a3Sbeck * 157695d5a3Sbeck * 2. Redistributions in binary form must reproduce the above copyright 167695d5a3Sbeck * notice, this list of conditions and the following disclaimer in 177695d5a3Sbeck * the documentation and/or other materials provided with the 187695d5a3Sbeck * distribution. 197695d5a3Sbeck * 207695d5a3Sbeck * 3. All advertising materials mentioning features or use of this 217695d5a3Sbeck * software must display the following acknowledgment: 227695d5a3Sbeck * "This product includes software developed by the OpenSSL Project 237695d5a3Sbeck * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 247695d5a3Sbeck * 257695d5a3Sbeck * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 267695d5a3Sbeck * endorse or promote products derived from this software without 277695d5a3Sbeck * prior written permission. For written permission, please contact 287695d5a3Sbeck * licensing@OpenSSL.org. 297695d5a3Sbeck * 307695d5a3Sbeck * 5. Products derived from this software may not be called "OpenSSL" 317695d5a3Sbeck * nor may "OpenSSL" appear in their names without prior written 327695d5a3Sbeck * permission of the OpenSSL Project. 337695d5a3Sbeck * 347695d5a3Sbeck * 6. Redistributions of any form whatsoever must retain the following 357695d5a3Sbeck * acknowledgment: 367695d5a3Sbeck * "This product includes software developed by the OpenSSL Project 377695d5a3Sbeck * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 387695d5a3Sbeck * 397695d5a3Sbeck * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 407695d5a3Sbeck * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 417695d5a3Sbeck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 427695d5a3Sbeck * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 437695d5a3Sbeck * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 447695d5a3Sbeck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 457695d5a3Sbeck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 467695d5a3Sbeck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 477695d5a3Sbeck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 487695d5a3Sbeck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 497695d5a3Sbeck * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 507695d5a3Sbeck * OF THE POSSIBILITY OF SUCH DAMAGE. 517695d5a3Sbeck * ==================================================================== 527695d5a3Sbeck * 537695d5a3Sbeck * This product includes cryptographic software written by Eric Young 547695d5a3Sbeck * (eay@cryptsoft.com). This product includes software written by Tim 557695d5a3Sbeck * Hudson (tjh@cryptsoft.com). 567695d5a3Sbeck * 577695d5a3Sbeck */ 587695d5a3Sbeck 597695d5a3Sbeck #include <stdio.h> 60b6ab114eSjsing 61b6ab114eSjsing #include <openssl/err.h> 627695d5a3Sbeck #include <openssl/pkcs12.h> 637695d5a3Sbeck 64e4978644Stb #include "pkcs12_local.h" 65e4978644Stb 667695d5a3Sbeck /* Simplified PKCS#12 routines */ 677695d5a3Sbeck 68f6e3f262Sbeck static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, 690a5d6edeSdjm EVP_PKEY **pkey, STACK_OF(X509) *ocerts); 70f6e3f262Sbeck 71c109e398Sbeck static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, 720a5d6edeSdjm int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); 73f6e3f262Sbeck 74f6e3f262Sbeck static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, 750a5d6edeSdjm EVP_PKEY **pkey, STACK_OF(X509) *ocerts); 76f6e3f262Sbeck 777695d5a3Sbeck /* Parse and decrypt a PKCS#12 structure returning user key, user cert 787695d5a3Sbeck * and other (CA) certs. Note either ca should be NULL, *ca should be NULL, 797695d5a3Sbeck * or it should point to a valid STACK structure. pkey and cert can be 80*00e52b80Stb * passed uninitialised. 817695d5a3Sbeck */ 827695d5a3Sbeck 83d2af6916Sjsing int 84d2af6916Sjsing PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, 85f6e3f262Sbeck STACK_OF(X509) **ca) 867695d5a3Sbeck { 870a5d6edeSdjm STACK_OF(X509) *ocerts = NULL; 880a5d6edeSdjm X509 *x = NULL; 897695d5a3Sbeck 90fc53f9beStb if (pkey != NULL) 910a5d6edeSdjm *pkey = NULL; 92fc53f9beStb if (cert != NULL) 930a5d6edeSdjm *cert = NULL; 947695d5a3Sbeck 95fc53f9beStb if (p12 == NULL) { 96fc53f9beStb PKCS12error(PKCS12_R_INVALID_NULL_PKCS12_POINTER); 97fc53f9beStb goto err; 98fc53f9beStb } 99fc53f9beStb 1007695d5a3Sbeck /* Check the mac */ 1017695d5a3Sbeck 102c109e398Sbeck /* If password is zero length or NULL then try verifying both cases 103c109e398Sbeck * to determine which password is correct. The reason for this is that 104c109e398Sbeck * under PKCS#12 password based encryption no password and a zero length 105c109e398Sbeck * password are two different things... 106c109e398Sbeck */ 107c109e398Sbeck 108fc53f9beStb if (pass == NULL || *pass == '\0') { 109d2af6916Sjsing if (PKCS12_verify_mac(p12, NULL, 0)) 110d2af6916Sjsing pass = NULL; 111d2af6916Sjsing else if (PKCS12_verify_mac(p12, "", 0)) 112d2af6916Sjsing pass = ""; 113c109e398Sbeck else { 1145067ae9fSbeck PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE); 115c109e398Sbeck goto err; 116c109e398Sbeck } 117c109e398Sbeck } else if (!PKCS12_verify_mac(p12, pass, -1)) { 1185067ae9fSbeck PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE); 1197695d5a3Sbeck goto err; 1207695d5a3Sbeck } 1217695d5a3Sbeck 1220a5d6edeSdjm /* Allocate stack for other certificates */ 123fc53f9beStb if ((ocerts = sk_X509_new_null()) == NULL) { 1245067ae9fSbeck PKCS12error(ERR_R_MALLOC_FAILURE); 125fc53f9beStb goto err; 1260a5d6edeSdjm } 1270a5d6edeSdjm 128d2af6916Sjsing if (!parse_pk12(p12, pass, -1, pkey, ocerts)) { 1295067ae9fSbeck PKCS12error(PKCS12_R_PARSE_ERROR); 1307695d5a3Sbeck goto err; 1317695d5a3Sbeck } 1327695d5a3Sbeck 133fc53f9beStb while ((x = sk_X509_pop(ocerts)) != NULL) { 134fc53f9beStb if (pkey != NULL && *pkey != NULL && 135fc53f9beStb cert != NULL && *cert == NULL) { 136c95ff24dStb ERR_set_mark(); 137d2af6916Sjsing if (X509_check_private_key(x, *pkey)) { 1380a5d6edeSdjm *cert = x; 1390a5d6edeSdjm x = NULL; 1400a5d6edeSdjm } 141c95ff24dStb ERR_pop_to_mark(); 1420a5d6edeSdjm } 1430a5d6edeSdjm 144fc53f9beStb if (ca != NULL && x != NULL) { 145fc53f9beStb if (*ca == NULL) 1460a5d6edeSdjm *ca = sk_X509_new_null(); 147fc53f9beStb if (*ca == NULL) 1480a5d6edeSdjm goto err; 1490a5d6edeSdjm if (!sk_X509_push(*ca, x)) 1500a5d6edeSdjm goto err; 1510a5d6edeSdjm x = NULL; 1520a5d6edeSdjm } 1530a5d6edeSdjm X509_free(x); 154fc53f9beStb x = NULL; 1550a5d6edeSdjm } 1560a5d6edeSdjm 1570a5d6edeSdjm sk_X509_pop_free(ocerts, X509_free); 1580a5d6edeSdjm 1597695d5a3Sbeck return 1; 1607695d5a3Sbeck 1617695d5a3Sbeck err: 162fc53f9beStb if (pkey != NULL) 1630a5d6edeSdjm EVP_PKEY_free(*pkey); 164fc53f9beStb if (cert != NULL) 1650a5d6edeSdjm X509_free(*cert); 1665cdd308eSdjm X509_free(x); 1670a5d6edeSdjm sk_X509_pop_free(ocerts, X509_free); 168fc53f9beStb 1697695d5a3Sbeck return 0; 1707695d5a3Sbeck } 171cedac418Stb LCRYPTO_ALIAS(PKCS12_parse); 1727695d5a3Sbeck 1737695d5a3Sbeck /* Parse the outer PKCS#12 structure */ 1747695d5a3Sbeck 175d2af6916Sjsing static int 176d2af6916Sjsing parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, 177d2af6916Sjsing STACK_OF(X509) *ocerts) 1787695d5a3Sbeck { 179c109e398Sbeck STACK_OF(PKCS7) *asafes; 180c109e398Sbeck STACK_OF(PKCS12_SAFEBAG) *bags; 1817695d5a3Sbeck int i, bagnid; 1827695d5a3Sbeck PKCS7 *p7; 183c109e398Sbeck 184d2af6916Sjsing if (!(asafes = PKCS12_unpack_authsafes(p12))) 185d2af6916Sjsing return 0; 186c109e398Sbeck for (i = 0; i < sk_PKCS7_num(asafes); i++) { 187c109e398Sbeck p7 = sk_PKCS7_value(asafes, i); 1887695d5a3Sbeck bagnid = OBJ_obj2nid(p7->type); 1897695d5a3Sbeck if (bagnid == NID_pkcs7_data) { 190da347917Sbeck bags = PKCS12_unpack_p7data(p7); 1917695d5a3Sbeck } else if (bagnid == NID_pkcs7_encrypted) { 192da347917Sbeck bags = PKCS12_unpack_p7encdata(p7, pass, passlen); 193d2af6916Sjsing } else 194d2af6916Sjsing continue; 1957695d5a3Sbeck if (!bags) { 196c109e398Sbeck sk_PKCS7_pop_free(asafes, PKCS7_free); 1977695d5a3Sbeck return 0; 1987695d5a3Sbeck } 1990a5d6edeSdjm if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { 200c109e398Sbeck sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 201c109e398Sbeck sk_PKCS7_pop_free(asafes, PKCS7_free); 2027695d5a3Sbeck return 0; 2037695d5a3Sbeck } 204c109e398Sbeck sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 2057695d5a3Sbeck } 206c109e398Sbeck sk_PKCS7_pop_free(asafes, PKCS7_free); 2077695d5a3Sbeck return 1; 2087695d5a3Sbeck } 2097695d5a3Sbeck 210d2af6916Sjsing static int 211d2af6916Sjsing parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen, 212d2af6916Sjsing EVP_PKEY **pkey, STACK_OF(X509) *ocerts) 2137695d5a3Sbeck { 2147695d5a3Sbeck int i; 215d2af6916Sjsing 216c109e398Sbeck for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 217d2af6916Sjsing if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), pass, passlen, 218d2af6916Sjsing pkey, ocerts)) 2190a5d6edeSdjm return 0; 2207695d5a3Sbeck } 2217695d5a3Sbeck return 1; 2227695d5a3Sbeck } 2237695d5a3Sbeck 224d2af6916Sjsing static int 225d2af6916Sjsing parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey, 226d2af6916Sjsing STACK_OF(X509) *ocerts) 2277695d5a3Sbeck { 2287695d5a3Sbeck PKCS8_PRIV_KEY_INFO *p8; 2297695d5a3Sbeck X509 *x509; 230b9c7d6b6Stb const ASN1_TYPE *attrib; 231c109e398Sbeck ASN1_BMPSTRING *fname = NULL; 2320a5d6edeSdjm ASN1_OCTET_STRING *lkid = NULL; 2337695d5a3Sbeck 234b9c7d6b6Stb if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) 235c109e398Sbeck fname = attrib->value.bmpstring; 2367695d5a3Sbeck 237b9c7d6b6Stb if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) 2380a5d6edeSdjm lkid = attrib->value.octet_string; 2397695d5a3Sbeck 240817b2ad6Sjsing switch (OBJ_obj2nid(bag->type)) { 2417695d5a3Sbeck case NID_keyBag: 2420a5d6edeSdjm if (!pkey || *pkey) 2430a5d6edeSdjm return 1; 2440a5d6edeSdjm if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag))) 2450a5d6edeSdjm return 0; 2467695d5a3Sbeck break; 2477695d5a3Sbeck 2487695d5a3Sbeck case NID_pkcs8ShroudedKeyBag: 2490a5d6edeSdjm if (!pkey || *pkey) 2500a5d6edeSdjm return 1; 251da347917Sbeck if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) 2527695d5a3Sbeck return 0; 2537695d5a3Sbeck *pkey = EVP_PKCS82PKEY(p8); 2547695d5a3Sbeck PKCS8_PRIV_KEY_INFO_free(p8); 255d2af6916Sjsing if (!(*pkey)) 256d2af6916Sjsing return 0; 2577695d5a3Sbeck break; 2587695d5a3Sbeck 2597695d5a3Sbeck case NID_certBag: 260817b2ad6Sjsing if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate ) 2617695d5a3Sbeck return 1; 2620a5d6edeSdjm if (!(x509 = PKCS12_certbag2x509(bag))) 2630a5d6edeSdjm return 0; 264d2af6916Sjsing if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) { 26540d8aef3Sdjm X509_free(x509); 26640d8aef3Sdjm return 0; 26740d8aef3Sdjm } 268c109e398Sbeck if (fname) { 26940d8aef3Sdjm int len, r; 270b356bd23Stb unsigned char *data = NULL; 271c109e398Sbeck len = ASN1_STRING_to_UTF8(&data, fname); 272d8bfa24eSlogan if (len >= 0) { 27340d8aef3Sdjm r = X509_alias_set1(x509, data, len); 2746f3a6cb1Sbeck free(data); 275d2af6916Sjsing if (!r) { 27640d8aef3Sdjm X509_free(x509); 27740d8aef3Sdjm return 0; 27840d8aef3Sdjm } 279c109e398Sbeck } 280c109e398Sbeck } 281c109e398Sbeck 282d2af6916Sjsing if (!sk_X509_push(ocerts, x509)) { 2830a5d6edeSdjm X509_free(x509); 2840a5d6edeSdjm return 0; 285f6e3f262Sbeck } 2860a5d6edeSdjm 2877695d5a3Sbeck break; 2887695d5a3Sbeck 2897695d5a3Sbeck case NID_safeContentsBag: 2907695d5a3Sbeck return parse_bags(bag->value.safes, pass, passlen, 2910a5d6edeSdjm pkey, ocerts); 2927695d5a3Sbeck break; 2937695d5a3Sbeck 2947695d5a3Sbeck default: 2957695d5a3Sbeck return 1; 2967695d5a3Sbeck break; 2977695d5a3Sbeck } 2987695d5a3Sbeck return 1; 2997695d5a3Sbeck } 300