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