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