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