xref: /onnv-gate/usr/src/common/openssl/crypto/pkcs12/p12_crt.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* p12_crt.c */
20Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3*2139Sjp161948  * project.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate /* ====================================================================
6*2139Sjp161948  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate  * are met:
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
160Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
170Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
180Sstevel@tonic-gate  *    distribution.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
210Sstevel@tonic-gate  *    software must display the following acknowledgment:
220Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
230Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
260Sstevel@tonic-gate  *    endorse or promote products derived from this software without
270Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
280Sstevel@tonic-gate  *    licensing@OpenSSL.org.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
310Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
320Sstevel@tonic-gate  *    permission of the OpenSSL Project.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
350Sstevel@tonic-gate  *    acknowledgment:
360Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
370Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
400Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
410Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
420Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
430Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
440Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
450Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
460Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
470Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
480Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
490Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
500Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
510Sstevel@tonic-gate  * ====================================================================
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
540Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
550Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include "cryptlib.h"
610Sstevel@tonic-gate #include <openssl/pkcs12.h>
620Sstevel@tonic-gate 
63*2139Sjp161948 
64*2139Sjp161948 static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag);
65*2139Sjp161948 
PKCS12_create(char * pass,char * name,EVP_PKEY * pkey,X509 * cert,STACK_OF (X509)* ca,int nid_key,int nid_cert,int iter,int mac_iter,int keytype)660Sstevel@tonic-gate PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
670Sstevel@tonic-gate 	     STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter,
680Sstevel@tonic-gate 	     int keytype)
690Sstevel@tonic-gate {
70*2139Sjp161948 	PKCS12 *p12 = NULL;
71*2139Sjp161948 	STACK_OF(PKCS7) *safes = NULL;
72*2139Sjp161948 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
73*2139Sjp161948 	PKCS12_SAFEBAG *bag = NULL;
740Sstevel@tonic-gate 	int i;
750Sstevel@tonic-gate 	unsigned char keyid[EVP_MAX_MD_SIZE];
76*2139Sjp161948 	unsigned int keyidlen = 0;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	/* Set defaults */
79*2139Sjp161948 	if (!nid_cert)
80*2139Sjp161948 		nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
81*2139Sjp161948 	if (!nid_key)
82*2139Sjp161948 		nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
83*2139Sjp161948 	if (!iter)
84*2139Sjp161948 		iter = PKCS12_DEFAULT_ITER;
85*2139Sjp161948 	if (!mac_iter)
86*2139Sjp161948 		mac_iter = 1;
870Sstevel@tonic-gate 
88*2139Sjp161948 	if(!pkey && !cert && !ca)
89*2139Sjp161948 		{
900Sstevel@tonic-gate 		PKCS12err(PKCS12_F_PKCS12_CREATE,PKCS12_R_INVALID_NULL_ARGUMENT);
910Sstevel@tonic-gate 		return NULL;
92*2139Sjp161948 		}
930Sstevel@tonic-gate 
94*2139Sjp161948 	if (pkey && cert)
95*2139Sjp161948 		{
96*2139Sjp161948 		if(!X509_check_private_key(cert, pkey))
97*2139Sjp161948 			return NULL;
98*2139Sjp161948 		X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
99*2139Sjp161948 		}
1000Sstevel@tonic-gate 
101*2139Sjp161948 	if (cert)
102*2139Sjp161948 		{
103*2139Sjp161948 		bag = PKCS12_add_cert(&bags, cert);
104*2139Sjp161948 		if(name && !PKCS12_add_friendlyname(bag, name, -1))
105*2139Sjp161948 			goto err;
106*2139Sjp161948 		if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
107*2139Sjp161948 			goto err;
108*2139Sjp161948 		}
109*2139Sjp161948 
1100Sstevel@tonic-gate 	/* Add all other certificates */
111*2139Sjp161948 	for(i = 0; i < sk_X509_num(ca); i++)
112*2139Sjp161948 		{
113*2139Sjp161948 		if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
114*2139Sjp161948 			goto err;
1150Sstevel@tonic-gate 		}
116*2139Sjp161948 
117*2139Sjp161948 	if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
118*2139Sjp161948 			goto err;
119*2139Sjp161948 
120*2139Sjp161948 	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
121*2139Sjp161948 	bags = NULL;
1220Sstevel@tonic-gate 
123*2139Sjp161948 	if (pkey)
124*2139Sjp161948 		{
125*2139Sjp161948 		int cspidx;
126*2139Sjp161948 		bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
1270Sstevel@tonic-gate 
128*2139Sjp161948 		if (!bag)
129*2139Sjp161948 			goto err;
1300Sstevel@tonic-gate 
131*2139Sjp161948 		cspidx = EVP_PKEY_get_attr_by_NID(pkey, NID_ms_csp_name, -1);
132*2139Sjp161948 		if (cspidx >= 0)
133*2139Sjp161948 			{
134*2139Sjp161948 			X509_ATTRIBUTE *cspattr;
135*2139Sjp161948 			cspattr = EVP_PKEY_get_attr(pkey, cspidx);
136*2139Sjp161948 			if (!X509at_add1_attr(&bag->attrib, cspattr))
137*2139Sjp161948 				goto err;
138*2139Sjp161948 			}
139*2139Sjp161948 
140*2139Sjp161948 		if(name && !PKCS12_add_friendlyname(bag, name, -1))
141*2139Sjp161948 			goto err;
142*2139Sjp161948 		if(keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
143*2139Sjp161948 			goto err;
144*2139Sjp161948 		}
145*2139Sjp161948 
146*2139Sjp161948 	if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
147*2139Sjp161948 			goto err;
148*2139Sjp161948 
1490Sstevel@tonic-gate 	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
150*2139Sjp161948 	bags = NULL;
1510Sstevel@tonic-gate 
152*2139Sjp161948 	p12 = PKCS12_add_safes(safes, 0);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	sk_PKCS7_pop_free(safes, PKCS7_free);
1550Sstevel@tonic-gate 
156*2139Sjp161948 	safes = NULL;
157*2139Sjp161948 
158*2139Sjp161948 	if ((mac_iter != -1) &&
159*2139Sjp161948 		!PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
160*2139Sjp161948 	    goto err;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	return p12;
1630Sstevel@tonic-gate 
164*2139Sjp161948 	err:
165*2139Sjp161948 
166*2139Sjp161948 	if (p12)
167*2139Sjp161948 		PKCS12_free(p12);
168*2139Sjp161948 	if (safes)
169*2139Sjp161948 		sk_PKCS7_pop_free(safes, PKCS7_free);
170*2139Sjp161948 	if (bags)
171*2139Sjp161948 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
172*2139Sjp161948 	return NULL;
173*2139Sjp161948 
1740Sstevel@tonic-gate }
175*2139Sjp161948 
PKCS12_add_cert(STACK_OF (PKCS12_SAFEBAG)** pbags,X509 * cert)176*2139Sjp161948 PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
177*2139Sjp161948 	{
178*2139Sjp161948 	PKCS12_SAFEBAG *bag = NULL;
179*2139Sjp161948 	char *name;
180*2139Sjp161948 	int namelen = -1;
181*2139Sjp161948 	unsigned char *keyid;
182*2139Sjp161948 	int keyidlen = -1;
183*2139Sjp161948 
184*2139Sjp161948 	/* Add user certificate */
185*2139Sjp161948 	if(!(bag = PKCS12_x5092certbag(cert)))
186*2139Sjp161948 		goto err;
187*2139Sjp161948 
188*2139Sjp161948 	/* Use friendlyName and localKeyID in certificate.
189*2139Sjp161948 	 * (if present)
190*2139Sjp161948 	 */
191*2139Sjp161948 
192*2139Sjp161948 	name = (char *)X509_alias_get0(cert, &namelen);
193*2139Sjp161948 
194*2139Sjp161948 	if(name && !PKCS12_add_friendlyname(bag, name, namelen))
195*2139Sjp161948 		goto err;
196*2139Sjp161948 
197*2139Sjp161948 	keyid = X509_keyid_get0(cert, &keyidlen);
198*2139Sjp161948 
199*2139Sjp161948 	if(keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
200*2139Sjp161948 		goto err;
201*2139Sjp161948 
202*2139Sjp161948 	if (!pkcs12_add_bag(pbags, bag))
203*2139Sjp161948 		goto err;
204*2139Sjp161948 
205*2139Sjp161948 	return bag;
206*2139Sjp161948 
207*2139Sjp161948 	err:
208*2139Sjp161948 
209*2139Sjp161948 	if (bag)
210*2139Sjp161948 		PKCS12_SAFEBAG_free(bag);
211*2139Sjp161948 
212*2139Sjp161948 	return NULL;
213*2139Sjp161948 
214*2139Sjp161948 	}
215*2139Sjp161948 
PKCS12_add_key(STACK_OF (PKCS12_SAFEBAG)** pbags,EVP_PKEY * key,int key_usage,int iter,int nid_key,char * pass)216*2139Sjp161948 PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
217*2139Sjp161948 						int key_usage, int iter,
218*2139Sjp161948 						int nid_key, char *pass)
219*2139Sjp161948 	{
220*2139Sjp161948 
221*2139Sjp161948 	PKCS12_SAFEBAG *bag = NULL;
222*2139Sjp161948 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
223*2139Sjp161948 
224*2139Sjp161948 	/* Make a PKCS#8 structure */
225*2139Sjp161948 	if(!(p8 = EVP_PKEY2PKCS8(key)))
226*2139Sjp161948 		goto err;
227*2139Sjp161948 	if(key_usage && !PKCS8_add_keyusage(p8, key_usage))
228*2139Sjp161948 		goto err;
229*2139Sjp161948 	if (nid_key != -1)
230*2139Sjp161948 		{
231*2139Sjp161948 		bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, iter, p8);
232*2139Sjp161948 		PKCS8_PRIV_KEY_INFO_free(p8);
233*2139Sjp161948 		}
234*2139Sjp161948 	else
235*2139Sjp161948 		bag = PKCS12_MAKE_KEYBAG(p8);
236*2139Sjp161948 
237*2139Sjp161948 	if(!bag)
238*2139Sjp161948 		goto err;
239*2139Sjp161948 
240*2139Sjp161948 	if (!pkcs12_add_bag(pbags, bag))
241*2139Sjp161948 		goto err;
242*2139Sjp161948 
243*2139Sjp161948 	return bag;
244*2139Sjp161948 
245*2139Sjp161948 	err:
246*2139Sjp161948 
247*2139Sjp161948 	if (bag)
248*2139Sjp161948 		PKCS12_SAFEBAG_free(bag);
249*2139Sjp161948 
250*2139Sjp161948 	return NULL;
251*2139Sjp161948 
252*2139Sjp161948 	}
253*2139Sjp161948 
PKCS12_add_safe(STACK_OF (PKCS7)** psafes,STACK_OF (PKCS12_SAFEBAG)* bags,int nid_safe,int iter,char * pass)254*2139Sjp161948 int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
255*2139Sjp161948 						int nid_safe, int iter, char *pass)
256*2139Sjp161948 	{
257*2139Sjp161948 	PKCS7 *p7 = NULL;
258*2139Sjp161948 	int free_safes = 0;
259*2139Sjp161948 
260*2139Sjp161948 	if (!*psafes)
261*2139Sjp161948 		{
262*2139Sjp161948 		*psafes = sk_PKCS7_new_null();
263*2139Sjp161948 		if (!*psafes)
264*2139Sjp161948 			return 0;
265*2139Sjp161948 		free_safes = 1;
266*2139Sjp161948 		}
267*2139Sjp161948 	else
268*2139Sjp161948 		free_safes = 0;
269*2139Sjp161948 
270*2139Sjp161948 	if (nid_safe == 0)
271*2139Sjp161948 		nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
272*2139Sjp161948 
273*2139Sjp161948 	if (nid_safe == -1)
274*2139Sjp161948 		p7 = PKCS12_pack_p7data(bags);
275*2139Sjp161948 	else
276*2139Sjp161948 		p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0,
277*2139Sjp161948 					  iter, bags);
278*2139Sjp161948 	if (!p7)
279*2139Sjp161948 		goto err;
280*2139Sjp161948 
281*2139Sjp161948 	if (!sk_PKCS7_push(*psafes, p7))
282*2139Sjp161948 		goto err;
283*2139Sjp161948 
284*2139Sjp161948 	return 1;
285*2139Sjp161948 
286*2139Sjp161948 	err:
287*2139Sjp161948 	if (free_safes)
288*2139Sjp161948 		{
289*2139Sjp161948 		sk_PKCS7_free(*psafes);
290*2139Sjp161948 		*psafes = NULL;
291*2139Sjp161948 		}
292*2139Sjp161948 
293*2139Sjp161948 	if (p7)
294*2139Sjp161948 		PKCS7_free(p7);
295*2139Sjp161948 
296*2139Sjp161948 	return 0;
297*2139Sjp161948 
298*2139Sjp161948 	}
299*2139Sjp161948 
pkcs12_add_bag(STACK_OF (PKCS12_SAFEBAG)** pbags,PKCS12_SAFEBAG * bag)300*2139Sjp161948 static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag)
301*2139Sjp161948 	{
302*2139Sjp161948 	int free_bags;
303*2139Sjp161948 	if (!pbags)
304*2139Sjp161948 		return 1;
305*2139Sjp161948 	if (!*pbags)
306*2139Sjp161948 		{
307*2139Sjp161948 		*pbags = sk_PKCS12_SAFEBAG_new_null();
308*2139Sjp161948 		if (!*pbags)
309*2139Sjp161948 			return 0;
310*2139Sjp161948 		free_bags = 1;
311*2139Sjp161948 		}
312*2139Sjp161948 	else
313*2139Sjp161948 		free_bags = 0;
314*2139Sjp161948 
315*2139Sjp161948 	if (!sk_PKCS12_SAFEBAG_push(*pbags, bag))
316*2139Sjp161948 		{
317*2139Sjp161948 		if (free_bags)
318*2139Sjp161948 			{
319*2139Sjp161948 			sk_PKCS12_SAFEBAG_free(*pbags);
320*2139Sjp161948 			*pbags = NULL;
321*2139Sjp161948 			}
322*2139Sjp161948 		return 0;
323*2139Sjp161948 		}
324*2139Sjp161948 
325*2139Sjp161948 	return 1;
326*2139Sjp161948 
327*2139Sjp161948 	}
328*2139Sjp161948 
329*2139Sjp161948 
PKCS12_add_safes(STACK_OF (PKCS7)* safes,int nid_p7)330*2139Sjp161948 PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
331*2139Sjp161948 	{
332*2139Sjp161948 	PKCS12 *p12;
333*2139Sjp161948 	if (nid_p7 <= 0)
334*2139Sjp161948 		nid_p7 = NID_pkcs7_data;
335*2139Sjp161948 	p12 = PKCS12_init(nid_p7);
336*2139Sjp161948 
337*2139Sjp161948 	if (!p12)
338*2139Sjp161948 		return NULL;
339*2139Sjp161948 
340*2139Sjp161948 	if(!PKCS12_pack_authsafes(p12, safes))
341*2139Sjp161948 		{
342*2139Sjp161948 		PKCS12_free(p12);
343*2139Sjp161948 		return NULL;
344*2139Sjp161948 		}
345*2139Sjp161948 
346*2139Sjp161948 	return p12;
347*2139Sjp161948 
348*2139Sjp161948 	}
349