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
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)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 */
sunw_PEM_contents(FILE * fp,pem_password_cb * cb,void * userdata,STACK_OF (EVP_PKEY)** pkey,STACK_OF (X509)** certs)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
sunw_PKCS12_contents(PKCS12 * p12,const char * pass,STACK_OF (EVP_PKEY)** pkey,STACK_OF (X509)** certs)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
sunw_split_certs(STACK_OF (EVP_PKEY)* allkeys,STACK_OF (X509)* allcerts,STACK_OF (X509)** keycerts,STACK_OF (EVP_PKEY)** nocerts)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 *
sunw_PKCS12_create(const char * pass,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,STACK_OF (X509)* cacerts)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
sunw_evp_pkey_free(EVP_PKEY * pkey)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
sunw_set_localkeyid(const char * keyid_str,int keyid_len,EVP_PKEY * pkey,X509 * cert)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
sunw_get_pkey_localkeyid(getdo_actions_t dowhat,EVP_PKEY * pkey,char ** keyid_str,int * keyid_len)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
sunw_get_pkey_fname(getdo_actions_t dowhat,EVP_PKEY * pkey,char ** fname)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
sunw_find_localkeyid(char * keyid_str,int len,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,EVP_PKEY ** matching_pkey,X509 ** matching_cert)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
sunw_find_fname(char * fname,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,EVP_PKEY ** matching_pkey,X509 ** matching_cert)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
sunw_get_cert_fname(getdo_actions_t dowhat,X509 * cert,char ** fname)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
sunw_set_fname(const char * ascname,EVP_PKEY * pkey,X509 * cert)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
sunw_check_keys(X509 * cert,EVP_PKEY * pkey)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
sunw_check_cert_times(chk_actions_t chkwhat,X509 * cert)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
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)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
parse_outer(PKCS12 * p12,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)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
parse_all_bags(STACK_OF (PKCS12_SAFEBAG)* bags,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)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
parse_one_bag(PKCS12_SAFEBAG * bag,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)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
pem_info(FILE * fp,pem_password_cb cb,void * userdata,STACK_OF (EVP_PKEY)** pkeys,STACK_OF (X509)** certs)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
sunw_append_keys(STACK_OF (EVP_PKEY)* dst,STACK_OF (EVP_PKEY)* src)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
move_certs(STACK_OF (X509)* dst,STACK_OF (X509)* src)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
get_key_cert(int n,STACK_OF (EVP_PKEY)* kl,EVP_PKEY ** pkey,STACK_OF (X509)* cl,X509 ** cert)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 *
asc2bmpstring(const char * str,int len)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 *
utf82ascstr(ASN1_UTF8STRING * ustr)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 *
type2attrib(ASN1_TYPE * ty,int nid)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 *
attrib2type(X509_ATTRIBUTE * attr)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
find_attr_by_nid(STACK_OF (X509_ATTRIBUTE)* attrs,int nid)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
ERR_load_SUNW_strings(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
ERR_SUNW_error(int function,int reason,char * file,int line)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
check_time(chk_actions_t chkwhat,X509 * cert)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
find_attr(int nid,ASN1_STRING * str,STACK_OF (EVP_PKEY)* kl,EVP_PKEY ** pkey,STACK_OF (X509)* cl,X509 ** cert)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
set_results(STACK_OF (EVP_PKEY)** pkeys,STACK_OF (EVP_PKEY)** work_kl,STACK_OF (X509)** certs,STACK_OF (X509)** work_cl,STACK_OF (X509)** cacerts,STACK_OF (X509)** work_ca,STACK_OF (EVP_PKEY)** xtrakeys,STACK_OF (EVP_PKEY)** work_xl)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