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