xref: /titanic_50/usr/src/lib/libpkg/common/p12lib.c (revision 7b07063d906859b2be1e88791f801b3c96e432f6)
1 /*
2  * ====================================================================
3  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    licensing@OpenSSL.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55 
56 /*
57  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
58  * Use is subject to license terms.
59  */
60 
61 /*
62  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
63  */
64 
65 
66 #include <strings.h>
67 #include <stdlib.h>
68 #include <assert.h>
69 
70 #include <openssl/crypto.h>
71 #include <openssl/err.h>
72 #include <openssl/x509.h>
73 #include <openssl/pem.h>
74 
75 #include <openssl/pkcs12.h>
76 #include "p12lib.h"
77 
78 /*
79  * OpenSSL provides a framework for pushing error codes onto a stack.
80  * When an error occurs, the consumer may use the framework to
81  * pop the errors off the stack and provide a trace of where the
82  * errors occurred.
83  *
84  * Our PKCS12 code plugs into this framework by calling
85  * ERR_load_SUNW_strings(). To push an error (which by the way, consists
86  * of a function code and an error code) onto the stack our PKCS12 code
87  * calls SUNWerr().
88  *
89  * Consumers of our PKCS12 code can then call the OpenSSL error routines
90  * when an error occurs and retrieve the stack of errors.
91  */
92 
93 #ifndef OPENSSL_NO_ERR
94 
95 /* Function codes and their matching strings */
96 static ERR_STRING_DATA SUNW_str_functs[] = {
97 	{ ERR_PACK(0, SUNW_F_USE_X509CERT, 0),	   "sunw_use_x509cert" },
98 	{ ERR_PACK(0, SUNW_F_USE_PKEY, 0),	   "sunw_use_pkey" },
99 	{ ERR_PACK(0, SUNW_F_USE_TASTORE, 0),	   "sunw_use_tastore" },
100 	{ ERR_PACK(0, SUNW_F_USE_CERTFILE, 0),	   "sunw_p12_use_certfile" },
101 	{ ERR_PACK(0, SUNW_F_USE_KEYFILE, 0),	   "sunw_p12_use_keyfile" },
102 	{ ERR_PACK(0, SUNW_F_USE_TRUSTFILE, 0),	   "sunw_p12_use_trustfile" },
103 	{ ERR_PACK(0, SUNW_F_READ_FILE, 0),	   "p12_read_file" },
104 	{ ERR_PACK(0, SUNW_F_DOPARSE, 0),	   "p12_doparse" },
105 	{ ERR_PACK(0, SUNW_F_PKCS12_PARSE, 0),	   "sunw_PKCS12_parse" },
106 	{ ERR_PACK(0, SUNW_F_PKCS12_CONTENTS, 0),  "sunw_PKCS12_contents" },
107 	{ ERR_PACK(0, SUNW_F_PARSE_ONE_BAG, 0),	   "parse_one_bag" },
108 	{ ERR_PACK(0, SUNW_F_PKCS12_CREATE, 0),	   "sunw_PKCS12_create" },
109 	{ ERR_PACK(0, SUNW_F_SPLIT_CERTS, 0),	   "sunw_split_certs" },
110 	{ ERR_PACK(0, SUNW_F_FIND_LOCALKEYID, 0),  "sunw_find_localkeyid" },
111 	{ ERR_PACK(0, SUNW_F_SET_LOCALKEYID, 0),   "sunw_set_localkeyid" },
112 	{ ERR_PACK(0, SUNW_F_GET_LOCALKEYID, 0),   "sunw_get_localkeyid" },
113 	{ ERR_PACK(0, SUNW_F_SET_FNAME, 0),	   "sunw_set_fname" },
114 	{ ERR_PACK(0, SUNW_F_GET_PKEY_FNAME, 0),   "sunw_get_pkey_fname" },
115 	{ ERR_PACK(0, SUNW_F_APPEND_KEYS, 0),	   "sunw_append_keys" },
116 	{ ERR_PACK(0, SUNW_F_PEM_CONTENTS, 0),	   "sunw_PEM_contents" },
117 	{ ERR_PACK(0, SUNW_F_PEM_INFO, 0),	   "pem_info" },
118 	{ ERR_PACK(0, SUNW_F_ASC2BMPSTRING, 0),	   "asc2bmpstring" },
119 	{ ERR_PACK(0, SUNW_F_UTF82ASCSTR, 0),	   "utf82ascstr" },
120 	{ ERR_PACK(0, SUNW_F_FINDATTR, 0),	   "findattr" },
121 	{ ERR_PACK(0, SUNW_F_TYPE2ATTRIB, 0),	   "type2attrib" },
122 	{ ERR_PACK(0, SUNW_F_MOVE_CERTS, 0),	   "move_certs" },
123 	{ ERR_PACK(0, SUNW_F_FIND_FNAME, 0),	   "sunw_find_fname" },
124 	{ ERR_PACK(0, SUNW_F_PARSE_OUTER, 0),	   "parse_outer" },
125 	{ ERR_PACK(0, SUNW_F_CHECKFILE, 0),	   "checkfile" },
126 	{ 0, NULL }
127 };
128 
129 /* Error codes and their matching strings */
130 static ERR_STRING_DATA SUNW_str_reasons[] = {
131 	{ SUNW_R_INVALID_ARG,		"invalid argument" },
132 	{ SUNW_R_MEMORY_FAILURE,	"memory failure" },
133 	{ SUNW_R_MAC_VERIFY_FAILURE,	"mac verify failure" },
134 	{ SUNW_R_MAC_CREATE_FAILURE,	"mac create failure" },
135 	{ SUNW_R_BAD_FILETYPE,		"bad file type" },
136 	{ SUNW_R_BAD_PKEY,		"bad or missing private key" },
137 	{ SUNW_R_BAD_PKEYTYPE,		"unsupported key type" },
138 	{ SUNW_R_PKEY_READ_ERR,		"unable to read private key" },
139 	{ SUNW_R_NO_TRUST_ANCHOR,	"no trust anchors found" },
140 	{ SUNW_R_READ_TRUST_ERR,	"unable to read trust anchor" },
141 	{ SUNW_R_ADD_TRUST_ERR,		"unable to add trust anchor" },
142 	{ SUNW_R_PKCS12_PARSE_ERR,	"PKCS12 parse error" },
143 	{ SUNW_R_PKCS12_CREATE_ERR,	"PKCS12 create error" },
144 	{ SUNW_R_BAD_CERTTYPE,		"unsupported certificate type" },
145 	{ SUNW_R_PARSE_CERT_ERR,	"error parsing PKCS12 certificate" },
146 	{ SUNW_R_PARSE_BAG_ERR,		"error parsing PKCS12 bag" },
147 	{ SUNW_R_MAKE_BAG_ERR,		"error making PKCS12 bag" },
148 	{ SUNW_R_BAD_LKID,		"bad localKeyID format" },
149 	{ SUNW_R_SET_LKID_ERR,		"error setting localKeyID" },
150 	{ SUNW_R_BAD_FNAME,		"bad friendlyName format" },
151 	{ SUNW_R_SET_FNAME_ERR,		"error setting friendlyName" },
152 	{ SUNW_R_BAD_TRUST,		"bad or missing trust anchor" },
153 	{ SUNW_R_BAD_BAGTYPE,		"unsupported bag type" },
154 	{ SUNW_R_CERT_ERR,		"certificate error" },
155 	{ SUNW_R_PKEY_ERR,		"private key error" },
156 	{ SUNW_R_READ_ERR,		"error reading file" },
157 	{ SUNW_R_ADD_ATTR_ERR,		"error adding attribute" },
158 	{ SUNW_R_STR_CONVERT_ERR,	"error converting string" },
159 	{ SUNW_R_PKCS12_EMPTY_ERR,	"empty PKCS12 structure" },
160 	{ SUNW_R_PASSWORD_ERR,		"bad password" },
161 	{ 0, NULL }
162 };
163 
164 /*
165  * The library name that our module will be known as. This name
166  * may be retrieved via OpenSSLs error APIs.
167  */
168 static ERR_STRING_DATA SUNW_lib_name[] = {
169 	{ 0,	SUNW_LIB_NAME },
170 	{ 0, NULL }
171 };
172 #endif
173 
174 /*
175  * The value of this variable (initialized by a call to
176  * ERR_load_SUNW_strings()) is what identifies our errors
177  * to OpenSSL as being ours.
178  */
179 static int SUNW_lib_error_code = 0;
180 
181 /* local routines */
182 static int	parse_pkcs12(PKCS12 *, const char *, int, char *, int, char *,
183     EVP_PKEY **, X509 **, STACK_OF(X509) **);
184 static int	pem_info(FILE *, pem_password_cb, void *,
185     STACK_OF(EVP_PKEY) **, STACK_OF(X509) **);
186 
187 static int	parse_outer(PKCS12 *, const char *, STACK_OF(EVP_PKEY) *,
188     STACK_OF(X509) *);
189 
190 static int	parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *, const char *,
191     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
192 
193 static int	parse_one_bag(PKCS12_SAFEBAG *, const char *,
194     STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
195 
196 static X509_ATTRIBUTE	*type2attrib(ASN1_TYPE *, int);
197 static ASN1_TYPE	*attrib2type(X509_ATTRIBUTE *);
198 static uchar_t		*utf82ascstr(ASN1_UTF8STRING *);
199 static ASN1_BMPSTRING	*asc2bmpstring(const char *, int);
200 static int		find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *, int);
201 static int		find_attr(int, ASN1_STRING *, STACK_OF(EVP_PKEY) *,
202     EVP_PKEY **, STACK_OF(X509) *, X509 **);
203 
204 static chk_errs_t	check_time(chk_actions_t, X509 *);
205 static int		get_key_cert(int, STACK_OF(EVP_PKEY) *, EVP_PKEY **,
206     STACK_OF(X509) *, X509 **cert);
207 static int		move_certs(STACK_OF(X509) *, STACK_OF(X509) *);
208 static int		sunw_append_keys(STACK_OF(EVP_PKEY) *,
209     STACK_OF(EVP_PKEY) *);
210 static int		set_results(STACK_OF(EVP_PKEY) **,
211     STACK_OF(EVP_PKEY) **, STACK_OF(X509) **, STACK_OF(X509) **,
212     STACK_OF(X509) **, STACK_OF(X509) **,
213     STACK_OF(EVP_PKEY) **, STACK_OF(EVP_PKEY) **);
214 
215 /*
216  * ----------------------------------------------------------------------------
217  * Public routines
218  * ----------------------------------------------------------------------------
219  */
220 
221 /*
222  * sunw_PKCS12_parse - Parse a PKCS12 structure and break it into its parts.
223  *
224  * Parse and decrypt a PKCS#12 structure returning user key, user cert and/or
225  * other (CA) certs. Note either ca should be NULL, *ca should be NULL,
226  * or it should point to a valid STACK_OF(X509) structure. pkey and cert can
227  * be passed uninitialized.
228  *
229  * Arguments:
230  *   p12      - Structure with pkcs12 info to be parsed
231  *   pass     - Pass phrase for the private key (possibly empty) or NULL if
232  *              there is none.
233  *   matchty  - Info about which certs/keys to return if many are in the file.
234  *   keyid    - If private key localkeyids friendlynames are to match a
235  *              predetermined value, the value to match. This value should
236  *		be an octet string.
237  *   keyid_len- Length of the keyid byte string.
238  *   name_str - If friendlynames are to match a predetermined value, the value
239  *		 to match. This value should be a NULL terminated string.
240  *   pkey     - Points to location pointing to the private key returned.
241  *   cert     - Points to locaiton which points to the client cert returned
242  *   ca       - Points to location that points to a stack of 'certificate
243  *               authority' certs/trust anchors.
244  *
245  * Match based on the value of 'matchty' and the contents of 'keyid'
246  * and/or 'name_str', as appropriate.  Go through the lists of certs and
247  * private keys which were taken from the pkcs12 structure, looking for
248  * matches of the requested type.  This function only searches the lists of
249  * matching private keys and client certificates.  Kinds of matches allowed,
250  * and the order in which they will be checked, are:
251  *
252  *   1) Find the key and/or cert whose localkeyid attributes matches
253  *      'keyid'.
254  *   2) Find the key and/or cert whose friendlyname attributes matches
255  *	'name_str'
256  *   3) Return the first matching key/cert pair found.
257  *   4) Return the last matching key/cert pair found.
258  *   5) Return whatever cert and/or key are available, even unmatching.
259  *
260  *   Append to the CA list, the certs which do not have matching private
261  *   keys and which were not selected.
262  *
263  * If none of the bits are set, no client certs or private keys will be
264  * returned.  CA (aka trust anchor) certs can be.
265  *
266  * Notes: If #3 is selected, then #4 will never occur.  CA certs will be
267  * selected after a cert/key pairs are isolated.
268  *
269  * Returns:
270  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
271  *         Where possible, memory has been freed.
272  *  >= 0 - Objects were found and returned.  Which objects are indicated by
273  *         which bits are set (FOUND_PKEY, FOUND_CERT, FOUND_CA_CERTS).
274  */
275 int
276 sunw_PKCS12_parse(PKCS12 *p12, const char *pass, int matchty, char *keyid,
277     int keyid_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
278     STACK_OF(X509) **ca)
279 {
280 	boolean_t ca_supplied;
281 	int retval = -1;
282 
283 	/* If NULL PKCS12 structure, this is an error */
284 	if (p12 == NULL) {
285 		SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
286 		return (-1);
287 	}
288 
289 	/* Set up arguments....  These will be allocated if needed */
290 	if (pkey)
291 		*pkey = NULL;
292 	if (cert)
293 		*cert = NULL;
294 
295 	/*
296 	 * If there is already a ca list, use it.  Otherwise, allocate one
297 	 * and free is later if an error occurs or whatever.)
298 	 */
299 	ca_supplied = (ca != NULL && *ca != NULL);
300 	if (ca != NULL && *ca == NULL) {
301 		if ((*ca = sk_X509_new_null()) == NULL) {
302 			SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MEMORY_FAILURE);
303 			return (-1);
304 		}
305 	}
306 
307 	/*
308 	 * If password is zero length or NULL then try verifying both cases
309 	 * to determine which password is correct. The reason for this is that
310 	 * under PKCS#12 password based encryption no password and a zero
311 	 * length password are two different things. If the password has a
312 	 * non-zero length and is not NULL then call PKCS12_verify_mac() with
313 	 * a length of '-1' and let it use strlen() to figure out the length
314 	 * of the password.
315 	 */
316 	/* Check the mac */
317 	if (pass == NULL || *pass == '\0') {
318 		if (PKCS12_verify_mac(p12, NULL, 0))
319 			pass = NULL;
320 		else if (PKCS12_verify_mac(p12, "", 0))
321 			pass = "";
322 		else {
323 			SUNWerr(SUNW_F_PKCS12_PARSE,
324 			    SUNW_R_MAC_VERIFY_FAILURE);
325 			goto err;
326 		}
327 	} else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
328 		SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MAC_VERIFY_FAILURE);
329 		goto err;
330 	}
331 
332 	retval = parse_pkcs12(p12, pass, matchty, keyid, keyid_len,
333 	    name_str, pkey, cert, ca);
334 	if (retval < 0) {
335 		SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_PKCS12_PARSE_ERR);
336 		goto err;
337 	}
338 	return (retval);
339 
340 err:
341 	if (pkey && *pkey) {
342 		sunw_evp_pkey_free(*pkey);
343 	}
344 	if (cert && *cert)
345 		X509_free(*cert);
346 	if (ca_supplied == B_FALSE && ca != NULL)
347 		sk_X509_pop_free(*ca, X509_free);
348 
349 	return (-1);
350 
351 }
352 
353 
354 /*
355  * sunw_PEM_contents() parses a PEM file and returns component parts found
356  *
357  * Parse and decrypt a PEM file, returning any user keys and certs.
358  *
359  * There are some limits to this function.  It will ignore the following:
360  * - certificates identified by "TRUSTED CERTIFICATE"
361  * - CERTIFICATE REQUEST and NEW CERTIFICATE REQUEST records.
362  * - X509 CRL
363  * - DH PARAMETERS
364  * - DSA PARAMETERS
365  * - Any PUBLIC KEY
366  * - PKCS7
367  * - PRIVATE KEY or ENCRYPTED PRIVATE KEY (PKCS 8)
368  *
369  * Arguments:
370  *   fp       - File pointer for file containing PEM data.
371  *   pass     - Pass phrase for the private key or NULL if there is none.
372  *   pkeys    - Points to address of a stack of private keys to return.
373  *   certs    - Points to address of a stack of client certs to return.
374  *
375  *   The pointers to stacks should either be NULL or their contents should
376  *   either be NULL or should point to a valid STACK_OF(X509) structure.
377  *   If the stacks contain information, corresponding information from the
378  *   file will be appended to the original contents.
379  *
380  *   Note:  Client certs and and their matching private keys will be in any
381  *   order.
382  *
383  *   Certs which have no matching private key are assumed to be ca certs.
384  *
385  * Returns:
386  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
387  *         Where possible, memory has been freed.
388  *  >= 0 - Objects were found and returned.  Which objects are indicated by
389  *         which bits are set (FOUND_PKEY, FOUND_CERT)
390  */
391 int sunw_PEM_contents(FILE *fp, pem_password_cb *cb, void *userdata,
392     STACK_OF(EVP_PKEY) **pkey, STACK_OF(X509) **certs)
393 {
394 	STACK_OF(EVP_PKEY) *work_kl = NULL;
395 	STACK_OF(X509) *work_ca = NULL;
396 	int retval = -1;
397 
398 	/*
399 	 * Allocate the working stacks for private key and for the
400 	 * ca certs.
401 	 */
402 	if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
403 		SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
404 		goto cleanup;
405 	}
406 
407 	if ((work_ca = sk_X509_new_null()) == NULL) {
408 		SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
409 		goto cleanup;
410 	}
411 
412 	/* Error strings are set within the following. */
413 	if (pem_info(fp, cb, userdata, &work_kl, &work_ca) <= 0) {
414 		goto cleanup;
415 	}
416 
417 	/* on error, set_results() returns an error on the stack */
418 	retval = set_results(pkey, &work_kl, certs, &work_ca, NULL, NULL, NULL,
419 	    NULL);
420 cleanup:
421 	if (work_kl != NULL) {
422 		sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
423 	}
424 	if (work_ca != NULL)
425 		sk_X509_pop_free(work_ca, X509_free);
426 
427 	return (retval);
428 }
429 
430 
431 /*
432  * sunw_PKCS12_contents() parses a pkcs#12 structure and returns component
433  *     parts found, without evaluation.
434  *
435  * Parse and decrypt a PKCS#12 structure returning any user keys and/or
436  * various certs. Note these should either be NULL, *whatever should
437  * be NULL, or it should point to a valid STACK_OF(X509) structure.
438  *
439  * Arguments:
440  *   p12      - Structure with pkcs12 info to be parsed
441  *   pass     - Pass phrase for the private key and entire pkcs12 wad (possibly
442  *              empty) or NULL if there is none.
443  *   pkeys    - Points to address of a stack of private keys to return.
444  *   certs    - Points to address of a stack of client certs return.
445  *
446  *   Note:  The certs and keys being returned are in random order.
447  *
448  * Returns:
449  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
450  *         Where possible, memory has been freed.
451  *  >= 0 - Objects were found and returned.  Which objects are indicated by
452  *         which bits are set (FOUND_PKEY or FOUND_CERT)
453  */
454 int
455 sunw_PKCS12_contents(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) **pkey,
456     STACK_OF(X509) **certs)
457 {
458 	STACK_OF(EVP_PKEY) *work_kl = NULL;
459 	STACK_OF(X509) *work_ca = NULL;
460 	int retval = -1;
461 
462 	/*
463 	 * Allocate the working stacks for private key and for the
464 	 * ca certs.
465 	 */
466 	if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
467 		SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
468 		goto cleanup;
469 	}
470 
471 	if ((work_ca = sk_X509_new_null()) == NULL) {
472 		SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
473 		goto cleanup;
474 	}
475 
476 	if (parse_outer(p12, pass, work_kl, work_ca) == 0) {
477 		/*
478 		 * Error already on stack
479 		 */
480 		goto cleanup;
481 	}
482 
483 	/* on error, set_results() returns an error on the stack */
484 	retval = set_results(pkey, &work_kl, certs, &work_ca, NULL,
485 	    NULL, NULL, NULL);
486 
487 cleanup:
488 	if (work_kl != NULL) {
489 		sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
490 	}
491 
492 	return (retval);
493 }
494 
495 
496 
497 /*
498  * sunw_split_certs() - Given a list of certs and a list of private keys,
499  *     moves certs which match one of the keys to a different stack.
500  *
501  * Arguments:
502  *   allkeys  - Points to a stack of private keys to search.
503  *   allcerts - Points to a stack of certs to be searched.
504  *   keycerts - Points to address of a stack of certs with matching private
505  *              keys.  They are moved from 'allcerts'.  This may not be NULL
506  *              when called.  If *keycerts is NULL upon entry, a new stack will
507  *              be allocated.  Otherwise, it must be a valid STACK_OF(509).
508  *   nocerts  - Points to address of a stack for keys which have no matching
509  *              certs.  Keys are moved from 'allkeys' here when they have no
510  *              matching certs.  If this is NULL, matchless keys will be
511  *              discarded.
512  *
513  *   Notes:  If an error occurs while moving certs, the cert being move may be
514  *   lost.  'keycerts' may only contain part of the matching certs.  The number
515  *   of certs successfully moved can be found by checking sk_X509_num(keycerts).
516  *
517  *   If there is a key which does not have a matching cert, it is moved to
518  *   the list nocerts.
519  *
520  *   If all certs are removed from 'certs' and/or 'pkeys', it will be the
521  *   caller's responsibility to free the empty stacks.
522  *
523  * Returns:
524  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
525  *         Where possible, memory has been freed.
526  *  >= 0 - The number of certs moved from 'cert' to 'pkcerts'.
527  */
528 int
529 sunw_split_certs(STACK_OF(EVP_PKEY) *allkeys, STACK_OF(X509) *allcerts,
530     STACK_OF(X509) **keycerts, STACK_OF(EVP_PKEY) **nocerts)
531 {
532 	STACK_OF(X509) *matching;
533 	STACK_OF(EVP_PKEY) *nomatch;
534 	EVP_PKEY *tmpkey;
535 	X509 *tmpcert;
536 	int count = 0;
537 	int found;
538 	int res;
539 	int i;
540 	int k;
541 
542 	*keycerts = NULL;
543 	if (nocerts != NULL)
544 		*nocerts = NULL;
545 	nomatch = NULL;
546 
547 	if ((matching = sk_X509_new_null()) == NULL) {
548 		SUNWerr(SUNW_F_SPLIT_CERTS, SUNW_R_MEMORY_FAILURE);
549 		return (-1);
550 	}
551 	*keycerts = matching;
552 
553 	k = 0;
554 	while (k < sk_EVP_PKEY_num(allkeys)) {
555 		found = 0;
556 		tmpkey = sk_EVP_PKEY_value(allkeys, k);
557 
558 		for (i = 0; i < sk_X509_num(allcerts); i++) {
559 			tmpcert = sk_X509_value(allcerts, i);
560 			res = X509_check_private_key(tmpcert, tmpkey);
561 			if (res != 0) {
562 				count++;
563 				found = 1;
564 				tmpcert = sk_X509_delete(allcerts, i);
565 				if (sk_X509_push(matching, tmpcert) == 0) {
566 					X509_free(tmpcert);
567 					SUNWerr(SUNW_F_SPLIT_CERTS,
568 					    SUNW_R_MEMORY_FAILURE);
569 					return (-1);
570 				}
571 				break;
572 			}
573 		}
574 		if (found != 0) {
575 			/*
576 			 * Found a match - keep the key & check out the next
577 			 * one.
578 			 */
579 			k++;
580 		} else {
581 			/*
582 			 * No cert matching this key.  Move the key if
583 			 * possible or discard it.  Don't increment the
584 			 * index.
585 			 */
586 			if (nocerts == NULL) {
587 				tmpkey = sk_EVP_PKEY_delete(allkeys, k);
588 				sunw_evp_pkey_free(tmpkey);
589 			} else {
590 				if (*nocerts == NULL) {
591 					nomatch = sk_EVP_PKEY_new_null();
592 					if (nomatch == NULL) {
593 						SUNWerr(SUNW_F_SPLIT_CERTS,
594 						    SUNW_R_MEMORY_FAILURE);
595 						return (-1);
596 					}
597 					*nocerts = nomatch;
598 				}
599 				tmpkey = sk_EVP_PKEY_delete(allkeys, k);
600 				if (sk_EVP_PKEY_push(nomatch, tmpkey) == 0) {
601 					sunw_evp_pkey_free(tmpkey);
602 					SUNWerr(SUNW_F_SPLIT_CERTS,
603 					    SUNW_R_MEMORY_FAILURE);
604 					return (-1);
605 				}
606 			}
607 		}
608 	}
609 
610 	return (count);
611 }
612 
613 /*
614  * sunw_PKCS12_create() creates a pkcs#12 structure and given component parts.
615  *
616  * Given one or more of user private key, user cert and/or other (CA) certs,
617  * return an encrypted PKCS12 structure containing them.
618  *
619  * Arguments:
620  *   pass     - Pass phrase for the pkcs12 structure and private key (possibly
621  *              empty) or NULL if there is none.  It will be used to encrypt
622  *              both the private key(s) and as the pass phrase for the whole
623  *              pkcs12 wad.
624  *   pkeys    - Points to stack of private keys.
625  *   certs    - Points to stack of client (public ke) certs
626  *   cacerts  - Points to stack of 'certificate authority' certs (or trust
627  *              anchors).
628  *
629  *   Note that any of these may be NULL.
630  *
631  * Returns:
632  *   NULL     - An error occurred.
633  *   != NULL  - Address of PKCS12 structure.  The user is responsible for
634  *              freeing the memory when done.
635  */
636 PKCS12 *
637 sunw_PKCS12_create(const char *pass, STACK_OF(EVP_PKEY) *pkeys,
638     STACK_OF(X509) *certs, STACK_OF(X509) *cacerts)
639 {
640 	int nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
641 	int nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
642 	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
643 	STACK_OF(PKCS7) *safes = NULL;
644 	PKCS12_SAFEBAG *bag = NULL;
645 	PKCS8_PRIV_KEY_INFO *p8 = NULL;
646 	EVP_PKEY *pkey = NULL;
647 	PKCS12 *ret_p12 = NULL;
648 	PKCS12 *p12 = NULL;
649 	PKCS7 *authsafe = NULL;
650 	X509 *cert = NULL;
651 	uchar_t *str = NULL;
652 	int certs_there = 0;
653 	int keys_there = 0;
654 	int len;
655 	int i;
656 
657 	if ((safes = sk_PKCS7_new_null()) == NULL) {
658 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
659 		return (NULL);
660 	}
661 
662 	if ((bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
663 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
664 		goto err_ret;
665 	}
666 
667 	if (certs != NULL && sk_X509_num(certs) > 0) {
668 
669 		for (i = 0; i < sk_X509_num(certs); i++) {
670 			cert = sk_X509_value(certs, i);
671 
672 			/* Add user certificate */
673 			if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
674 				SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
675 				goto err_ret;
676 			}
677 			if (cert->aux != NULL && cert->aux->alias != NULL &&
678 			    cert->aux->alias->type == V_ASN1_UTF8STRING) {
679 				str = utf82ascstr(cert->aux->alias);
680 				if (str == NULL) {
681 					/*
682 					 * Error already on stack
683 					 */
684 					goto err_ret;
685 				}
686 				if (PKCS12_add_friendlyname_asc(bag,
687 				    (char const *) str,
688 				    strlen((char const *) str)) == 0) {
689 					SUNWerr(SUNW_F_PKCS12_CREATE,
690 					    SUNW_R_ADD_ATTR_ERR);
691 					goto err_ret;
692 				}
693 			}
694 			if (cert->aux != NULL && cert->aux->keyid != NULL &&
695 			    cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
696 				str = cert->aux->keyid->data;
697 				len = cert->aux->keyid->length;
698 
699 				if (str != NULL &&
700 				    PKCS12_add_localkeyid(bag, str, len) == 0) {
701 					SUNWerr(SUNW_F_PKCS12_CREATE,
702 					    SUNW_R_ADD_ATTR_ERR);
703 					goto err_ret;
704 				}
705 			}
706 			if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
707 				SUNWerr(SUNW_F_PKCS12_CREATE,
708 				    SUNW_R_MEMORY_FAILURE);
709 				goto err_ret;
710 			}
711 			certs_there++;
712 			bag = NULL;
713 		}
714 	}
715 
716 	if (cacerts != NULL && sk_X509_num(cacerts) > 0) {
717 
718 		/* Put all certs in structure */
719 		for (i = 0; i < sk_X509_num(cacerts); i++) {
720 			cert = sk_X509_value(cacerts, i);
721 			if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
722 				SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
723 				goto err_ret;
724 			}
725 
726 			if (cert->aux != NULL && cert->aux->alias != NULL &&
727 			    cert->aux->alias->type == V_ASN1_UTF8STRING) {
728 				str = utf82ascstr(cert->aux->alias);
729 				if (str == NULL) {
730 					/*
731 					 * Error already on stack
732 					 */
733 					goto err_ret;
734 				}
735 				if (PKCS12_add_friendlyname_asc(
736 				    bag, (char const *) str,
737 				    strlen((char const *) str)) == 0) {
738 					SUNWerr(SUNW_F_PKCS12_CREATE,
739 					    SUNW_R_ADD_ATTR_ERR);
740 					goto err_ret;
741 				}
742 			}
743 			if (cert->aux != NULL && cert->aux->keyid != NULL &&
744 			    cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
745 				str = cert->aux->keyid->data;
746 				len = cert->aux->keyid->length;
747 
748 				if (str != NULL &&
749 				    PKCS12_add_localkeyid(bag, str, len) == 0) {
750 					SUNWerr(SUNW_F_PKCS12_CREATE,
751 					    SUNW_R_ADD_ATTR_ERR);
752 					goto err_ret;
753 				}
754 			}
755 			if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
756 				SUNWerr(SUNW_F_PKCS12_CREATE,
757 				    SUNW_R_MEMORY_FAILURE);
758 				goto err_ret;
759 			}
760 			certs_there++;
761 			bag = NULL;
762 		}
763 	}
764 
765 	if (certs != NULL || cacerts != NULL && certs_there) {
766 		/* Turn certbags into encrypted authsafe */
767 		authsafe = PKCS12_pack_p7encdata(nid_cert, pass, -1,
768 		    NULL, 0, PKCS12_DEFAULT_ITER, bags);
769 		if (authsafe == NULL) {
770 			SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
771 			goto err_ret;
772 		}
773 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
774 		bags = NULL;
775 
776 		if (sk_PKCS7_push(safes, authsafe) == 0) {
777 			SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
778 			goto err_ret;
779 		}
780 		authsafe = NULL;
781 	}
782 
783 	if (pkeys != NULL && sk_EVP_PKEY_num(pkeys) > 0) {
784 
785 		if (bags == NULL &&
786 		    (bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
787 			SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
788 			goto err_ret;
789 		}
790 
791 		for (i = 0; i < sk_EVP_PKEY_num(pkeys); i++) {
792 
793 			pkey = sk_EVP_PKEY_value(pkeys, i);
794 
795 			/* Make a shrouded key bag */
796 			if ((p8 = EVP_PKEY2PKCS8(pkey)) == NULL) {
797 				SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKEY_ERR);
798 				goto err_ret;
799 			}
800 
801 			bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0,
802 			    PKCS12_DEFAULT_ITER, p8);
803 			if (bag == NULL) {
804 				SUNWerr(SUNW_F_PKCS12_CREATE,
805 				    SUNW_R_MAKE_BAG_ERR);
806 				goto err_ret;
807 			}
808 			PKCS8_PRIV_KEY_INFO_free(p8);
809 			p8 = NULL;
810 
811 			len = sunw_get_pkey_fname(GETDO_COPY, pkey,
812 			    (char **)&str);
813 			if (str != NULL) {
814 				if (PKCS12_add_friendlyname_asc(bag,
815 				    (const char *)str, len) == 0) {
816 					SUNWerr(SUNW_F_PKCS12_CREATE,
817 					    SUNW_R_ADD_ATTR_ERR);
818 					goto err_ret;
819 				}
820 			}
821 			str = NULL;
822 
823 			len = sunw_get_pkey_localkeyid(GETDO_COPY, pkey,
824 			    (char **)&str, &len);
825 			if (str != NULL) {
826 				if (PKCS12_add_localkeyid(bag, str, len) == 0) {
827 					SUNWerr(SUNW_F_PKCS12_CREATE,
828 					    SUNW_R_ADD_ATTR_ERR);
829 					goto err_ret;
830 				}
831 			}
832 			str = NULL;
833 
834 			if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
835 				SUNWerr(SUNW_F_PKCS12_CREATE,
836 				    SUNW_R_MEMORY_FAILURE);
837 				goto err_ret;
838 			}
839 			keys_there++;
840 			bag = NULL;
841 		}
842 
843 		if (keys_there) {
844 			/* Turn into unencrypted authsafe */
845 			authsafe = PKCS12_pack_p7data(bags);
846 			if (authsafe == NULL) {
847 				SUNWerr(SUNW_F_PKCS12_CREATE,
848 				    SUNW_R_PKCS12_CREATE_ERR);
849 				goto err_ret;
850 			}
851 			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
852 			bags = NULL;
853 
854 			if (sk_PKCS7_push(safes, authsafe) == 0) {
855 				SUNWerr(SUNW_F_PKCS12_CREATE,
856 				    SUNW_R_MEMORY_FAILURE);
857 			}
858 			authsafe = NULL;
859 		}
860 	}
861 
862 	if (certs_there == 0 && keys_there == 0) {
863 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_EMPTY_ERR);
864 		goto err_ret;
865 	}
866 
867 	if ((p12 = PKCS12_init(NID_pkcs7_data)) == NULL) {
868 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
869 		goto err_ret;
870 	}
871 
872 	/*
873 	 * Note that safes is copied by the following.  Therefore, it needs
874 	 * to be freed whether or not the following succeeds.
875 	 */
876 	if (M_PKCS12_pack_authsafes(p12, safes) == 0) {
877 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
878 		goto err_ret;
879 	}
880 	if (PKCS12_set_mac(p12, pass, -1, NULL, 0, 2048, NULL) == 0) {
881 		SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MAC_CREATE_FAILURE);
882 		goto err_ret;
883 	}
884 
885 	ret_p12 = p12;
886 	p12 = NULL;
887 
888 	/* Fallthrough is intentional */
889 
890 err_ret:
891 
892 	if (str != NULL)
893 		free(str);
894 
895 	if (p8 != NULL)
896 		PKCS8_PRIV_KEY_INFO_free(p8);
897 
898 	if (bag != NULL)
899 		PKCS12_SAFEBAG_free(bag);
900 	if (bags != NULL)
901 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
902 	if (authsafe != NULL)
903 		PKCS7_free(authsafe);
904 	if (safes != NULL)
905 		sk_PKCS7_pop_free(safes, PKCS7_free);
906 	if (p12 != NULL)
907 		PKCS12_free(p12);
908 
909 	return (ret_p12);
910 }
911 
912 /*
913  * sunw_evp_pkey_free() Given an EVP_PKEY structure, free any attributes
914  *     that are attached.  Then free the EVP_PKEY itself.
915  *
916  *     This is a replacement for EVP_PKEY_free() for the sunw stuff.
917  *     It should be used in places where EVP_PKEY_free would be used,
918  *     including calls to sk_EVP_PKEY_pop_free().
919  *
920  * Arguments:
921  *   pkey     - Entry which potentially has attributes to be freed.
922  *
923  * Returns:
924  *   None.
925  */
926 void
927 sunw_evp_pkey_free(EVP_PKEY *pkey)
928 {
929 	if (pkey != NULL) {
930 		if (pkey->attributes != NULL) {
931 			sk_X509_ATTRIBUTE_pop_free(pkey->attributes,
932 			    X509_ATTRIBUTE_free);
933 			pkey->attributes = NULL;
934 		}
935 		EVP_PKEY_free(pkey);
936 	}
937 }
938 
939 /*
940  * sunw_set_localkeyid() sets the localkeyid in a cert, a private key or
941  *     both.  Any existing localkeyid will be discarded.
942  *
943  * Arguments:
944  *   keyid_str- A byte string with the localkeyid to set
945  *   keyid_len- Length of the keyid byte string.
946  *   pkey     - Points to a private key to set the keyidstr in.
947  *   cert     - Points to a cert to set the keyidstr in.
948  *
949  * Note that setting a keyid into a cert which will not be written out as
950  * a PKCS12 cert is pointless since it will be lost.
951  *
952  * Returns:
953  *   0        - Success.
954  *   < 0      - An error occurred.  It was probably an error in allocating
955  *              memory.  The error will be set in the error stack.  Call
956  *              ERR_get_error() to get specific information.
957  */
958 int
959 sunw_set_localkeyid(const char *keyid_str, int keyid_len, EVP_PKEY *pkey,
960     X509 *cert)
961 {
962 	X509_ATTRIBUTE *attr = NULL;
963 	ASN1_STRING *str = NULL;
964 	ASN1_TYPE *keyid = NULL;
965 	int retval = -1;
966 	int i;
967 
968 	if (cert != NULL) {
969 		if (X509_keyid_set1(cert, (uchar_t *)keyid_str, keyid_len)
970 		    == 0) {
971 			SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_SET_LKID_ERR);
972 			goto cleanup;
973 		}
974 	}
975 	if (pkey != NULL) {
976 		str = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
977 		if (str == NULL ||
978 		    M_ASN1_OCTET_STRING_set(str, keyid_str, keyid_len) == 0 ||
979 		    (keyid = ASN1_TYPE_new()) == NULL) {
980 			SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
981 			goto cleanup;
982 		}
983 
984 		ASN1_TYPE_set(keyid, V_ASN1_OCTET_STRING, str);
985 		str = NULL;
986 
987 		attr = type2attrib(keyid, NID_localKeyID);
988 		if (attr == NULL) {
989 			/*
990 			 * Error already on stack
991 			 */
992 			goto cleanup;
993 		}
994 		keyid = NULL;
995 
996 		if (pkey->attributes == NULL) {
997 			pkey->attributes = sk_X509_ATTRIBUTE_new_null();
998 			if (pkey->attributes == NULL) {
999 				SUNWerr(SUNW_F_SET_LOCALKEYID,
1000 				    SUNW_R_MEMORY_FAILURE);
1001 				goto cleanup;
1002 			}
1003 		} else {
1004 			i = find_attr_by_nid(pkey->attributes, NID_localKeyID);
1005 			if (i >= 0)
1006 				sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1007 		}
1008 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
1009 			SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1010 			goto cleanup;
1011 		}
1012 		attr = NULL;
1013 	}
1014 	retval = 0;
1015 
1016 cleanup:
1017 	if (str != NULL)
1018 		ASN1_STRING_free(str);
1019 	if (keyid != NULL)
1020 		ASN1_TYPE_free(keyid);
1021 	if (attr != NULL)
1022 		X509_ATTRIBUTE_free(attr);
1023 
1024 	return (retval);
1025 }
1026 
1027 /*
1028  * sunw_get_pkey_localkeyid() gets the localkeyid from a private key.  It can
1029  *     optionally remove the value found.
1030  *
1031  * Arguments:
1032  *   dowhat   - What to do with the attributes (remove them or copy them).
1033  *   pkey     - Points to a private key to set the keyidstr in.
1034  *   keyid_str- Points to a location which will receive the pointer to
1035  *              a byte string containing the binary localkeyid.  Note that
1036  *              this is a copy, and the caller must free it.
1037  *   keyid_len- Length of keyid_str.
1038  *
1039  * Returns:
1040  *   >= 0     - The number of characters in the keyid returned.
1041  *   < 0      - An error occurred.  It was probably an error in allocating
1042  *              memory.  The error will be set in the error stack.  Call
1043  *              ERR_get_error() to get specific information.
1044  */
1045 int
1046 sunw_get_pkey_localkeyid(getdo_actions_t dowhat, EVP_PKEY *pkey,
1047     char **keyid_str, int *keyid_len)
1048 {
1049 	X509_ATTRIBUTE *attr = NULL;
1050 	ASN1_OCTET_STRING *str = NULL;
1051 	ASN1_TYPE *ty = NULL;
1052 	int len = 0;
1053 	int i;
1054 
1055 	if (keyid_str != NULL)
1056 		*keyid_str = NULL;
1057 	if (keyid_len != NULL)
1058 		*keyid_len = 0;
1059 
1060 	if (pkey == NULL || pkey->attributes == NULL) {
1061 		return (0);
1062 	}
1063 
1064 	if ((i = find_attr_by_nid(pkey->attributes, NID_localKeyID)) < 0) {
1065 		return (0);
1066 	}
1067 	attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
1068 
1069 	if ((ty = attrib2type(attr)) == NULL ||
1070 	    ty->type != V_ASN1_OCTET_STRING) {
1071 		return (0);
1072 	}
1073 
1074 	if (dowhat == GETDO_DEL) {
1075 		attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1076 		if (attr != NULL)
1077 			X509_ATTRIBUTE_free(attr);
1078 		return (0);
1079 	}
1080 
1081 	str = ty->value.octet_string;
1082 	len = str->length;
1083 	if ((*keyid_str = malloc(len)) == NULL) {
1084 		SUNWerr(SUNW_F_GET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1085 		return (-1);
1086 	}
1087 
1088 	(void) memcpy(*keyid_str, str->data, len);
1089 	*keyid_len = len;
1090 
1091 	return (len);
1092 }
1093 
1094 /*
1095  * sunw_get_pkey_fname() gets the friendlyName from a private key.  It can
1096  *     optionally remove the value found.
1097  *
1098  * Arguments:
1099  *   dowhat   - What to do with the attributes (remove them or copy them).
1100  *   pkey     - Points to a private key to get the frientlyname from
1101  *   fname    - Points to a location which will receive the pointer to a
1102  *              byte string with the ASCII friendlyname
1103  *
1104  * Returns:
1105  *   >= 0     - The number of characters in the frienlyname returned.
1106  *   < 0      - An error occurred.  It was probably an error in allocating
1107  *              memory.  The error will be set in the error stack.  Call
1108  *              ERR_get_error() to get specific information.
1109  */
1110 int
1111 sunw_get_pkey_fname(getdo_actions_t dowhat, EVP_PKEY *pkey, char **fname)
1112 {
1113 	X509_ATTRIBUTE *attr = NULL;
1114 	ASN1_BMPSTRING *str = NULL;
1115 	ASN1_TYPE *ty = NULL;
1116 	int len = 0;
1117 	int i;
1118 
1119 	if (fname != NULL)
1120 		*fname = NULL;
1121 
1122 	if (pkey == NULL || pkey->attributes == NULL) {
1123 		return (0);
1124 	}
1125 
1126 	if ((i = find_attr_by_nid(pkey->attributes, NID_friendlyName)) < 0) {
1127 		return (0);
1128 	}
1129 	attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
1130 
1131 	if ((ty = attrib2type(attr)) == NULL ||
1132 	    ty->type != V_ASN1_BMPSTRING) {
1133 		return (0);
1134 	}
1135 
1136 	if (dowhat == GETDO_DEL) {
1137 		attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1138 		if (attr != NULL)
1139 			X509_ATTRIBUTE_free(attr);
1140 		return (0);
1141 	}
1142 
1143 	str = ty->value.bmpstring;
1144 #if OPENSSL_VERSION_NUMBER < 0x10000000L
1145 	*fname = uni2asc(str->data, str->length);
1146 #else
1147 	*fname = OPENSSL_uni2asc(str->data, str->length);
1148 #endif
1149 	if (*fname == NULL) {
1150 		SUNWerr(SUNW_F_GET_PKEY_FNAME, SUNW_R_MEMORY_FAILURE);
1151 		return (-1);
1152 	}
1153 
1154 	len = strlen(*fname);
1155 
1156 	return (len);
1157 }
1158 
1159 /*
1160  * sunw_find_localkeyid() searches stacks of certs and private keys,
1161  *     and returns  the first matching cert/private key found.
1162  *
1163  * Look for a keyid in a stack of certs.  if 'certs' is NULL and 'pkeys' is
1164  * not NULL, search the list of private keys.  Move the matching cert to
1165  * 'matching_cert' and its matching private key to 'matching_pkey'.  If no
1166  * cert or keys match, no match occurred.
1167  *
1168  * Arguments:
1169  *   keyid_str- A byte string with the localkeyid to match
1170  *   keyid_len- Length of the keyid byte string.
1171  *   pkeys    - Points to a stack of private keys which match the certs.
1172  *              This may be NULL, in which case no keys are returned.
1173  *   certs    - Points to a stack of certs to search.  If NULL, search the
1174  *              stack of keys instead.
1175  *   matching_pkey
1176  *            - Pointer to receive address of first matching pkey found.
1177  *              'matching_pkey' must not be NULL; '*matching_pkey' will be
1178  *              reset.
1179  *   matching_cert
1180  *            - Pointer to receive address of first matching cert found.
1181  *              'matching_cert' must not be NULL; '*matching_cert' will be
1182  *              reset.
1183  *
1184  * Returns:
1185  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
1186  *         Where possible, memory has been freed.
1187  *  >= 0 - Objects were found and returned.  Which objects are indicated by
1188  *         which bits are set (FOUND_PKEY and/or FOUND_CERT).
1189  */
1190 int
1191 sunw_find_localkeyid(char *keyid_str, int len, STACK_OF(EVP_PKEY) *pkeys,
1192 STACK_OF(X509) *certs, EVP_PKEY **matching_pkey, X509 **matching_cert)
1193 {
1194 	ASN1_STRING *cmpstr = NULL;
1195 	EVP_PKEY *tmp_pkey = NULL;
1196 	X509 *tmp_cert = NULL;
1197 	int retval = 0;
1198 
1199 	/* If NULL arguments, this is an error */
1200 	if (keyid_str == NULL ||
1201 	    (pkeys == NULL || certs == NULL) ||
1202 	    (pkeys != NULL && matching_pkey == NULL) ||
1203 	    (certs != NULL && matching_cert == NULL)) {
1204 		SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_INVALID_ARG);
1205 		return (-1);
1206 	}
1207 
1208 	if (matching_pkey != NULL)
1209 		*matching_pkey = NULL;
1210 	if (matching_cert != NULL)
1211 		*matching_cert = NULL;
1212 
1213 	cmpstr = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
1214 	if (cmpstr == NULL ||
1215 	    M_ASN1_OCTET_STRING_set(cmpstr, keyid_str, len) == 0) {
1216 		SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1217 		return (-1);
1218 	}
1219 
1220 	retval = find_attr(NID_localKeyID, cmpstr, pkeys, &tmp_pkey, certs,
1221 	    &tmp_cert);
1222 	if (retval == 0) {
1223 		ASN1_STRING_free(cmpstr);
1224 		return (retval);
1225 	}
1226 
1227 	if (matching_pkey != NULL)
1228 		*matching_pkey = tmp_pkey;
1229 	if (matching_cert != NULL)
1230 		*matching_cert = tmp_cert;
1231 
1232 	return (retval);
1233 }
1234 
1235 /*
1236  * sunw_find_fname() searches stacks of certs and private keys for one with
1237  *     a matching friendlyname and returns the first matching cert/private
1238  *     key found.
1239  *
1240  * Look for a friendlyname in a stack of certs.  if 'certs' is NULL and 'pkeys'
1241  * is not NULL, search the list of private keys.  Move the matching cert to
1242  * 'matching_cert' and its matching private key to 'matching_pkey'.  If no
1243  * cert or keys match, no match occurred.
1244  *
1245  * Arguments:
1246  *   fname    - Friendlyname to find (NULL-terminated ASCII string).
1247  *   pkeys    - Points to a stack of private keys which match the certs.
1248  *              This may be NULL, in which case no keys are returned.
1249  *   certs    - Points to a stack of certs to search.  If NULL, search the
1250  *              stack of keys instead.
1251  *   matching_pkey
1252  *            - Pointer to receive address of first matching pkey found.
1253  *   matching_cert
1254  *            - Pointer to receive address of first matching cert found.
1255  *
1256  * Returns:
1257  *  <  0 - An error returned.  Call ERR_get_error() to get errors information.
1258  *         Where possible, memory has been freed.
1259  *  >= 0 - Objects were found and returned.  Which objects are indicated by
1260  *         which bits are set (FOUND_PKEY and/or FOUND_CERT).
1261  */
1262 int
1263 sunw_find_fname(char *fname, STACK_OF(EVP_PKEY) *pkeys, STACK_OF(X509) *certs,
1264     EVP_PKEY **matching_pkey, X509 ** matching_cert)
1265 {
1266 	ASN1_STRING *cmpstr = NULL;
1267 	EVP_PKEY *tmp_pkey = NULL;
1268 	X509 *tmp_cert = NULL;
1269 	int retval = 0;
1270 
1271 	/* If NULL arguments, this is an error */
1272 	if (fname == NULL ||
1273 	    (pkeys == NULL && certs == NULL) ||
1274 	    (pkeys != NULL && matching_pkey == NULL) ||
1275 	    (certs != NULL && matching_cert == NULL)) {
1276 		SUNWerr(SUNW_F_FIND_FNAME, SUNW_R_INVALID_ARG);
1277 		return (-1);
1278 	}
1279 
1280 	if (matching_pkey != NULL)
1281 		*matching_pkey = NULL;
1282 	if (matching_cert != NULL)
1283 		*matching_cert = NULL;
1284 
1285 	cmpstr = (ASN1_STRING *)asc2bmpstring(fname, strlen(fname));
1286 	if (cmpstr == NULL) {
1287 		/*
1288 		 * Error already on stack
1289 		 */
1290 		return (-1);
1291 	}
1292 
1293 	retval = find_attr(NID_friendlyName, cmpstr, pkeys, &tmp_pkey, certs,
1294 	    &tmp_cert);
1295 	if (retval == 0) {
1296 		ASN1_STRING_free(cmpstr);
1297 		return (retval);
1298 	}
1299 
1300 	if (matching_pkey != NULL)
1301 		*matching_pkey = tmp_pkey;
1302 	if (matching_cert != NULL)
1303 		*matching_cert = tmp_cert;
1304 
1305 	return (retval);
1306 }
1307 
1308 /*
1309  * sunw_get_cert_fname() gets the fiendlyname from a cert.  It can
1310  *     optionally remove the value found.
1311  *
1312  * Arguments:
1313  *   dowhat   - What to do with the attributes (remove them or copy them).
1314  *   cert     - Points to a cert to get the friendlyName from.
1315  *   fname    - Points to a location which will receive the pointer to a
1316  *              byte string with the ASCII friendlyname
1317  *
1318  * Returns:
1319  *   >= 0     - The number of characters in the friendlyname returned.
1320  *   < 0      - An error occurred.  It was probably an error in allocating
1321  *              memory.  The error will be set in the error stack.  Call
1322  *              ERR_get_error() to get specific information.
1323  */
1324 int
1325 sunw_get_cert_fname(getdo_actions_t dowhat, X509 *cert, char **fname)
1326 {
1327 	int len;
1328 
1329 	if (fname != NULL)
1330 		*fname = NULL;
1331 
1332 	if (cert == NULL || cert->aux == NULL || cert->aux->alias == NULL) {
1333 		return (0);
1334 	}
1335 
1336 	if (dowhat == GETDO_DEL) {
1337 		/* Delete the entry */
1338 		ASN1_UTF8STRING_free(cert->aux->alias);
1339 		cert->aux->alias = NULL;
1340 		return (0);
1341 	}
1342 
1343 	*((uchar_t **)fname) = utf82ascstr(cert->aux->alias);
1344 	if (*fname == NULL) {
1345 		/*
1346 		 * Error already on stack
1347 		 */
1348 		return (-1);
1349 	}
1350 
1351 	len = strlen(*fname);
1352 
1353 	return (len);
1354 }
1355 
1356 /*
1357  * sunw_set_fname() sets the friendlyName in a cert, a private key or
1358  *     both.  Any existing friendlyname will be discarded.
1359  *
1360  * Arguments:
1361  *   ascname  - An ASCII string with the friendlyName to set
1362  *   pkey     - Points to a private key to set the fname in.
1363  *   cert     - Points to a cert to set the fname in.
1364  *
1365  * Note that setting a friendlyName into a cert which will not be written out
1366  * as a PKCS12 cert is pointless since it will be lost.
1367  *
1368  * Returns:
1369  *   0        - Success.
1370  *   <0       - An error occurred.  It was probably an error in allocating
1371  *              memory.  The error will be set in the error stack.  Call
1372  *              ERR_get_error() to get specific information.
1373  */
1374 int
1375 sunw_set_fname(const char *ascname, EVP_PKEY *pkey, X509 *cert)
1376 {
1377 	X509_ATTRIBUTE *attr = NULL;
1378 	ASN1_BMPSTRING *str = NULL;
1379 	ASN1_TYPE *fname = NULL;
1380 	unsigned char *data = NULL;
1381 	int retval = -1;
1382 	int len;
1383 	int i;
1384 
1385 	str = asc2bmpstring(ascname, strlen(ascname));
1386 	if (str == NULL) {
1387 		/*
1388 		 * Error already on stack
1389 		 */
1390 		return (-1);
1391 	}
1392 
1393 	if (cert != NULL) {
1394 		if (cert->aux != NULL && cert->aux->alias != NULL) {
1395 			ASN1_UTF8STRING_free(cert->aux->alias);
1396 		}
1397 
1398 		len = ASN1_STRING_to_UTF8(&data, str);
1399 		i = -23;
1400 		if (len <= 0 || (i = X509_alias_set1(cert, data, len)) == 0) {
1401 			SUNWerr(SUNW_F_SET_FNAME, SUNW_R_SET_FNAME_ERR);
1402 			goto cleanup;
1403 		}
1404 	}
1405 	if (pkey != NULL) {
1406 		if ((fname = ASN1_TYPE_new()) == NULL) {
1407 			SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
1408 			goto cleanup;
1409 		}
1410 
1411 		ASN1_TYPE_set(fname, V_ASN1_BMPSTRING, str);
1412 		str = NULL;
1413 
1414 		attr = type2attrib(fname, NID_friendlyName);
1415 		if (attr == NULL) {
1416 			/*
1417 			 * Error already on stack
1418 			 */
1419 			goto cleanup;
1420 		}
1421 		fname = NULL;
1422 
1423 		if (pkey->attributes == NULL) {
1424 			pkey->attributes = sk_X509_ATTRIBUTE_new_null();
1425 			if (pkey->attributes == NULL) {
1426 				SUNWerr(SUNW_F_SET_FNAME,
1427 				    SUNW_R_MEMORY_FAILURE);
1428 				goto cleanup;
1429 			}
1430 		} else if ((i = find_attr_by_nid(pkey->attributes,
1431 		    NID_friendlyName)) >= 0) {
1432 			(void) sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1433 		}
1434 
1435 		if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
1436 			SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
1437 			goto cleanup;
1438 		}
1439 
1440 		attr = NULL;
1441 	}
1442 	retval = 0;
1443 
1444 cleanup:
1445 	if (data != NULL)
1446 		OPENSSL_free(data);
1447 	if (str != NULL)
1448 		ASN1_BMPSTRING_free(str);
1449 	if (fname != NULL)
1450 		ASN1_TYPE_free(fname);
1451 	if (attr != NULL)
1452 		X509_ATTRIBUTE_free(attr);
1453 
1454 	return (retval);
1455 }
1456 
1457 /*
1458  * sunw_check_keys() compares the public key in the certificate and a
1459  *     private key to ensure that they match.
1460  *
1461  * Arguments:
1462  *   cert     - Points to a certificate.
1463  *   pkey     - Points to a private key.
1464  *
1465  * Returns:
1466  *  == 0 - These do not match.
1467  *  != 0 - The cert's public key and the private key match.
1468  */
1469 int
1470 sunw_check_keys(X509 *cert, EVP_PKEY *pkey)
1471 {
1472 	int retval = 0;
1473 
1474 	if (pkey != NULL && cert != NULL)
1475 		retval = X509_check_private_key(cert, pkey);
1476 
1477 	return (retval);
1478 }
1479 
1480 /*
1481  * sunw_check_cert_times() compares the time fields in a certificate
1482  *
1483  * Compare the 'not before' and the 'not after' times in the cert
1484  * to the current time.  Return the results of the comparison (bad time formats,
1485  * cert not yet in force, cert expired or in range)
1486  *
1487  * Arguments:
1488  *   dowhat   - what field(s) to check.
1489  *   cert     - Points to a cert to check
1490  *
1491  * Returns:
1492  *   Results of the comparison.
1493  */
1494 chk_errs_t
1495 sunw_check_cert_times(chk_actions_t chkwhat, X509 *cert)
1496 {
1497 	return (check_time(chkwhat, cert));
1498 }
1499 
1500 /*
1501  * ----------------------------------------------------------------------------
1502  * Local routines
1503  * ----------------------------------------------------------------------------
1504  */
1505 
1506 
1507 /*
1508  * parse_pkcs12 - Oversee parsing of the pkcs12 structure.  Get it
1509  *         parsed.  After that either return what's found directly, or
1510  *         do any required matching.
1511  *
1512  * Arguments:
1513  *   p12      - Structure with pkcs12 info to be parsed
1514  *   pass     - Pass phrase for the private key (possibly empty) or NULL if
1515  *              there is none.
1516  *   matchty  - Info about which certs/keys to return if many are in the file.
1517  *   keyid    - If private key localkeyids friendlynames are to match a
1518  *              predetermined value, the value to match. This value should
1519  *		be an octet string.
1520  *   keyid_len- Length of the keyid byte string.
1521  *   name_str - If friendlynames are to match a predetermined value, the value
1522  *		 to match. This value should be a NULL terminated string.
1523  *   pkey     - Points to location pointing to the private key returned.
1524  *   cert     - Points to locaiton which points to the client cert returned
1525  *   ca       - Points to location that points to a stack of 'certificate
1526  *              authority' certs/trust anchors.
1527  *
1528  *   Note about error codes:  This function is an internal function, and the
1529  *   place where it is called sets error codes.  Therefore only set an error
1530  *   code if it is something that is unique or if the function which detected
1531  *   the error doesn't set one.
1532  *
1533  * Returns:
1534  *   == -1 - An error occurred.  Call ERR_get_error() to get error information.
1535  *           Where possible, memory has been freed.
1536  *   == 0  - No matching returns were found.
1537  *    > 0  - This is the aithmetic 'or' of the FOUND_* bits that indicate which
1538  *           of the requested entries were found.
1539  */
1540 static int
1541 parse_pkcs12(PKCS12 *p12, const char *pass, int matchty, char *keyid,
1542     int kstr_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
1543     STACK_OF(X509) **ca)
1544 {
1545 	STACK_OF(EVP_PKEY) *work_kl = NULL;	/* Head for private key list */
1546 	STACK_OF(EVP_PKEY) *nocerts = NULL;	/* Head for alt. key list */
1547 	STACK_OF(X509) *work_ca = NULL;		/* Head for cert list */
1548 	STACK_OF(X509) *work_cl = NULL;
1549 	int retval = 0;
1550 	int n;
1551 
1552 	retval = sunw_PKCS12_contents(p12, pass, &work_kl, &work_ca);
1553 	if (retval < 0) {
1554 		goto cleanup;
1555 	} else if (retval == 0) {
1556 		/*
1557 		 * Not really an error here - its just that nothing was found.
1558 		 */
1559 		goto cleanup;
1560 	}
1561 
1562 	if (sk_EVP_PKEY_num(work_kl) > 0) {
1563 
1564 		if (sunw_split_certs(work_kl, work_ca, &work_cl, &nocerts)
1565 		    < 0) {
1566 			goto cleanup;
1567 		}
1568 	}
1569 
1570 	/*
1571 	 * Go through the lists of certs and private keys which were
1572 	 * returned, looking for matches of the appropriate type.  Do these
1573 	 * in the order described above.
1574 	 */
1575 	if ((matchty & DO_FIND_KEYID) != 0) {
1576 
1577 		if (keyid == NULL) {
1578 			SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
1579 			retval = -1;
1580 			goto cleanup;
1581 		}
1582 
1583 		/* See if string matches localkeyid's */
1584 		retval = sunw_find_localkeyid(keyid, kstr_len,
1585 		    work_kl, work_cl, pkey, cert);
1586 		if (retval != 0) {
1587 			if (retval == -1)
1588 				goto cleanup;
1589 			else
1590 				goto last_part;
1591 		}
1592 	}
1593 	if ((matchty & DO_FIND_FN) != 0) {
1594 
1595 		if (name_str == NULL) {
1596 			SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
1597 			retval = -1;
1598 			goto cleanup;
1599 		}
1600 
1601 		/* See if string matches friendly names */
1602 		retval = sunw_find_fname(name_str, work_kl, work_cl,
1603 		    pkey, cert);
1604 		if (retval != 0) {
1605 			if (retval == -1)
1606 				goto cleanup;
1607 			else
1608 				goto last_part;
1609 		}
1610 	}
1611 
1612 	if (matchty & DO_FIRST_PAIR) {
1613 
1614 		/* Find the first cert and private key and return them */
1615 		retval = get_key_cert(0, work_kl, pkey, work_cl, cert);
1616 		if (retval != 0) {
1617 			if (retval == -1)
1618 				goto cleanup;
1619 			else
1620 				goto last_part;
1621 		}
1622 	}
1623 
1624 	if (matchty & DO_LAST_PAIR) {
1625 
1626 		/*
1627 		 * Find the last matching cert and private key and return
1628 		 * them.  Since keys which don't have matching client certs
1629 		 * are at the end of the list of keys, use the number of
1630 		 * client certs to compute the position of the last private
1631 		 * key which matches a client cert.
1632 		 */
1633 		n = sk_X509_num(work_cl) - 1;
1634 		retval = get_key_cert(n, work_kl, pkey, work_cl, cert);
1635 		if (retval != 0) {
1636 			if (retval == -1)
1637 				goto cleanup;
1638 			else
1639 				goto last_part;
1640 		}
1641 	}
1642 
1643 	if (matchty & DO_UNMATCHING) {
1644 		STACK_OF(EVP_PKEY) *tmpk;
1645 		STACK_OF(X509) *tmpc;
1646 
1647 		/* Find the first cert and private key and return them */
1648 		tmpc = work_cl;
1649 		if (work_cl == NULL || sk_X509_num(work_cl) == 0)
1650 			tmpc = work_ca;
1651 		tmpk = work_kl;
1652 		if (work_kl == NULL || sk_EVP_PKEY_num(work_kl) == 0)
1653 			tmpk = nocerts;
1654 		retval = get_key_cert(0, tmpk, pkey, tmpc, cert);
1655 		if (retval != 0) {
1656 			if (retval == -1)
1657 				goto cleanup;
1658 			else
1659 				goto last_part;
1660 		}
1661 	}
1662 
1663 last_part:
1664 	/* If no errors, terminate normally */
1665 	if (retval != -1)
1666 		retval |= set_results(NULL, NULL, NULL, NULL, ca, &work_ca,
1667 		    NULL, NULL);
1668 	if (retval >= 0) {
1669 		goto clean_part;
1670 	}
1671 
1672 	/* Fallthrough is intentional in error cases. */
1673 cleanup:
1674 	if (pkey != NULL && *pkey != NULL) {
1675 		sunw_evp_pkey_free(*pkey);
1676 		*pkey = NULL;
1677 	}
1678 	if (cert != NULL && *cert != NULL) {
1679 		X509_free(*cert);
1680 		*cert = NULL;
1681 	}
1682 
1683 clean_part:
1684 
1685 	if (work_kl != NULL) {
1686 		sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
1687 	}
1688 	if (work_ca != NULL)
1689 		sk_X509_pop_free(work_ca, X509_free);
1690 	if (work_cl != NULL)
1691 		sk_X509_pop_free(work_cl, X509_free);
1692 
1693 	return (retval);
1694 }
1695 
1696 /*
1697  * parse_outer - Unpack the outer PKCS#12 structure and go through the
1698  *         individual bags.  Return stacks of certs, private keys found and
1699  *         CA certs found.
1700  *
1701  *   Note about error codes:  This function is an internal function, and the
1702  *   place where it is called sets error codes.
1703  *
1704  * Returns:
1705  *    0 - An error returned.  Call ERR_get_error() to get errors information.
1706  *        Where possible, memory has been freed.
1707  *    1 - PKCS12 data object was parsed and lists of certs and private keys
1708  *        were returned.
1709  */
1710 static int
1711 parse_outer(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) *kl,
1712     STACK_OF(X509) *cl)
1713 {
1714 	STACK_OF(PKCS12_SAFEBAG) *bags;
1715 	STACK_OF(PKCS7) *asafes;
1716 	int i, bagnid;
1717 	PKCS7 *p7;
1718 
1719 	if ((asafes = M_PKCS12_unpack_authsafes(p12)) == NULL)
1720 		return (0);
1721 
1722 	for (i = 0; i < sk_PKCS7_num(asafes); i++) {
1723 		p7 = sk_PKCS7_value(asafes, i);
1724 		bagnid = OBJ_obj2nid(p7->type);
1725 		if (bagnid == NID_pkcs7_data) {
1726 			bags = M_PKCS12_unpack_p7data(p7);
1727 		} else if (bagnid == NID_pkcs7_encrypted) {
1728 			/*
1729 			 * A length of '-1' means strlen() can be used
1730 			 * to determine the password length.
1731 			 */
1732 			bags = M_PKCS12_unpack_p7encdata(p7, pass, -1);
1733 		} else {
1734 			SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_BAD_BAGTYPE);
1735 			return (0);
1736 		}
1737 
1738 		if (bags == NULL) {
1739 			SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_PARSE_BAG_ERR);
1740 			sk_PKCS7_pop_free(asafes, PKCS7_free);
1741 			return (0);
1742 		}
1743 		if (parse_all_bags(bags, pass, kl, cl) == 0) {
1744 			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
1745 			sk_PKCS7_pop_free(asafes, PKCS7_free);
1746 			return (0);
1747 		}
1748 	}
1749 
1750 	return (1);
1751 }
1752 
1753 /*
1754  * parse_all_bags - go through the stack of bags, parsing each.
1755  *
1756  *   Note about error codes:  This function is an internal function, and the
1757  *   place where it is called sets error codes.
1758  *
1759  * Returns:
1760  *    0 - An error returned.  Call ERR_get_error() to get errors information.
1761  *        Where possible, memory has been freed.
1762  *    1 - Stack of safebags was parsed and lists of certs and private keys
1763  *        were returned.
1764  */
1765 static int
1766 parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
1767     STACK_OF(EVP_PKEY) *kl, STACK_OF(X509) *cl)
1768 {
1769 	int i;
1770 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
1771 		if (parse_one_bag(sk_PKCS12_SAFEBAG_value(bags, i),
1772 		    pass, kl, cl) == 0)
1773 			return (0);
1774 	}
1775 	return (1);
1776 }
1777 
1778 /*
1779  * parse_one_bag - Parse an individual bag
1780  *
1781  *   i = parse_one_bag(bag, pass, kl, cl);
1782  *
1783  * Arguments:
1784  *   bag	- pkcs12 safebag to parse.
1785  *   pass 	- password for use in decryption of shrouded keybag
1786  *   kl         - Stack of private keys found so far.  New private keys will
1787  *                be added here if found.
1788  *   cl         - Stack of certs found so far.  New certificates will be
1789  *                added here if found.
1790  *
1791  * Returns:
1792  *    0 - An error returned.  Call ERR_get_error() to get errors information.
1793  *        Where possible, memory has been freed.
1794  *    1 - one safebag was parsed. If it contained a cert or private key, it
1795  *        was added to the stack of certs or private keys found, respectively.
1796  *        localKeyId or friendlyName attributes are returned with the
1797  *        private key or certificate.
1798  */
1799 static int
1800 parse_one_bag(PKCS12_SAFEBAG *bag, const char *pass, STACK_OF(EVP_PKEY) *kl,
1801     STACK_OF(X509) *cl)
1802 {
1803 	X509_ATTRIBUTE *attr = NULL;
1804 	ASN1_TYPE *keyid = NULL;
1805 	ASN1_TYPE *fname = NULL;
1806 	PKCS8_PRIV_KEY_INFO *p8;
1807 	EVP_PKEY *pkey = NULL;
1808 	X509 *x509 = NULL;
1809 	uchar_t *data = NULL;
1810 	char *str = NULL;
1811 	int retval = 1;
1812 
1813 	keyid = PKCS12_get_attr(bag, NID_localKeyID);
1814 	fname = PKCS12_get_attr(bag, NID_friendlyName);
1815 
1816 	switch (M_PKCS12_bag_type(bag)) {
1817 	case NID_keyBag:
1818 		if ((pkey = EVP_PKCS82PKEY(bag->value.keybag)) == NULL) {
1819 			SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1820 			retval = 0;
1821 			break;
1822 		}
1823 		break;
1824 
1825 	case NID_pkcs8ShroudedKeyBag:
1826 		/*
1827 		 * A length of '-1' means strlen() can be used
1828 		 * to determine the password length.
1829 		 */
1830 		if ((p8 = M_PKCS12_decrypt_skey(bag, pass, -1)) == NULL) {
1831 			SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1832 			retval = 0;
1833 			break;
1834 		}
1835 		pkey = EVP_PKCS82PKEY(p8);
1836 		PKCS8_PRIV_KEY_INFO_free(p8);
1837 		if (pkey == NULL) {
1838 			SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1839 			retval = 0;
1840 		}
1841 		break;
1842 
1843 	case NID_certBag:
1844 		if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) {
1845 			SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_CERTTYPE);
1846 			break;
1847 		}
1848 		if ((x509 = M_PKCS12_certbag2x509(bag)) == NULL) {
1849 			SUNWerr(SUNW_F_PARSE_ONE_BAG,
1850 			    SUNW_R_PARSE_CERT_ERR);
1851 			retval = 0;
1852 			break;
1853 		}
1854 
1855 		if (keyid != NULL) {
1856 			if (keyid->type != V_ASN1_OCTET_STRING) {
1857 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1858 				    SUNW_R_BAD_LKID);
1859 				retval = 0;
1860 				break;
1861 			}
1862 			if (X509_keyid_set1(x509,
1863 			    keyid->value.octet_string->data,
1864 			    keyid->value.octet_string->length) == 0) {
1865 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1866 				    SUNW_R_SET_LKID_ERR);
1867 				retval = 0;
1868 				break;
1869 			}
1870 		}
1871 
1872 		if (fname != NULL) {
1873 			ASN1_STRING *tmpstr = NULL;
1874 			int len;
1875 
1876 			if (fname->type != V_ASN1_BMPSTRING) {
1877 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1878 				    SUNW_R_BAD_FNAME);
1879 				retval = 0;
1880 				break;
1881 			}
1882 
1883 			tmpstr = fname->value.asn1_string;
1884 			len = ASN1_STRING_to_UTF8(&data, tmpstr);
1885 			if (len < 0) {
1886 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1887 				    SUNW_R_SET_FNAME_ERR);
1888 				retval = 0;
1889 				break;
1890 			}
1891 
1892 			if (X509_alias_set1(x509, data, len) == 0) {
1893 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1894 				    SUNW_R_SET_FNAME_ERR);
1895 				retval = 0;
1896 				break;
1897 			}
1898 		}
1899 
1900 		if (sk_X509_push(cl, x509) == 0) {
1901 			SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_MEMORY_FAILURE);
1902 			retval = 0;
1903 			break;
1904 		}
1905 		x509 = NULL;
1906 		break;
1907 
1908 	case NID_safeContentsBag:
1909 		if (keyid != NULL)
1910 			ASN1_TYPE_free(keyid);
1911 		if (fname != NULL)
1912 			ASN1_TYPE_free(fname);
1913 		if (parse_all_bags(bag->value.safes, pass, kl, cl) == 0) {
1914 			/*
1915 			 * Error already on stack
1916 			 */
1917 			return (0);
1918 		}
1919 		return (1);
1920 
1921 	default:
1922 		if (keyid != NULL)
1923 			ASN1_TYPE_free(keyid);
1924 		if (fname != NULL)
1925 			ASN1_TYPE_free(fname);
1926 		SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_BAGTYPE);
1927 		return (0);
1928 	}
1929 
1930 
1931 	if (pkey != NULL) {
1932 		if (retval != 0 && (keyid != NULL || fname != NULL) &&
1933 		    pkey->attributes == NULL) {
1934 			pkey->attributes = sk_X509_ATTRIBUTE_new_null();
1935 			if (pkey->attributes == NULL) {
1936 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1937 				    SUNW_R_MEMORY_FAILURE);
1938 				retval = 0;
1939 			}
1940 		}
1941 
1942 		if (retval != 0 && keyid != NULL) {
1943 			attr = type2attrib(keyid, NID_localKeyID);
1944 			if (attr == NULL)
1945 				/*
1946 				 * Error already on stack
1947 				 */
1948 				retval = 0;
1949 			else {
1950 				keyid = NULL;
1951 				if (sk_X509_ATTRIBUTE_push(pkey->attributes,
1952 				    attr) == 0) {
1953 					SUNWerr(SUNW_F_PARSE_ONE_BAG,
1954 					    SUNW_R_MEMORY_FAILURE);
1955 					retval = 0;
1956 				} else {
1957 					attr = NULL;
1958 				}
1959 			}
1960 		}
1961 
1962 		if (retval != 0 && fname != NULL) {
1963 			attr = type2attrib(fname, NID_friendlyName);
1964 			if (attr == NULL) {
1965 				/*
1966 				 * Error already on stack
1967 				 */
1968 				retval = 0;
1969 			} else {
1970 				fname = NULL;
1971 				if (sk_X509_ATTRIBUTE_push(pkey->attributes,
1972 				    attr) == 0) {
1973 					SUNWerr(SUNW_F_PARSE_ONE_BAG,
1974 					    SUNW_R_MEMORY_FAILURE);
1975 					retval = 0;
1976 				} else {
1977 					attr = NULL;
1978 				}
1979 			}
1980 		}
1981 
1982 		/* Save the private key */
1983 		if (retval != 0) {
1984 			if (sk_EVP_PKEY_push(kl, pkey) == 0) {
1985 				SUNWerr(SUNW_F_PARSE_ONE_BAG,
1986 				    SUNW_R_MEMORY_FAILURE);
1987 				retval = 0;
1988 			} else {
1989 				pkey = NULL;
1990 			}
1991 		}
1992 	}
1993 
1994 	if (pkey != NULL) {
1995 		sunw_evp_pkey_free(pkey);
1996 	}
1997 
1998 	if (x509 != NULL)
1999 		X509_free(x509);
2000 
2001 	if (keyid != NULL)
2002 		ASN1_TYPE_free(keyid);
2003 
2004 	if (fname != NULL)
2005 		ASN1_TYPE_free(fname);
2006 
2007 	if (attr != NULL)
2008 		X509_ATTRIBUTE_free(attr);
2009 
2010 	if (data != NULL)
2011 		OPENSSL_free(data);
2012 
2013 	if (str != NULL)
2014 		OPENSSL_free(str);
2015 
2016 	return (retval);
2017 }
2018 
2019 /*
2020  * This function uses the only function that reads PEM files, regardless of
2021  * the kinds of information included (private keys, public keys, cert requests,
2022  * certs).  Other interfaces that read files require that the application
2023  * specifically know what kinds of things to read next, and call different
2024  * interfaces for the different kinds of entities.
2025  *
2026  * There is only one aspect of this function that's a bit problematic.
2027  * If it finds an encrypted private key, it does not decrypt it.  It returns
2028  * the encrypted data and other information needed to decrypt it.  The caller
2029  * must do the decryption.  This function does the decoding.
2030  */
2031 static int
2032 pem_info(FILE *fp, pem_password_cb cb, void *userdata,
2033     STACK_OF(EVP_PKEY) **pkeys, STACK_OF(X509) **certs)
2034 {
2035 	STACK_OF(X509_INFO) *info;
2036 	STACK_OF(EVP_PKEY) *work_kl;
2037 	STACK_OF(X509) *work_cl;
2038 	X509_INFO *x;
2039 	int retval = 0;
2040 	int i;
2041 
2042 	info = PEM_X509_INFO_read(fp, NULL, cb, userdata);
2043 	if (info == NULL) {
2044 		SUNWerr(SUNW_F_PEM_INFO, SUNW_R_READ_ERR);
2045 		return (-1);
2046 	}
2047 
2048 	/*
2049 	 * Allocate the working stacks for private key(s) and for the cert(s).
2050 	 */
2051 	if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
2052 		SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
2053 		retval = -1;
2054 		goto cleanup;
2055 	}
2056 
2057 	if ((work_cl = sk_X509_new_null()) == NULL) {
2058 		SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
2059 		retval = -1;
2060 		goto cleanup;
2061 	}
2062 
2063 	/*
2064 	 * Go through the entries in the info structure.
2065 	 */
2066 	for (i = 0; i < sk_X509_INFO_num(info); i++) {
2067 		x = sk_X509_INFO_value(info, i);
2068 		if (x->x509) {
2069 			if (sk_X509_push(work_cl, x->x509) == 0) {
2070 				retval = -1;
2071 				break;
2072 			}
2073 			x->x509 = NULL;
2074 		}
2075 		if (x->x_pkey != NULL && x->x_pkey->dec_pkey != NULL &&
2076 		    (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA ||
2077 		    x->x_pkey->dec_pkey->type == EVP_PKEY_DSA)) {
2078 			const uchar_t *p;
2079 
2080 			/*
2081 			 * If the key was encrypted, PEM_X509_INFO_read does
2082 			 * not decrypt it.  If that is the case, the 'enc_pkey'
2083 			 * field is set to point to the unencrypted key data.
2084 			 * Go through the additional steps to decode it before
2085 			 * going on.
2086 			 */
2087 			if (x->x_pkey->enc_pkey != NULL) {
2088 
2089 				if (PEM_do_header(&x->enc_cipher,
2090 				    (uchar_t *)x->enc_data,
2091 				    (long *)&x->enc_len,
2092 				    cb, userdata) == 0) {
2093 					if (ERR_GET_REASON(ERR_peek_error()) ==
2094 					    PEM_R_BAD_PASSWORD_READ) {
2095 						SUNWerr(SUNW_F_PEM_INFO,
2096 						    SUNW_R_PASSWORD_ERR);
2097 					} else {
2098 						SUNWerr(SUNW_F_PEM_INFO,
2099 						    SUNW_R_PKEY_READ_ERR);
2100 					}
2101 					retval = -1;
2102 					break;
2103 				}
2104 				if (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA) {
2105 					RSA **pp;
2106 
2107 					pp = &(x->x_pkey->dec_pkey->pkey.rsa);
2108 					p = (uchar_t *)x->enc_data;
2109 					if (d2i_RSAPrivateKey(pp, &p,
2110 					    x->enc_len) == NULL) {
2111 						SUNWerr(SUNW_F_PEM_INFO,
2112 						    SUNW_R_PKEY_READ_ERR);
2113 						retval = -1;
2114 						break;
2115 					}
2116 				} else {
2117 					DSA **pp;
2118 
2119 					pp = &(x->x_pkey->dec_pkey->pkey.dsa);
2120 					p = (uchar_t *)x->enc_data;
2121 					if (d2i_DSAPrivateKey(pp, &p,
2122 					    x->enc_len) == NULL) {
2123 						SUNWerr(SUNW_F_PEM_INFO,
2124 						    SUNW_R_PKEY_READ_ERR);
2125 						retval = -1;
2126 						break;
2127 					}
2128 				}
2129 			}
2130 
2131 			/* Save the key. */
2132 			retval = sk_EVP_PKEY_push(work_kl, x->x_pkey->dec_pkey);
2133 			if (retval == 0) {
2134 				retval = -1;
2135 				break;
2136 			}
2137 			x->x_pkey->dec_pkey = NULL;
2138 		} else if (x->x_pkey != NULL) {
2139 			SUNWerr(SUNW_F_PEM_INFO, SUNW_R_BAD_PKEYTYPE);
2140 			retval = -1;
2141 			break;
2142 		}
2143 	}
2144 	if (retval == -1)
2145 		goto cleanup;
2146 
2147 	/* If error occurs, then error already on stack */
2148 	retval = set_results(pkeys, &work_kl, certs, &work_cl, NULL, NULL,
2149 	    NULL, NULL);
2150 
2151 cleanup:
2152 	if (work_kl != NULL) {
2153 		sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
2154 	}
2155 	if (work_cl != NULL)
2156 		sk_X509_pop_free(work_cl, X509_free);
2157 
2158 	sk_X509_INFO_pop_free(info, X509_INFO_free);
2159 
2160 	return (retval);
2161 }
2162 
2163 /*
2164  * sunw_append_keys - Given two stacks of private keys, remove the keys from
2165  *      the second stack and append them to the first.  Both stacks must exist
2166  *      at time of call.
2167  *
2168  * Arguments:
2169  *   dst 	- the stack to receive the keys from 'src'
2170  *   src	- the stack whose keys are to be moved.
2171  *
2172  * Returns:
2173  *   -1  	- An error occurred.  The error status is set.
2174  *   >= 0       - The number of keys that were copied.
2175  */
2176 static int
2177 sunw_append_keys(STACK_OF(EVP_PKEY) *dst, STACK_OF(EVP_PKEY) *src)
2178 {
2179 	EVP_PKEY *tmpk;
2180 	int count = 0;
2181 
2182 	while (sk_EVP_PKEY_num(src) > 0) {
2183 		tmpk = sk_EVP_PKEY_delete(src, 0);
2184 		if (sk_EVP_PKEY_push(dst, tmpk) == 0) {
2185 			sunw_evp_pkey_free(tmpk);
2186 			SUNWerr(SUNW_F_APPEND_KEYS, SUNW_R_MEMORY_FAILURE);
2187 			return (-1);
2188 		}
2189 		count ++;
2190 	}
2191 
2192 	return (count);
2193 }
2194 
2195 /*
2196  * move_certs - Given two stacks of certs, remove the certs from
2197  *      the second stack and append them to the first.
2198  *
2199  * Arguments:
2200  *   dst 	- the stack to receive the certs from 'src'
2201  *   src	- the stack whose certs are to be moved.
2202  *
2203  * Returns:
2204  *   -1  	- An error occurred.  The error status is set.
2205  *   >= 0       - The number of certs that were copied.
2206  */
2207 static int
2208 move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src)
2209 {
2210 	X509 *tmpc;
2211 	int count = 0;
2212 
2213 	while (sk_X509_num(src) > 0) {
2214 		tmpc = sk_X509_delete(src, 0);
2215 		if (sk_X509_push(dst, tmpc) == 0) {
2216 			X509_free(tmpc);
2217 			SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE);
2218 			return (-1);
2219 		}
2220 		count++;
2221 	}
2222 
2223 	return (count);
2224 }
2225 
2226 /*
2227  * get_key_cert - Get a cert and its matching key from the stacks of certs
2228  *      and keys.  They are removed from the stacks.
2229  *
2230  * Arguments:
2231  *   n        - Offset of the entries to return.
2232  *   kl       - Points to a stack of private keys that matches the list of
2233  *              certs below.
2234  *   pkey     - Points at location where the address of the matching private
2235  *              key will be stored.
2236  *   cl       - Points to a stack of client certs with matching private keys.
2237  *   cert     - Points to locaiton where the address of the matching client cert
2238  *              will be returned
2239  *
2240  * The assumption is that the stacks of keys and certs contain key/cert pairs,
2241  * with entries in the same order and hence at the same offset.  Provided
2242  * the key and cert selected match, each will be removed from its stack and
2243  * returned.
2244  *
2245  * A stack of certs can be passed in without a stack of private keys, and vise
2246  * versa.  In that case, the indicated key/cert will be returned.
2247  *
2248  * Returns:
2249  *     0 - No matches were found.
2250  *   > 0 - Bits set based on FOUND_* definitions, indicating what is returned.
2251  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
2252  */
2253 static int
2254 get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl,
2255     X509 **cert)
2256 {
2257 	int retval = 0;
2258 	int nk;
2259 	int nc;
2260 
2261 	nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0;
2262 	nc = (cl != NULL) ? sk_X509_num(cl) : 0;
2263 
2264 	if (pkey != NULL && *pkey == NULL) {
2265 		if (nk > 0 && n >= 0 || n < nk) {
2266 			*pkey = sk_EVP_PKEY_delete(kl, n);
2267 			if (*pkey != NULL)
2268 				retval |= FOUND_PKEY;
2269 		}
2270 	}
2271 
2272 	if (cert != NULL && *cert == NULL) {
2273 		if (nc > 0 && n >= 0 && n < nc) {
2274 			*cert = sk_X509_delete(cl, n);
2275 			if (*cert != NULL)
2276 				retval |= FOUND_CERT;
2277 		}
2278 	}
2279 
2280 	return (retval);
2281 }
2282 
2283 
2284 /*
2285  * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in
2286  *         ASN1_BMPSTRING format.
2287  *
2288  * Arguments:
2289  *   str      - String to be convered.
2290  *   len      - Length of the string.
2291  *
2292  * Returns:
2293  *   == NULL  - An error occurred.  Error information (accessible by
2294  *              ERR_get_error()) is set.
2295  *   != NULL  - Points to an ASN1_BMPSTRING structure with the converted
2296  *              string as a value.
2297  */
2298 static ASN1_BMPSTRING *
2299 asc2bmpstring(const char *str, int len)
2300 {
2301 	ASN1_BMPSTRING *bmp = NULL;
2302 	uchar_t *uni = NULL;
2303 	int unilen;
2304 
2305 	/* Convert the character to the bmp format. */
2306 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2307 	if (asc2uni(str, len, &uni, &unilen) == 0) {
2308 #else
2309 	if (OPENSSL_asc2uni(str, len, &uni, &unilen) == 0) {
2310 #endif
2311 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
2312 		return (NULL);
2313 	}
2314 
2315 	/*
2316 	 * Adjust for possible pair of NULL bytes at the end because
2317 	 * asc2uni() returns a doubly null terminated string.
2318 	 */
2319 	if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0')
2320 		unilen -= 2;
2321 
2322 	/* Construct comparison string with correct format */
2323 	bmp = M_ASN1_BMPSTRING_new();
2324 	if (bmp == NULL) {
2325 		SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
2326 		OPENSSL_free(uni);
2327 		return (NULL);
2328 	}
2329 
2330 	bmp->data = uni;
2331 	bmp->length = unilen;
2332 
2333 	return (bmp);
2334 }
2335 
2336 /*
2337  * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string.
2338  *         This goes through an intermediate step with a ASN1_STRING type of
2339  *         IA5STRING (International Alphabet 5, which is the same as ASCII).
2340  *
2341  * Arguments:
2342  *   str      - UTF8STRING to be converted.
2343  *
2344  * Returns:
2345  *   == NULL  - An error occurred.  Error information (accessible by
2346  *              ERR_get_error()) is set.
2347  *   != NULL  - Points to a NULL-termianted ASCII string.  The caller must
2348  *              free it.
2349  */
2350 static uchar_t *
2351 utf82ascstr(ASN1_UTF8STRING *ustr)
2352 {
2353 	ASN1_STRING tmpstr;
2354 	ASN1_STRING *astr = &tmpstr;
2355 	uchar_t *retstr = NULL;
2356 	int mbflag;
2357 	int ret;
2358 
2359 	if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) {
2360 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG);
2361 		return (NULL);
2362 	}
2363 
2364 	mbflag = MBSTRING_ASC;
2365 	tmpstr.data = NULL;
2366 	tmpstr.length = 0;
2367 
2368 	ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag,
2369 	    B_ASN1_IA5STRING);
2370 	if (ret < 0) {
2371 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR);
2372 		return (NULL);
2373 	}
2374 
2375 	retstr = OPENSSL_malloc(astr->length + 1);
2376 	if (retstr == NULL) {
2377 		SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE);
2378 		return (NULL);
2379 	}
2380 
2381 	(void) memcpy(retstr, astr->data, astr->length);
2382 	retstr[astr->length] = '\0';
2383 	OPENSSL_free(astr->data);
2384 
2385 	return (retstr);
2386 }
2387 
2388 
2389 /*
2390  * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type
2391  *     specified by the given NID.
2392  *
2393  * Arguments:
2394  *   ty       - Type structure to be made into an attribute
2395  *   nid      - NID of the attribute
2396  *
2397  * Returns:
2398  *   NULL	An error occurred.
2399  *   != NULL	An X509_ATTRIBUTE structure.
2400  */
2401 X509_ATTRIBUTE *
2402 type2attrib(ASN1_TYPE *ty, int nid)
2403 {
2404 	X509_ATTRIBUTE *a;
2405 
2406 	if ((a = X509_ATTRIBUTE_new()) == NULL ||
2407 	    (a->value.set = sk_ASN1_TYPE_new_null()) == NULL ||
2408 	    sk_ASN1_TYPE_push(a->value.set, ty) == 0) {
2409 		if (a != NULL)
2410 			X509_ATTRIBUTE_free(a);
2411 			SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE);
2412 		return (NULL);
2413 	}
2414 	a->single = 0;
2415 	a->object = OBJ_nid2obj(nid);
2416 
2417 	return (a);
2418 }
2419 
2420 /*
2421  * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE
2422  *     component
2423  *
2424  * Arguments:
2425  *   attr     - Attribute structure containing a type.
2426  *
2427  * Returns:
2428  *   NULL	An error occurred.
2429  *   != NULL	An ASN1_TYPE structure.
2430  */
2431 static ASN1_TYPE *
2432 attrib2type(X509_ATTRIBUTE *attr)
2433 {
2434 	ASN1_TYPE *ty = NULL;
2435 
2436 	if (attr == NULL || attr->single == 1)
2437 		return (NULL);
2438 
2439 	if (sk_ASN1_TYPE_num(attr->value.set) > 0)
2440 		ty = sk_ASN1_TYPE_value(attr->value.set, 0);
2441 
2442 	return (ty);
2443 }
2444 
2445 /*
2446  * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE
2447  *     of the type specified by the given NID.
2448  *
2449  * Arguments:
2450  *   attrs    - Stack of attributes to search
2451  *   nid      - NID of the attribute being searched for
2452  *
2453  * Returns:
2454  *   -1 	None found
2455  *   != -1	Offset of the matching attribute.
2456  */
2457 static int
2458 find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
2459 {
2460 	X509_ATTRIBUTE *a;
2461 	int i;
2462 
2463 	if (attrs == NULL)
2464 		return (-1);
2465 
2466 	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
2467 		a = sk_X509_ATTRIBUTE_value(attrs, i);
2468 		if (OBJ_obj2nid(a->object) == nid)
2469 			return (i);
2470 	}
2471 	return (-1);
2472 }
2473 
2474 /*
2475  * Called by our PKCS12 code to read our function and error codes
2476  * into memory so that the OpenSSL framework can retrieve them.
2477  */
2478 void
2479 ERR_load_SUNW_strings(void)
2480 {
2481 	assert(SUNW_lib_error_code == 0);
2482 #ifndef OPENSSL_NO_ERR
2483 	/*
2484 	 * Have OpenSSL provide us with a unique ID.
2485 	 */
2486 	SUNW_lib_error_code = ERR_get_next_error_library();
2487 
2488 	ERR_load_strings(SUNW_lib_error_code, SUNW_str_functs);
2489 	ERR_load_strings(SUNW_lib_error_code, SUNW_str_reasons);
2490 
2491 	SUNW_lib_name->error = ERR_PACK(SUNW_lib_error_code, 0, 0);
2492 	ERR_load_strings(0, SUNW_lib_name);
2493 #endif
2494 }
2495 
2496 /*
2497  * The SUNWerr macro resolves to this routine. So when we need
2498  * to push an error, this routine does it for us. Notice that
2499  * the SUNWerr macro provides a filename and line #.
2500  */
2501 void
2502 ERR_SUNW_error(int function, int reason, char *file, int line)
2503 {
2504 	assert(SUNW_lib_error_code != 0);
2505 #ifndef OPENSSL_NO_ERR
2506 	ERR_PUT_error(SUNW_lib_error_code, function, reason, file, line);
2507 #endif
2508 }
2509 
2510 /*
2511  * check_time - Given an indication of the which time(s) to check, check
2512  *      that time or those times against the current time and return the
2513  *      relationship.
2514  *
2515  * Arguments:
2516  *   chkwhat    - What kind of check to do.
2517  *   cert	- The cert to check.
2518  *
2519  * Returns:
2520  *   CHKERR_* values.
2521  */
2522 static chk_errs_t
2523 check_time(chk_actions_t chkwhat, X509 *cert)
2524 {
2525 	int i;
2526 
2527 	if (chkwhat == CHK_NOT_BEFORE || chkwhat == CHK_BOTH) {
2528 		i = X509_cmp_time(X509_get_notBefore(cert), NULL);
2529 		if (i == 0)
2530 			return (CHKERR_TIME_BEFORE_BAD);
2531 		if (i > 0)
2532 			return (CHKERR_TIME_IS_BEFORE);
2533 
2534 		/* The current time is after the 'not before' time */
2535 	}
2536 
2537 	if (chkwhat == CHK_NOT_AFTER || chkwhat == CHK_BOTH) {
2538 		i = X509_cmp_time(X509_get_notAfter(cert), NULL);
2539 		if (i == 0)
2540 			return (CHKERR_TIME_AFTER_BAD);
2541 		if (i < 0)
2542 			return (CHKERR_TIME_HAS_EXPIRED);
2543 	}
2544 
2545 	return (CHKERR_TIME_OK);
2546 }
2547 
2548 /*
2549  * find_attr - Look for a given attribute of the type associated with the NID.
2550  *
2551  * Arguments:
2552  *   nid      - NID for the attribute to be found (either NID_friendlyName or
2553  *              NID_locakKeyId)
2554  *   str      - ASN1_STRING-type structure containing the value to be found,
2555  *              FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a
2556  *              ASN1_STRING.
2557  *   kl       - Points to a stack of private keys.
2558  *   pkey     - Points at a location where the address of the matching private
2559  *              key will be stored.
2560  *   cl       - Points to a stack of client certs with matching private keys.
2561  *   cert     - Points to locaiton where the address of the matching client cert
2562  *              will be returned
2563  *
2564  * This function is designed to process lists of certs and private keys.
2565  * This is made complex because these the attributes are stored differently
2566  * for certs and for keys.  For certs, only a few attributes are retained.
2567  * FriendlyName is stored in the aux structure, under the name 'alias'.
2568  * LocalKeyId is also stored in the aux structure, under the name 'keyid'.
2569  * A pkey structure has a stack of attributes.
2570  *
2571  * The basic approach is:
2572  *   - If there there is no stack of certs but a stack of private keys exists,
2573  *     search the stack of keys for a match. Alternately, if there is a stack
2574  *     of certs and no private keys, search the certs.
2575  *
2576  *   - If there are both certs and keys, assume that the matching certs and
2577  *     keys are in their respective stacks, with matching entries in the same
2578  *     order.  Search for the name or keyid in the stack of certs.  If it is
2579  *     not found, then this function returns 0 (nothing found).
2580  *
2581  *   - Once a cert is found, verify that the key actually matches by
2582  *     comparing the private key with the public key (in the cert).
2583  *     If they don't match, return an error.
2584  *
2585  *   A pointer to cert and/or pkey which matches the name or keyid is stored
2586  *   in the return arguments.
2587  *
2588  * Returns:
2589  *     0 - No matches were found.
2590  *   > 0 - Bits set based on FOUND_* definitions, indicating what was found.
2591  *         This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
2592  */
2593 static int
2594 find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey,
2595     STACK_OF(X509) *cl, X509 **cert)
2596 {
2597 	ASN1_UTF8STRING *ustr = NULL;
2598 	ASN1_STRING *s;
2599 	ASN1_TYPE *t;
2600 	EVP_PKEY *p;
2601 	uchar_t *fname = NULL;
2602 	X509 *x;
2603 	int found = 0;
2604 	int chkcerts;
2605 	int len;
2606 	int res;
2607 	int c = -1;
2608 	int k = -1;
2609 
2610 	chkcerts = (cert != NULL || pkey != NULL) && cl != NULL;
2611 	if (chkcerts && nid == NID_friendlyName &&
2612 	    str->type == V_ASN1_BMPSTRING) {
2613 		ustr = ASN1_UTF8STRING_new();
2614 		if (ustr == NULL) {
2615 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
2616 			return (0);
2617 		}
2618 		len = ASN1_STRING_to_UTF8(&fname, str);
2619 		if (fname == NULL) {
2620 			ASN1_UTF8STRING_free(ustr);
2621 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR);
2622 			return (0);
2623 		}
2624 
2625 		if (ASN1_STRING_set(ustr, fname, len) == 0) {
2626 			ASN1_UTF8STRING_free(ustr);
2627 			OPENSSL_free(fname);
2628 			SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
2629 			return (0);
2630 		}
2631 	}
2632 
2633 	if (chkcerts) {
2634 		for (c = 0; c < sk_X509_num(cl); c++) {
2635 			res = -1;
2636 			x = sk_X509_value(cl, c);
2637 			if (nid == NID_friendlyName && ustr != NULL) {
2638 				if (x->aux == NULL || x->aux->alias == NULL)
2639 					continue;
2640 				s = x->aux->alias;
2641 				if (s != NULL && s->type == ustr->type &&
2642 				    s->data != NULL) {
2643 					res = ASN1_STRING_cmp(s, ustr);
2644 				}
2645 			} else {
2646 				if (x->aux == NULL || x->aux->keyid == NULL)
2647 					continue;
2648 				s = x->aux->keyid;
2649 				if (s != NULL && s->type == str->type &&
2650 				    s->data != NULL) {
2651 					res = ASN1_STRING_cmp(s, str);
2652 				}
2653 			}
2654 			if (res == 0) {
2655 				if (cert != NULL)
2656 					*cert = sk_X509_delete(cl, c);
2657 				found = FOUND_CERT;
2658 				break;
2659 			}
2660 		}
2661 		if (ustr != NULL) {
2662 			ASN1_UTF8STRING_free(ustr);
2663 			OPENSSL_free(fname);
2664 		}
2665 	}
2666 
2667 	if (pkey != NULL && kl != NULL) {
2668 		/*
2669 		 * Looking for pkey to match a cert?  If so, assume that
2670 		 * lists of certs and their matching pkeys are in the same
2671 		 * order.  Call X509_check_private_key() to verify this
2672 		 * assumption.
2673 		 */
2674 		if (found != 0 && cert != NULL) {
2675 			k = c;
2676 			p = sk_EVP_PKEY_value(kl, k);
2677 			if (X509_check_private_key(x, p) != 0) {
2678 				if (pkey != NULL)
2679 					*pkey = sk_EVP_PKEY_delete(kl, k);
2680 				found |= FOUND_PKEY;
2681 			}
2682 		} else if (cert == NULL) {
2683 			for (k = 0; k < sk_EVP_PKEY_num(kl); k++) {
2684 				p = sk_EVP_PKEY_value(kl, k);
2685 				if (p == NULL || p->attributes == NULL)
2686 					continue;
2687 
2688 				t = PKCS12_get_attr_gen(p->attributes, nid);
2689 				if (t != NULL || ASN1_STRING_cmp(str,
2690 				    t->value.asn1_string) == 0)
2691 					continue;
2692 
2693 				found |= FOUND_PKEY;
2694 				if (pkey != NULL)
2695 					*pkey = sk_EVP_PKEY_delete(kl, k);
2696 				break;
2697 			}
2698 		}
2699 	}
2700 
2701 	return (found);
2702 }
2703 
2704 /*
2705  * set_results - Given two pointers to stacks of private keys, certs or CA
2706  *     CA certs, either copy the second stack to the first, or append the
2707  *     contents of the second to the first.
2708  *
2709  * Arguments:
2710  *   pkeys    - Points to stack of pkeys
2711  *   work_kl  - Points to working stack of pkeys
2712  *   certs    - Points to stack of certs
2713  *   work_cl  - Points to working stack of certs
2714  *   cacerts  - Points to stack of CA certs
2715  *   work_ca  - Points to working stack of CA certs
2716  *   xtrakeys - Points to stack of unmatcned pkeys
2717  *   work_xl  - Points to working stack of unmatcned pkeys
2718  *
2719  *   The arguments are in pairs.  The first of each pair points to a stack
2720  *   of keys or certs.  The second of the pair points at a 'working stack'
2721  *   of the same type of entities.   Actions taken are as follows:
2722  *
2723  *   - If either the first or second argument is NULL, or if there are no
2724  *     members in the second stack, there is nothing to do.
2725  *   - If the first argument points to a pointer which is NULL, then there
2726  *     is no existing stack for the first argument.  Copy the stack pointer
2727  *     from the second argument to the first argument and NULL out the stack
2728  *     pointer for the second.
2729  *   - Otherwise, go through the elements of the second stack, removing each
2730  *     and adding it to the first stack.
2731  *
2732  * Returns:
2733  *   == -1 - An error occurred.  Call ERR_get_error() to get error information.
2734  *   == 0  - No matching returns were found.
2735  *    > 0  - This is the arithmetic 'or' of the FOUND_* bits that indicate which
2736  *           of the requested entries were manipulated.
2737  */
2738 static int
2739 set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl,
2740     STACK_OF(X509) **certs, STACK_OF(X509) **work_cl,
2741     STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca,
2742     STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl)
2743 {
2744 	int retval = 0;
2745 
2746 	if (pkeys != NULL && work_kl != NULL && *work_kl != NULL &&
2747 	    sk_EVP_PKEY_num(*work_kl) > 0) {
2748 		if (*pkeys == NULL) {
2749 			*pkeys = *work_kl;
2750 			*work_kl = NULL;
2751 		} else {
2752 			if (sunw_append_keys(*pkeys, *work_kl) < 0) {
2753 				return (-1);
2754 			}
2755 		}
2756 		retval |= FOUND_PKEY;
2757 	}
2758 	if (certs != NULL && work_cl != NULL && *work_cl != NULL &&
2759 	    sk_X509_num(*work_cl) > 0) {
2760 		if (*certs == NULL) {
2761 			*certs = *work_cl;
2762 			*work_cl = NULL;
2763 		} else {
2764 			if (move_certs(*certs, *work_cl) < 0) {
2765 				return (-1);
2766 			}
2767 		}
2768 		retval |= FOUND_CERT;
2769 	}
2770 
2771 	if (cacerts != NULL && work_ca != NULL && *work_ca != NULL &&
2772 	    sk_X509_num(*work_ca) > 0) {
2773 		if (*cacerts == NULL) {
2774 			*cacerts = *work_ca;
2775 			*work_ca = NULL;
2776 		} else {
2777 			if (move_certs(*cacerts, *work_ca) < 0) {
2778 				return (-1);
2779 			}
2780 		}
2781 		retval |= FOUND_CA_CERTS;
2782 	}
2783 
2784 	if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL &&
2785 	    sk_EVP_PKEY_num(*work_xl) > 0) {
2786 		if (*xtrakeys == NULL) {
2787 			*xtrakeys = *work_xl;
2788 			*work_xl = NULL;
2789 		} else {
2790 			if (sunw_append_keys(*xtrakeys, *work_xl) < 0) {
2791 				return (-1);
2792 			}
2793 		}
2794 		retval |= FOUND_XPKEY;
2795 	}
2796 
2797 	return (retval);
2798 }
2799