p12_crt.c revision 296341
1/* p12_crt.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 1999-2002 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#include <stdio.h>
61#include "cryptlib.h"
62#include <openssl/pkcs12.h>
63
64static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
65                          PKCS12_SAFEBAG *bag);
66
67static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
68{
69    int idx;
70    X509_ATTRIBUTE *attr;
71    idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1);
72    if (idx < 0)
73        return 1;
74    attr = EVP_PKEY_get_attr(pkey, idx);
75    if (!X509at_add1_attr(&bag->attrib, attr))
76        return 0;
77    return 1;
78}
79
80PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
81                      STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
82                      int mac_iter, int keytype)
83{
84    PKCS12 *p12 = NULL;
85    STACK_OF(PKCS7) *safes = NULL;
86    STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
87    PKCS12_SAFEBAG *bag = NULL;
88    int i;
89    unsigned char keyid[EVP_MAX_MD_SIZE];
90    unsigned int keyidlen = 0;
91
92    /* Set defaults */
93    if (!nid_cert) {
94#ifdef OPENSSL_FIPS
95        if (FIPS_mode())
96            nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
97        else
98#endif
99#ifdef OPENSSL_NO_RC2
100            nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
101#else
102            nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
103#endif
104    }
105    if (!nid_key)
106        nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
107    if (!iter)
108        iter = PKCS12_DEFAULT_ITER;
109    if (!mac_iter)
110        mac_iter = 1;
111
112    if (!pkey && !cert && !ca) {
113        PKCS12err(PKCS12_F_PKCS12_CREATE, PKCS12_R_INVALID_NULL_ARGUMENT);
114        return NULL;
115    }
116
117    if (pkey && cert) {
118        if (!X509_check_private_key(cert, pkey))
119            return NULL;
120        X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
121    }
122
123    if (cert) {
124        bag = PKCS12_add_cert(&bags, cert);
125        if (name && !PKCS12_add_friendlyname(bag, name, -1))
126            goto err;
127        if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
128            goto err;
129    }
130
131    /* Add all other certificates */
132    for (i = 0; i < sk_X509_num(ca); i++) {
133        if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
134            goto err;
135    }
136
137    if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
138        goto err;
139
140    sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
141    bags = NULL;
142
143    if (pkey) {
144        bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
145
146        if (!bag)
147            goto err;
148
149        if (!copy_bag_attr(bag, pkey, NID_ms_csp_name))
150            goto err;
151        if (!copy_bag_attr(bag, pkey, NID_LocalKeySet))
152            goto err;
153
154        if (name && !PKCS12_add_friendlyname(bag, name, -1))
155            goto err;
156        if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
157            goto err;
158    }
159
160    if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
161        goto err;
162
163    sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
164    bags = NULL;
165
166    p12 = PKCS12_add_safes(safes, 0);
167
168    if (!p12)
169        goto err;
170
171    sk_PKCS7_pop_free(safes, PKCS7_free);
172
173    safes = NULL;
174
175    if ((mac_iter != -1) &&
176        !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
177        goto err;
178
179    return p12;
180
181 err:
182
183    if (p12)
184        PKCS12_free(p12);
185    if (safes)
186        sk_PKCS7_pop_free(safes, PKCS7_free);
187    if (bags)
188        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
189    return NULL;
190
191}
192
193PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
194{
195    PKCS12_SAFEBAG *bag = NULL;
196    char *name;
197    int namelen = -1;
198    unsigned char *keyid;
199    int keyidlen = -1;
200
201    /* Add user certificate */
202    if (!(bag = PKCS12_x5092certbag(cert)))
203        goto err;
204
205    /*
206     * Use friendlyName and localKeyID in certificate. (if present)
207     */
208
209    name = (char *)X509_alias_get0(cert, &namelen);
210
211    if (name && !PKCS12_add_friendlyname(bag, name, namelen))
212        goto err;
213
214    keyid = X509_keyid_get0(cert, &keyidlen);
215
216    if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
217        goto err;
218
219    if (!pkcs12_add_bag(pbags, bag))
220        goto err;
221
222    return bag;
223
224 err:
225
226    if (bag)
227        PKCS12_SAFEBAG_free(bag);
228
229    return NULL;
230
231}
232
233PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
234                               EVP_PKEY *key, int key_usage, int iter,
235                               int nid_key, char *pass)
236{
237
238    PKCS12_SAFEBAG *bag = NULL;
239    PKCS8_PRIV_KEY_INFO *p8 = NULL;
240
241    /* Make a PKCS#8 structure */
242    if (!(p8 = EVP_PKEY2PKCS8(key)))
243        goto err;
244    if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
245        goto err;
246    if (nid_key != -1) {
247        bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, iter, p8);
248        PKCS8_PRIV_KEY_INFO_free(p8);
249    } else
250        bag = PKCS12_MAKE_KEYBAG(p8);
251
252    if (!bag)
253        goto err;
254
255    if (!pkcs12_add_bag(pbags, bag))
256        goto err;
257
258    return bag;
259
260 err:
261
262    if (bag)
263        PKCS12_SAFEBAG_free(bag);
264
265    return NULL;
266
267}
268
269int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
270                    int nid_safe, int iter, char *pass)
271{
272    PKCS7 *p7 = NULL;
273    int free_safes = 0;
274
275    if (!*psafes) {
276        *psafes = sk_PKCS7_new_null();
277        if (!*psafes)
278            return 0;
279        free_safes = 1;
280    } else
281        free_safes = 0;
282
283    if (nid_safe == 0)
284#ifdef OPENSSL_NO_RC2
285        nid_safe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
286#else
287        nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
288#endif
289
290    if (nid_safe == -1)
291        p7 = PKCS12_pack_p7data(bags);
292    else
293        p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0, iter, bags);
294    if (!p7)
295        goto err;
296
297    if (!sk_PKCS7_push(*psafes, p7))
298        goto err;
299
300    return 1;
301
302 err:
303    if (free_safes) {
304        sk_PKCS7_free(*psafes);
305        *psafes = NULL;
306    }
307
308    if (p7)
309        PKCS7_free(p7);
310
311    return 0;
312
313}
314
315static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
316                          PKCS12_SAFEBAG *bag)
317{
318    int free_bags;
319    if (!pbags)
320        return 1;
321    if (!*pbags) {
322        *pbags = sk_PKCS12_SAFEBAG_new_null();
323        if (!*pbags)
324            return 0;
325        free_bags = 1;
326    } else
327        free_bags = 0;
328
329    if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) {
330        if (free_bags) {
331            sk_PKCS12_SAFEBAG_free(*pbags);
332            *pbags = NULL;
333        }
334        return 0;
335    }
336
337    return 1;
338
339}
340
341PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
342{
343    PKCS12 *p12;
344    if (nid_p7 <= 0)
345        nid_p7 = NID_pkcs7_data;
346    p12 = PKCS12_init(nid_p7);
347
348    if (!p12)
349        return NULL;
350
351    if (!PKCS12_pack_authsafes(p12, safes)) {
352        PKCS12_free(p12);
353        return NULL;
354    }
355
356    return p12;
357
358}
359