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