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