1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <link.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/socket.h>
36 #include <ber_der.h>
37 #include <kmfapiP.h>
38 #include <pem_encode.h>
39 #include <libgen.h>
40 #include <cryptoutil.h>
41 
42 #define	CERTFILE_TEMPNAME	"/tmp/user.certXXXXXX"
43 #define	CRLFILE_TEMPNAME	"/tmp/crlXXXXXX"
44 #define	X509_FORMAT_VERSION 2
45 
46 static KMF_RETURN
47 sign_cert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *,
48     KMF_OID *, KMF_DATA *);
49 
50 static KMF_RETURN
51 verify_cert_with_key(KMF_HANDLE_T, KMF_DATA *, const KMF_DATA *);
52 
53 static KMF_RETURN
54 verify_cert_with_cert(KMF_HANDLE_T, const KMF_DATA *, const KMF_DATA *);
55 
56 static KMF_RETURN
57 get_sigalg_from_cert(KMF_DATA *, KMF_ALGORITHM_INDEX *);
58 
59 static KMF_RETURN
60 get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg)
61 {
62 	KMF_RETURN rv;
63 	KMF_X509_CERTIFICATE *SignerCert = NULL;
64 	KMF_ALGORITHM_INDEX AlgorithmId;
65 
66 	rv = DerDecodeSignedCertificate(cert, &SignerCert);
67 
68 	if (rv != KMF_OK)
69 		return (rv);
70 
71 	/* Get the algorithm info from the signer certificate */
72 	AlgorithmId = x509_algoid_to_algid(
73 	    &SignerCert->signature.algorithmIdentifier.algorithm);
74 
75 	switch (AlgorithmId) {
76 		case KMF_ALGID_MD5WithRSA:
77 		case KMF_ALGID_MD2WithRSA:
78 		case KMF_ALGID_SHA1WithRSA:
79 			*keyalg = KMF_RSA;
80 			break;
81 		case KMF_ALGID_SHA1WithDSA:
82 			*keyalg = KMF_DSA;
83 			break;
84 		default:
85 			rv = KMF_ERR_BAD_ALGORITHM;
86 	}
87 
88 	kmf_free_signed_cert(SignerCert);
89 	free(SignerCert);
90 	return (rv);
91 }
92 
93 /*
94  * Name: kmf_find_prikey_by_cert
95  *
96  * Description:
97  *   This function finds the corresponding private key in keystore
98  *   for a certificate
99  */
100 KMF_RETURN
101 kmf_find_prikey_by_cert(KMF_HANDLE_T handle, int numattr,
102     KMF_ATTRIBUTE *attrlist)
103 {
104 	KMF_PLUGIN *plugin;
105 	KMF_RETURN ret = KMF_OK;
106 	KMF_KEYSTORE_TYPE kstype;
107 	KMF_KEY_ALG keyalg;
108 	KMF_KEY_HANDLE *key = NULL;
109 	KMF_DATA *cert = NULL;
110 
111 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
112 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
113 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
114 	    {KMF_KEY_HANDLE_ATTR, TRUE, sizeof (KMF_KEY_HANDLE),
115 	    sizeof (KMF_KEY_HANDLE)}
116 	};
117 
118 	int num_req_attrs = sizeof (required_attrs) /
119 	    sizeof (KMF_ATTRIBUTE_TESTER);
120 
121 	if (handle == NULL)
122 		return (KMF_ERR_BAD_PARAMETER);
123 
124 	CLEAR_ERROR(handle, ret);
125 
126 	ret = test_attributes(num_req_attrs, required_attrs,
127 	    0, NULL, numattr, attrlist);
128 	if (ret != KMF_OK)
129 		return (ret);
130 
131 	/*
132 	 * First, get the key algorithm info from the certificate and saves it
133 	 * in the returned key handle.
134 	 */
135 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
136 	if (cert == NULL)
137 		return (KMF_ERR_BAD_PARAMETER);
138 
139 	ret = get_keyalg_from_cert(cert, &keyalg);
140 	if (ret != KMF_OK)
141 		return (ret);
142 
143 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
144 	if (key == NULL)
145 		return (KMF_ERR_BAD_PARAMETER);
146 	key->keyalg = keyalg;
147 
148 	/* Call the plugin to do the work. */
149 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
150 	    &kstype, NULL);
151 	if (ret != KMF_OK)
152 		return (ret);
153 
154 	plugin = FindPlugin(handle, kstype);
155 	if (plugin == NULL || plugin->funclist->FindPrikeyByCert == NULL)
156 		return (KMF_ERR_PLUGIN_NOTFOUND);
157 
158 	return (plugin->funclist->FindPrikeyByCert(handle, numattr, attrlist));
159 }
160 
161 
162 KMF_RETURN
163 check_key_usage(void *handle,
164 	const KMF_DATA *cert,
165 	const KMF_KU_PURPOSE purpose)
166 {
167 	KMF_X509EXT_BASICCONSTRAINTS constraint;
168 	KMF_BOOL	critical = B_FALSE;
169 	KMF_X509EXT_KEY_USAGE keyusage;
170 	KMF_RETURN ret = KMF_OK;
171 
172 	if (handle == NULL || cert == NULL)
173 		return (KMF_ERR_BAD_PARAMETER);
174 
175 	(void) memset(&constraint, 0, sizeof (KMF_X509EXT_BASICCONSTRAINTS));
176 	(void) memset(&keyusage, 0, sizeof (KMF_X509EXT_KEY_USAGE));
177 
178 	ret = kmf_get_cert_ku(cert, &keyusage);
179 	if (ret != KMF_OK)
180 		/*
181 		 * If absent or error, the cert is assumed to be invalid
182 		 * for all key usage checking.
183 		 */
184 		return (ret);
185 
186 	switch (purpose) {
187 	case KMF_KU_SIGN_CERT:
188 		/*
189 		 * RFC 3280:
190 		 * The keyCertSign bit is asserted when the subject
191 		 * public key is used for verifying a signature on
192 		 * public key certificates.  If the keyCertSign bit
193 		 * is asserted, then the cA bit in the basic constraints
194 		 * extension (section 4.2.1.10) MUST also be asserted.
195 		 * The basic constraints extension MUST appear as a
196 		 * critical extension in all CA certificates that
197 		 * contain public keys used to validate digital
198 		 * signatures on certificates.
199 		 */
200 		ret = kmf_get_cert_basic_constraint(cert, &critical,
201 		    &constraint);
202 
203 		if ((ret != KMF_ERR_EXTENSION_NOT_FOUND) && (ret != KMF_OK)) {
204 			/* real error */
205 			return (ret);
206 		}
207 
208 		if ((!critical) || (!constraint.cA) ||
209 		    (!(keyusage.KeyUsageBits & KMF_keyCertSign)))
210 			return (KMF_ERR_KEYUSAGE);
211 		break;
212 	case KMF_KU_SIGN_DATA:
213 		/*
214 		 * RFC 3280:
215 		 * The digitalSignature bit is asserted when the subject
216 		 * public key is used with a digital signature mechanism
217 		 * to support security services other than certificate
218 		 * signing(bit 5), or CRL signing(bit 6).
219 		 */
220 		if (!(keyusage.KeyUsageBits & KMF_digitalSignature))
221 			return (KMF_ERR_KEYUSAGE);
222 		break;
223 	case KMF_KU_ENCRYPT_DATA:
224 		/*
225 		 * RFC 3280:
226 		 * The dataEncipherment bit is asserted when the subject
227 		 * public key is used for enciphering user data, other than
228 		 * cryptographic keys.
229 		 */
230 		if (!(keyusage.KeyUsageBits & KMF_dataEncipherment))
231 			return (KMF_ERR_KEYUSAGE);
232 		break;
233 	default:
234 		return (KMF_ERR_BAD_PARAMETER);
235 	}
236 
237 	return (KMF_OK);
238 }
239 
240 KMF_RETURN
241 kmf_find_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
242 {
243 	KMF_PLUGIN *plugin;
244 	KMF_RETURN ret = KMF_OK;
245 	KMF_KEYSTORE_TYPE kstype;
246 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
247 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
248 	    {KMF_COUNT_ATTR, FALSE, sizeof (uint32_t), sizeof (uint32_t)}
249 	};
250 	int num_req_attrs = sizeof (required_attrs) /
251 	    sizeof (KMF_ATTRIBUTE_TESTER);
252 
253 	if (handle == NULL)
254 		return (KMF_ERR_BAD_PARAMETER);
255 
256 	CLEAR_ERROR(handle, ret);
257 
258 	ret = test_attributes(num_req_attrs, required_attrs,
259 	    0, NULL, numattr, attrlist);
260 	if (ret != KMF_OK)
261 		return (ret);
262 
263 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
264 	    &kstype, NULL);
265 	if (ret != KMF_OK)
266 		return (ret);
267 
268 	plugin = FindPlugin(handle, kstype);
269 	if (plugin == NULL || plugin->funclist->FindCert == NULL)
270 		return (KMF_ERR_PLUGIN_NOTFOUND);
271 
272 	return (plugin->funclist->FindCert(handle, numattr, attrlist));
273 }
274 
275 #define	NODATA(d) (d.Data == NULL || d.Length == NULL)
276 
277 KMF_RETURN
278 kmf_encode_cert_record(KMF_X509_CERTIFICATE *CertData, KMF_DATA *encodedCert)
279 {
280 	KMF_RETURN ret;
281 	KMF_X509_TBS_CERT *tbs_cert;
282 
283 	if (CertData == NULL || encodedCert == NULL)
284 		return (KMF_ERR_BAD_PARAMETER);
285 
286 	/*
287 	 * Validate that all required fields are present.
288 	 */
289 	tbs_cert = &(CertData->certificate);
290 	if (NODATA(tbs_cert->version) ||
291 	    NODATA(tbs_cert->signature.algorithm) ||
292 	    NODATA(tbs_cert->subjectPublicKeyInfo.subjectPublicKey) ||
293 	    tbs_cert->serialNumber.val == NULL ||
294 	    tbs_cert->serialNumber.len == 0 ||
295 	    tbs_cert->subject.numberOfRDNs == 0 ||
296 	    tbs_cert->issuer.numberOfRDNs == 0) {
297 		return (KMF_ERR_INCOMPLETE_TBS_CERT);
298 	}
299 
300 	encodedCert->Length = 0;
301 	encodedCert->Data = NULL;
302 
303 	/* Pack the new certificate */
304 	ret = DerEncodeSignedCertificate(CertData, encodedCert);
305 
306 	return (ret);
307 }
308 
309 /*
310  * This function is used to setup the attribute list before calling
311  * kmf_find_prikey_by_cert().  This function is used by
312  *	kmf_decrypt_with_cert
313  *	kmf_sign_cert
314  *	kmf_sign_data
315  *
316  * The attribute list in these callers contain all the attributes
317  * needed by kmf_find_prikey_by_cert(), except the
318  * KMF_KEY_HANDLE attribute and the KMF_CERT_DATA_ATTR attribute.
319  * These 2 attributes need to be added or reset.
320  *
321  * The caller should free the new_attrlist after use it.
322  */
323 static KMF_RETURN
324 setup_findprikey_attrlist(KMF_ATTRIBUTE *src_attrlist, int src_num,
325     KMF_ATTRIBUTE **new_attrlist, int *new_num, KMF_KEY_HANDLE *key,
326     KMF_DATA *cert)
327 {
328 	KMF_ATTRIBUTE *attrlist = NULL;
329 	int cur_num = src_num;
330 	int index;
331 	int i;
332 
333 	if (src_attrlist == NULL || new_num == NULL || key == NULL ||
334 	    cert == NULL)
335 		return (KMF_ERR_BAD_PARAMETER);
336 
337 	/* Create a new attribute list with 2 more elements */
338 	attrlist = (KMF_ATTRIBUTE *) malloc(
339 	    (src_num + 2) * sizeof (KMF_ATTRIBUTE));
340 	if (attrlist == NULL)
341 		return (KMF_ERR_MEMORY);
342 
343 	/* Copy the src_attrlist to the new list */
344 	for (i = 0; i < src_num; i++) {
345 		attrlist[i].type = src_attrlist[i].type;
346 		attrlist[i].pValue = src_attrlist[i].pValue;
347 		attrlist[i].valueLen = src_attrlist[i].valueLen;
348 	}
349 
350 	/* Add or reset the key handle attribute */
351 	index = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist, cur_num);
352 	if (index == -1) {
353 		/* not found; add it */
354 		kmf_set_attr_at_index(attrlist, cur_num,
355 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
356 		cur_num++;
357 	} else {
358 		/* found; just reset it */
359 		kmf_set_attr_at_index(attrlist, index,
360 		    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
361 	}
362 
363 	/* add or reset the cert data attribute */
364 	index = kmf_find_attr(KMF_CERT_DATA_ATTR, attrlist, cur_num);
365 	if (index == -1) {
366 		/* not found; add it */
367 		kmf_set_attr_at_index(attrlist, cur_num,
368 		    KMF_CERT_DATA_ATTR, cert, sizeof (KMF_DATA));
369 		cur_num++;
370 	} else {
371 		/* found; just reset it */
372 		kmf_set_attr_at_index(attrlist, index,
373 		    KMF_CERT_DATA_ATTR, cert, sizeof (KMF_DATA));
374 	}
375 
376 	*new_attrlist = attrlist;
377 	*new_num = cur_num;
378 	return (KMF_OK);
379 }
380 
381 
382 /*
383  * Name: kmf_sign_cert
384  *
385  * Description:
386  *   This function signs a certificate using the signer cert and
387  *   returns a signed and DER-encoded certificate.
388  *
389  * The following types of certificate data can be submitted to be signed:
390  *	KMF_TBS_CERT_DATA_ATTR - a KMF_DATA ptr is provided in the attrlist
391  *		and is signed directly.
392  *	KMF_X509_CERTIFICATE_ATTR - a KMF_X509_CERTIFICATE record is provided
393  *		in the attribute list.  This is converted to raw KMF_DATA
394  *		prior to signing.
395  *
396  * The key for the signing operation can be provided as a KMF_KEY_HANDLE_ATTR
397  * or the caller may choose to provide a KMF_SIGNER_CERT_ATTR (KMF_DATA *).
398  * If the latter, this function will then attempt to find the private key
399  * associated with the certificate.  The private key must be stored in
400  * the same keystore as the signer certificate.
401  */
402 KMF_RETURN
403 kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
404 {
405 	KMF_RETURN ret;
406 	int new_numattr = numattr + 1;
407 	KMF_ATTRIBUTE *new_attrlist = NULL;
408 	KMF_DATA *signer_cert = NULL;
409 	KMF_DATA *tbs_cert = NULL;  /* to be signed cert */
410 	KMF_DATA *signed_cert = NULL;
411 	KMF_DATA unsignedCert = {NULL, 0};
412 	KMF_KEY_HANDLE sign_key, *sign_key_ptr;
413 	int freethekey = 0;
414 	KMF_POLICY_RECORD *policy;
415 	KMF_OID *oid = NULL;
416 	KMF_ALGORITHM_INDEX AlgId;
417 	KMF_X509_CERTIFICATE *x509cert;
418 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
419 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
420 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)}
421 	};
422 	int num_req_attrs = sizeof (required_attrs) /
423 	    sizeof (KMF_ATTRIBUTE_TESTER);
424 
425 	if (handle == NULL)
426 		return (KMF_ERR_BAD_PARAMETER);
427 
428 	CLEAR_ERROR(handle, ret);
429 
430 	ret = test_attributes(num_req_attrs, required_attrs,
431 	    0, NULL, numattr, attrlist);
432 	if (ret != KMF_OK)
433 		return (ret);
434 
435 	/* Get the signer cert and check its keyUsage */
436 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, attrlist,
437 	    numattr);
438 	sign_key_ptr = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist,
439 	    numattr);
440 	/*
441 	 * Only accept 1 or the other, not both.
442 	 */
443 	if (signer_cert == NULL && sign_key_ptr == NULL)
444 		return (KMF_ERR_BAD_PARAMETER);
445 	if (signer_cert != NULL && sign_key_ptr != NULL)
446 		return (KMF_ERR_BAD_PARAMETER);
447 
448 	if (signer_cert != NULL) {
449 		policy = handle->policy;
450 		ret = check_key_usage(handle, signer_cert, KMF_KU_SIGN_CERT);
451 		if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
452 			ret = KMF_OK;
453 		if (ret != KMF_OK)
454 			return (ret);
455 
456 		/*
457 		 * Find the private key from the signer certificate by calling
458 		 * kmf_find_prikey_by_cert().
459 		 */
460 		ret = setup_findprikey_attrlist(attrlist, numattr,
461 		    &new_attrlist, &new_numattr, &sign_key, signer_cert);
462 		if (ret != KMF_OK)
463 			goto out;
464 
465 		ret = kmf_find_prikey_by_cert(handle, new_numattr,
466 		    new_attrlist);
467 		if (ret != KMF_OK) {
468 			goto out;
469 		}
470 		sign_key_ptr = &sign_key;
471 		freethekey = 1;
472 
473 		ret = get_sigalg_from_cert(signer_cert, &AlgId);
474 		if (ret != KMF_OK)
475 			goto out;
476 		else
477 			oid = x509_algid_to_algoid(AlgId);
478 	} else if (sign_key_ptr != NULL) {
479 		if (sign_key_ptr->keyalg == KMF_RSA) {
480 			oid = (KMF_OID *)&KMFOID_SHA1WithRSA;
481 		} else if (sign_key_ptr->keyalg == KMF_DSA) {
482 			oid = (KMF_OID *)&KMFOID_SHA1WithDSA;
483 		}
484 	}
485 
486 	/* Now we are ready to sign */
487 	tbs_cert = kmf_get_attr_ptr(KMF_TBS_CERT_DATA_ATTR, attrlist,
488 	    numattr);
489 	if (tbs_cert == NULL) {
490 		x509cert = kmf_get_attr_ptr(KMF_X509_CERTIFICATE_ATTR, attrlist,
491 		    numattr);
492 		if (x509cert == NULL) {
493 			ret = KMF_ERR_BAD_PARAMETER;
494 			goto out;
495 		}
496 		ret = kmf_encode_cert_record(x509cert, &unsignedCert);
497 		if (ret == KMF_OK)
498 			tbs_cert = &unsignedCert;
499 		else
500 			goto out;
501 	}
502 
503 	signed_cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist,
504 	    numattr);
505 	if (signed_cert == NULL) {
506 		ret = KMF_ERR_BAD_PARAMETER;
507 		goto out;
508 	}
509 
510 	ret = sign_cert(handle, tbs_cert, sign_key_ptr, oid, signed_cert);
511 
512 out:
513 	if (new_attrlist)
514 		(void) free(new_attrlist);
515 
516 	/* If we had to find the key, free it here. */
517 	if (freethekey)
518 		kmf_free_kmf_key(handle, &sign_key);
519 
520 	kmf_free_data(&unsignedCert);
521 	return (ret);
522 }
523 
524 static KMF_RETURN
525 get_sigalg_from_cert(KMF_DATA *signer_cert, KMF_ALGORITHM_INDEX *AlgId)
526 {
527 	KMF_RETURN ret = KMF_OK;
528 	KMF_X509_CERTIFICATE *x509_cert = NULL;
529 	KMF_OID *oid;
530 
531 	*AlgId = KMF_ALGID_NONE;
532 
533 	/* if no OID and no AlgID, use the signer cert */
534 	ret = DerDecodeSignedCertificate(signer_cert, &x509_cert);
535 	if (ret != KMF_OK)
536 		return (ret);
537 
538 	oid = CERT_ALG_OID(x509_cert);
539 	*AlgId = x509_algoid_to_algid(oid);
540 
541 	if (*AlgId == KMF_ALGID_NONE)
542 		ret = KMF_ERR_BAD_PARAMETER;
543 
544 	if (x509_cert != NULL) {
545 		kmf_free_signed_cert(x509_cert);
546 		free(x509_cert);
547 	}
548 	return (ret);
549 }
550 
551 /*
552  * Name: kmf_sign_data
553  *
554  * Description:
555  *   This function signs a block of data using the signer cert and
556  *   returns the the signature in output
557  */
558 KMF_RETURN
559 kmf_sign_data(KMF_HANDLE_T handle, int numattr,
560     KMF_ATTRIBUTE *attrlist)
561 {
562 	KMF_PLUGIN *plugin;
563 	KMF_RETURN ret = KMF_OK;
564 	KMF_ATTRIBUTE *new_attrlist = NULL;
565 	int new_numattr = numattr;
566 	KMF_DATA *signer_cert = NULL;
567 	KMF_DATA *tbs_data = NULL;  /* to be signed data */
568 	KMF_DATA *output = NULL;
569 	KMF_KEY_HANDLE sign_key, *sign_key_ptr;
570 	KMF_ALGORITHM_INDEX AlgId;
571 	KMF_DATA	signature = {0, NULL};
572 	KMF_OID *oid;
573 	KMF_POLICY_RECORD *policy;
574 
575 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
576 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
577 	    {KMF_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
578 	    {KMF_OUT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)}
579 	};
580 	int num_req_attrs = sizeof (required_attrs) /
581 	    sizeof (KMF_ATTRIBUTE_TESTER);
582 
583 	if (handle == NULL)
584 		return (KMF_ERR_BAD_PARAMETER);
585 
586 	CLEAR_ERROR(handle, ret);
587 
588 	ret = test_attributes(num_req_attrs, required_attrs,
589 	    0, NULL, numattr, attrlist);
590 	if (ret != KMF_OK)
591 		return (ret);
592 
593 	/* Get the signer cert and check its keyUsage. */
594 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, attrlist,
595 	    numattr);
596 	sign_key_ptr = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist,
597 	    numattr);
598 
599 	if (signer_cert == NULL && sign_key_ptr == NULL)
600 		return (KMF_ERR_BAD_PARAMETER);
601 
602 	/*
603 	 * If a signer cert was given, use it to find the private key
604 	 * to use for signing the data.
605 	 */
606 	if (signer_cert != NULL) {
607 		ret = check_key_usage(handle, signer_cert, KMF_KU_SIGN_DATA);
608 
609 		/*
610 		 * Signing generic data does not require the
611 		 * KeyUsage extension.
612 		 */
613 		policy = handle->policy;
614 		if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
615 			ret = KMF_OK;
616 		if (ret != KMF_OK)
617 			return (ret);
618 
619 		/*
620 		 * Find the private key from the signer certificate.
621 		 */
622 		ret = setup_findprikey_attrlist(attrlist, numattr,
623 		    &new_attrlist, &new_numattr, &sign_key, signer_cert);
624 		if (ret != KMF_OK) {
625 			goto cleanup;
626 		}
627 
628 		ret = kmf_find_prikey_by_cert(handle, new_numattr,
629 		    new_attrlist);
630 		if (ret != KMF_OK) {
631 			goto cleanup;
632 		}
633 		sign_key_ptr = &sign_key;
634 	}
635 
636 	/* Get the tbs_data and signed_data attributes now */
637 	tbs_data = kmf_get_attr_ptr(KMF_DATA_ATTR, attrlist, numattr);
638 	if (tbs_data == NULL) {
639 		ret = KMF_ERR_BAD_PARAMETER;
640 		goto cleanup;
641 	}
642 
643 	output = kmf_get_attr_ptr(KMF_OUT_DATA_ATTR, attrlist, numattr);
644 	if (output == NULL) {
645 		ret = KMF_ERR_BAD_PARAMETER;
646 		goto cleanup;
647 	}
648 
649 	/*
650 	 * Get the algorithm index attribute and its oid. If this attribute
651 	 * is not provided, then we use the algorithm in the signer cert.
652 	 */
653 	oid = kmf_get_attr_ptr(KMF_OID_ATTR, attrlist, numattr);
654 	ret = kmf_get_attr(KMF_ALGORITHM_INDEX_ATTR, attrlist, numattr,
655 	    &AlgId, NULL);
656 	/*
657 	 * We need to know the Algorithm ID, it can be found 3 ways:
658 	 * 1. caller supplied OID in the attribute list.
659 	 * 2. caller supplied Algorithm Index in the attribute list.
660 	 * 3. caller supplied neither, but did supply a certificate, find
661 	 *    the ALG OID from the certificate.
662 	 */
663 	/* If none of the above, return error. */
664 	if (oid == NULL && ret != KMF_OK && signer_cert == NULL) {
665 		ret = KMF_ERR_BAD_PARAMETER;
666 		goto cleanup;
667 	} else if (oid == NULL && ret != KMF_OK) {
668 		ret = get_sigalg_from_cert(signer_cert, &AlgId);
669 		if (ret != KMF_OK)
670 			goto cleanup;
671 		else
672 			oid = x509_algid_to_algoid(AlgId);
673 
674 	} else if (oid == NULL && ret == KMF_OK) {
675 		/* AlgID was given by caller, convert it to OID */
676 		oid = x509_algid_to_algoid(AlgId);
677 	} else if (oid != NULL && ret == KMF_ERR_ATTR_NOT_FOUND) {
678 		AlgId = x509_algoid_to_algid(oid);
679 	} else { /* Else, the OID must have been given */
680 		ret = KMF_OK;
681 	}
682 
683 	/* Now call the plugin function to sign it */
684 	plugin = FindPlugin(handle, sign_key_ptr->kstype);
685 	if (plugin == NULL || plugin->funclist->SignData == NULL) {
686 		ret = KMF_ERR_PLUGIN_NOTFOUND;
687 		goto cleanup;
688 	}
689 
690 	ret = plugin->funclist->SignData(handle, sign_key_ptr, oid, tbs_data,
691 	    output);
692 	if (ret != KMF_OK)
693 		goto cleanup;
694 
695 	/*
696 	 * For DSA, NSS returns an encoded signature. Decode the
697 	 * signature as DSA signature should be 40-byte long.
698 	 */
699 	if (plugin->type == KMF_KEYSTORE_NSS &&
700 	    AlgId == KMF_ALGID_SHA1WithDSA) {
701 		ret = DerDecodeDSASignature(output, &signature);
702 		if (ret != KMF_OK)
703 			goto cleanup;
704 		output->Length = signature.Length;
705 		(void) memcpy(output->Data, signature.Data, signature.Length);
706 	}
707 
708 cleanup:
709 	if (new_attrlist != NULL)
710 		free(new_attrlist);
711 
712 	if (signature.Data)
713 		free(signature.Data);
714 
715 	if (signer_cert != NULL && sign_key_ptr != NULL)
716 		kmf_free_kmf_key(handle, sign_key_ptr);
717 
718 
719 	return (ret);
720 }
721 
722 /*
723  * kmf_verify_data
724  *
725  * This routine will try to verify a block of data using
726  * either a public key or a certificate as the source
727  * of the verification (the key).
728  *
729  * The caller may provider either a KMF_KEY_HANDLE_ATTR or
730  * a KMF_SIGNER_CERT_DATA_ATTR (with a KMF_DATA record) to
731  * use for the key to the verification step.  If a certificate
732  * is used and that certificate has the KeyUsage extension,
733  * the SIGN-DATA bit must be set.  Also, if a certificate
734  * is used, the verification will be done in a specific
735  * keystore mechanism.
736  *
737  * If a KMF_KEY_HANDLE is given in the attribute list, the
738  * verification will occur in the framework itself using
739  * PKCS#11 C_Verify functions.
740  */
741 KMF_RETURN
742 kmf_verify_data(KMF_HANDLE_T handle,
743 	int	num_args,
744 	KMF_ATTRIBUTE	*attrlist)
745 {
746 	KMF_RETURN ret = KMF_OK;
747 	KMF_PLUGIN *plugin;
748 	KMF_KEYSTORE_TYPE kstype;
749 	uint32_t len;
750 	KMF_DATA	derkey = {0, NULL};
751 	KMF_KEY_HANDLE *KMFKey;
752 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_NONE;
753 	KMF_DATA *indata;
754 	KMF_DATA *insig;
755 	KMF_DATA *signer_cert;
756 	KMF_X509_SPKI spki;
757 	KMF_POLICY_RECORD *policy;
758 
759 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
760 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
761 		{KMF_DATA_ATTR, FALSE, sizeof (KMF_DATA),
762 			sizeof (KMF_DATA)},
763 		{KMF_IN_SIGN_ATTR, FALSE, sizeof (KMF_DATA),
764 			sizeof (KMF_DATA)}
765 	};
766 
767 	int num_req_attrs = sizeof (required_attrs) /
768 	    sizeof (KMF_ATTRIBUTE_TESTER);
769 
770 	if (handle == NULL)
771 		return (KMF_ERR_BAD_PARAMETER);
772 
773 	CLEAR_ERROR(handle, ret);
774 
775 	ret = test_attributes(num_req_attrs, required_attrs,
776 	    0, NULL, num_args, attrlist);
777 
778 	if (ret != KMF_OK)
779 		return (ret);
780 
781 	len = sizeof (kstype);
782 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
783 	    &kstype, &len);
784 	if (ret != KMF_OK)
785 		return (ret);
786 
787 	KMFKey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, num_args);
788 	signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, attrlist,
789 	    num_args);
790 	if (KMFKey == NULL && signer_cert == NULL) {
791 		return (KMF_ERR_BAD_PARAMETER);
792 	}
793 
794 	len = sizeof (sigAlg);
795 	ret = kmf_get_attr(KMF_ALGORITHM_INDEX_ATTR, attrlist, num_args,
796 	    &sigAlg, &len);
797 
798 	/* We only need the algorithm index if we don't have a signer cert. */
799 	if (ret != KMF_OK && signer_cert == NULL)
800 		return (ret);
801 
802 	indata = kmf_get_attr_ptr(KMF_DATA_ATTR, attrlist, num_args);
803 	if (indata == NULL)
804 		return (KMF_ERR_BAD_PARAMETER);
805 
806 	insig = kmf_get_attr_ptr(KMF_IN_SIGN_ATTR, attrlist, num_args);
807 	if (insig == NULL)
808 		return (KMF_ERR_BAD_PARAMETER);
809 
810 	/* If the caller passed a signer cert instead of a key use it. */
811 	if (signer_cert != NULL) {
812 		policy = handle->policy;
813 		ret = check_key_usage(handle, signer_cert, KMF_KU_SIGN_DATA);
814 		if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
815 			ret = KMF_OK;
816 		if (ret != KMF_OK)
817 			return (ret);
818 
819 		if (kstype == KMF_KEYSTORE_NSS)
820 			kstype = KMF_KEYSTORE_PK11TOKEN;
821 		plugin = FindPlugin(handle, kstype);
822 		if (plugin == NULL)
823 			return (KMF_ERR_PLUGIN_NOTFOUND);
824 		if (plugin->funclist->VerifyDataWithCert == NULL)
825 			return (KMF_ERR_FUNCTION_NOT_FOUND);
826 
827 		CLEAR_ERROR(handle, ret);
828 		ret = plugin->funclist->VerifyDataWithCert(handle,
829 		    sigAlg, indata, insig, signer_cert);
830 	} else {
831 		/* Retrieve public key data from keystore */
832 		plugin = FindPlugin(handle, kstype);
833 		if (plugin != NULL &&
834 		    plugin->funclist->EncodePubkeyData != NULL) {
835 			ret = plugin->funclist->EncodePubkeyData(handle,
836 			    KMFKey, &derkey);
837 		} else {
838 			return (KMF_ERR_PLUGIN_NOTFOUND);
839 		}
840 
841 		ret = DerDecodeSPKI(&derkey, &spki);
842 		if (ret == KMF_OK) {
843 			ret = PKCS_VerifyData(handle, sigAlg, &spki,
844 			    indata, insig);
845 		}
846 
847 		if (derkey.Data != NULL)
848 			free(derkey.Data);
849 
850 		kmf_free_algoid(&spki.algorithm);
851 		kmf_free_data(&spki.subjectPublicKey);
852 	}
853 
854 	return (ret);
855 }
856 /*
857  * Name: kmf_verify_cert
858  *
859  * Description:
860  *   This function verifies that the a certificate was signed
861  * using a specific private key and that the certificate has not
862  * been altered since it was signed using that private key
863  * The public key used for verification may be given in the
864  * attribute list as a KMF_KEY_HANDLE or the caller may give
865  * just the signing certificate (as KMF_SIGNER_CERT_DATA_ATTR)
866  * from which the public key needed for verification can be
867  * derived.
868  *
869  * Parameters:
870  *	handle(input) - opaque handle for KMF session
871  *	numattr  - number of attributes in the list
872  *	attrlist - KMF_ATTRIBUTES
873  *
874  * Returns:
875  *   A KMF_RETURN value indicating success or specifying a particular
876  * error condition.  The value KMF_OK indicates success. All other
877  * values represent an error condition.
878  */
879 KMF_RETURN
880 kmf_verify_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
881 {
882 	KMF_RETURN	ret;
883 	KMF_DATA	derkey = {0, NULL};
884 	KMF_PLUGIN	*plugin;
885 	KMF_KEY_HANDLE *KMFKey;
886 	KMF_DATA *CertToBeVerified;
887 	KMF_DATA *SignerCert;
888 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
889 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)}
890 	};
891 
892 	int num_req_attrs = sizeof (required_attrs) /
893 	    sizeof (KMF_ATTRIBUTE_TESTER);
894 
895 	CLEAR_ERROR(handle, ret);
896 	if (ret != KMF_OK)
897 		return (ret);
898 
899 	ret = test_attributes(num_req_attrs, required_attrs,
900 	    0, NULL, numattr, attrlist);
901 	if (ret != KMF_OK)
902 		return (ret);
903 
904 	KMFKey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
905 	SignerCert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR, attrlist,
906 	    numattr);
907 
908 	/*
909 	 * Caller must provide at least a key handle or a cert to use
910 	 * as the "key" for verification.
911 	 */
912 	if (KMFKey == NULL && SignerCert == NULL)
913 		return (KMF_ERR_BAD_PARAMETER);
914 
915 	CertToBeVerified = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist,
916 	    numattr);
917 	if (CertToBeVerified == NULL)
918 		return (KMF_ERR_BAD_PARAMETER);
919 
920 	if (SignerCert != NULL) {
921 		ret = verify_cert_with_cert(handle, CertToBeVerified,
922 		    SignerCert);
923 	} else {
924 		/*
925 		 * The keystore must extract the pubkey data because
926 		 * the framework doesn't have access to the raw key bytes
927 		 * that are needed to construct the DER encoded public
928 		 * key information needed for the verify operation.
929 		 */
930 		plugin = FindPlugin(handle, KMFKey->kstype);
931 		if (plugin != NULL && plugin->funclist->EncodePubkeyData !=
932 		    NULL) {
933 			ret = plugin->funclist->EncodePubkeyData(handle,
934 			    KMFKey, &derkey);
935 		} else {
936 			return (KMF_ERR_PLUGIN_NOTFOUND);
937 		}
938 
939 		if (ret == KMF_OK && derkey.Length > 0) {
940 			ret = verify_cert_with_key(handle, &derkey,
941 			    CertToBeVerified);
942 
943 			if (derkey.Data != NULL)
944 				free(derkey.Data);
945 		}
946 	}
947 
948 	return (ret);
949 }
950 
951 /*
952  * Utility routine for verifying generic data using a
953  * certificate to derive the public key.  This is
954  * done in a specific plugin because there are situations
955  * where we want to force this operation to happen in
956  * a specific keystore.
957  * For example:
958  *    libelfsign verifies signatures on crypto libraries.
959  *    We cannot use libpkcs11 functions to verify the pkcs11
960  *    libraries because it results in a circular dependency.
961  *    So, when libelfsign is verifying library sigs, it
962  *    always forces the operation to happen in OpenSSL
963  *    to avoid the circular dependency.
964  */
965 static KMF_RETURN
966 plugin_verify_data_with_cert(KMF_HANDLE_T handle,
967 	KMF_KEYSTORE_TYPE kstype,
968 	KMF_ALGORITHM_INDEX algid,
969 	KMF_DATA *indata,
970 	KMF_DATA *insig,
971 	const KMF_DATA *SignerCert)
972 {
973 	KMF_PLUGIN *plugin;
974 	KMF_RETURN ret = KMF_OK;
975 
976 	/*
977 	 * If NSS, use PKCS#11, we are not accessing the database(s),
978 	 * we just prefer the "verify" operation from the crypto framework.
979 	 * The OpenSSL version is unique in order to avoid a dependency loop
980 	 * with the kcfd(1M) process.
981 	 */
982 	if (kstype == KMF_KEYSTORE_NSS)
983 		kstype = KMF_KEYSTORE_PK11TOKEN;
984 
985 	plugin = FindPlugin(handle, kstype);
986 	if (plugin == NULL)
987 		return (KMF_ERR_PLUGIN_NOTFOUND);
988 
989 	if (plugin->funclist->VerifyDataWithCert == NULL)
990 		return (KMF_ERR_FUNCTION_NOT_FOUND);
991 
992 	CLEAR_ERROR(handle, ret);
993 	ret = (plugin->funclist->VerifyDataWithCert(handle,
994 	    algid, indata, insig, (KMF_DATA *)SignerCert));
995 
996 	return (ret);
997 }
998 
999 /*
1000  * Name: kmf_encrypt
1001  *
1002  * Description:
1003  *   Uses the public key from the cert to encrypt the plaintext
1004  *   into the ciphertext.
1005  *
1006  * Parameters:
1007  *   handle(input) - opaque handle for KMF session
1008  *   cert(input) - pointer to a DER encoded certificate for encryption
1009  *		by using its public key
1010  *   plaintext(input) - pointer to the plaintext to be encrypted
1011  *   ciphertext(output) - pointer to the ciphertext contains
1012  *		encrypted data
1013  *
1014  * Returns:
1015  *   A KMF_RETURN value indicating success or specifying a particular
1016  * error condition.
1017  *   The value KMF_OK indicates success. All other values represent
1018  * an error condition.
1019  *
1020  */
1021 KMF_RETURN
1022 kmf_encrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1023 {
1024 	KMF_RETURN ret;
1025 	KMF_X509_CERTIFICATE *x509cert = NULL;
1026 	KMF_X509_SPKI *pubkey;
1027 	KMF_OID *alg;
1028 	KMF_ALGORITHM_INDEX algid;
1029 	KMF_DATA *cert;
1030 	KMF_DATA *plaintext;
1031 	KMF_DATA *ciphertext;
1032 	KMF_POLICY_RECORD *policy;
1033 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1034 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1035 		sizeof (KMF_DATA)},
1036 	    {KMF_PLAINTEXT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1037 		sizeof (KMF_DATA)},
1038 	    {KMF_CIPHERTEXT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1039 		sizeof (KMF_DATA)}
1040 	};
1041 
1042 	int num_req_attrs = sizeof (required_attrs) /
1043 	    sizeof (KMF_ATTRIBUTE_TESTER);
1044 
1045 	CLEAR_ERROR(handle, ret);
1046 	if (ret != KMF_OK)
1047 		return (ret);
1048 
1049 	ret = test_attributes(num_req_attrs, required_attrs,
1050 	    0, NULL, numattr, attrlist);
1051 	if (ret != KMF_OK)
1052 		return (ret);
1053 
1054 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist,
1055 	    numattr);
1056 	plaintext = kmf_get_attr_ptr(KMF_PLAINTEXT_DATA_ATTR, attrlist,
1057 	    numattr);
1058 	ciphertext = kmf_get_attr_ptr(KMF_CIPHERTEXT_DATA_ATTR, attrlist,
1059 	    numattr);
1060 
1061 	if (cert == NULL || plaintext == NULL || ciphertext == NULL)
1062 		return (KMF_ERR_BAD_PARAMETER);
1063 
1064 	/* check the keyUsage of the certificate */
1065 	policy = handle->policy;
1066 	ret = check_key_usage(handle, cert, KMF_KU_ENCRYPT_DATA);
1067 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
1068 		ret = KMF_OK;
1069 	if (ret != KMF_OK)
1070 		return (ret);
1071 
1072 	/* Decode the cert so we can get the SPKI data */
1073 	if ((ret = DerDecodeSignedCertificate(cert, &x509cert)) != KMF_OK)
1074 		return (ret);
1075 
1076 	/* Get the public key info from the certificate */
1077 	pubkey = &x509cert->certificate.subjectPublicKeyInfo;
1078 
1079 	/* Use the algorithm in SPKI to encrypt data */
1080 	alg = &pubkey->algorithm.algorithm;
1081 
1082 	algid = x509_algoid_to_algid(alg);
1083 
1084 	/* DSA does not support encrypt */
1085 	if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) {
1086 		kmf_free_signed_cert(x509cert);
1087 		free(x509cert);
1088 		return (KMF_ERR_BAD_ALGORITHM);
1089 	}
1090 
1091 	/*
1092 	 * Encrypt using the crypto framework (not the KMF plugin mechanism).
1093 	 */
1094 	ret = PKCS_EncryptData(handle, algid, pubkey, plaintext, ciphertext);
1095 
1096 	kmf_free_signed_cert(x509cert);
1097 	free(x509cert);
1098 
1099 	return (ret);
1100 }
1101 
1102 /*
1103  * Name: kmf_decrypt
1104  *
1105  * Description:
1106  *   Uses the private key associated with the cert to decrypt
1107  *   the ciphertext into the plaintext.
1108  */
1109 KMF_RETURN
1110 kmf_decrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1111 {
1112 	KMF_RETURN ret;
1113 	KMF_X509_CERTIFICATE *x509cert = NULL;
1114 	KMF_X509_SPKI *spki_ptr;
1115 	KMF_PLUGIN *plugin;
1116 	KMF_ALGORITHM_INDEX AlgorithmId;
1117 	KMF_ATTRIBUTE *new_attrlist = NULL;
1118 	int new_numattr;
1119 	KMF_DATA *cert = NULL;
1120 	KMF_DATA *ciphertext = NULL;
1121 	KMF_DATA *plaintext = NULL;
1122 	KMF_KEY_HANDLE prikey;
1123 	KMF_POLICY_RECORD *policy;
1124 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1125 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
1126 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
1127 	    {KMF_PLAINTEXT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1128 		sizeof (KMF_DATA)},
1129 	    {KMF_CIPHERTEXT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1130 		sizeof (KMF_DATA)},
1131 	};
1132 	int num_req_attrs = sizeof (required_attrs) /
1133 	    sizeof (KMF_ATTRIBUTE_TESTER);
1134 
1135 	if (handle == NULL)
1136 		return (KMF_ERR_BAD_PARAMETER);
1137 	CLEAR_ERROR(handle, ret);
1138 
1139 	ret = test_attributes(num_req_attrs, required_attrs,
1140 	    0, NULL, numattr, attrlist);
1141 	if (ret != KMF_OK)
1142 		return (ret);
1143 
1144 
1145 	/* Get the cert and check its keyUsage */
1146 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist,
1147 	    numattr);
1148 	if (cert == NULL)
1149 		return (KMF_ERR_BAD_PARAMETER);
1150 
1151 	/* check the keyUsage of the certificate */
1152 	policy = handle->policy;
1153 	ret = check_key_usage(handle, cert, KMF_KU_ENCRYPT_DATA);
1154 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
1155 		ret = KMF_OK;
1156 	if (ret != KMF_OK)
1157 		return (ret);
1158 
1159 	/* Get the ciphertext and plaintext attributes */
1160 	ciphertext = kmf_get_attr_ptr(KMF_CIPHERTEXT_DATA_ATTR, attrlist,
1161 	    numattr);
1162 	if (ciphertext == NULL)
1163 		return (KMF_ERR_BAD_PARAMETER);
1164 
1165 	plaintext = kmf_get_attr_ptr(KMF_PLAINTEXT_DATA_ATTR, attrlist,
1166 	    numattr);
1167 	if (plaintext == NULL)
1168 		return (KMF_ERR_BAD_PARAMETER);
1169 
1170 	/*
1171 	 * Retrieve the private key from the keystore based on
1172 	 * the certificate.
1173 	 */
1174 	ret = setup_findprikey_attrlist(attrlist, numattr, &new_attrlist,
1175 	    &new_numattr, &prikey, cert);
1176 	if (ret != KMF_OK)
1177 		goto cleanup;
1178 
1179 	ret = kmf_find_prikey_by_cert(handle, new_numattr, new_attrlist);
1180 	if (ret != KMF_OK)
1181 		goto cleanup;
1182 
1183 	/* Decode the cert so we can get the alogorithm */
1184 	ret = DerDecodeSignedCertificate(cert, &x509cert);
1185 	if (ret != KMF_OK)
1186 		goto cleanup;
1187 
1188 	spki_ptr = &x509cert->certificate.subjectPublicKeyInfo;
1189 	AlgorithmId = x509_algoid_to_algid((KMF_OID *)
1190 	    &spki_ptr->algorithm.algorithm);
1191 
1192 	/* DSA does not support decrypt */
1193 	if (AlgorithmId == KMF_ALGID_DSA) {
1194 		ret = KMF_ERR_BAD_ALGORITHM;
1195 		goto cleanup;
1196 	}
1197 
1198 	plugin = FindPlugin(handle, prikey.kstype);
1199 
1200 	if (plugin != NULL && plugin->funclist->DecryptData != NULL) {
1201 		ret = plugin->funclist->DecryptData(handle,
1202 		    &prikey, &spki_ptr->algorithm.algorithm,
1203 		    ciphertext, plaintext);
1204 	} else {
1205 		ret = KMF_ERR_PLUGIN_NOTFOUND;
1206 	}
1207 
1208 cleanup:
1209 	if (new_attrlist != NULL)
1210 		free(new_attrlist);
1211 
1212 	kmf_free_kmf_key(handle, &prikey);
1213 	kmf_free_signed_cert(x509cert);
1214 	free(x509cert);
1215 
1216 	return (ret);
1217 }
1218 
1219 KMF_RETURN
1220 kmf_store_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1221 {
1222 	KMF_PLUGIN *plugin;
1223 	KMF_RETURN ret = KMF_OK;
1224 	KMF_KEYSTORE_TYPE kstype;
1225 
1226 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1227 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
1228 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
1229 	};
1230 
1231 	int num_req_attrs = sizeof (required_attrs) /
1232 	    sizeof (KMF_ATTRIBUTE_TESTER);
1233 
1234 	if (handle == NULL)
1235 		return (KMF_ERR_BAD_PARAMETER);
1236 
1237 	CLEAR_ERROR(handle, ret);
1238 
1239 	ret = test_attributes(num_req_attrs, required_attrs,
1240 	    0, NULL, numattr, attrlist);
1241 	if (ret != KMF_OK)
1242 		return (ret);
1243 
1244 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
1245 	    &kstype, NULL);
1246 	if (ret != KMF_OK)
1247 		return (ret);
1248 
1249 	plugin = FindPlugin(handle, kstype);
1250 	if (plugin == NULL || plugin->funclist->StoreCert == NULL)
1251 		return (KMF_ERR_PLUGIN_NOTFOUND);
1252 
1253 	return (plugin->funclist->StoreCert(handle, numattr, attrlist));
1254 }
1255 
1256 KMF_RETURN
1257 kmf_import_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1258 {
1259 	KMF_PLUGIN *plugin;
1260 	KMF_RETURN ret = KMF_OK;
1261 	KMF_KEYSTORE_TYPE kstype;
1262 
1263 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1264 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
1265 	    {KMF_CERT_FILENAME_ATTR, TRUE, 1, 0},
1266 	};
1267 
1268 	int num_req_attrs = sizeof (required_attrs) /
1269 	    sizeof (KMF_ATTRIBUTE_TESTER);
1270 
1271 	if (handle == NULL)
1272 		return (KMF_ERR_BAD_PARAMETER);
1273 
1274 	CLEAR_ERROR(handle, ret);
1275 
1276 	ret = test_attributes(num_req_attrs, required_attrs, 0, NULL,
1277 	    numattr, attrlist);
1278 	if (ret != KMF_OK)
1279 		return (ret);
1280 
1281 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
1282 	    &kstype, NULL);
1283 	if (ret != KMF_OK)
1284 		return (ret);
1285 
1286 	plugin = FindPlugin(handle, kstype);
1287 	if (plugin == NULL || plugin->funclist->ImportCert == NULL)
1288 		return (KMF_ERR_PLUGIN_NOTFOUND);
1289 
1290 	return (plugin->funclist->ImportCert(handle, numattr, attrlist));
1291 }
1292 
1293 KMF_RETURN
1294 kmf_delete_cert_from_keystore(KMF_HANDLE_T handle, int numattr,
1295     KMF_ATTRIBUTE *attrlist)
1296 {
1297 	KMF_PLUGIN *plugin;
1298 	KMF_RETURN ret = KMF_OK;
1299 	KMF_KEYSTORE_TYPE kstype;
1300 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1301 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}
1302 	};
1303 	int num_req_attrs = sizeof (required_attrs) /
1304 	    sizeof (KMF_ATTRIBUTE_TESTER);
1305 
1306 	if (handle == NULL)
1307 		return (KMF_ERR_BAD_PARAMETER);
1308 
1309 	CLEAR_ERROR(handle, ret);
1310 
1311 	ret = test_attributes(num_req_attrs, required_attrs,
1312 	    0, NULL, numattr, attrlist);
1313 	if (ret != KMF_OK)
1314 		return (ret);
1315 
1316 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
1317 	    &kstype, NULL);
1318 	if (ret != KMF_OK)
1319 		return (ret);
1320 
1321 	plugin = FindPlugin(handle, kstype);
1322 	if (plugin == NULL || plugin->funclist->DeleteCert == NULL)
1323 		return (KMF_ERR_PLUGIN_NOTFOUND);
1324 
1325 	return (plugin->funclist->DeleteCert(handle, numattr, attrlist));
1326 }
1327 
1328 
1329 /*
1330  * This function gets the CRL URI entries from the certificate's Distribution
1331  * points extension, and downloads the CRL file.  The function also returns
1332  * the URI string and the format of the CRL file.   The caller should free
1333  * the space allocated for the returned URI string.
1334  */
1335 static KMF_RETURN
1336 cert_get_crl(KMF_HANDLE_T handle, const KMF_DATA *cert, char *proxy,
1337     char *filename, char **retn_uri, KMF_ENCODE_FORMAT *format)
1338 {
1339 	KMF_RETURN ret = KMF_OK;
1340 	KMF_X509EXT_CRLDISTPOINTS crl_dps;
1341 	boolean_t done = B_FALSE;
1342 	char uri[1024];
1343 	char *proxyname = NULL;
1344 	char *proxy_port_s = NULL;
1345 	int proxy_port = 0;
1346 	int i, j;
1347 	char *path = NULL;
1348 
1349 	if (handle == NULL || cert == NULL || filename == NULL ||
1350 	    retn_uri == NULL || format == NULL)
1351 		return (KMF_ERR_BAD_PARAMETER);
1352 
1353 	/* Get the proxy info */
1354 	if (proxy != NULL) {
1355 		proxyname = strtok(proxy, ":");
1356 		proxy_port_s = strtok(NULL, "\0");
1357 		if (proxy_port_s != NULL) {
1358 			proxy_port = strtol(proxy_port_s, NULL, 0);
1359 		} else {
1360 			proxy_port = 8080; /* default */
1361 		}
1362 	}
1363 
1364 	/*
1365 	 * Get the CRL URI from the certificate's CRL Distribution
1366 	 * Points extension and download the CRL file.  There maybe more than
1367 	 * one CRL URI entries in the DP extension, so we will continue
1368 	 * the process until a CRL file is sucessfully downloaded or we
1369 	 * are running out the CRL URI's.
1370 	 */
1371 	ret = kmf_get_cert_crl_dist_pts((const KMF_DATA *)cert,
1372 	    &crl_dps);
1373 	if (ret != KMF_OK)
1374 		goto out;
1375 
1376 	for (i = 0; i < crl_dps.number; i++) {
1377 		KMF_CRL_DIST_POINT *dp = &(crl_dps.dplist[i]);
1378 		KMF_GENERALNAMES *fullname = &(dp->name.full_name);
1379 		KMF_DATA *data;
1380 
1381 		if (done)
1382 			break;
1383 		for (j = 0; j < fullname->number; j++) {
1384 			data = &(fullname->namelist[j].name);
1385 			(void) memcpy(uri, data->Data, data->Length);
1386 			uri[data->Length] = '\0';
1387 			ret = kmf_download_crl(handle, uri, proxyname,
1388 			    proxy_port, 30, filename, format);
1389 			if (ret == KMF_OK) {
1390 				done = B_TRUE;
1391 				path = malloc(data->Length + 1);
1392 				if (path == NULL) {
1393 					ret = KMF_ERR_MEMORY;
1394 					goto out;
1395 				}
1396 				(void) strncpy(path, uri, data->Length);
1397 				*retn_uri = path;
1398 				break;
1399 			}
1400 		}
1401 	}
1402 
1403 out:
1404 	kmf_free_crl_dist_pts(&crl_dps);
1405 	return (ret);
1406 }
1407 
1408 static KMF_RETURN
1409 check_crl_validity(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype,
1410 	char *crlfilename, KMF_DATA *issuer_cert)
1411 {
1412 	KMF_RETURN ret = KMF_OK;
1413 	KMF_POLICY_RECORD *policy;
1414 
1415 	if (handle == NULL)
1416 		return (KMF_ERR_BAD_PARAMETER);
1417 
1418 	policy = handle->policy;
1419 
1420 	/*
1421 	 * NSS CRL is not file based, and its signature
1422 	 * has been verified during CRL import.
1423 	 * We only check CRL validity for file-based CRLs,
1424 	 * NSS handles these checks internally.
1425 	 */
1426 	if (kstype == KMF_KEYSTORE_NSS)
1427 		return (KMF_OK);
1428 
1429 	/*
1430 	 * Check the CRL signature if needed.
1431 	 */
1432 	if (!policy->validation_info.crl_info.ignore_crl_sign) {
1433 		ret = kmf_verify_crl_file(handle, crlfilename,
1434 		    issuer_cert);
1435 		if (ret != KMF_OK)
1436 			return (ret);
1437 	}
1438 	/*
1439 	 * Check the CRL validity if needed.
1440 	 */
1441 	if (!policy->validation_info.crl_info.ignore_crl_date) {
1442 		ret = kmf_check_crl_date(handle, crlfilename);
1443 		if (ret != KMF_OK)
1444 			return (ret);
1445 	}
1446 
1447 	return (ret);
1448 }
1449 
1450 static KMF_RETURN
1451 cert_crl_check(KMF_HANDLE_T handle,  KMF_KEYSTORE_TYPE *kstype,
1452 	KMF_DATA *user_cert, KMF_DATA *issuer_cert)
1453 {
1454 	KMF_POLICY_RECORD *policy;
1455 	KMF_RETURN ret = KMF_OK;
1456 	KMF_ATTRIBUTE attrlist[16];
1457 	int numattr = 0;
1458 	int fd;
1459 	boolean_t crlchk;
1460 	char user_certfile[MAXPATHLEN];
1461 	char crlfile_tmp[MAXPATHLEN];
1462 	char *basefilename = NULL;
1463 	char *dir = NULL;
1464 	char *crlfilename = NULL;
1465 	char *proxy = NULL;
1466 	char *uri = NULL;
1467 	KMF_ENCODE_FORMAT format;
1468 
1469 	if (handle == NULL || kstype == NULL || user_cert == NULL ||
1470 	    issuer_cert == NULL)
1471 		return (KMF_ERR_BAD_PARAMETER);
1472 
1473 	if (!is_valid_keystore_type(*kstype))
1474 		return (KMF_ERR_BAD_PARAMETER);
1475 
1476 	policy = handle->policy;
1477 
1478 	/*
1479 	 * If the get-crl-uri policy is TRUE, then download the CRL
1480 	 * file first.   The newly downloaded file will be stored in the
1481 	 * NSS internal database for NSS keystore, and stored in a file for
1482 	 * the File-based CRL plugins (OpenSSL and PKCS11).
1483 	 *
1484 	 * For file-based plugins, if the get-crl-uri policy is FALSE,
1485 	 * then the caller should provide a CRL file in the policy.
1486 	 * Also, after this step is done, the "crlfilename" variable should
1487 	 * contain the proper CRL file to be used for the rest of CRL
1488 	 * validation process.
1489 	 */
1490 	basefilename = policy->validation_info.crl_info.basefilename;
1491 	dir = policy->validation_info.crl_info.directory;
1492 	if (policy->validation_info.crl_info.get_crl_uri) {
1493 		/*
1494 		 * Check to see if we already have this CRL.
1495 		 */
1496 		if (basefilename == NULL)
1497 			basefilename = basename(uri);
1498 
1499 		crlfilename = get_fullpath(dir == NULL ? "./" : dir,
1500 		    basefilename);
1501 		if (crlfilename == NULL) {
1502 			ret = KMF_ERR_BAD_CRLFILE;
1503 			goto cleanup;
1504 		}
1505 
1506 		/*
1507 		 * If this file already exists and is valid, we don't need to
1508 		 * download a new one.
1509 		 */
1510 		if ((fd = open(crlfilename, O_RDONLY)) != -1) {
1511 			(void) close(fd);
1512 			if ((ret = check_crl_validity(handle, *kstype,
1513 			    crlfilename, issuer_cert)) == KMF_OK) {
1514 				goto checkcrl;
1515 			}
1516 		}
1517 
1518 		/*
1519 		 * Create a temporary file to hold the new CRL file initially.
1520 		 */
1521 		(void) strlcpy(crlfile_tmp, CRLFILE_TEMPNAME,
1522 		    sizeof (crlfile_tmp));
1523 		if (mkstemp(crlfile_tmp) == -1) {
1524 			ret = KMF_ERR_INTERNAL;
1525 			goto cleanup;
1526 		}
1527 
1528 		/*
1529 		 * Get the URI entry from the certificate's CRL distribution
1530 		 * points extension and download the CRL file.
1531 		 */
1532 		proxy = policy->validation_info.crl_info.proxy;
1533 		ret = cert_get_crl(handle, user_cert, proxy, crlfile_tmp,
1534 		    &uri, &format);
1535 		if (ret != KMF_OK) {
1536 			(void) unlink(crlfile_tmp);
1537 			goto cleanup;
1538 		}
1539 		/*
1540 		 * If we just downloaded one, make sure it is OK.
1541 		 */
1542 		if ((ret = check_crl_validity(handle, *kstype, crlfile_tmp,
1543 		    issuer_cert)) != KMF_OK)
1544 			return (ret);
1545 
1546 		/* Cache the CRL file. */
1547 		if (*kstype == KMF_KEYSTORE_NSS) {
1548 			/*
1549 			 * For NSS keystore, import this CRL file into th
1550 			 * internal database.
1551 			 */
1552 			numattr = 0;
1553 			kmf_set_attr_at_index(attrlist, numattr,
1554 			    KMF_KEYSTORE_TYPE_ATTR, kstype, sizeof (kstype));
1555 			numattr++;
1556 
1557 			kmf_set_attr_at_index(attrlist, numattr,
1558 			    KMF_CRL_FILENAME_ATTR, crlfile_tmp,
1559 			    strlen(crlfile_tmp));
1560 			numattr++;
1561 
1562 			crlchk = B_FALSE;
1563 			kmf_set_attr_at_index(attrlist, numattr,
1564 			    KMF_CRL_CHECK_ATTR,	&crlchk, sizeof (boolean_t));
1565 			numattr++;
1566 
1567 			ret = kmf_import_crl(handle, numattr, attrlist);
1568 			(void) unlink(crlfile_tmp);
1569 			if (ret != KMF_OK)
1570 				goto cleanup;
1571 		} else {
1572 			if (rename(crlfile_tmp, crlfilename) == -1) {
1573 				(void) unlink(crlfile_tmp);
1574 				ret = KMF_ERR_WRITE_FILE;
1575 				goto cleanup;
1576 			}
1577 		}
1578 	} else {
1579 		/*
1580 		 * If the get_crl_uri policy is FALSE, for File-based CRL
1581 		 * plugins, get the input CRL file from the policy.
1582 		 */
1583 		if (*kstype != KMF_KEYSTORE_NSS) {
1584 			if (basefilename == NULL) {
1585 				ret = KMF_ERR_BAD_PARAMETER;
1586 				goto cleanup;
1587 			}
1588 
1589 			crlfilename = get_fullpath(dir == NULL ? "./" : dir,
1590 			    basefilename);
1591 			if (crlfilename == NULL) {
1592 				ret = KMF_ERR_BAD_CRLFILE;
1593 				goto cleanup;
1594 			}
1595 			/*
1596 			 * Make sure this CRL is still valid.
1597 			 */
1598 			if ((ret = check_crl_validity(handle, *kstype,
1599 			    crlfilename, issuer_cert)) != KMF_OK)
1600 				return (ret);
1601 			}
1602 	}
1603 
1604 checkcrl:
1605 	/*
1606 	 * Check the CRL revocation for the certificate.
1607 	 */
1608 	numattr = 0;
1609 
1610 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1611 	    kstype, sizeof (kstype));
1612 	numattr++;
1613 
1614 	switch (*kstype) {
1615 	case KMF_KEYSTORE_NSS:
1616 		kmf_set_attr_at_index(attrlist, numattr,
1617 		    KMF_CERT_DATA_ATTR, user_cert, sizeof (KMF_DATA));
1618 		numattr++;
1619 		break;
1620 	case KMF_KEYSTORE_PK11TOKEN:
1621 	case KMF_KEYSTORE_OPENSSL:
1622 		/*
1623 		 * Create temporary file to hold the user certificate.
1624 		 */
1625 		(void) strlcpy(user_certfile, CERTFILE_TEMPNAME,
1626 		    sizeof (user_certfile));
1627 		if (mkstemp(user_certfile) == -1) {
1628 			ret = KMF_ERR_INTERNAL;
1629 			goto cleanup;
1630 		}
1631 
1632 		ret = kmf_create_cert_file(user_cert, KMF_FORMAT_ASN1,
1633 		    user_certfile);
1634 		if (ret != KMF_OK)  {
1635 			goto cleanup;
1636 		}
1637 
1638 		kmf_set_attr_at_index(attrlist,  numattr,
1639 		    KMF_CERT_FILENAME_ATTR,
1640 		    user_certfile, strlen(user_certfile));
1641 		numattr++;
1642 
1643 		kmf_set_attr_at_index(attrlist,  numattr,
1644 		    KMF_CRL_FILENAME_ATTR,
1645 		    crlfilename, strlen(crlfilename));
1646 		numattr++;
1647 		break;
1648 	default:
1649 		ret = KMF_ERR_PLUGIN_NOTFOUND;
1650 		goto cleanup;
1651 	}
1652 
1653 	ret = kmf_find_cert_in_crl(handle, numattr, attrlist);
1654 	if (ret == KMF_ERR_NOT_REVOKED)  {
1655 		ret = KMF_OK;
1656 	}
1657 
1658 cleanup:
1659 	(void) unlink(user_certfile);
1660 
1661 	if (crlfilename != NULL)
1662 		free(crlfilename);
1663 
1664 	if (uri != NULL)
1665 		free(uri);
1666 
1667 	return (ret);
1668 }
1669 
1670 static KMF_RETURN
1671 cert_ocsp_check(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
1672 	KMF_DATA *user_cert, KMF_DATA *issuer_cert, KMF_DATA *response,
1673 	char *slotlabel, char *dirpath)
1674 {
1675 	KMF_RETURN ret = KMF_OK;
1676 	KMF_POLICY_RECORD *policy;
1677 	KMF_DATA *new_response = NULL;
1678 	boolean_t ignore_response_sign = B_FALSE;
1679 	uint32_t ltime = 0;
1680 	KMF_DATA *signer_cert = NULL;
1681 	KMF_BIGINT sernum = { NULL, 0 };
1682 	int response_status;
1683 	int reason;
1684 	int cert_status;
1685 	KMF_ATTRIBUTE attrlist[32];
1686 	int numattr;
1687 
1688 	if (handle == NULL || kstype == NULL || user_cert == NULL ||
1689 	    issuer_cert == NULL)
1690 		return (KMF_ERR_BAD_PARAMETER);
1691 
1692 	policy = handle->policy;
1693 
1694 	/*
1695 	 * Get the response lifetime from policy.
1696 	 */
1697 	if (policy->VAL_OCSP_BASIC.response_lifetime != NULL &&
1698 	    (str2lifetime(policy->VAL_OCSP_BASIC.response_lifetime, &ltime)
1699 	    < 0))
1700 		return (KMF_ERR_OCSP_RESPONSE_LIFETIME);
1701 
1702 	/*
1703 	 * Get the ignore_response_sign policy.
1704 	 *
1705 	 * If ignore_response_sign is FALSE, we need to verify the response.
1706 	 * Find the OCSP Responder certificate if it is specified in the OCSP
1707 	 * policy.
1708 	 */
1709 	ignore_response_sign = policy->VAL_OCSP_BASIC.ignore_response_sign;
1710 
1711 	if (ignore_response_sign == B_FALSE &&
1712 	    policy->VAL_OCSP.has_resp_cert == B_TRUE) {
1713 		char *signer_name;
1714 		KMF_X509_DER_CERT signer_retrcert;
1715 		uchar_t *bytes = NULL;
1716 		size_t bytelen;
1717 		uint32_t num = 0;
1718 		KMF_ATTRIBUTE fc_attrlist[16];
1719 		int fc_numattr = 0;
1720 		char *dir = "./";
1721 
1722 		if (policy->VAL_OCSP_RESP_CERT.name == NULL ||
1723 		    policy->VAL_OCSP_RESP_CERT.serial == NULL)
1724 			return (KMF_ERR_POLICY_NOT_FOUND);
1725 
1726 		signer_cert = malloc(sizeof (KMF_DATA));
1727 		if (signer_cert == NULL) {
1728 			ret = KMF_ERR_MEMORY;
1729 			goto out;
1730 		}
1731 		(void) memset(signer_cert, 0, sizeof (KMF_DATA));
1732 
1733 		signer_name = policy->VAL_OCSP_RESP_CERT.name;
1734 		ret = kmf_hexstr_to_bytes(
1735 		    (uchar_t *)policy->VAL_OCSP_RESP_CERT.serial,
1736 		    &bytes, &bytelen);
1737 		if (ret != KMF_OK || bytes == NULL) {
1738 			ret = KMF_ERR_OCSP_POLICY;
1739 			goto out;
1740 		}
1741 		sernum.val = bytes;
1742 		sernum.len = bytelen;
1743 
1744 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1745 		    KMF_KEYSTORE_TYPE_ATTR, kstype,
1746 		    sizeof (KMF_KEYSTORE_TYPE));
1747 		fc_numattr++;
1748 
1749 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1750 		    KMF_SUBJECT_NAME_ATTR, signer_name, strlen(signer_name));
1751 		fc_numattr++;
1752 
1753 		kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_BIGINT_ATTR,
1754 		    &sernum, sizeof (KMF_BIGINT));
1755 		fc_numattr++;
1756 
1757 		if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
1758 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1759 			    KMF_TOKEN_LABEL_ATTR, slotlabel,
1760 			    strlen(slotlabel));
1761 			fc_numattr++;
1762 		}
1763 
1764 		if (*kstype == KMF_KEYSTORE_OPENSSL) {
1765 			if (dirpath == NULL) {
1766 				kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1767 				    KMF_DIRPATH_ATTR, dir, strlen(dir));
1768 				fc_numattr++;
1769 			} else {
1770 				kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1771 				    KMF_DIRPATH_ATTR, dirpath,
1772 				    strlen(dirpath));
1773 				fc_numattr++;
1774 			}
1775 		}
1776 
1777 		num = 0;
1778 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1779 		    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
1780 		fc_numattr++;
1781 
1782 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
1783 		if (ret != KMF_OK || num != 1) {
1784 			if (num == 0)
1785 				ret = KMF_ERR_CERT_NOT_FOUND;
1786 			if (num > 0)
1787 				ret = KMF_ERR_CERT_MULTIPLE_FOUND;
1788 			goto out;
1789 		}
1790 
1791 		(void) memset(&signer_retrcert, 0, sizeof (KMF_X509_DER_CERT));
1792 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1793 		    KMF_X509_DER_CERT_ATTR, &signer_retrcert,
1794 		    sizeof (KMF_X509_DER_CERT));
1795 		fc_numattr++;
1796 
1797 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
1798 		if (ret == KMF_OK) {
1799 			signer_cert->Length =
1800 			    signer_retrcert.certificate.Length;
1801 			signer_cert->Data = signer_retrcert.certificate.Data;
1802 		} else {
1803 			goto out;
1804 		}
1805 	}
1806 
1807 	/*
1808 	 * If the caller provides an OCSP response, we will use it directly.
1809 	 * Otherwise, we will try to fetch an OCSP response for the given
1810 	 * certificate now.
1811 	 */
1812 	if (response == NULL) {
1813 		new_response = (KMF_DATA *) malloc(sizeof (KMF_DATA));
1814 		if (new_response == NULL) {
1815 			ret = KMF_ERR_MEMORY;
1816 			goto out;
1817 		}
1818 		new_response->Data = NULL;
1819 		new_response->Length = 0;
1820 
1821 		ret = kmf_get_ocsp_for_cert(handle, user_cert, issuer_cert,
1822 		    new_response);
1823 		if (ret != KMF_OK)
1824 			goto out;
1825 	}
1826 
1827 	/*
1828 	 * Process the OCSP response and retrieve the certificate status.
1829 	 */
1830 	numattr = 0;
1831 	kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_CERT_DATA_ATTR,
1832 	    issuer_cert, sizeof (KMF_DATA));
1833 	numattr++;
1834 
1835 	kmf_set_attr_at_index(attrlist, numattr, KMF_USER_CERT_DATA_ATTR,
1836 	    user_cert, sizeof (KMF_DATA));
1837 	numattr++;
1838 
1839 	if (signer_cert != NULL) {
1840 		kmf_set_attr_at_index(attrlist, numattr,
1841 		    KMF_SIGNER_CERT_DATA_ATTR, user_cert, sizeof (KMF_DATA));
1842 		numattr++;
1843 	}
1844 
1845 	kmf_set_attr_at_index(attrlist, numattr, KMF_OCSP_RESPONSE_DATA_ATTR,
1846 	    response == NULL ? new_response : response, sizeof (KMF_DATA));
1847 	numattr++;
1848 
1849 	kmf_set_attr_at_index(attrlist, numattr, KMF_RESPONSE_LIFETIME_ATTR,
1850 	    &ltime, sizeof (uint32_t));
1851 	numattr++;
1852 
1853 	kmf_set_attr_at_index(attrlist, numattr,
1854 	    KMF_IGNORE_RESPONSE_SIGN_ATTR, &ignore_response_sign,
1855 	    sizeof (boolean_t));
1856 	numattr++;
1857 
1858 	kmf_set_attr_at_index(attrlist, numattr,
1859 	    KMF_OCSP_RESPONSE_STATUS_ATTR, &response_status, sizeof (int));
1860 	numattr++;
1861 
1862 	kmf_set_attr_at_index(attrlist, numattr,
1863 	    KMF_OCSP_RESPONSE_REASON_ATTR, &reason, sizeof (int));
1864 	numattr++;
1865 
1866 	kmf_set_attr_at_index(attrlist, numattr,
1867 	    KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, &cert_status, sizeof (int));
1868 	numattr++;
1869 
1870 	ret = kmf_get_ocsp_status_for_cert(handle, numattr, attrlist);
1871 	if (ret == KMF_OK) {
1872 		switch (cert_status) {
1873 		case OCSP_GOOD:
1874 			break;
1875 		case OCSP_UNKNOWN:
1876 			ret = KMF_ERR_OCSP_UNKNOWN_CERT;
1877 			break;
1878 		case OCSP_REVOKED:
1879 			ret = KMF_ERR_OCSP_REVOKED;
1880 			break;
1881 		}
1882 	}
1883 
1884 out:
1885 	if (new_response) {
1886 		kmf_free_data(new_response);
1887 		free(new_response);
1888 	}
1889 
1890 	if (signer_cert) {
1891 		kmf_free_data(signer_cert);
1892 		free(signer_cert);
1893 	}
1894 
1895 	if (sernum.val != NULL)
1896 		free(sernum.val);
1897 
1898 	return (ret);
1899 }
1900 
1901 static KMF_RETURN
1902 cert_ku_check(KMF_HANDLE_T handle, KMF_DATA *cert)
1903 {
1904 	KMF_POLICY_RECORD *policy;
1905 	KMF_X509EXT_KEY_USAGE keyusage;
1906 	KMF_RETURN ret = KMF_OK;
1907 	KMF_X509EXT_BASICCONSTRAINTS constraint;
1908 	KMF_BOOL	critical = B_FALSE;
1909 
1910 	if (handle == NULL || cert == NULL)
1911 		return (KMF_ERR_BAD_PARAMETER);
1912 
1913 	policy = handle->policy;
1914 	(void) memset(&keyusage, 0, sizeof (keyusage));
1915 	ret = kmf_get_cert_ku(cert, &keyusage);
1916 
1917 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
1918 		if (policy->ku_bits) {
1919 			/* keyusage is not set in cert but is set in policy */
1920 			return (KMF_ERR_KEYUSAGE);
1921 		} else {
1922 			/* no keyusage set in both cert and policy */
1923 			return (KMF_OK);
1924 		}
1925 	}
1926 
1927 	if (ret != KMF_OK) {
1928 		/* real error */
1929 		return (ret);
1930 	}
1931 
1932 	/*
1933 	 * If KeyCertSign is set, then constraints.cA must be TRUE and
1934 	 * marked critical.
1935 	 */
1936 	if ((keyusage.KeyUsageBits & KMF_keyCertSign)) {
1937 		(void) memset(&constraint, 0, sizeof (constraint));
1938 		ret = kmf_get_cert_basic_constraint(cert,
1939 		    &critical, &constraint);
1940 
1941 		if (ret != KMF_OK) {
1942 			/* real error */
1943 			return (ret);
1944 		}
1945 		if (!constraint.cA || !critical)
1946 			return (KMF_ERR_KEYUSAGE);
1947 	}
1948 
1949 	/*
1950 	 * Rule: if the KU bit is set in policy, the corresponding KU bit
1951 	 * must be set in the certificate (but not vice versa).
1952 	 */
1953 	if ((policy->ku_bits & keyusage.KeyUsageBits) == policy->ku_bits) {
1954 		return (KMF_OK);
1955 	} else {
1956 		return (KMF_ERR_KEYUSAGE);
1957 	}
1958 
1959 }
1960 
1961 static KMF_RETURN
1962 cert_eku_check(KMF_HANDLE_T handle, KMF_DATA *cert)
1963 {
1964 	KMF_POLICY_RECORD *policy;
1965 	KMF_RETURN ret = KMF_OK;
1966 	KMF_X509EXT_EKU eku;
1967 	uint16_t cert_eku = 0, policy_eku = 0;
1968 	int i;
1969 
1970 	if (handle == NULL || cert == NULL)
1971 		return (KMF_ERR_BAD_PARAMETER);
1972 	policy = handle->policy;
1973 
1974 	/*
1975 	 * If the policy does not have any EKU, then there is
1976 	 * nothing further to check.
1977 	 */
1978 	if (policy->eku_set.eku_count == 0)
1979 		return (KMF_OK);
1980 
1981 	ret = kmf_get_cert_eku(cert, &eku);
1982 	if ((ret != KMF_ERR_EXTENSION_NOT_FOUND) && (ret != KMF_OK)) {
1983 		/* real error */
1984 		return (ret);
1985 	}
1986 
1987 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
1988 		cert_eku = 0;
1989 	} else {
1990 		/*
1991 		 * Build the EKU bitmap based on the certificate
1992 		 */
1993 		for (i = 0; i < eku.nEKUs; i++) {
1994 			if (IsEqualOid(&eku.keyPurposeIdList[i],
1995 			    (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
1996 				cert_eku |= KMF_EKU_SERVERAUTH;
1997 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1998 			    (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
1999 				cert_eku |= KMF_EKU_CLIENTAUTH;
2000 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
2001 			    (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
2002 				cert_eku |= KMF_EKU_CODESIGNING;
2003 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
2004 			    (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) {
2005 				cert_eku |= KMF_EKU_EMAIL;
2006 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
2007 			    (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
2008 				cert_eku |= KMF_EKU_TIMESTAMP;
2009 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
2010 			    (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
2011 				cert_eku |= KMF_EKU_OCSPSIGNING;
2012 			} else if (!policy->ignore_unknown_ekus) {
2013 				return (KMF_ERR_KEYUSAGE);
2014 			}
2015 		} /* for */
2016 	}
2017 
2018 
2019 	/*
2020 	 * Build the EKU bitmap based on the policy
2021 	 */
2022 	for (i = 0; i < policy->eku_set.eku_count; i++) {
2023 		if (IsEqualOid(&policy->eku_set.ekulist[i],
2024 		    (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
2025 			policy_eku |= KMF_EKU_SERVERAUTH;
2026 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
2027 		    (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
2028 			policy_eku |= KMF_EKU_CLIENTAUTH;
2029 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
2030 		    (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
2031 			policy_eku |= KMF_EKU_CODESIGNING;
2032 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
2033 		    (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) {
2034 			policy_eku |= KMF_EKU_EMAIL;
2035 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
2036 		    (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
2037 			policy_eku |= KMF_EKU_TIMESTAMP;
2038 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
2039 		    (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
2040 			policy_eku |= KMF_EKU_OCSPSIGNING;
2041 		} else if (!policy->ignore_unknown_ekus) {
2042 			return (KMF_ERR_KEYUSAGE);
2043 		}
2044 	} /* for */
2045 
2046 	/*
2047 	 * Rule: if the EKU OID is set in policy, the corresponding EKU OID
2048 	 * must be set in the certificate (but not vice versa).
2049 	 */
2050 	if ((policy_eku & cert_eku) == policy_eku) {
2051 		return (KMF_OK);
2052 	} else {
2053 		return (KMF_ERR_KEYUSAGE);
2054 	}
2055 }
2056 
2057 static KMF_RETURN
2058 find_issuer_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
2059     char *user_issuer, KMF_DATA *issuer_cert,
2060     char *slotlabel, char *dirpath)
2061 {
2062 	KMF_RETURN ret = KMF_OK;
2063 	KMF_X509_DER_CERT *certlist = NULL;
2064 	uint32_t i, num = 0;
2065 	time_t t_notbefore;
2066 	time_t t_notafter;
2067 	time_t latest;
2068 	KMF_DATA tmp_cert = {0, NULL};
2069 	KMF_ATTRIBUTE fc_attrlist[16];
2070 	int fc_numattr = 0;
2071 	char *dir = "./";
2072 
2073 	if (handle == NULL || kstype == NULL || user_issuer == NULL ||
2074 	    issuer_cert == NULL)
2075 		return (KMF_ERR_BAD_PARAMETER);
2076 
2077 	if (!is_valid_keystore_type(*kstype))
2078 		return (KMF_ERR_BAD_PARAMETER);
2079 
2080 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_KEYSTORE_TYPE_ATTR,
2081 	    kstype, sizeof (KMF_KEYSTORE_TYPE));
2082 	fc_numattr++;
2083 
2084 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_SUBJECT_NAME_ATTR,
2085 	    user_issuer, strlen(user_issuer));
2086 	fc_numattr++;
2087 
2088 	if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
2089 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2090 		    KMF_TOKEN_LABEL_ATTR, slotlabel, strlen(slotlabel));
2091 		fc_numattr++;
2092 	}
2093 
2094 	if (*kstype == KMF_KEYSTORE_OPENSSL) {
2095 		if (dirpath == NULL) {
2096 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2097 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
2098 			fc_numattr++;
2099 		} else {
2100 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2101 			    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2102 			fc_numattr++;
2103 		}
2104 	}
2105 
2106 	num = 0;
2107 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2108 	    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
2109 	fc_numattr++;
2110 
2111 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2112 
2113 	if (ret == KMF_OK && num > 0) {
2114 		certlist = (KMF_X509_DER_CERT *)malloc(num *
2115 		    sizeof (KMF_X509_DER_CERT));
2116 
2117 		if (certlist == NULL) {
2118 			ret = KMF_ERR_MEMORY;
2119 			goto out;
2120 		}
2121 
2122 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2123 		    KMF_X509_DER_CERT_ATTR, certlist,
2124 		    sizeof (KMF_X509_DER_CERT));
2125 		fc_numattr++;
2126 
2127 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2128 		if (ret != KMF_OK) {
2129 			free(certlist);
2130 			certlist = NULL;
2131 			goto out;
2132 		}
2133 	} else {
2134 		goto out;
2135 	}
2136 
2137 	if (num == 1) {
2138 		/* only one issuer cert is found */
2139 		tmp_cert.Length = certlist[0].certificate.Length;
2140 		tmp_cert.Data = certlist[0].certificate.Data;
2141 	} else {
2142 		/*
2143 		 * More than one issuer certs are found. We will
2144 		 * pick the latest one.
2145 		 */
2146 		latest = 0;
2147 		for (i = 0; i < num; i++) {
2148 			ret = kmf_get_cert_validity(&certlist[i].certificate,
2149 			    &t_notbefore, &t_notafter);
2150 			if (ret != KMF_OK) {
2151 				ret = KMF_ERR_VALIDITY_PERIOD;
2152 				goto out;
2153 			}
2154 
2155 			if (t_notbefore > latest) {
2156 				tmp_cert.Length =
2157 				    certlist[i].certificate.Length;
2158 				tmp_cert.Data =
2159 				    certlist[i].certificate.Data;
2160 				latest = t_notbefore;
2161 			}
2162 
2163 		}
2164 	}
2165 
2166 	issuer_cert->Length = tmp_cert.Length;
2167 	issuer_cert->Data = malloc(tmp_cert.Length);
2168 	if (issuer_cert->Data == NULL) {
2169 		ret = KMF_ERR_MEMORY;
2170 		goto out;
2171 	}
2172 	(void) memcpy(issuer_cert->Data, tmp_cert.Data,
2173 	    tmp_cert.Length);
2174 
2175 out:
2176 	if (certlist != NULL) {
2177 		for (i = 0; i < num; i++)
2178 			kmf_free_kmf_cert(handle, &certlist[i]);
2179 		free(certlist);
2180 	}
2181 
2182 	return (ret);
2183 
2184 }
2185 
2186 static KMF_RETURN
2187 find_ta_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
2188 	KMF_DATA *ta_cert, KMF_X509_NAME *user_issuerDN,
2189 	char *slotlabel, char *dirpath)
2190 {
2191 	KMF_POLICY_RECORD *policy;
2192 	KMF_RETURN ret = KMF_OK;
2193 	uint32_t num = 0;
2194 	char *ta_name;
2195 	KMF_BIGINT serial = { NULL, 0 };
2196 	uchar_t *bytes = NULL;
2197 	size_t bytelen;
2198 	KMF_X509_DER_CERT ta_retrCert;
2199 	char *ta_subject = NULL;
2200 	KMF_X509_NAME ta_subjectDN;
2201 	KMF_ATTRIBUTE fc_attrlist[16];
2202 	int fc_numattr = 0;
2203 	char *dir = "./";
2204 
2205 	if (handle == NULL || kstype == NULL || ta_cert == NULL ||
2206 	    user_issuerDN == NULL)
2207 		return (KMF_ERR_BAD_PARAMETER);
2208 
2209 	if (!is_valid_keystore_type(*kstype))
2210 		return (KMF_ERR_BAD_PARAMETER);
2211 
2212 	/* Get the TA name and serial number from the policy */
2213 	policy = handle->policy;
2214 	ta_name = policy->ta_name;
2215 	ret = kmf_hexstr_to_bytes((uchar_t *)policy->ta_serial,
2216 	    &bytes, &bytelen);
2217 	if (ret != KMF_OK || bytes == NULL) {
2218 		ret = KMF_ERR_TA_POLICY;
2219 		goto out;
2220 	}
2221 	serial.val = bytes;
2222 	serial.len = bytelen;
2223 
2224 	/* set up fc_attrlist for kmf_find_cert */
2225 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_KEYSTORE_TYPE_ATTR,
2226 	    kstype, sizeof (KMF_KEYSTORE_TYPE));
2227 	fc_numattr++;
2228 
2229 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_SUBJECT_NAME_ATTR,
2230 	    ta_name, strlen(ta_name));
2231 	fc_numattr++;
2232 
2233 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_BIGINT_ATTR,
2234 	    &serial, sizeof (KMF_BIGINT));
2235 	fc_numattr++;
2236 
2237 	if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
2238 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2239 		    KMF_TOKEN_LABEL_ATTR, slotlabel, strlen(slotlabel));
2240 		fc_numattr++;
2241 	}
2242 
2243 	if (*kstype == KMF_KEYSTORE_OPENSSL) {
2244 		if (dirpath == NULL) {
2245 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2246 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
2247 			fc_numattr++;
2248 		} else {
2249 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2250 			    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2251 			fc_numattr++;
2252 		}
2253 	}
2254 
2255 	num = 0;
2256 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2257 	    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
2258 	fc_numattr++;
2259 
2260 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2261 	if (ret != KMF_OK || num != 1)  {
2262 		if (num == 0)
2263 			ret = KMF_ERR_CERT_NOT_FOUND;
2264 		if (num > 1)
2265 			ret = KMF_ERR_CERT_MULTIPLE_FOUND;
2266 		goto out;
2267 	}
2268 
2269 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2270 	    KMF_X509_DER_CERT_ATTR, &ta_retrCert, sizeof (KMF_X509_DER_CERT));
2271 	fc_numattr++;
2272 
2273 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2274 	if (ret == KMF_OK)  {
2275 		ta_cert->Length = ta_retrCert.certificate.Length;
2276 		ta_cert->Data = malloc(ta_retrCert.certificate.Length);
2277 		if (ta_cert->Data == NULL) {
2278 			ret = KMF_ERR_MEMORY;
2279 			goto out;
2280 		}
2281 		(void) memcpy(ta_cert->Data, ta_retrCert.certificate.Data,
2282 		    ta_retrCert.certificate.Length);
2283 	} else {
2284 		goto out;
2285 	}
2286 
2287 	/*
2288 	 * The found TA's name must be matching with issuer name in
2289 	 * subscriber's certificate.
2290 	 */
2291 	(void) memset(&ta_subjectDN, 0, sizeof (ta_subjectDN));
2292 
2293 	ret = kmf_get_cert_subject_str(handle, ta_cert, &ta_subject);
2294 	if (ret != KMF_OK)
2295 		goto out;
2296 
2297 	ret = kmf_dn_parser(ta_subject,  &ta_subjectDN);
2298 	if (ret != KMF_OK)
2299 		goto out;
2300 
2301 	if (kmf_compare_rdns(user_issuerDN, &ta_subjectDN) != 0)
2302 		ret = KMF_ERR_CERT_NOT_FOUND;
2303 
2304 	kmf_free_dn(&ta_subjectDN);
2305 
2306 	/* Make sure the TA cert has the correct extensions */
2307 	if (ret == KMF_OK) {
2308 		ret = check_key_usage(handle, ta_cert, KMF_KU_SIGN_CERT);
2309 		if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
2310 			ret = KMF_OK;
2311 	}
2312 out:
2313 	if (ta_retrCert.certificate.Data)
2314 		kmf_free_kmf_cert(handle, &ta_retrCert);
2315 
2316 	if ((ret != KMF_OK) && (ta_cert->Data != NULL))
2317 		free(ta_cert->Data);
2318 
2319 	if (serial.val != NULL)
2320 		free(serial.val);
2321 
2322 	if (ta_subject)
2323 		free(ta_subject);
2324 
2325 	return (ret);
2326 }
2327 
2328 KMF_RETURN
2329 kmf_validate_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2330 {
2331 	KMF_RETURN ret = KMF_OK;
2332 	KMF_KEYSTORE_TYPE *kstype = NULL;
2333 	KMF_DATA *pcert = NULL;
2334 	int *result = NULL;
2335 	char *slotlabel = NULL;
2336 	char *dirpath = NULL;
2337 	KMF_DATA *ocsp_response = NULL;
2338 	KMF_DATA ta_cert = {0, NULL};
2339 	KMF_DATA issuer_cert = {0, NULL};
2340 	char *user_issuer = NULL, *user_subject = NULL;
2341 	KMF_X509_NAME user_issuerDN, user_subjectDN;
2342 	boolean_t	self_signed = B_FALSE;
2343 	KMF_POLICY_RECORD *policy;
2344 
2345 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
2346 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
2347 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
2348 	    {KMF_VALIDATE_RESULT_ATTR, FALSE, 1, sizeof (int)}
2349 	};
2350 	int num_req_attrs = sizeof (required_attrs) /
2351 	    sizeof (KMF_ATTRIBUTE_TESTER);
2352 
2353 	if (handle == NULL)
2354 		return (KMF_ERR_BAD_PARAMETER);
2355 
2356 	CLEAR_ERROR(handle, ret);
2357 
2358 	ret = test_attributes(num_req_attrs, required_attrs,
2359 	    0, NULL, numattr, attrlist);
2360 	if (ret != KMF_OK)
2361 		return (ret);
2362 
2363 	policy = handle->policy;
2364 
2365 	/* Get the attribute values */
2366 	kstype = kmf_get_attr_ptr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr);
2367 	pcert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2368 	result = kmf_get_attr_ptr(KMF_VALIDATE_RESULT_ATTR, attrlist, numattr);
2369 	if (kstype == NULL || pcert == NULL || result == NULL)
2370 		return (KMF_ERR_BAD_PARAMETER);
2371 
2372 	slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
2373 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2374 	ocsp_response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, attrlist,
2375 	    numattr);
2376 
2377 	/* Initialize the returned result */
2378 	*result = KMF_CERT_VALIDATE_OK;
2379 
2380 	/*
2381 	 * Get the issuer information from the input certficate first.
2382 	 */
2383 	if ((ret = kmf_get_cert_issuer_str(handle, pcert,
2384 	    &user_issuer)) != KMF_OK) {
2385 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2386 		goto out;
2387 	}
2388 
2389 	if ((ret = kmf_dn_parser(user_issuer,  &user_issuerDN)) != KMF_OK) {
2390 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2391 		goto out;
2392 	}
2393 
2394 	/*
2395 	 * Check if the certificate is a self-signed cert.
2396 	 */
2397 	if ((ret = kmf_get_cert_subject_str(handle, pcert,
2398 	    &user_subject)) != KMF_OK) {
2399 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2400 		kmf_free_dn(&user_issuerDN);
2401 		goto out;
2402 	}
2403 
2404 	if ((ret = kmf_dn_parser(user_subject,  &user_subjectDN)) != KMF_OK) {
2405 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2406 		kmf_free_dn(&user_issuerDN);
2407 		goto out;
2408 	}
2409 
2410 	if ((kmf_compare_rdns(&user_issuerDN, &user_subjectDN)) == 0) {
2411 		/*
2412 		 * this is a self-signed cert
2413 		 */
2414 		self_signed = B_TRUE;
2415 	}
2416 
2417 	kmf_free_dn(&user_subjectDN);
2418 
2419 	/*
2420 	 * Check KeyUsage extension of the subscriber's certificate
2421 	 */
2422 	ret = cert_ku_check(handle, pcert);
2423 	if (ret != KMF_OK)  {
2424 		*result |= KMF_CERT_VALIDATE_ERR_KEYUSAGE;
2425 		goto out;
2426 	}
2427 
2428 	/*
2429 	 * Validate Extended KeyUsage extension
2430 	 */
2431 	ret = cert_eku_check(handle, pcert);
2432 	if (ret != KMF_OK)  {
2433 		*result |= KMF_CERT_VALIDATE_ERR_EXT_KEYUSAGE;
2434 		goto out;
2435 	}
2436 
2437 	/*
2438 	 * Check the certificate's validity period
2439 	 *
2440 	 * This step is needed when "ignore_date" in policy is set
2441 	 * to false.
2442 	 */
2443 	if (!policy->ignore_date) {
2444 		/*
2445 		 * Validate expiration date
2446 		 */
2447 		ret = kmf_check_cert_date(handle, pcert);
2448 		if (ret != KMF_OK)  {
2449 			*result |= KMF_CERT_VALIDATE_ERR_TIME;
2450 			goto out;
2451 		}
2452 	}
2453 
2454 	/*
2455 	 * When "ignore_trust_anchor" in policy is set to FALSE,
2456 	 * we will try to find the TA cert based on the TA policy
2457 	 * attributes.
2458 	 *
2459 	 * TA's subject name (ta_name) and serial number (ta_serial)
2460 	 * are defined as optional attributes in policy dtd, but they
2461 	 * should exist in policy when "ignore_trust_anchor" is set
2462 	 * to FALSE. The policy verification code has enforced that.
2463 	 */
2464 	if (policy->ignore_trust_anchor) {
2465 		goto check_revocation;
2466 	}
2467 
2468 	/*
2469 	 * Verify the signature of subscriber's certificate using
2470 	 * TA certificate.
2471 	 */
2472 	if (self_signed) {
2473 		ret = verify_cert_with_cert(handle, pcert, pcert);
2474 	} else {
2475 		ret = find_ta_cert(handle, kstype, &ta_cert,
2476 		    &user_issuerDN, slotlabel, dirpath);
2477 		if (ret != KMF_OK)  {
2478 			*result |= KMF_CERT_VALIDATE_ERR_TA;
2479 			goto out;
2480 		}
2481 
2482 		ret = verify_cert_with_cert(handle, pcert, &ta_cert);
2483 	}
2484 	if (ret != KMF_OK)  {
2485 		*result |= KMF_CERT_VALIDATE_ERR_SIGNATURE;
2486 		goto out;
2487 	}
2488 
2489 check_revocation:
2490 	/*
2491 	 * Check certificate revocation
2492 	 */
2493 	if (self_signed) {
2494 		/* skip revocation checking */
2495 		goto out;
2496 	}
2497 
2498 	/*
2499 	 * When CRL or OCSP revocation method is set in the policy,
2500 	 * we will try to find the issuer of the subscriber certificate
2501 	 * using the issuer name of the subscriber certificate. The
2502 	 * issuer certificate will be used to do the CRL checking
2503 	 * and OCSP checking.
2504 	 */
2505 	if (!(policy->revocation & KMF_REVOCATION_METHOD_CRL) &&
2506 	    !(policy->revocation & KMF_REVOCATION_METHOD_OCSP)) {
2507 		goto out;
2508 	}
2509 
2510 	ret = find_issuer_cert(handle, kstype, user_issuer, &issuer_cert,
2511 	    slotlabel, dirpath);
2512 	if (ret != KMF_OK)  {
2513 		*result |= KMF_CERT_VALIDATE_ERR_ISSUER;
2514 		goto out;
2515 	}
2516 
2517 	if (policy->revocation & KMF_REVOCATION_METHOD_CRL) {
2518 		ret = cert_crl_check(handle, kstype, pcert, &issuer_cert);
2519 		if (ret != KMF_OK)  {
2520 			*result |= KMF_CERT_VALIDATE_ERR_CRL;
2521 			goto out;
2522 		}
2523 	}
2524 
2525 	if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) {
2526 		ret = cert_ocsp_check(handle, kstype, pcert, &issuer_cert,
2527 		    ocsp_response, slotlabel, dirpath);
2528 		if (ret != KMF_OK)  {
2529 			*result |= KMF_CERT_VALIDATE_ERR_OCSP;
2530 			goto out;
2531 		}
2532 	}
2533 
2534 out:
2535 	if (user_issuer) {
2536 		kmf_free_dn(&user_issuerDN);
2537 		free(user_issuer);
2538 	}
2539 
2540 	if (user_subject)
2541 		free(user_subject);
2542 
2543 	if (ta_cert.Data)
2544 		free(ta_cert.Data);
2545 
2546 	if (issuer_cert.Data)
2547 		free(issuer_cert.Data);
2548 
2549 	return (ret);
2550 
2551 }
2552 
2553 KMF_RETURN
2554 kmf_create_cert_file(const KMF_DATA *certdata, KMF_ENCODE_FORMAT format,
2555 	char *certfile)
2556 {
2557 	KMF_RETURN rv = KMF_OK;
2558 	int fd = -1;
2559 	KMF_DATA pemdata = {NULL, 0};
2560 
2561 	if (certdata == NULL || certfile == NULL)
2562 		return (KMF_ERR_BAD_PARAMETER);
2563 
2564 	if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1)
2565 		return (KMF_ERR_BAD_PARAMETER);
2566 
2567 	if (format == KMF_FORMAT_PEM) {
2568 		int len;
2569 		rv = kmf_der_to_pem(KMF_CERT,
2570 		    certdata->Data, certdata->Length,
2571 		    &pemdata.Data, &len);
2572 		if (rv != KMF_OK)
2573 			goto cleanup;
2574 		pemdata.Length = (size_t)len;
2575 	}
2576 
2577 	if ((fd = open(certfile, O_CREAT | O_RDWR | O_TRUNC, 0644)) == -1) {
2578 		rv = KMF_ERR_OPEN_FILE;
2579 		goto cleanup;
2580 	}
2581 
2582 	if (format == KMF_FORMAT_PEM) {
2583 		if (write(fd, pemdata.Data, pemdata.Length) !=
2584 		    pemdata.Length) {
2585 			rv = KMF_ERR_WRITE_FILE;
2586 		}
2587 	} else {
2588 		if (write(fd, certdata->Data, certdata->Length) !=
2589 		    certdata->Length) {
2590 			rv = KMF_ERR_WRITE_FILE;
2591 		}
2592 	}
2593 
2594 cleanup:
2595 	if (fd != -1)
2596 		(void) close(fd);
2597 
2598 	kmf_free_data(&pemdata);
2599 
2600 	return (rv);
2601 }
2602 
2603 /*
2604  * kmf_is_cert_data
2605  *
2606  * Determine if a KMF_DATA buffer contains an encoded X.509 certificate.
2607  *
2608  * Return:
2609  *   KMF_OK if it is a certificate
2610  *   KMF_ERR_ENCODING (or other error) if not.
2611  */
2612 KMF_RETURN
2613 kmf_is_cert_data(KMF_DATA *data, KMF_ENCODE_FORMAT *fmt)
2614 {
2615 	KMF_RETURN rv = KMF_OK;
2616 	KMF_X509_CERTIFICATE *x509 = NULL;
2617 	KMF_DATA oldpem = {0, NULL};
2618 	uchar_t *d = NULL;
2619 	int len = 0;
2620 
2621 	if (data == NULL || fmt == NULL)
2622 		return (KMF_ERR_BAD_PARAMETER);
2623 
2624 	rv = kmf_get_data_format(data, fmt);
2625 	if (rv != KMF_OK)
2626 		return (rv);
2627 	switch (*fmt) {
2628 		case KMF_FORMAT_ASN1:
2629 			rv = DerDecodeSignedCertificate(data, &x509);
2630 			break;
2631 		case KMF_FORMAT_PEM:
2632 			/* Convert to ASN.1 DER first */
2633 			rv = kmf_pem_to_der(data->Data, data->Length,
2634 			    &d, &len);
2635 			if (rv != KMF_OK)
2636 				return (rv);
2637 			oldpem.Data = d;
2638 			oldpem.Length = len;
2639 			rv = DerDecodeSignedCertificate(&oldpem, &x509);
2640 			kmf_free_data(&oldpem);
2641 			break;
2642 		case KMF_FORMAT_PKCS12:
2643 		case KMF_FORMAT_UNDEF:
2644 		default:
2645 			return (KMF_ERR_ENCODING);
2646 	}
2647 
2648 	if (x509 != NULL) {
2649 		kmf_free_signed_cert(x509);
2650 		free(x509);
2651 	}
2652 	return (rv);
2653 }
2654 
2655 KMF_RETURN
2656 kmf_is_cert_file(KMF_HANDLE_T handle, char *filename,
2657 	KMF_ENCODE_FORMAT *pformat)
2658 {
2659 	KMF_RETURN ret;
2660 	KMF_DATA filedata;
2661 
2662 	CLEAR_ERROR(handle, ret);
2663 	if (ret != KMF_OK)
2664 		return (ret);
2665 
2666 	if (filename  == NULL || pformat == NULL)
2667 		return (KMF_ERR_BAD_PARAMETER);
2668 
2669 	ret = kmf_read_input_file(handle, filename, &filedata);
2670 	if (ret != KMF_OK)
2671 		return (ret);
2672 
2673 	ret = kmf_is_cert_data(&filedata, pformat);
2674 	if (ret == KMF_ERR_BAD_CERT_FORMAT)
2675 		ret = KMF_ERR_BAD_CERTFILE;
2676 
2677 	kmf_free_data(&filedata);
2678 	return (ret);
2679 }
2680 
2681 /*
2682  * This function checks the validity period of a der-encoded certificate.
2683  */
2684 KMF_RETURN
2685 kmf_check_cert_date(KMF_HANDLE_T handle, const KMF_DATA *cert)
2686 {
2687 	KMF_RETURN rv;
2688 	struct tm *gmt;
2689 	time_t t_now;
2690 	time_t t_notbefore;
2691 	time_t t_notafter;
2692 	KMF_POLICY_RECORD *policy;
2693 	uint32_t adj;
2694 
2695 	CLEAR_ERROR(handle, rv);
2696 	if (rv != KMF_OK)
2697 		return (rv);
2698 
2699 	if (cert == NULL || cert->Data == NULL || cert->Length == 0)
2700 		return (KMF_ERR_BAD_PARAMETER);
2701 
2702 	policy = handle->policy;
2703 	rv = kmf_get_cert_validity(cert, &t_notbefore, &t_notafter);
2704 	if (rv != KMF_OK)
2705 		return (rv);
2706 
2707 	/*
2708 	 * Get the current time. The time returned from time() is local which
2709 	 * cannot be used directly. It must be converted to UTC/GMT first.
2710 	 */
2711 	t_now = time(NULL);
2712 	gmt = gmtime(&t_now);
2713 	t_now = mktime(gmt);
2714 
2715 	/*
2716 	 * Adjust the validity time
2717 	 */
2718 	if (policy->validity_adjusttime != NULL) {
2719 		if (str2lifetime(policy->validity_adjusttime, &adj) < 0)
2720 			return (KMF_ERR_VALIDITY_PERIOD);
2721 	} else {
2722 		adj = 0;
2723 	}
2724 
2725 	t_notafter += adj;
2726 	t_notbefore -= adj;
2727 
2728 	if (t_now <= t_notafter && t_now >= t_notbefore) {
2729 		rv = KMF_OK;
2730 	} else {
2731 		rv = KMF_ERR_VALIDITY_PERIOD;
2732 	}
2733 
2734 	return (rv);
2735 }
2736 
2737 KMF_RETURN
2738 kmf_export_pk12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2739 {
2740 	KMF_PLUGIN *plugin;
2741 	KMF_RETURN ret = KMF_OK;
2742 	KMF_KEYSTORE_TYPE kstype;
2743 
2744 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
2745 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
2746 	    {KMF_OUTPUT_FILENAME_ATTR, TRUE, 1, 0},
2747 	};
2748 
2749 	int num_req_attrs = sizeof (required_attrs) /
2750 	    sizeof (KMF_ATTRIBUTE_TESTER);
2751 
2752 	if (handle == NULL)
2753 		return (KMF_ERR_BAD_PARAMETER);
2754 
2755 	CLEAR_ERROR(handle, ret);
2756 
2757 	ret = test_attributes(num_req_attrs, required_attrs, 0, NULL,
2758 	    numattr, attrlist);
2759 	if (ret != KMF_OK)
2760 		return (ret);
2761 
2762 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
2763 	    &kstype, NULL);
2764 	if (ret != KMF_OK)
2765 		return (ret);
2766 
2767 	plugin = FindPlugin(handle, kstype);
2768 	if (plugin == NULL || plugin->funclist->ExportPK12 == NULL)
2769 		return (KMF_ERR_PLUGIN_NOTFOUND);
2770 
2771 	return (plugin->funclist->ExportPK12(handle, numattr, attrlist));
2772 }
2773 
2774 
2775 KMF_RETURN
2776 kmf_build_pk12(KMF_HANDLE_T handle, int numcerts,
2777     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
2778     KMF_CREDENTIAL *p12cred, char *filename)
2779 {
2780 	KMF_RETURN rv;
2781 	KMF_PLUGIN *plugin;
2782 	KMF_RETURN (*buildpk12)(KMF_HANDLE *, int, KMF_X509_DER_CERT *,
2783 	    int, KMF_KEY_HANDLE *, KMF_CREDENTIAL *, char *);
2784 
2785 	CLEAR_ERROR(handle, rv);
2786 	if (rv != KMF_OK)
2787 		return (rv);
2788 
2789 	if (filename == NULL ||	p12cred == NULL ||
2790 	    (certlist == NULL && keylist == NULL))
2791 		return (KMF_ERR_BAD_PARAMETER);
2792 
2793 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2794 	if (plugin == NULL || plugin->dldesc == NULL) {
2795 		return (KMF_ERR_PLUGIN_NOTFOUND);
2796 	}
2797 
2798 	buildpk12 = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2799 	    "openssl_build_pk12");
2800 	if (buildpk12 == NULL) {
2801 		return (KMF_ERR_FUNCTION_NOT_FOUND);
2802 	}
2803 
2804 	rv = buildpk12(handle, numcerts, certlist, numkeys, keylist, p12cred,
2805 	    filename);
2806 
2807 	return (rv);
2808 }
2809 
2810 
2811 KMF_RETURN
2812 kmf_import_objects(KMF_HANDLE_T handle, char *filename,
2813 	KMF_CREDENTIAL *cred,
2814 	KMF_X509_DER_CERT **certs, int *ncerts,
2815 	KMF_RAW_KEY_DATA **rawkeys, int *nkeys)
2816 {
2817 	KMF_RETURN rv;
2818 	KMF_PLUGIN *plugin;
2819 	KMF_RETURN (*import_objects)(KMF_HANDLE *, char *, KMF_CREDENTIAL *,
2820 	    KMF_X509_DER_CERT **, int *, KMF_RAW_KEY_DATA **, int *);
2821 
2822 	CLEAR_ERROR(handle, rv);
2823 	if (rv != KMF_OK)
2824 		return (rv);
2825 
2826 	if (filename == NULL ||	cred == NULL ||	certs == NULL ||
2827 	    ncerts == NULL ||rawkeys == NULL || nkeys == NULL)
2828 		return (KMF_ERR_BAD_PARAMETER);
2829 
2830 	/*
2831 	 * Use the Keypair reader from the OpenSSL plugin.
2832 	 */
2833 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2834 	if (plugin == NULL || plugin->dldesc == NULL) {
2835 		return (KMF_ERR_PLUGIN_NOTFOUND);
2836 	}
2837 
2838 	import_objects = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2839 	    "openssl_import_objects");
2840 	if (import_objects == NULL) {
2841 		return (KMF_ERR_FUNCTION_NOT_FOUND);
2842 	}
2843 
2844 	/* Use OpenSSL interfaces to get raw key and cert data */
2845 	rv = import_objects(handle, filename, cred, certs, ncerts,
2846 	    rawkeys, nkeys);
2847 
2848 	return (rv);
2849 }
2850 
2851 KMF_BOOL
2852 IsEqualOid(KMF_OID *Oid1, KMF_OID *Oid2)
2853 {
2854 	return ((Oid1->Length == Oid2->Length) &&
2855 	    !memcmp(Oid1->Data, Oid2->Data, Oid1->Length));
2856 }
2857 
2858 static KMF_RETURN
2859 set_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
2860 	KMF_OID *newoid)
2861 {
2862 	if (destid == NULL || newoid == NULL)
2863 		return (KMF_ERR_BAD_PARAMETER);
2864 
2865 	destid->algorithm.Length = newoid->Length;
2866 	destid->algorithm.Data = malloc(destid->algorithm.Length);
2867 	if (destid->algorithm.Data == NULL)
2868 		return (KMF_ERR_MEMORY);
2869 
2870 	(void) memcpy(destid->algorithm.Data, newoid->Data,
2871 	    destid->algorithm.Length);
2872 
2873 	return (KMF_OK);
2874 }
2875 
2876 KMF_RETURN
2877 copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
2878 	KMF_X509_ALGORITHM_IDENTIFIER *srcid)
2879 {
2880 	KMF_RETURN ret = KMF_OK;
2881 	if (!destid || !srcid)
2882 		return (KMF_ERR_BAD_PARAMETER);
2883 
2884 	destid->algorithm.Length = srcid->algorithm.Length;
2885 	destid->algorithm.Data = malloc(destid->algorithm.Length);
2886 	if (destid->algorithm.Data == NULL)
2887 		return (KMF_ERR_MEMORY);
2888 
2889 	(void) memcpy(destid->algorithm.Data, srcid->algorithm.Data,
2890 	    destid->algorithm.Length);
2891 
2892 	destid->parameters.Length = srcid->parameters.Length;
2893 	if (destid->parameters.Length > 0) {
2894 		destid->parameters.Data = malloc(destid->parameters.Length);
2895 		if (destid->parameters.Data == NULL)
2896 			return (KMF_ERR_MEMORY);
2897 
2898 		(void) memcpy(destid->parameters.Data, srcid->parameters.Data,
2899 		    destid->parameters.Length);
2900 	} else {
2901 		destid->parameters.Data = NULL;
2902 	}
2903 	return (ret);
2904 }
2905 
2906 static KMF_RETURN
2907 sign_cert(KMF_HANDLE_T handle,
2908 	const KMF_DATA *SubjectCert,
2909 	KMF_KEY_HANDLE	*Signkey,
2910 	KMF_OID		*signature_oid,
2911 	KMF_DATA	*SignedCert)
2912 {
2913 	KMF_X509_CERTIFICATE	*subj_cert = NULL;
2914 	KMF_DATA		data_to_sign = {0, NULL};
2915 	KMF_DATA		signed_data = {0, NULL};
2916 	KMF_RETURN		ret = KMF_OK;
2917 	KMF_ALGORITHM_INDEX	algid;
2918 	int i = 0;
2919 	KMF_ATTRIBUTE attrlist[8];
2920 
2921 	if (!SignedCert)
2922 		return (KMF_ERR_BAD_PARAMETER);
2923 
2924 	SignedCert->Length = 0;
2925 	SignedCert->Data = NULL;
2926 
2927 	if (!SubjectCert)
2928 		return (KMF_ERR_BAD_PARAMETER);
2929 
2930 	if (!SubjectCert->Data || !SubjectCert->Length)
2931 		return (KMF_ERR_BAD_PARAMETER);
2932 
2933 	/*
2934 	 * Shortcut - just extract the already encoded TBS cert data from
2935 	 * the original data buffer.  Since we haven't changed anything,
2936 	 * there is no need to re-encode it.
2937 	 */
2938 	ret = ExtractX509CertParts((KMF_DATA *)SubjectCert,
2939 	    &data_to_sign, NULL);
2940 	if (ret != KMF_OK) {
2941 		goto cleanup;
2942 	}
2943 
2944 	/* Estimate the signed data length generously */
2945 	signed_data.Length = data_to_sign.Length*2;
2946 	signed_data.Data = calloc(1, signed_data.Length);
2947 	if (!signed_data.Data) {
2948 		ret = KMF_ERR_MEMORY;
2949 		goto cleanup;
2950 	}
2951 
2952 	/*
2953 	 * If we got here OK, decode into a structure and then re-encode
2954 	 * the complete certificate.
2955 	 */
2956 	ret = DerDecodeSignedCertificate(SubjectCert, &subj_cert);
2957 	if (ret != KMF_OK) {
2958 		goto cleanup;
2959 	}
2960 
2961 	/* We are re-signing this cert, so clear out old signature data */
2962 	if (subj_cert->signature.algorithmIdentifier.algorithm.Length == 0) {
2963 		kmf_free_algoid(&subj_cert->signature.algorithmIdentifier);
2964 		ret = set_algoid(&subj_cert->signature.algorithmIdentifier,
2965 		    signature_oid);
2966 		if (ret != KMF_OK)
2967 			goto cleanup;
2968 		ret = set_algoid(&subj_cert->certificate.signature,
2969 		    signature_oid);
2970 
2971 	}
2972 
2973 	if (ret)
2974 		goto cleanup;
2975 
2976 	kmf_set_attr_at_index(attrlist, i, KMF_KEYSTORE_TYPE_ATTR,
2977 	    &Signkey->kstype, sizeof (KMF_KEYSTORE_TYPE));
2978 	i++;
2979 	kmf_set_attr_at_index(attrlist, i, KMF_KEY_HANDLE_ATTR,
2980 	    Signkey, sizeof (KMF_KEY_HANDLE));
2981 	i++;
2982 	kmf_set_attr_at_index(attrlist, i, KMF_DATA_ATTR,
2983 	    &data_to_sign, sizeof (KMF_DATA));
2984 	i++;
2985 	kmf_set_attr_at_index(attrlist, i, KMF_OUT_DATA_ATTR,
2986 	    &signed_data, sizeof (KMF_DATA));
2987 	i++;
2988 	kmf_set_attr_at_index(attrlist, i, KMF_OID_ATTR,
2989 	    signature_oid, sizeof (KMF_OID));
2990 	i++;
2991 
2992 	/* Sign the data */
2993 	ret = kmf_sign_data(handle, i, attrlist);
2994 
2995 	if (ret != KMF_OK)
2996 		goto cleanup;
2997 
2998 	algid = x509_algoid_to_algid(signature_oid);
2999 
3000 	/*
3001 	 * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded
3002 	 * signature. So we must encode the signature correctly.
3003 	 */
3004 	if (algid == KMF_ALGID_SHA1WithDSA) {
3005 
3006 		KMF_DATA signature;
3007 
3008 		ret = DerEncodeDSASignature(&signed_data, &signature);
3009 		kmf_free_data(&signed_data);
3010 
3011 		if (ret != KMF_OK)
3012 			goto cleanup;
3013 
3014 		subj_cert->signature.encrypted = signature;
3015 	} else {
3016 		subj_cert->signature.encrypted = signed_data;
3017 	}
3018 
3019 	/* Now, re-encode the cert with the new signature */
3020 	ret = DerEncodeSignedCertificate(subj_cert, SignedCert);
3021 
3022 cleanup:
3023 	/* Cleanup & return */
3024 	if (ret != KMF_OK)
3025 		kmf_free_data(SignedCert);
3026 
3027 	kmf_free_data(&data_to_sign);
3028 
3029 	if (subj_cert != NULL) {
3030 		kmf_free_signed_cert(subj_cert);
3031 		free(subj_cert);
3032 	}
3033 
3034 	return (ret);
3035 }
3036 
3037 static KMF_RETURN
3038 verify_cert_with_key(KMF_HANDLE_T handle,
3039 	KMF_DATA *derkey,
3040 	const KMF_DATA *CertToBeVerified)
3041 {
3042 	KMF_RETURN ret = KMF_OK;
3043 	KMF_X509_CERTIFICATE *signed_cert = NULL;
3044 	KMF_X509_SPKI	spki;
3045 	KMF_DATA	data_to_verify = {0, NULL};
3046 	KMF_DATA	signed_data = {0, NULL};
3047 	KMF_DATA	signature = { 0, NULL };
3048 	KMF_ALGORITHM_INDEX	algid;
3049 
3050 	/* check the caller and do other setup for this SPI call */
3051 	if (handle == NULL || CertToBeVerified == NULL ||
3052 	    derkey == NULL || derkey->Data == NULL)
3053 		return (KMF_ERR_BAD_PARAMETER);
3054 
3055 	(void) memset(&spki, 0, sizeof (KMF_X509_SPKI));
3056 
3057 	ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerified,
3058 	    &data_to_verify, &signed_data);
3059 
3060 	if (ret != KMF_OK)
3061 		goto cleanup;
3062 
3063 	ret = DerDecodeSPKI(derkey, &spki);
3064 	if (ret != KMF_OK)
3065 		goto cleanup;
3066 
3067 	/* Decode the signer cert so we can get the Algorithm data */
3068 	ret = DerDecodeSignedCertificate(CertToBeVerified, &signed_cert);
3069 	if (ret != KMF_OK)
3070 		return (ret);
3071 
3072 	algid = x509_algoid_to_algid(CERT_SIG_OID(signed_cert));
3073 
3074 	if (algid == KMF_ALGID_NONE)
3075 		return (KMF_ERR_BAD_ALGORITHM);
3076 
3077 	if (algid == KMF_ALGID_SHA1WithDSA) {
3078 		ret = DerDecodeDSASignature(&signed_data, &signature);
3079 		if (ret != KMF_OK)
3080 			goto cleanup;
3081 	} else {
3082 		signature.Data = signed_data.Data;
3083 		signature.Length = signed_data.Length;
3084 	}
3085 
3086 	ret = PKCS_VerifyData(handle, algid, &spki,
3087 	    &data_to_verify, &signature);
3088 
3089 cleanup:
3090 	if (data_to_verify.Data != NULL)
3091 		free(data_to_verify.Data);
3092 
3093 	if (signed_data.Data != NULL)
3094 		free(signed_data.Data);
3095 
3096 	if (signed_cert) {
3097 		kmf_free_signed_cert(signed_cert);
3098 		free(signed_cert);
3099 	}
3100 	if (algid == KMF_ALGID_SHA1WithDSA) {
3101 		free(signature.Data);
3102 	}
3103 
3104 	kmf_free_algoid(&spki.algorithm);
3105 	kmf_free_data(&spki.subjectPublicKey);
3106 
3107 	return (ret);
3108 }
3109 
3110 /*
3111  * Use a signer cert to verify another certificate's signature.
3112  * This code forces the use of the OPENSSL mechanism
3113  * for the verify operation to avoid a circular dependency
3114  * with libelfsign when it attempts to verify the PKCS#11 libraries.
3115  */
3116 static KMF_RETURN
3117 verify_cert_with_cert(KMF_HANDLE_T handle,
3118 	const KMF_DATA *CertToBeVerifiedData,
3119 	const KMF_DATA *SignerCertData)
3120 {
3121 	KMF_RETURN ret = KMF_OK;
3122 	KMF_X509_CERTIFICATE *SignerCert = NULL;
3123 	KMF_X509_CERTIFICATE *ToBeVerifiedCert = NULL;
3124 	KMF_DATA	data_to_verify = {0, NULL};
3125 	KMF_DATA	signed_data = {0, NULL};
3126 	KMF_DATA	signature;
3127 	KMF_ALGORITHM_INDEX	algid;
3128 	KMF_POLICY_RECORD	*policy;
3129 
3130 	if (handle == NULL ||
3131 	    !CertToBeVerifiedData ||
3132 	    !CertToBeVerifiedData->Data ||
3133 	    !CertToBeVerifiedData->Length)
3134 		return (KMF_ERR_BAD_PARAMETER);
3135 
3136 	if (!SignerCertData ||
3137 	    !SignerCertData->Data ||
3138 	    !SignerCertData->Length)
3139 		return (KMF_ERR_BAD_PARAMETER);
3140 
3141 	policy = handle->policy;
3142 
3143 	/* Make sure the signer has proper key usage bits */
3144 	ret = check_key_usage(handle, SignerCertData, KMF_KU_SIGN_CERT);
3145 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
3146 		ret = KMF_OK;
3147 	if (ret != KMF_OK)
3148 		return (ret);
3149 
3150 	/* Decode the cert into parts for verification */
3151 	ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerifiedData,
3152 	    &data_to_verify, &signed_data);
3153 	if (ret != KMF_OK)
3154 		goto cleanup;
3155 
3156 	/* Decode the to-be-verified cert so we know what algorithm to use */
3157 	ret = DerDecodeSignedCertificate(CertToBeVerifiedData,
3158 	    &ToBeVerifiedCert);
3159 
3160 	if (ret != KMF_OK)
3161 		goto cleanup;
3162 
3163 	algid = x509_algoid_to_algid(CERT_SIG_OID(ToBeVerifiedCert));
3164 
3165 	if (algid == KMF_ALGID_SHA1WithDSA) {
3166 		ret = DerDecodeDSASignature(&signed_data, &signature);
3167 		if (ret != KMF_OK)
3168 			goto cleanup;
3169 	} else {
3170 		signature.Data = signed_data.Data;
3171 		signature.Length = signed_data.Length;
3172 	}
3173 
3174 	/*
3175 	 * To avoid recursion with kcfd consumer and libpkcs11,
3176 	 * do the certificate verification using the OpenSSL
3177 	 * plugin algorithms instead of the crypto framework.
3178 	 */
3179 	ret = plugin_verify_data_with_cert(handle, KMF_KEYSTORE_OPENSSL,
3180 	    algid, &data_to_verify, &signature,	SignerCertData);
3181 
3182 cleanup:
3183 	kmf_free_data(&data_to_verify);
3184 	kmf_free_data(&signed_data);
3185 
3186 	if (SignerCert) {
3187 		kmf_free_signed_cert(SignerCert);
3188 		free(SignerCert);
3189 	}
3190 
3191 	if (ToBeVerifiedCert) {
3192 		kmf_free_signed_cert(ToBeVerifiedCert);
3193 		free(ToBeVerifiedCert);
3194 	}
3195 
3196 	if (algid == KMF_ALGID_SHA1WithDSA) {
3197 		free(signature.Data);
3198 	}
3199 
3200 	return (ret);
3201 }
3202 
3203 /*
3204  * Phase 1 APIs still needed to maintain compat with elfsign.
3205  */
3206 KMF_RETURN
3207 KMF_VerifyDataWithCert(KMF_HANDLE_T handle,
3208 	KMF_KEYSTORE_TYPE kstype,
3209 	KMF_ALGORITHM_INDEX algid,
3210 	KMF_DATA *indata,
3211 	KMF_DATA *insig,
3212 	const KMF_DATA *SignerCert)
3213 {
3214 	KMF_ATTRIBUTE attrlist[8];
3215 	int numattr = 0;
3216 
3217 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3218 	    &kstype,  sizeof (kstype));
3219 	numattr++;
3220 
3221 	kmf_set_attr_at_index(attrlist, numattr, KMF_DATA_ATTR,
3222 	    indata, sizeof (KMF_DATA));
3223 	numattr++;
3224 
3225 	kmf_set_attr_at_index(attrlist, numattr, KMF_IN_SIGN_ATTR,
3226 	    insig, sizeof (KMF_DATA));
3227 	numattr++;
3228 
3229 	kmf_set_attr_at_index(attrlist, numattr, KMF_SIGNER_CERT_DATA_ATTR,
3230 	    (KMF_DATA *)SignerCert, sizeof (KMF_DATA));
3231 	numattr++;
3232 
3233 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
3234 	    &algid, sizeof (algid));
3235 	numattr++;
3236 
3237 	return (kmf_verify_data(handle, numattr, attrlist));
3238 }
3239 
3240 KMF_RETURN
3241 KMF_VerifyCertWithCert(KMF_HANDLE_T handle,
3242 	const KMF_DATA *CertToBeVerified,
3243 	const KMF_DATA *SignerCert)
3244 {
3245 	if (CertToBeVerified == NULL || SignerCert == NULL)
3246 		return (KMF_ERR_BAD_PARAMETER);
3247 
3248 	return (verify_cert_with_cert(handle, CertToBeVerified,
3249 	    SignerCert));
3250 }
3251 
3252 KMF_RETURN
3253 KMF_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *target,
3254 		KMF_X509_DER_CERT *kmf_cert,
3255 		uint32_t *num_certs)
3256 {
3257 	KMF_ATTRIBUTE attrlist[32];
3258 	int i = 0;
3259 
3260 	if (target == NULL || num_certs == NULL)
3261 		return (KMF_ERR_BAD_PARAMETER); /* ILLEGAL ARGS ERROR */
3262 
3263 	if ((target->find_cert_validity < KMF_ALL_CERTS) ||
3264 	    (target->find_cert_validity > KMF_EXPIRED_CERTS))
3265 		return (KMF_ERR_BAD_PARAMETER);
3266 
3267 	kmf_set_attr_at_index(attrlist, i,
3268 	    KMF_KEYSTORE_TYPE_ATTR, &target->kstype, sizeof (target->kstype));
3269 	i++;
3270 
3271 	if (kmf_cert != NULL) {
3272 		kmf_set_attr_at_index(attrlist, i,
3273 		    KMF_X509_DER_CERT_ATTR, kmf_cert,
3274 		    sizeof (KMF_X509_DER_CERT));
3275 		i++;
3276 	}
3277 
3278 	kmf_set_attr_at_index(attrlist, i,
3279 	    KMF_COUNT_ATTR, num_certs, sizeof (uint32_t));
3280 	i++;
3281 
3282 	/* Set the optional searching attributes for all 3 plugins. */
3283 	if (target->issuer != NULL) {
3284 		kmf_set_attr_at_index(attrlist, i, KMF_ISSUER_NAME_ATTR,
3285 		    target->issuer, strlen(target->issuer));
3286 		i++;
3287 	}
3288 	if (target->subject != NULL) {
3289 		kmf_set_attr_at_index(attrlist, i, KMF_SUBJECT_NAME_ATTR,
3290 		    target->subject, strlen(target->subject));
3291 		i++;
3292 	}
3293 	if (target->serial != NULL) {
3294 		kmf_set_attr_at_index(attrlist, i, KMF_BIGINT_ATTR,
3295 		    target->serial, sizeof (KMF_BIGINT));
3296 		i++;
3297 	}
3298 
3299 	kmf_set_attr_at_index(attrlist, i, KMF_CERT_VALIDITY_ATTR,
3300 	    &target->find_cert_validity, sizeof (KMF_CERT_VALIDITY));
3301 	i++;
3302 
3303 	if (target->kstype == KMF_KEYSTORE_NSS) {
3304 		if (target->certLabel != NULL) {
3305 			kmf_set_attr_at_index(attrlist, i,
3306 			    KMF_CERT_LABEL_ATTR,
3307 			    target->certLabel, strlen(target->certLabel));
3308 			i++;
3309 		}
3310 
3311 		if (target->nssparms.slotlabel != NULL) {
3312 			kmf_set_attr_at_index(attrlist, i,
3313 			    KMF_TOKEN_LABEL_ATTR,
3314 			    target->nssparms.slotlabel,
3315 			    strlen(target->nssparms.slotlabel));
3316 			i++;
3317 		}
3318 
3319 	} else if (target->kstype == KMF_KEYSTORE_OPENSSL) {
3320 		if (target->sslparms.certfile != NULL) {
3321 			kmf_set_attr_at_index(attrlist, i,
3322 			    KMF_CERT_FILENAME_ATTR,
3323 			    target->sslparms.certfile,
3324 			    strlen(target->sslparms.certfile));
3325 			i++;
3326 		}
3327 
3328 		if (target->sslparms.dirpath != NULL) {
3329 			kmf_set_attr_at_index(attrlist, i,
3330 			    KMF_DIRPATH_ATTR,
3331 			    target->sslparms.dirpath,
3332 			    strlen(target->sslparms.dirpath));
3333 			i++;
3334 		}
3335 
3336 	} else if (target->kstype == KMF_KEYSTORE_PK11TOKEN) {
3337 		if (target->certLabel != NULL) {
3338 			kmf_set_attr_at_index(attrlist, i,
3339 			    KMF_CERT_LABEL_ATTR,
3340 			    target->certLabel, strlen(target->certLabel));
3341 			i++;
3342 		}
3343 
3344 		kmf_set_attr_at_index(attrlist, i, KMF_PRIVATE_BOOL_ATTR,
3345 		    &target->pkcs11parms.private,
3346 		    sizeof (target->pkcs11parms.private));
3347 		i++;
3348 	}
3349 
3350 	return (kmf_find_cert(handle, i, attrlist));
3351 }
3352