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