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