155714Skris/* p12_kiss.c */
2296341Sdelphij/*
3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296341Sdelphij * 1999.
555714Skris */
655714Skris/* ====================================================================
755714Skris * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14296341Sdelphij *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris
6055714Skris#include <stdio.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/pkcs12.h>
6355714Skris
6455714Skris/* Simplified PKCS#12 routines */
6555714Skris
66296341Sdelphijstatic int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
67296341Sdelphij                      EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
6859191Skris
69296341Sdelphijstatic int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
70296341Sdelphij                      int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
7159191Skris
72296341Sdelphijstatic int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
73296341Sdelphij                     EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
7459191Skris
75296341Sdelphij/*
76296341Sdelphij * Parse and decrypt a PKCS#12 structure returning user key, user cert and
77296341Sdelphij * other (CA) certs. Note either ca should be NULL, *ca should be NULL, or it
78296341Sdelphij * should point to a valid STACK structure. pkey and cert can be passed
79296341Sdelphij * unitialised.
8055714Skris */
8155714Skris
82160814Ssimonint PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
83296341Sdelphij                 STACK_OF(X509) **ca)
8455714Skris{
85296341Sdelphij    STACK_OF(X509) *ocerts = NULL;
86296341Sdelphij    X509 *x = NULL;
87296341Sdelphij    /* Check for NULL PKCS12 structure */
8855714Skris
89296341Sdelphij    if (!p12) {
90296341Sdelphij        PKCS12err(PKCS12_F_PKCS12_PARSE,
91296341Sdelphij                  PKCS12_R_INVALID_NULL_PKCS12_POINTER);
92296341Sdelphij        return 0;
93296341Sdelphij    }
9455714Skris
95296341Sdelphij    if (pkey)
96296341Sdelphij        *pkey = NULL;
97296341Sdelphij    if (cert)
98296341Sdelphij        *cert = NULL;
9955714Skris
100296341Sdelphij    /* Check the mac */
10155714Skris
102296341Sdelphij    /*
103296341Sdelphij     * If password is zero length or NULL then try verifying both cases to
104296341Sdelphij     * determine which password is correct. The reason for this is that under
105296341Sdelphij     * PKCS#12 password based encryption no password and a zero length
106296341Sdelphij     * password are two different things...
107296341Sdelphij     */
10868651Skris
109296341Sdelphij    if (!pass || !*pass) {
110296341Sdelphij        if (PKCS12_verify_mac(p12, NULL, 0))
111296341Sdelphij            pass = NULL;
112296341Sdelphij        else if (PKCS12_verify_mac(p12, "", 0))
113296341Sdelphij            pass = "";
114296341Sdelphij        else {
115296341Sdelphij            PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE);
116296341Sdelphij            goto err;
117296341Sdelphij        }
118296341Sdelphij    } else if (!PKCS12_verify_mac(p12, pass, -1)) {
119296341Sdelphij        PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE);
120296341Sdelphij        goto err;
121296341Sdelphij    }
12255714Skris
123296341Sdelphij    /* Allocate stack for other certificates */
124296341Sdelphij    ocerts = sk_X509_new_null();
125238405Sjkim
126296341Sdelphij    if (!ocerts) {
127296341Sdelphij        PKCS12err(PKCS12_F_PKCS12_PARSE, ERR_R_MALLOC_FAILURE);
128296341Sdelphij        return 0;
129296341Sdelphij    }
130238405Sjkim
131296341Sdelphij    if (!parse_pk12(p12, pass, -1, pkey, ocerts)) {
132296341Sdelphij        PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_PARSE_ERROR);
133296341Sdelphij        goto err;
134296341Sdelphij    }
13555714Skris
136296341Sdelphij    while ((x = sk_X509_pop(ocerts))) {
137296341Sdelphij        if (pkey && *pkey && cert && !*cert) {
138296341Sdelphij            ERR_set_mark();
139296341Sdelphij            if (X509_check_private_key(x, *pkey)) {
140296341Sdelphij                *cert = x;
141296341Sdelphij                x = NULL;
142296341Sdelphij            }
143296341Sdelphij            ERR_pop_to_mark();
144296341Sdelphij        }
145238405Sjkim
146296341Sdelphij        if (ca && x) {
147296341Sdelphij            if (!*ca)
148296341Sdelphij                *ca = sk_X509_new_null();
149296341Sdelphij            if (!*ca)
150296341Sdelphij                goto err;
151296341Sdelphij            if (!sk_X509_push(*ca, x))
152296341Sdelphij                goto err;
153296341Sdelphij            x = NULL;
154296341Sdelphij        }
155296341Sdelphij        if (x)
156296341Sdelphij            X509_free(x);
157296341Sdelphij    }
158238405Sjkim
159296341Sdelphij    if (ocerts)
160296341Sdelphij        sk_X509_pop_free(ocerts, X509_free);
161238405Sjkim
162296341Sdelphij    return 1;
16355714Skris
16459191Skris err:
16555714Skris
166296341Sdelphij    if (pkey && *pkey)
167296341Sdelphij        EVP_PKEY_free(*pkey);
168296341Sdelphij    if (cert && *cert)
169296341Sdelphij        X509_free(*cert);
170296341Sdelphij    if (x)
171296341Sdelphij        X509_free(x);
172296341Sdelphij    if (ocerts)
173296341Sdelphij        sk_X509_pop_free(ocerts, X509_free);
174296341Sdelphij    return 0;
17559191Skris
17655714Skris}
17755714Skris
17855714Skris/* Parse the outer PKCS#12 structure */
17955714Skris
180160814Ssimonstatic int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
181296341Sdelphij                      EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
18255714Skris{
183296341Sdelphij    STACK_OF(PKCS7) *asafes;
184296341Sdelphij    STACK_OF(PKCS12_SAFEBAG) *bags;
185296341Sdelphij    int i, bagnid;
186296341Sdelphij    PKCS7 *p7;
18768651Skris
188296341Sdelphij    if (!(asafes = PKCS12_unpack_authsafes(p12)))
189296341Sdelphij        return 0;
190296341Sdelphij    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
191296341Sdelphij        p7 = sk_PKCS7_value(asafes, i);
192296341Sdelphij        bagnid = OBJ_obj2nid(p7->type);
193296341Sdelphij        if (bagnid == NID_pkcs7_data) {
194296341Sdelphij            bags = PKCS12_unpack_p7data(p7);
195296341Sdelphij        } else if (bagnid == NID_pkcs7_encrypted) {
196296341Sdelphij            bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
197296341Sdelphij        } else
198296341Sdelphij            continue;
199296341Sdelphij        if (!bags) {
200296341Sdelphij            sk_PKCS7_pop_free(asafes, PKCS7_free);
201296341Sdelphij            return 0;
202296341Sdelphij        }
203296341Sdelphij        if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
204296341Sdelphij            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
205296341Sdelphij            sk_PKCS7_pop_free(asafes, PKCS7_free);
206296341Sdelphij            return 0;
207296341Sdelphij        }
208296341Sdelphij        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
209296341Sdelphij    }
210296341Sdelphij    sk_PKCS7_pop_free(asafes, PKCS7_free);
211296341Sdelphij    return 1;
21255714Skris}
21355714Skris
214160814Ssimonstatic int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
215296341Sdelphij                      int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
21655714Skris{
217296341Sdelphij    int i;
218296341Sdelphij    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
219296341Sdelphij        if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i),
220296341Sdelphij                       pass, passlen, pkey, ocerts))
221296341Sdelphij            return 0;
222296341Sdelphij    }
223296341Sdelphij    return 1;
22455714Skris}
22555714Skris
22659191Skrisstatic int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
227296341Sdelphij                     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
22855714Skris{
229296341Sdelphij    PKCS8_PRIV_KEY_INFO *p8;
230296341Sdelphij    X509 *x509;
231296341Sdelphij    ASN1_TYPE *attrib;
232296341Sdelphij    ASN1_BMPSTRING *fname = NULL;
233296341Sdelphij    ASN1_OCTET_STRING *lkid = NULL;
23455714Skris
235296341Sdelphij    if ((attrib = PKCS12_get_attr(bag, NID_friendlyName)))
236296341Sdelphij        fname = attrib->value.bmpstring;
23755714Skris
238296341Sdelphij    if ((attrib = PKCS12_get_attr(bag, NID_localKeyID)))
239296341Sdelphij        lkid = attrib->value.octet_string;
24055714Skris
241296341Sdelphij    switch (M_PKCS12_bag_type(bag)) {
242296341Sdelphij    case NID_keyBag:
243296341Sdelphij        if (!pkey || *pkey)
244296341Sdelphij            return 1;
245296341Sdelphij        if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag)))
246296341Sdelphij            return 0;
247296341Sdelphij        break;
24855714Skris
249296341Sdelphij    case NID_pkcs8ShroudedKeyBag:
250296341Sdelphij        if (!pkey || *pkey)
251296341Sdelphij            return 1;
252296341Sdelphij        if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
253296341Sdelphij            return 0;
254296341Sdelphij        *pkey = EVP_PKCS82PKEY(p8);
255296341Sdelphij        PKCS8_PRIV_KEY_INFO_free(p8);
256296341Sdelphij        if (!(*pkey))
257296341Sdelphij            return 0;
258296341Sdelphij        break;
25955714Skris
260296341Sdelphij    case NID_certBag:
261296341Sdelphij        if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
262296341Sdelphij            return 1;
263296341Sdelphij        if (!(x509 = PKCS12_certbag2x509(bag)))
264296341Sdelphij            return 0;
265296341Sdelphij        if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) {
266296341Sdelphij            X509_free(x509);
267296341Sdelphij            return 0;
268296341Sdelphij        }
269296341Sdelphij        if (fname) {
270296341Sdelphij            int len, r;
271296341Sdelphij            unsigned char *data;
272296341Sdelphij            len = ASN1_STRING_to_UTF8(&data, fname);
273296341Sdelphij            if (len >= 0) {
274296341Sdelphij                r = X509_alias_set1(x509, data, len);
275296341Sdelphij                OPENSSL_free(data);
276296341Sdelphij                if (!r) {
277296341Sdelphij                    X509_free(x509);
278296341Sdelphij                    return 0;
279296341Sdelphij                }
280296341Sdelphij            }
281296341Sdelphij        }
28268651Skris
283296341Sdelphij        if (!sk_X509_push(ocerts, x509)) {
284296341Sdelphij            X509_free(x509);
285296341Sdelphij            return 0;
286296341Sdelphij        }
28768651Skris
288296341Sdelphij        break;
28955714Skris
290296341Sdelphij    case NID_safeContentsBag:
291296341Sdelphij        return parse_bags(bag->value.safes, pass, passlen, pkey, ocerts);
292296341Sdelphij        break;
29355714Skris
294296341Sdelphij    default:
295296341Sdelphij        return 1;
296296341Sdelphij        break;
297296341Sdelphij    }
298296341Sdelphij    return 1;
29955714Skris}
300