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