xref: /titanic_51/usr/src/common/net/wanboot/auxutil.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * ====================================================================
3*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
6*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
7*7c478bd9Sstevel@tonic-gate  * are met:
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
10*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
13*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
14*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
15*7c478bd9Sstevel@tonic-gate  *    distribution.
16*7c478bd9Sstevel@tonic-gate  *
17*7c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
18*7c478bd9Sstevel@tonic-gate  *    software must display the following acknowledgment:
19*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
20*7c478bd9Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
24*7c478bd9Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
25*7c478bd9Sstevel@tonic-gate  *    licensing@OpenSSL.org.
26*7c478bd9Sstevel@tonic-gate  *
27*7c478bd9Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
28*7c478bd9Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
29*7c478bd9Sstevel@tonic-gate  *    permission of the OpenSSL Project.
30*7c478bd9Sstevel@tonic-gate  *
31*7c478bd9Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
32*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
33*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
34*7c478bd9Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37*7c478bd9Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39*7c478bd9Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40*7c478bd9Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41*7c478bd9Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42*7c478bd9Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43*7c478bd9Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44*7c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45*7c478bd9Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46*7c478bd9Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47*7c478bd9Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
48*7c478bd9Sstevel@tonic-gate  * ====================================================================
49*7c478bd9Sstevel@tonic-gate  *
50*7c478bd9Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
51*7c478bd9Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
52*7c478bd9Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
53*7c478bd9Sstevel@tonic-gate  *
54*7c478bd9Sstevel@tonic-gate  */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * Copyright 2002, 2003 Sun Microsystems, Inc.  All rights reserved.
58*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
59*7c478bd9Sstevel@tonic-gate  *
60*7c478bd9Sstevel@tonic-gate  * All of the functions included here are internal to the pkcs12 functions
61*7c478bd9Sstevel@tonic-gate  * in this library.  None of these are exposed.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #include <stdio.h>
67*7c478bd9Sstevel@tonic-gate #include <string.h>
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate #include <openssl/crypto.h>
70*7c478bd9Sstevel@tonic-gate #include <openssl/err.h>
71*7c478bd9Sstevel@tonic-gate #include <openssl/x509.h>
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate #include <openssl/pkcs12.h>
74*7c478bd9Sstevel@tonic-gate #include <p12aux.h>
75*7c478bd9Sstevel@tonic-gate #include <auxutil.h>
76*7c478bd9Sstevel@tonic-gate #include <p12err.h>
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in
80*7c478bd9Sstevel@tonic-gate  *         ASN1_BMPSTRING format.
81*7c478bd9Sstevel@tonic-gate  *
82*7c478bd9Sstevel@tonic-gate  * Arguments:
83*7c478bd9Sstevel@tonic-gate  *   str      - String to be convered.
84*7c478bd9Sstevel@tonic-gate  *   len      - Length of the string.
85*7c478bd9Sstevel@tonic-gate  *
86*7c478bd9Sstevel@tonic-gate  * Returns:
87*7c478bd9Sstevel@tonic-gate  *   == NULL  - An error occurred.  Error information (accessible by
88*7c478bd9Sstevel@tonic-gate  *              ERR_get_error()) is set.
89*7c478bd9Sstevel@tonic-gate  *   != NULL  - Points to an ASN1_BMPSTRING structure with the converted
90*7c478bd9Sstevel@tonic-gate  *              string as a value.
91*7c478bd9Sstevel@tonic-gate  */
92*7c478bd9Sstevel@tonic-gate ASN1_BMPSTRING *
93*7c478bd9Sstevel@tonic-gate asc2bmpstring(const char *str, int len)
94*7c478bd9Sstevel@tonic-gate {
95*7c478bd9Sstevel@tonic-gate 	ASN1_BMPSTRING *bmp = NULL;
96*7c478bd9Sstevel@tonic-gate 	uchar_t *uni = NULL;
97*7c478bd9Sstevel@tonic-gate 	int unilen;
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	/* Convert the character to the bmp format. */
100*7c478bd9Sstevel@tonic-gate 	if (asc2uni(str, len, &uni, &unilen) == 0) {
101*7c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
102*7c478bd9Sstevel@tonic-gate 		return (NULL);
103*7c478bd9Sstevel@tonic-gate 	}
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	/*
106*7c478bd9Sstevel@tonic-gate 	 * Adjust for possible pair of NULL bytes at the end because
107*7c478bd9Sstevel@tonic-gate 	 * asc2uni() returns a doubly null terminated string.
108*7c478bd9Sstevel@tonic-gate 	 */
109*7c478bd9Sstevel@tonic-gate 	if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0')
110*7c478bd9Sstevel@tonic-gate 		unilen -= 2;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	/* Construct comparison string with correct format */
113*7c478bd9Sstevel@tonic-gate 	bmp = M_ASN1_BMPSTRING_new();
114*7c478bd9Sstevel@tonic-gate 	if (bmp == NULL) {
115*7c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
116*7c478bd9Sstevel@tonic-gate 		OPENSSL_free(uni);
117*7c478bd9Sstevel@tonic-gate 		return (NULL);
118*7c478bd9Sstevel@tonic-gate 	}
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	bmp->data = uni;
121*7c478bd9Sstevel@tonic-gate 	bmp->length = unilen;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	return (bmp);
124*7c478bd9Sstevel@tonic-gate }
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate /*
127*7c478bd9Sstevel@tonic-gate  * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string.
128*7c478bd9Sstevel@tonic-gate  *         This goes through an intermediate step with a ASN1_STRING type of
129*7c478bd9Sstevel@tonic-gate  *         IA5STRING (International Alphabet 5, which is the same as ASCII).
130*7c478bd9Sstevel@tonic-gate  *
131*7c478bd9Sstevel@tonic-gate  * Arguments:
132*7c478bd9Sstevel@tonic-gate  *   str      - UTF8STRING to be converted.
133*7c478bd9Sstevel@tonic-gate  *
134*7c478bd9Sstevel@tonic-gate  * Returns:
135*7c478bd9Sstevel@tonic-gate  *   == NULL  - An error occurred.  Error information (accessible by
136*7c478bd9Sstevel@tonic-gate  *              ERR_get_error()) is set.
137*7c478bd9Sstevel@tonic-gate  *   != NULL  - Points to a NULL-termianted ASCII string.  The caller must
138*7c478bd9Sstevel@tonic-gate  *              free it.
139*7c478bd9Sstevel@tonic-gate  */
140*7c478bd9Sstevel@tonic-gate uchar_t *
141*7c478bd9Sstevel@tonic-gate utf82ascstr(ASN1_UTF8STRING *ustr)
142*7c478bd9Sstevel@tonic-gate {
143*7c478bd9Sstevel@tonic-gate 	ASN1_STRING tmpstr;
144*7c478bd9Sstevel@tonic-gate 	ASN1_STRING *astr = &tmpstr;
145*7c478bd9Sstevel@tonic-gate 	uchar_t *retstr = NULL;
146*7c478bd9Sstevel@tonic-gate 	int mbflag;
147*7c478bd9Sstevel@tonic-gate 	int ret;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) {
150*7c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG);
151*7c478bd9Sstevel@tonic-gate 		return (NULL);
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	mbflag = MBSTRING_ASC;
155*7c478bd9Sstevel@tonic-gate 	tmpstr.data = NULL;
156*7c478bd9Sstevel@tonic-gate 	tmpstr.length = 0;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag,
159*7c478bd9Sstevel@tonic-gate 	    B_ASN1_IA5STRING);
160*7c478bd9Sstevel@tonic-gate 	if (ret < 0) {
161*7c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR);
162*7c478bd9Sstevel@tonic-gate 		return (NULL);
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	retstr = OPENSSL_malloc(astr->length + 1);
166*7c478bd9Sstevel@tonic-gate 	if (retstr == NULL) {
167*7c478bd9Sstevel@tonic-gate 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE);
168*7c478bd9Sstevel@tonic-gate 		return (NULL);
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	(void) memcpy(retstr, astr->data, astr->length);
172*7c478bd9Sstevel@tonic-gate 	retstr[astr->length] = '\0';
173*7c478bd9Sstevel@tonic-gate 	OPENSSL_free(astr->data);
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	return (retstr);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate  * set_results - Given two pointers to stacks of private keys, certs or CA
180*7c478bd9Sstevel@tonic-gate  *     CA certs, either copy the second stack to the first, or append the
181*7c478bd9Sstevel@tonic-gate  *     contents of the second to the first.
182*7c478bd9Sstevel@tonic-gate  *
183*7c478bd9Sstevel@tonic-gate  * Arguments:
184*7c478bd9Sstevel@tonic-gate  *   pkeys    - Points to stack of pkeys
185*7c478bd9Sstevel@tonic-gate  *   work_kl  - Points to working stack of pkeys
186*7c478bd9Sstevel@tonic-gate  *   certs    - Points to stack of certs
187*7c478bd9Sstevel@tonic-gate  *   work_cl  - Points to working stack of certs
188*7c478bd9Sstevel@tonic-gate  *   cacerts  - Points to stack of CA certs
189*7c478bd9Sstevel@tonic-gate  *   work_ca  - Points to working stack of CA certs
190*7c478bd9Sstevel@tonic-gate  *   xtrakeys - Points to stack of unmatcned pkeys
191*7c478bd9Sstevel@tonic-gate  *   work_xl  - Points to working stack of unmatcned pkeys
192*7c478bd9Sstevel@tonic-gate  *
193*7c478bd9Sstevel@tonic-gate  *   The arguments are in pairs.  The first of each pair points to a stack
194*7c478bd9Sstevel@tonic-gate  *   of keys or certs.  The second of the pair points at a 'working stack'
195*7c478bd9Sstevel@tonic-gate  *   of the same type of entities.   Actions taken are as follows:
196*7c478bd9Sstevel@tonic-gate  *
197*7c478bd9Sstevel@tonic-gate  *   - If either the first or second argument is NULL, or if there are no
198*7c478bd9Sstevel@tonic-gate  *     members in the second stack, there is nothing to do.
199*7c478bd9Sstevel@tonic-gate  *   - If the first argument points to a pointer which is NULL, then there
200*7c478bd9Sstevel@tonic-gate  *     is no existing stack for the first argument.  Copy the stack pointer
201*7c478bd9Sstevel@tonic-gate  *     from the second argument to the first argument and NULL out the stack
202*7c478bd9Sstevel@tonic-gate  *     pointer for the second.
203*7c478bd9Sstevel@tonic-gate  *   - Otherwise, go through the elements of the second stack, removing each
204*7c478bd9Sstevel@tonic-gate  *     and adding it to the first stack.
205*7c478bd9Sstevel@tonic-gate  *
206*7c478bd9Sstevel@tonic-gate  * Returns:
207*7c478bd9Sstevel@tonic-gate  *   == -1 - An error occurred.  Call ERR_get_error() to get error information.
208*7c478bd9Sstevel@tonic-gate  *   == 0  - No matching returns were found.
209*7c478bd9Sstevel@tonic-gate  *    > 0  - This is the arithmetic 'or' of the FOUND_* bits that indicate which
210*7c478bd9Sstevel@tonic-gate  *           of the requested entries were manipulated.
211*7c478bd9Sstevel@tonic-gate  */
212*7c478bd9Sstevel@tonic-gate int
213*7c478bd9Sstevel@tonic-gate set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl,
214*7c478bd9Sstevel@tonic-gate     STACK_OF(X509) **certs, STACK_OF(X509) **work_cl,
215*7c478bd9Sstevel@tonic-gate     STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca,
216*7c478bd9Sstevel@tonic-gate     STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl)
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	int retval = 0;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if (pkeys != NULL && work_kl != NULL && *work_kl != NULL &&
221*7c478bd9Sstevel@tonic-gate 	    sk_EVP_PKEY_num(*work_kl) > 0) {
222*7c478bd9Sstevel@tonic-gate 		if (*pkeys == NULL) {
223*7c478bd9Sstevel@tonic-gate 			*pkeys = *work_kl;
224*7c478bd9Sstevel@tonic-gate 			*work_kl = NULL;
225*7c478bd9Sstevel@tonic-gate 		} else {
226*7c478bd9Sstevel@tonic-gate 			if (sunw_append_keys(*pkeys, *work_kl) < 0) {
227*7c478bd9Sstevel@tonic-gate 				return (-1);
228*7c478bd9Sstevel@tonic-gate 			}
229*7c478bd9Sstevel@tonic-gate 		}
230*7c478bd9Sstevel@tonic-gate 		retval |= FOUND_PKEY;
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	if (certs != NULL && work_cl != NULL && *work_cl != NULL &&
233*7c478bd9Sstevel@tonic-gate 	    sk_X509_num(*work_cl) > 0) {
234*7c478bd9Sstevel@tonic-gate 		if (*certs == NULL) {
235*7c478bd9Sstevel@tonic-gate 			*certs = *work_cl;
236*7c478bd9Sstevel@tonic-gate 			*work_cl = NULL;
237*7c478bd9Sstevel@tonic-gate 		} else {
238*7c478bd9Sstevel@tonic-gate 			if (move_certs(*certs, *work_cl) < 0) {
239*7c478bd9Sstevel@tonic-gate 				return (-1);
240*7c478bd9Sstevel@tonic-gate 			}
241*7c478bd9Sstevel@tonic-gate 		}
242*7c478bd9Sstevel@tonic-gate 		retval |= FOUND_CERT;
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (cacerts != NULL && work_ca != NULL && *work_ca != NULL &&
246*7c478bd9Sstevel@tonic-gate 	    sk_X509_num(*work_ca) > 0) {
247*7c478bd9Sstevel@tonic-gate 		if (*cacerts == NULL) {
248*7c478bd9Sstevel@tonic-gate 			*cacerts = *work_ca;
249*7c478bd9Sstevel@tonic-gate 			*work_ca = NULL;
250*7c478bd9Sstevel@tonic-gate 		} else {
251*7c478bd9Sstevel@tonic-gate 			if (move_certs(*cacerts, *work_ca) < 0) {
252*7c478bd9Sstevel@tonic-gate 				return (-1);
253*7c478bd9Sstevel@tonic-gate 			}
254*7c478bd9Sstevel@tonic-gate 		}
255*7c478bd9Sstevel@tonic-gate 		retval |= FOUND_CA_CERTS;
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL &&
259*7c478bd9Sstevel@tonic-gate 	    sk_EVP_PKEY_num(*work_xl) > 0) {
260*7c478bd9Sstevel@tonic-gate 		if (*xtrakeys == NULL) {
261*7c478bd9Sstevel@tonic-gate 			*xtrakeys = *work_xl;
262*7c478bd9Sstevel@tonic-gate 			*work_xl = NULL;
263*7c478bd9Sstevel@tonic-gate 		} else {
264*7c478bd9Sstevel@tonic-gate 			if (sunw_append_keys(*xtrakeys, *work_xl) < 0) {
265*7c478bd9Sstevel@tonic-gate 				return (-1);
266*7c478bd9Sstevel@tonic-gate 			}
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 		retval |= FOUND_XPKEY;
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	return (retval);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  * find_attr - Look for a given attribute of the type associated with the NID.
276*7c478bd9Sstevel@tonic-gate  *
277*7c478bd9Sstevel@tonic-gate  * Arguments:
278*7c478bd9Sstevel@tonic-gate  *   nid      - NID for the attribute to be found (either NID_friendlyName or
279*7c478bd9Sstevel@tonic-gate  *              NID_locakKeyId)
280*7c478bd9Sstevel@tonic-gate  *   str      - ASN1_STRING-type structure containing the value to be found,
281*7c478bd9Sstevel@tonic-gate  *              FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a
282*7c478bd9Sstevel@tonic-gate  *              ASN1_STRING.
283*7c478bd9Sstevel@tonic-gate  *   kl       - Points to a stack of private keys.
284*7c478bd9Sstevel@tonic-gate  *   pkey     - Points at a location where the address of the matching private
285*7c478bd9Sstevel@tonic-gate  *              key will be stored.
286*7c478bd9Sstevel@tonic-gate  *   cl       - Points to a stack of client certs with matching private keys.
287*7c478bd9Sstevel@tonic-gate  *   cert     - Points to locaiton where the address of the matching client cert
288*7c478bd9Sstevel@tonic-gate  *              will be returned
289*7c478bd9Sstevel@tonic-gate  *
290*7c478bd9Sstevel@tonic-gate  * This function is designed to process lists of certs and private keys.
291*7c478bd9Sstevel@tonic-gate  * This is made complex because these the attributes are stored differently
292*7c478bd9Sstevel@tonic-gate  * for certs and for keys.  For certs, only a few attributes are retained.
293*7c478bd9Sstevel@tonic-gate  * FriendlyName is stored in the aux structure, under the name 'alias'.
294*7c478bd9Sstevel@tonic-gate  * LocalKeyId is also stored in the aux structure, under the name 'keyid'.
295*7c478bd9Sstevel@tonic-gate  * A pkey structure has a stack of attributes.
296*7c478bd9Sstevel@tonic-gate  *
297*7c478bd9Sstevel@tonic-gate  * The basic approach is:
298*7c478bd9Sstevel@tonic-gate  *   - If there there is no stack of certs but a stack of private keys exists,
299*7c478bd9Sstevel@tonic-gate  *     search the stack of keys for a match. Alternately, if there is a stack
300*7c478bd9Sstevel@tonic-gate  *     of certs and no private keys, search the certs.
301*7c478bd9Sstevel@tonic-gate  *
302*7c478bd9Sstevel@tonic-gate  *   - If there are both certs and keys, assume that the matching certs and
303*7c478bd9Sstevel@tonic-gate  *     keys are in their respective stacks, with matching entries in the same
304*7c478bd9Sstevel@tonic-gate  *     order.  Search for the name or keyid in the stack of certs.  If it is
305*7c478bd9Sstevel@tonic-gate  *     not found, then this function returns 0 (nothing found).
306*7c478bd9Sstevel@tonic-gate  *
307*7c478bd9Sstevel@tonic-gate  *   - Once a cert is found, verify that the key actually matches by
308*7c478bd9Sstevel@tonic-gate  *     comparing the private key with the public key (in the cert).
309*7c478bd9Sstevel@tonic-gate  *     If they don't match, return an error.
310*7c478bd9Sstevel@tonic-gate  *
311*7c478bd9Sstevel@tonic-gate  *   A pointer to cert and/or pkey which matches the name or keyid is stored
312*7c478bd9Sstevel@tonic-gate  *   in the return arguments.
313*7c478bd9Sstevel@tonic-gate  *
314*7c478bd9Sstevel@tonic-gate  * Returns:
315*7c478bd9Sstevel@tonic-gate  *     0 - No matches were found.
316*7c478bd9Sstevel@tonic-gate  *   > 0 - Bits set based on FOUND_* definitions, indicating what was found.
317*7c478bd9Sstevel@tonic-gate  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
318*7c478bd9Sstevel@tonic-gate  */
319*7c478bd9Sstevel@tonic-gate int
320*7c478bd9Sstevel@tonic-gate find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey,
321*7c478bd9Sstevel@tonic-gate     STACK_OF(X509) *cl, X509 **cert)
322*7c478bd9Sstevel@tonic-gate {
323*7c478bd9Sstevel@tonic-gate 	ASN1_UTF8STRING *ustr = NULL;
324*7c478bd9Sstevel@tonic-gate 	ASN1_STRING *s;
325*7c478bd9Sstevel@tonic-gate 	ASN1_TYPE *t;
326*7c478bd9Sstevel@tonic-gate 	EVP_PKEY *p;
327*7c478bd9Sstevel@tonic-gate 	uchar_t *fname = NULL;
328*7c478bd9Sstevel@tonic-gate 	X509 *x;
329*7c478bd9Sstevel@tonic-gate 	int found = 0;
330*7c478bd9Sstevel@tonic-gate 	int chkcerts;
331*7c478bd9Sstevel@tonic-gate 	int len;
332*7c478bd9Sstevel@tonic-gate 	int res;
333*7c478bd9Sstevel@tonic-gate 	int c = -1;
334*7c478bd9Sstevel@tonic-gate 	int k = -1;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	chkcerts = (cert != NULL || pkey != NULL) && cl != NULL;
337*7c478bd9Sstevel@tonic-gate 	if (chkcerts && nid == NID_friendlyName &&
338*7c478bd9Sstevel@tonic-gate 	    str->type == V_ASN1_BMPSTRING) {
339*7c478bd9Sstevel@tonic-gate 		ustr = ASN1_UTF8STRING_new();
340*7c478bd9Sstevel@tonic-gate 		if (ustr == NULL) {
341*7c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
342*7c478bd9Sstevel@tonic-gate 			return (0);
343*7c478bd9Sstevel@tonic-gate 		}
344*7c478bd9Sstevel@tonic-gate 		len = ASN1_STRING_to_UTF8(&fname, str);
345*7c478bd9Sstevel@tonic-gate 		if (fname == NULL) {
346*7c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
347*7c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR);
348*7c478bd9Sstevel@tonic-gate 			return (0);
349*7c478bd9Sstevel@tonic-gate 		}
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 		if (ASN1_STRING_set(ustr, fname, len) == 0) {
352*7c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
353*7c478bd9Sstevel@tonic-gate 			OPENSSL_free(fname);
354*7c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
355*7c478bd9Sstevel@tonic-gate 			return (0);
356*7c478bd9Sstevel@tonic-gate 		}
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	if (chkcerts) {
360*7c478bd9Sstevel@tonic-gate 		for (c = 0; c < sk_X509_num(cl); c++) {
361*7c478bd9Sstevel@tonic-gate 			res = -1;
362*7c478bd9Sstevel@tonic-gate 			x = sk_X509_value(cl, c);
363*7c478bd9Sstevel@tonic-gate 			if (nid == NID_friendlyName && ustr != NULL) {
364*7c478bd9Sstevel@tonic-gate 				if (x->aux == NULL || x->aux->alias == NULL)
365*7c478bd9Sstevel@tonic-gate 					continue;
366*7c478bd9Sstevel@tonic-gate 				s = x->aux->alias;
367*7c478bd9Sstevel@tonic-gate 				if (s != NULL && s->type == ustr->type &&
368*7c478bd9Sstevel@tonic-gate 				    s->data != NULL) {
369*7c478bd9Sstevel@tonic-gate 					res = ASN1_STRING_cmp(s, ustr);
370*7c478bd9Sstevel@tonic-gate 				}
371*7c478bd9Sstevel@tonic-gate 			} else {
372*7c478bd9Sstevel@tonic-gate 				if (x->aux == NULL || x->aux->keyid == NULL)
373*7c478bd9Sstevel@tonic-gate 					continue;
374*7c478bd9Sstevel@tonic-gate 				s = x->aux->keyid;
375*7c478bd9Sstevel@tonic-gate 				if (s != NULL && s->type == str->type &&
376*7c478bd9Sstevel@tonic-gate 				    s->data != NULL) {
377*7c478bd9Sstevel@tonic-gate 					res = ASN1_STRING_cmp(s, str);
378*7c478bd9Sstevel@tonic-gate 				}
379*7c478bd9Sstevel@tonic-gate 			}
380*7c478bd9Sstevel@tonic-gate 			if (res == 0) {
381*7c478bd9Sstevel@tonic-gate 				if (cert != NULL)
382*7c478bd9Sstevel@tonic-gate 					*cert = sk_X509_delete(cl, c);
383*7c478bd9Sstevel@tonic-gate 				found = FOUND_CERT;
384*7c478bd9Sstevel@tonic-gate 				break;
385*7c478bd9Sstevel@tonic-gate 			}
386*7c478bd9Sstevel@tonic-gate 		}
387*7c478bd9Sstevel@tonic-gate 		if (ustr != NULL) {
388*7c478bd9Sstevel@tonic-gate 			ASN1_UTF8STRING_free(ustr);
389*7c478bd9Sstevel@tonic-gate 			OPENSSL_free(fname);
390*7c478bd9Sstevel@tonic-gate 		}
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (pkey != NULL && kl != NULL) {
394*7c478bd9Sstevel@tonic-gate 		/*
395*7c478bd9Sstevel@tonic-gate 		 * Looking for pkey to match a cert?  If so, assume that
396*7c478bd9Sstevel@tonic-gate 		 * lists of certs and their matching pkeys are in the same
397*7c478bd9Sstevel@tonic-gate 		 * order.  Call X509_check_private_key() to verify this
398*7c478bd9Sstevel@tonic-gate 		 * assumption.
399*7c478bd9Sstevel@tonic-gate 		 */
400*7c478bd9Sstevel@tonic-gate 		if (found != 0 && cert != NULL) {
401*7c478bd9Sstevel@tonic-gate 			k = c;
402*7c478bd9Sstevel@tonic-gate 			p = sk_EVP_PKEY_value(kl, k);
403*7c478bd9Sstevel@tonic-gate 			if (X509_check_private_key(x, p) != 0) {
404*7c478bd9Sstevel@tonic-gate 				if (pkey != NULL)
405*7c478bd9Sstevel@tonic-gate 					*pkey = sk_EVP_PKEY_delete(kl, k);
406*7c478bd9Sstevel@tonic-gate 				found |= FOUND_PKEY;
407*7c478bd9Sstevel@tonic-gate 			}
408*7c478bd9Sstevel@tonic-gate 		} else if (cert == NULL) {
409*7c478bd9Sstevel@tonic-gate 			for (k = 0; k < sk_EVP_PKEY_num(kl); k++) {
410*7c478bd9Sstevel@tonic-gate 				p = sk_EVP_PKEY_value(kl, k);
411*7c478bd9Sstevel@tonic-gate 				if (p == NULL || p->attributes == NULL)
412*7c478bd9Sstevel@tonic-gate 					continue;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 				t = PKCS12_get_attr_gen(p->attributes, nid);
415*7c478bd9Sstevel@tonic-gate 				if (t != NULL || ASN1_STRING_cmp(str,
416*7c478bd9Sstevel@tonic-gate 				    t->value.asn1_string) == 0)
417*7c478bd9Sstevel@tonic-gate 					continue;
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 				found |= FOUND_PKEY;
420*7c478bd9Sstevel@tonic-gate 				if (pkey != NULL)
421*7c478bd9Sstevel@tonic-gate 					*pkey = sk_EVP_PKEY_delete(kl, k);
422*7c478bd9Sstevel@tonic-gate 				break;
423*7c478bd9Sstevel@tonic-gate 			}
424*7c478bd9Sstevel@tonic-gate 		}
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	return (found);
428*7c478bd9Sstevel@tonic-gate }
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate /*
431*7c478bd9Sstevel@tonic-gate  * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE
432*7c478bd9Sstevel@tonic-gate  *     of the type specified by the given NID.
433*7c478bd9Sstevel@tonic-gate  *
434*7c478bd9Sstevel@tonic-gate  * Arguments:
435*7c478bd9Sstevel@tonic-gate  *   attrs    - Stack of attributes to search
436*7c478bd9Sstevel@tonic-gate  *   nid      - NID of the attribute being searched for
437*7c478bd9Sstevel@tonic-gate  *
438*7c478bd9Sstevel@tonic-gate  * Returns:
439*7c478bd9Sstevel@tonic-gate  *   -1 	None found
440*7c478bd9Sstevel@tonic-gate  *   != -1	Offset of the matching attribute.
441*7c478bd9Sstevel@tonic-gate  */
442*7c478bd9Sstevel@tonic-gate int
443*7c478bd9Sstevel@tonic-gate find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
444*7c478bd9Sstevel@tonic-gate {
445*7c478bd9Sstevel@tonic-gate 	X509_ATTRIBUTE *a;
446*7c478bd9Sstevel@tonic-gate 	int i;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	if (attrs == NULL)
449*7c478bd9Sstevel@tonic-gate 		return (-1);
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
452*7c478bd9Sstevel@tonic-gate 		a = sk_X509_ATTRIBUTE_value(attrs, i);
453*7c478bd9Sstevel@tonic-gate 		if (OBJ_obj2nid(a->object) == nid)
454*7c478bd9Sstevel@tonic-gate 			return (i);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 	return (-1);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate /*
460*7c478bd9Sstevel@tonic-gate  * get_key_cert - Get a cert and its matching key from the stacks of certs
461*7c478bd9Sstevel@tonic-gate  *      and keys.  They are removed from the stacks.
462*7c478bd9Sstevel@tonic-gate  *
463*7c478bd9Sstevel@tonic-gate  * Arguments:
464*7c478bd9Sstevel@tonic-gate  *   n        - Offset of the entries to return.
465*7c478bd9Sstevel@tonic-gate  *   kl       - Points to a stack of private keys that matches the list of
466*7c478bd9Sstevel@tonic-gate  *              certs below.
467*7c478bd9Sstevel@tonic-gate  *   pkey     - Points at location where the address of the matching private
468*7c478bd9Sstevel@tonic-gate  *              key will be stored.
469*7c478bd9Sstevel@tonic-gate  *   cl       - Points to a stack of client certs with matching private keys.
470*7c478bd9Sstevel@tonic-gate  *   cert     - Points to locaiton where the address of the matching client cert
471*7c478bd9Sstevel@tonic-gate  *              will be returned
472*7c478bd9Sstevel@tonic-gate  *
473*7c478bd9Sstevel@tonic-gate  * The assumption is that the stacks of keys and certs contain key/cert pairs,
474*7c478bd9Sstevel@tonic-gate  * with entries in the same order and hence at the same offset.  Provided
475*7c478bd9Sstevel@tonic-gate  * the key and cert selected match, each will be removed from its stack and
476*7c478bd9Sstevel@tonic-gate  * returned.
477*7c478bd9Sstevel@tonic-gate  *
478*7c478bd9Sstevel@tonic-gate  * A stack of certs can be passed in without a stack of private keys, and vise
479*7c478bd9Sstevel@tonic-gate  * versa.  In that case, the indicated key/cert will be returned.
480*7c478bd9Sstevel@tonic-gate  *
481*7c478bd9Sstevel@tonic-gate  * Returns:
482*7c478bd9Sstevel@tonic-gate  *     0 - No matches were found.
483*7c478bd9Sstevel@tonic-gate  *   > 0 - Bits set based on FOUND_* definitions, indicating what is returned.
484*7c478bd9Sstevel@tonic-gate  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
485*7c478bd9Sstevel@tonic-gate  */
486*7c478bd9Sstevel@tonic-gate int
487*7c478bd9Sstevel@tonic-gate get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl,
488*7c478bd9Sstevel@tonic-gate     X509 **cert)
489*7c478bd9Sstevel@tonic-gate {
490*7c478bd9Sstevel@tonic-gate 	int retval = 0;
491*7c478bd9Sstevel@tonic-gate 	int nk;
492*7c478bd9Sstevel@tonic-gate 	int nc;
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0;
495*7c478bd9Sstevel@tonic-gate 	nc = (cl != NULL) ? sk_X509_num(cl) : 0;
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	if (pkey != NULL && *pkey == NULL) {
498*7c478bd9Sstevel@tonic-gate 		if (nk > 0 && n >= 0 || n < nk) {
499*7c478bd9Sstevel@tonic-gate 			*pkey = sk_EVP_PKEY_delete(kl, n);
500*7c478bd9Sstevel@tonic-gate 			if (*pkey != NULL)
501*7c478bd9Sstevel@tonic-gate 				retval |= FOUND_PKEY;
502*7c478bd9Sstevel@tonic-gate 		}
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	if (cert != NULL && *cert == NULL) {
506*7c478bd9Sstevel@tonic-gate 		if (nc > 0 && n >= 0 && n < nc) {
507*7c478bd9Sstevel@tonic-gate 			*cert = sk_X509_delete(cl, n);
508*7c478bd9Sstevel@tonic-gate 			if (*cert != NULL)
509*7c478bd9Sstevel@tonic-gate 				retval |= FOUND_CERT;
510*7c478bd9Sstevel@tonic-gate 		}
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	return (retval);
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate /*
517*7c478bd9Sstevel@tonic-gate  * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type
518*7c478bd9Sstevel@tonic-gate  *     specified by the given NID.
519*7c478bd9Sstevel@tonic-gate  *
520*7c478bd9Sstevel@tonic-gate  * Arguments:
521*7c478bd9Sstevel@tonic-gate  *   ty       - Type structure to be made into an attribute
522*7c478bd9Sstevel@tonic-gate  *   nid      - NID of the attribute
523*7c478bd9Sstevel@tonic-gate  *
524*7c478bd9Sstevel@tonic-gate  * Returns:
525*7c478bd9Sstevel@tonic-gate  *   NULL	An error occurred.
526*7c478bd9Sstevel@tonic-gate  *   != NULL	An X509_ATTRIBUTE structure.
527*7c478bd9Sstevel@tonic-gate  */
528*7c478bd9Sstevel@tonic-gate X509_ATTRIBUTE *
529*7c478bd9Sstevel@tonic-gate type2attrib(ASN1_TYPE *ty, int nid)
530*7c478bd9Sstevel@tonic-gate {
531*7c478bd9Sstevel@tonic-gate 	X509_ATTRIBUTE *a;
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	if ((a = X509_ATTRIBUTE_new()) == NULL ||
534*7c478bd9Sstevel@tonic-gate 	    (a->value.set = sk_ASN1_TYPE_new_null()) == NULL ||
535*7c478bd9Sstevel@tonic-gate 	    sk_ASN1_TYPE_push(a->value.set, ty) == 0) {
536*7c478bd9Sstevel@tonic-gate 		if (a != NULL)
537*7c478bd9Sstevel@tonic-gate 			X509_ATTRIBUTE_free(a);
538*7c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE);
539*7c478bd9Sstevel@tonic-gate 		return (NULL);
540*7c478bd9Sstevel@tonic-gate 	}
541*7c478bd9Sstevel@tonic-gate 	a->single = 0;
542*7c478bd9Sstevel@tonic-gate 	a->object = OBJ_nid2obj(nid);
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	return (a);
545*7c478bd9Sstevel@tonic-gate }
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate /*
548*7c478bd9Sstevel@tonic-gate  * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE
549*7c478bd9Sstevel@tonic-gate  *     component
550*7c478bd9Sstevel@tonic-gate  *
551*7c478bd9Sstevel@tonic-gate  * Arguments:
552*7c478bd9Sstevel@tonic-gate  *   attr     - Attribute structure containing a type.
553*7c478bd9Sstevel@tonic-gate  *
554*7c478bd9Sstevel@tonic-gate  * Returns:
555*7c478bd9Sstevel@tonic-gate  *   NULL	An error occurred.
556*7c478bd9Sstevel@tonic-gate  *   != NULL	An ASN1_TYPE structure.
557*7c478bd9Sstevel@tonic-gate  */
558*7c478bd9Sstevel@tonic-gate ASN1_TYPE *
559*7c478bd9Sstevel@tonic-gate attrib2type(X509_ATTRIBUTE *attr)
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate 	ASN1_TYPE *ty = NULL;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	if (attr == NULL || attr->single == 1)
564*7c478bd9Sstevel@tonic-gate 		return (NULL);
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	if (sk_ASN1_TYPE_num(attr->value.set) > 0)
567*7c478bd9Sstevel@tonic-gate 		ty = sk_ASN1_TYPE_value(attr->value.set, 0);
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	return (ty);
570*7c478bd9Sstevel@tonic-gate }
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate /*
573*7c478bd9Sstevel@tonic-gate  * move_certs - Given two stacks of certs, remove the certs from
574*7c478bd9Sstevel@tonic-gate  *      the second stack and append them to the first.
575*7c478bd9Sstevel@tonic-gate  *
576*7c478bd9Sstevel@tonic-gate  * Arguments:
577*7c478bd9Sstevel@tonic-gate  *   dst 	- the stack to receive the certs from 'src'
578*7c478bd9Sstevel@tonic-gate  *   src	- the stack whose certs are to be moved.
579*7c478bd9Sstevel@tonic-gate  *
580*7c478bd9Sstevel@tonic-gate  * Returns:
581*7c478bd9Sstevel@tonic-gate  *   -1  	- An error occurred.  The error status is set.
582*7c478bd9Sstevel@tonic-gate  *   >= 0       - The number of certs that were copied.
583*7c478bd9Sstevel@tonic-gate  */
584*7c478bd9Sstevel@tonic-gate int
585*7c478bd9Sstevel@tonic-gate move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src)
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	X509 *tmpc;
588*7c478bd9Sstevel@tonic-gate 	int count = 0;
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	while (sk_X509_num(src) > 0) {
591*7c478bd9Sstevel@tonic-gate 		tmpc = sk_X509_delete(src, 0);
592*7c478bd9Sstevel@tonic-gate 		if (sk_X509_push(dst, tmpc) == 0) {
593*7c478bd9Sstevel@tonic-gate 			X509_free(tmpc);
594*7c478bd9Sstevel@tonic-gate 			SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE);
595*7c478bd9Sstevel@tonic-gate 			return (-1);
596*7c478bd9Sstevel@tonic-gate 		}
597*7c478bd9Sstevel@tonic-gate 		count++;
598*7c478bd9Sstevel@tonic-gate 	}
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 	return (count);
601*7c478bd9Sstevel@tonic-gate }
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate /*
604*7c478bd9Sstevel@tonic-gate  * print_time - Given an ASN1_TIME, print one or both of the times.
605*7c478bd9Sstevel@tonic-gate  *
606*7c478bd9Sstevel@tonic-gate  * Arguments:
607*7c478bd9Sstevel@tonic-gate  *   fp         - File to write to
608*7c478bd9Sstevel@tonic-gate  *   t          - The time to format and print.
609*7c478bd9Sstevel@tonic-gate  *
610*7c478bd9Sstevel@tonic-gate  * Returns:
611*7c478bd9Sstevel@tonic-gate  *   0          - Error occurred while opening or writing.
612*7c478bd9Sstevel@tonic-gate  *   > 0        - Success.
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate int
615*7c478bd9Sstevel@tonic-gate print_time(FILE *fp, ASN1_TIME *t)
616*7c478bd9Sstevel@tonic-gate {
617*7c478bd9Sstevel@tonic-gate 	BIO *bp;
618*7c478bd9Sstevel@tonic-gate 	int ret = 1;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	if ((bp = BIO_new(BIO_s_file())) == NULL) {
621*7c478bd9Sstevel@tonic-gate 		return (0);
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	(void) BIO_set_fp(bp, fp, BIO_NOCLOSE);
625*7c478bd9Sstevel@tonic-gate 	ret = ASN1_TIME_print(bp, t);
626*7c478bd9Sstevel@tonic-gate 	(void) BIO_free(bp);
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 	return (ret);
629*7c478bd9Sstevel@tonic-gate }
630