1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <link.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/socket.h>
36 #include <ber_der.h>
37 #include <kmfapiP.h>
38 #include <pem_encode.h>
39 #include <libgen.h>
40 #include <cryptoutil.h>
41 
42 #define	CERTFILE_TEMPNAME	"/tmp/user.certXXXXXX"
43 #define	CRLFILE_TEMPNAME	"/tmp/crlXXXXXX"
44 #define	X509_FORMAT_VERSION 2
45 
46 static KMF_RETURN
47 sign_cert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *, KMF_DATA *);
48 
49 static KMF_RETURN
50 verify_cert_with_key(KMF_HANDLE_T, KMF_DATA *, const KMF_DATA *);
51 
52 static KMF_RETURN
53 verify_cert_with_cert(KMF_HANDLE_T, const KMF_DATA *, const KMF_DATA *);
54 
55 
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 check_crl_validity(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype,
1354 	char *crlfilename, KMF_DATA *issuer_cert)
1355 {
1356 	KMF_RETURN ret = KMF_OK;
1357 	KMF_POLICY_RECORD *policy;
1358 
1359 	if (handle == NULL)
1360 		return (KMF_ERR_BAD_PARAMETER);
1361 
1362 	policy = handle->policy;
1363 
1364 	/*
1365 	 * NSS CRL is not file based, and its signature
1366 	 * has been verified during CRL import.
1367 	 * We only check CRL validity for file-based CRLs,
1368 	 * NSS handles these checks internally.
1369 	 */
1370 	if (kstype == KMF_KEYSTORE_NSS)
1371 		return (KMF_OK);
1372 
1373 	/*
1374 	 * Check the CRL signature if needed.
1375 	 */
1376 	if (!policy->validation_info.crl_info.ignore_crl_sign) {
1377 		ret = kmf_verify_crl_file(handle, crlfilename,
1378 		    issuer_cert);
1379 		if (ret != KMF_OK)
1380 			return (ret);
1381 	}
1382 	/*
1383 	 * Check the CRL validity if needed.
1384 	 */
1385 	if (!policy->validation_info.crl_info.ignore_crl_date) {
1386 		ret = kmf_check_crl_date(handle, crlfilename);
1387 		if (ret != KMF_OK)
1388 			return (ret);
1389 	}
1390 
1391 	return (ret);
1392 }
1393 
1394 static KMF_RETURN
1395 cert_crl_check(KMF_HANDLE_T handle,  KMF_KEYSTORE_TYPE *kstype,
1396 	KMF_DATA *user_cert, KMF_DATA *issuer_cert)
1397 {
1398 	KMF_POLICY_RECORD *policy;
1399 	KMF_RETURN ret = KMF_OK;
1400 	KMF_ATTRIBUTE attrlist[16];
1401 	int numattr = 0;
1402 	int fd;
1403 	boolean_t crlchk;
1404 	char user_certfile[MAXPATHLEN];
1405 	char crlfile_tmp[MAXPATHLEN];
1406 	char *basefilename = NULL;
1407 	char *dir = NULL;
1408 	char *crlfilename = NULL;
1409 	char *proxy = NULL;
1410 	char *uri = NULL;
1411 	KMF_ENCODE_FORMAT format;
1412 
1413 	if (handle == NULL || kstype == NULL || user_cert == NULL ||
1414 	    issuer_cert == NULL)
1415 		return (KMF_ERR_BAD_PARAMETER);
1416 
1417 	if (!is_valid_keystore_type(*kstype))
1418 		return (KMF_ERR_BAD_PARAMETER);
1419 
1420 	policy = handle->policy;
1421 
1422 	/*
1423 	 * If the get-crl-uri policy is TRUE, then download the CRL
1424 	 * file first.   The newly downloaded file will be stored in the
1425 	 * NSS internal database for NSS keystore, and stored in a file for
1426 	 * the File-based CRL plugins (OpenSSL and PKCS11).
1427 	 *
1428 	 * For file-based plugins, if the get-crl-uri policy is FALSE,
1429 	 * then the caller should provide a CRL file in the policy.
1430 	 * Also, after this step is done, the "crlfilename" variable should
1431 	 * contain the proper CRL file to be used for the rest of CRL
1432 	 * validation process.
1433 	 */
1434 	basefilename = policy->validation_info.crl_info.basefilename;
1435 	dir = policy->validation_info.crl_info.directory;
1436 	if (policy->validation_info.crl_info.get_crl_uri) {
1437 		/*
1438 		 * Check to see if we already have this CRL.
1439 		 */
1440 		if (basefilename == NULL)
1441 			basefilename = basename(uri);
1442 
1443 		crlfilename = get_fullpath(dir == NULL ? "./" : dir,
1444 		    basefilename);
1445 		if (crlfilename == NULL) {
1446 			ret = KMF_ERR_BAD_CRLFILE;
1447 			goto cleanup;
1448 		}
1449 
1450 		/*
1451 		 * If this file already exists and is valid, we don't need to
1452 		 * download a new one.
1453 		 */
1454 		if ((fd = open(crlfilename, O_RDONLY)) != -1) {
1455 			(void) close(fd);
1456 			if ((ret = check_crl_validity(handle, *kstype,
1457 			    crlfilename, issuer_cert)) == KMF_OK) {
1458 				goto checkcrl;
1459 			}
1460 		}
1461 
1462 		/*
1463 		 * Create a temporary file to hold the new CRL file initially.
1464 		 */
1465 		(void) strlcpy(crlfile_tmp, CRLFILE_TEMPNAME,
1466 		    sizeof (crlfile_tmp));
1467 		if (mkstemp(crlfile_tmp) == -1) {
1468 			ret = KMF_ERR_INTERNAL;
1469 			goto cleanup;
1470 		}
1471 
1472 		/*
1473 		 * Get the URI entry from the certificate's CRL distribution
1474 		 * points extension and download the CRL file.
1475 		 */
1476 		proxy = policy->validation_info.crl_info.proxy;
1477 		ret = cert_get_crl(handle, user_cert, proxy, crlfile_tmp,
1478 		    &uri, &format);
1479 		if (ret != KMF_OK) {
1480 			(void) unlink(crlfile_tmp);
1481 			goto cleanup;
1482 		}
1483 		/*
1484 		 * If we just downloaded one, make sure it is OK.
1485 		 */
1486 		if ((ret = check_crl_validity(handle, *kstype, crlfile_tmp,
1487 		    issuer_cert)) != KMF_OK)
1488 			return (ret);
1489 
1490 		/* Cache the CRL file. */
1491 		if (*kstype == KMF_KEYSTORE_NSS) {
1492 			/*
1493 			 * For NSS keystore, import this CRL file into th
1494 			 * internal database.
1495 			 */
1496 			numattr = 0;
1497 			kmf_set_attr_at_index(attrlist, numattr,
1498 			    KMF_KEYSTORE_TYPE_ATTR, kstype, sizeof (kstype));
1499 			numattr++;
1500 
1501 			kmf_set_attr_at_index(attrlist, numattr,
1502 			    KMF_CRL_FILENAME_ATTR, crlfile_tmp,
1503 			    strlen(crlfile_tmp));
1504 			numattr++;
1505 
1506 			crlchk = B_FALSE;
1507 			kmf_set_attr_at_index(attrlist, numattr,
1508 			    KMF_CRL_CHECK_ATTR,	&crlchk, sizeof (boolean_t));
1509 			numattr++;
1510 
1511 			ret = kmf_import_crl(handle, numattr, attrlist);
1512 			(void) unlink(crlfile_tmp);
1513 			if (ret != KMF_OK)
1514 				goto cleanup;
1515 		} else {
1516 			if (rename(crlfile_tmp, crlfilename) == -1) {
1517 				(void) unlink(crlfile_tmp);
1518 				ret = KMF_ERR_WRITE_FILE;
1519 				goto cleanup;
1520 			}
1521 		}
1522 	} else {
1523 		/*
1524 		 * If the get_crl_uri policy is FALSE, for File-based CRL
1525 		 * plugins, get the input CRL file from the policy.
1526 		 */
1527 		if (*kstype != KMF_KEYSTORE_NSS) {
1528 			if (basefilename == NULL) {
1529 				ret = KMF_ERR_BAD_PARAMETER;
1530 				goto cleanup;
1531 			}
1532 
1533 			crlfilename = get_fullpath(dir == NULL ? "./" : dir,
1534 			    basefilename);
1535 			if (crlfilename == NULL) {
1536 				ret = KMF_ERR_BAD_CRLFILE;
1537 				goto cleanup;
1538 			}
1539 			/*
1540 			 * Make sure this CRL is still valid.
1541 			 */
1542 			if ((ret = check_crl_validity(handle, *kstype,
1543 			    crlfilename, issuer_cert)) != KMF_OK)
1544 				return (ret);
1545 			}
1546 	}
1547 
1548 checkcrl:
1549 	/*
1550 	 * Check the CRL revocation for the certificate.
1551 	 */
1552 	numattr = 0;
1553 
1554 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1555 	    kstype, sizeof (kstype));
1556 	numattr++;
1557 
1558 	switch (*kstype) {
1559 	case KMF_KEYSTORE_NSS:
1560 		kmf_set_attr_at_index(attrlist, numattr,
1561 		    KMF_CERT_DATA_ATTR, user_cert, sizeof (KMF_DATA));
1562 		numattr++;
1563 		break;
1564 	case KMF_KEYSTORE_PK11TOKEN:
1565 	case KMF_KEYSTORE_OPENSSL:
1566 		/*
1567 		 * Create temporary file to hold the user certificate.
1568 		 */
1569 		(void) strlcpy(user_certfile, CERTFILE_TEMPNAME,
1570 		    sizeof (user_certfile));
1571 		if (mkstemp(user_certfile) == -1) {
1572 			ret = KMF_ERR_INTERNAL;
1573 			goto cleanup;
1574 		}
1575 
1576 		ret = kmf_create_cert_file(user_cert, KMF_FORMAT_ASN1,
1577 		    user_certfile);
1578 		if (ret != KMF_OK)  {
1579 			goto cleanup;
1580 		}
1581 
1582 		kmf_set_attr_at_index(attrlist,  numattr,
1583 		    KMF_CERT_FILENAME_ATTR,
1584 		    user_certfile, strlen(user_certfile));
1585 		numattr++;
1586 
1587 		kmf_set_attr_at_index(attrlist,  numattr,
1588 		    KMF_CRL_FILENAME_ATTR,
1589 		    crlfilename, strlen(crlfilename));
1590 		numattr++;
1591 		break;
1592 	default:
1593 		ret = KMF_ERR_PLUGIN_NOTFOUND;
1594 		goto cleanup;
1595 	}
1596 
1597 	ret = kmf_find_cert_in_crl(handle, numattr, attrlist);
1598 	if (ret == KMF_ERR_NOT_REVOKED)  {
1599 		ret = KMF_OK;
1600 	}
1601 
1602 cleanup:
1603 	(void) unlink(user_certfile);
1604 
1605 	if (crlfilename != NULL)
1606 		free(crlfilename);
1607 
1608 	if (uri != NULL)
1609 		free(uri);
1610 
1611 	return (ret);
1612 }
1613 
1614 static KMF_RETURN
1615 cert_ocsp_check(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
1616 	KMF_DATA *user_cert, KMF_DATA *issuer_cert, KMF_DATA *response,
1617 	char *slotlabel, char *dirpath)
1618 {
1619 	KMF_RETURN ret = KMF_OK;
1620 	KMF_POLICY_RECORD *policy;
1621 	KMF_DATA *new_response = NULL;
1622 	boolean_t ignore_response_sign = B_FALSE;
1623 	uint32_t ltime = 0;
1624 	KMF_DATA *signer_cert = NULL;
1625 	KMF_BIGINT sernum = { NULL, 0 };
1626 	int response_status;
1627 	int reason;
1628 	int cert_status;
1629 	KMF_ATTRIBUTE attrlist[32];
1630 	int numattr;
1631 
1632 	if (handle == NULL || kstype == NULL || user_cert == NULL ||
1633 	    issuer_cert == NULL)
1634 		return (KMF_ERR_BAD_PARAMETER);
1635 
1636 	policy = handle->policy;
1637 
1638 	/*
1639 	 * Get the response lifetime from policy.
1640 	 */
1641 	if (policy->VAL_OCSP_BASIC.response_lifetime != NULL &&
1642 	    (str2lifetime(policy->VAL_OCSP_BASIC.response_lifetime, &ltime)
1643 	    < 0))
1644 		return (KMF_ERR_OCSP_RESPONSE_LIFETIME);
1645 
1646 	/*
1647 	 * Get the ignore_response_sign policy.
1648 	 *
1649 	 * If ignore_response_sign is FALSE, we need to verify the response.
1650 	 * Find the OCSP Responder certificate if it is specified in the OCSP
1651 	 * policy.
1652 	 */
1653 	ignore_response_sign = policy->VAL_OCSP_BASIC.ignore_response_sign;
1654 
1655 	if (ignore_response_sign == B_FALSE &&
1656 	    policy->VAL_OCSP.has_resp_cert == B_TRUE) {
1657 		char *signer_name;
1658 		KMF_X509_DER_CERT signer_retrcert;
1659 		uchar_t *bytes = NULL;
1660 		size_t bytelen;
1661 		uint32_t num = 0;
1662 		KMF_ATTRIBUTE fc_attrlist[16];
1663 		int fc_numattr = 0;
1664 		char *dir = "./";
1665 
1666 		if (policy->VAL_OCSP_RESP_CERT.name == NULL ||
1667 		    policy->VAL_OCSP_RESP_CERT.serial == NULL)
1668 			return (KMF_ERR_POLICY_NOT_FOUND);
1669 
1670 		signer_cert = malloc(sizeof (KMF_DATA));
1671 		if (signer_cert == NULL) {
1672 			ret = KMF_ERR_MEMORY;
1673 			goto out;
1674 		}
1675 		(void) memset(signer_cert, 0, sizeof (KMF_DATA));
1676 
1677 		signer_name = policy->VAL_OCSP_RESP_CERT.name;
1678 		ret = kmf_hexstr_to_bytes(
1679 		    (uchar_t *)policy->VAL_OCSP_RESP_CERT.serial,
1680 		    &bytes, &bytelen);
1681 		if (ret != KMF_OK || bytes == NULL) {
1682 			ret = KMF_ERR_OCSP_POLICY;
1683 			goto out;
1684 		}
1685 		sernum.val = bytes;
1686 		sernum.len = bytelen;
1687 
1688 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1689 		    KMF_KEYSTORE_TYPE_ATTR, kstype,
1690 		    sizeof (KMF_KEYSTORE_TYPE));
1691 		fc_numattr++;
1692 
1693 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1694 		    KMF_SUBJECT_NAME_ATTR, signer_name, strlen(signer_name));
1695 		fc_numattr++;
1696 
1697 		kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_BIGINT_ATTR,
1698 		    &sernum, sizeof (KMF_BIGINT));
1699 		fc_numattr++;
1700 
1701 		if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
1702 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1703 			    KMF_TOKEN_LABEL_ATTR, slotlabel,
1704 			    strlen(slotlabel));
1705 			fc_numattr++;
1706 		}
1707 
1708 		if (*kstype == KMF_KEYSTORE_OPENSSL) {
1709 			if (dirpath == NULL) {
1710 				kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1711 				    KMF_DIRPATH_ATTR, dir, strlen(dir));
1712 				fc_numattr++;
1713 			} else {
1714 				kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1715 				    KMF_DIRPATH_ATTR, dirpath,
1716 				    strlen(dirpath));
1717 				fc_numattr++;
1718 			}
1719 		}
1720 
1721 		num = 0;
1722 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1723 		    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
1724 		fc_numattr++;
1725 
1726 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
1727 		if (ret != KMF_OK || num != 1) {
1728 			if (num == 0)
1729 				ret = KMF_ERR_CERT_NOT_FOUND;
1730 			if (num > 0)
1731 				ret = KMF_ERR_CERT_MULTIPLE_FOUND;
1732 			goto out;
1733 		}
1734 
1735 		(void) memset(&signer_retrcert, 0, sizeof (KMF_X509_DER_CERT));
1736 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
1737 		    KMF_X509_DER_CERT_ATTR, &signer_retrcert,
1738 		    sizeof (KMF_X509_DER_CERT));
1739 		fc_numattr++;
1740 
1741 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
1742 		if (ret == KMF_OK) {
1743 			signer_cert->Length =
1744 			    signer_retrcert.certificate.Length;
1745 			signer_cert->Data = signer_retrcert.certificate.Data;
1746 		} else {
1747 			goto out;
1748 		}
1749 	}
1750 
1751 	/*
1752 	 * If the caller provides an OCSP response, we will use it directly.
1753 	 * Otherwise, we will try to fetch an OCSP response for the given
1754 	 * certificate now.
1755 	 */
1756 	if (response == NULL) {
1757 		new_response = (KMF_DATA *) malloc(sizeof (KMF_DATA));
1758 		if (new_response == NULL) {
1759 			ret = KMF_ERR_MEMORY;
1760 			goto out;
1761 		}
1762 		new_response->Data = NULL;
1763 		new_response->Length = 0;
1764 
1765 		ret = kmf_get_ocsp_for_cert(handle, user_cert, issuer_cert,
1766 		    new_response);
1767 		if (ret != KMF_OK)
1768 			goto out;
1769 	}
1770 
1771 	/*
1772 	 * Process the OCSP response and retrieve the certificate status.
1773 	 */
1774 	numattr = 0;
1775 	kmf_set_attr_at_index(attrlist, numattr, KMF_ISSUER_CERT_DATA_ATTR,
1776 	    issuer_cert, sizeof (KMF_DATA));
1777 	numattr++;
1778 
1779 	kmf_set_attr_at_index(attrlist, numattr, KMF_USER_CERT_DATA_ATTR,
1780 	    user_cert, sizeof (KMF_DATA));
1781 	numattr++;
1782 
1783 	if (signer_cert != NULL) {
1784 		kmf_set_attr_at_index(attrlist, numattr,
1785 		    KMF_SIGNER_CERT_DATA_ATTR, user_cert, sizeof (KMF_DATA));
1786 		numattr++;
1787 	}
1788 
1789 	kmf_set_attr_at_index(attrlist, numattr, KMF_OCSP_RESPONSE_DATA_ATTR,
1790 	    response == NULL ? new_response : response, sizeof (KMF_DATA));
1791 	numattr++;
1792 
1793 	kmf_set_attr_at_index(attrlist, numattr, KMF_RESPONSE_LIFETIME_ATTR,
1794 	    &ltime, sizeof (uint32_t));
1795 	numattr++;
1796 
1797 	kmf_set_attr_at_index(attrlist, numattr,
1798 	    KMF_IGNORE_RESPONSE_SIGN_ATTR, &ignore_response_sign,
1799 	    sizeof (boolean_t));
1800 	numattr++;
1801 
1802 	kmf_set_attr_at_index(attrlist, numattr,
1803 	    KMF_OCSP_RESPONSE_STATUS_ATTR, &response_status, sizeof (int));
1804 	numattr++;
1805 
1806 	kmf_set_attr_at_index(attrlist, numattr,
1807 	    KMF_OCSP_RESPONSE_REASON_ATTR, &reason, sizeof (int));
1808 	numattr++;
1809 
1810 	kmf_set_attr_at_index(attrlist, numattr,
1811 	    KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, &cert_status, sizeof (int));
1812 	numattr++;
1813 
1814 	ret = kmf_get_ocsp_status_for_cert(handle, numattr, attrlist);
1815 	if (ret == KMF_OK) {
1816 		switch (cert_status) {
1817 		case OCSP_GOOD:
1818 			break;
1819 		case OCSP_UNKNOWN:
1820 			ret = KMF_ERR_OCSP_UNKNOWN_CERT;
1821 			break;
1822 		case OCSP_REVOKED:
1823 			ret = KMF_ERR_OCSP_REVOKED;
1824 			break;
1825 		}
1826 	}
1827 
1828 out:
1829 	if (new_response) {
1830 		kmf_free_data(new_response);
1831 		free(new_response);
1832 	}
1833 
1834 	if (signer_cert) {
1835 		kmf_free_data(signer_cert);
1836 		free(signer_cert);
1837 	}
1838 
1839 	if (sernum.val != NULL)
1840 		free(sernum.val);
1841 
1842 	return (ret);
1843 }
1844 
1845 static KMF_RETURN
1846 cert_ku_check(KMF_HANDLE_T handle, KMF_DATA *cert)
1847 {
1848 	KMF_POLICY_RECORD *policy;
1849 	KMF_X509EXT_KEY_USAGE keyusage;
1850 	KMF_RETURN ret = KMF_OK;
1851 	KMF_X509EXT_BASICCONSTRAINTS constraint;
1852 	KMF_BOOL	critical = B_FALSE;
1853 
1854 	if (handle == NULL || cert == NULL)
1855 		return (KMF_ERR_BAD_PARAMETER);
1856 
1857 	policy = handle->policy;
1858 	(void) memset(&keyusage, 0, sizeof (keyusage));
1859 	ret = kmf_get_cert_ku(cert, &keyusage);
1860 
1861 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
1862 		if (policy->ku_bits) {
1863 			/* keyusage is not set in cert but is set in policy */
1864 			return (KMF_ERR_KEYUSAGE);
1865 		} else {
1866 			/* no keyusage set in both cert and policy */
1867 			return (KMF_OK);
1868 		}
1869 	}
1870 
1871 	if (ret != KMF_OK) {
1872 		/* real error */
1873 		return (ret);
1874 	}
1875 
1876 	/*
1877 	 * If KeyCertSign is set, then constraints.cA must be TRUE and
1878 	 * marked critical.
1879 	 */
1880 	if ((keyusage.KeyUsageBits & KMF_keyCertSign)) {
1881 		(void) memset(&constraint, 0, sizeof (constraint));
1882 		ret = kmf_get_cert_basic_constraint(cert,
1883 		    &critical, &constraint);
1884 
1885 		if (ret != KMF_OK) {
1886 			/* real error */
1887 			return (ret);
1888 		}
1889 		if (!constraint.cA || !critical)
1890 			return (KMF_ERR_KEYUSAGE);
1891 	}
1892 
1893 	/*
1894 	 * Rule: if the KU bit is set in policy, the corresponding KU bit
1895 	 * must be set in the certificate (but not vice versa).
1896 	 */
1897 	if ((policy->ku_bits & keyusage.KeyUsageBits) == policy->ku_bits) {
1898 		return (KMF_OK);
1899 	} else {
1900 		return (KMF_ERR_KEYUSAGE);
1901 	}
1902 
1903 }
1904 
1905 static KMF_RETURN
1906 cert_eku_check(KMF_HANDLE_T handle, KMF_DATA *cert)
1907 {
1908 	KMF_POLICY_RECORD *policy;
1909 	KMF_RETURN ret = KMF_OK;
1910 	KMF_X509EXT_EKU eku;
1911 	uint16_t cert_eku = 0, policy_eku = 0;
1912 	int i;
1913 
1914 	if (handle == NULL || cert == NULL)
1915 		return (KMF_ERR_BAD_PARAMETER);
1916 	policy = handle->policy;
1917 
1918 	/*
1919 	 * If the policy does not have any EKU, then there is
1920 	 * nothing further to check.
1921 	 */
1922 	if (policy->eku_set.eku_count == 0)
1923 		return (KMF_OK);
1924 
1925 	ret = kmf_get_cert_eku(cert, &eku);
1926 	if ((ret != KMF_ERR_EXTENSION_NOT_FOUND) && (ret != KMF_OK)) {
1927 		/* real error */
1928 		return (ret);
1929 	}
1930 
1931 	if (ret == KMF_ERR_EXTENSION_NOT_FOUND) {
1932 		cert_eku = 0;
1933 	} else {
1934 		/*
1935 		 * Build the EKU bitmap based on the certificate
1936 		 */
1937 		for (i = 0; i < eku.nEKUs; i++) {
1938 			if (IsEqualOid(&eku.keyPurposeIdList[i],
1939 			    (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
1940 				cert_eku |= KMF_EKU_SERVERAUTH;
1941 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1942 			    (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
1943 				cert_eku |= KMF_EKU_CLIENTAUTH;
1944 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1945 			    (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
1946 				cert_eku |= KMF_EKU_CODESIGNING;
1947 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1948 			    (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) {
1949 				cert_eku |= KMF_EKU_EMAIL;
1950 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1951 			    (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
1952 				cert_eku |= KMF_EKU_TIMESTAMP;
1953 			} else if (IsEqualOid(&eku.keyPurposeIdList[i],
1954 			    (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
1955 				cert_eku |= KMF_EKU_OCSPSIGNING;
1956 			} else if (!policy->ignore_unknown_ekus) {
1957 				return (KMF_ERR_KEYUSAGE);
1958 			}
1959 		} /* for */
1960 	}
1961 
1962 
1963 	/*
1964 	 * Build the EKU bitmap based on the policy
1965 	 */
1966 	for (i = 0; i < policy->eku_set.eku_count; i++) {
1967 		if (IsEqualOid(&policy->eku_set.ekulist[i],
1968 		    (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) {
1969 			policy_eku |= KMF_EKU_SERVERAUTH;
1970 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
1971 		    (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) {
1972 			policy_eku |= KMF_EKU_CLIENTAUTH;
1973 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
1974 		    (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) {
1975 			policy_eku |= KMF_EKU_CODESIGNING;
1976 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
1977 		    (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) {
1978 			policy_eku |= KMF_EKU_EMAIL;
1979 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
1980 		    (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) {
1981 			policy_eku |= KMF_EKU_TIMESTAMP;
1982 		} else if (IsEqualOid(&policy->eku_set.ekulist[i],
1983 		    (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) {
1984 			policy_eku |= KMF_EKU_OCSPSIGNING;
1985 		} else if (!policy->ignore_unknown_ekus) {
1986 			return (KMF_ERR_KEYUSAGE);
1987 		}
1988 	} /* for */
1989 
1990 	/*
1991 	 * Rule: if the EKU OID is set in policy, the corresponding EKU OID
1992 	 * must be set in the certificate (but not vice versa).
1993 	 */
1994 	if ((policy_eku & cert_eku) == policy_eku) {
1995 		return (KMF_OK);
1996 	} else {
1997 		return (KMF_ERR_KEYUSAGE);
1998 	}
1999 }
2000 
2001 static KMF_RETURN
2002 find_issuer_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
2003     char *user_issuer, KMF_DATA *issuer_cert,
2004     char *slotlabel, char *dirpath)
2005 {
2006 	KMF_RETURN ret = KMF_OK;
2007 	KMF_X509_DER_CERT *certlist = NULL;
2008 	uint32_t i, num = 0;
2009 	time_t t_notbefore;
2010 	time_t t_notafter;
2011 	time_t latest;
2012 	KMF_DATA tmp_cert = {0, NULL};
2013 	KMF_ATTRIBUTE fc_attrlist[16];
2014 	int fc_numattr = 0;
2015 	char *dir = "./";
2016 
2017 	if (handle == NULL || kstype == NULL || user_issuer == NULL ||
2018 	    issuer_cert == NULL)
2019 		return (KMF_ERR_BAD_PARAMETER);
2020 
2021 	if (!is_valid_keystore_type(*kstype))
2022 		return (KMF_ERR_BAD_PARAMETER);
2023 
2024 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_KEYSTORE_TYPE_ATTR,
2025 	    kstype, sizeof (KMF_KEYSTORE_TYPE));
2026 	fc_numattr++;
2027 
2028 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_SUBJECT_NAME_ATTR,
2029 	    user_issuer, strlen(user_issuer));
2030 	fc_numattr++;
2031 
2032 	if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
2033 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2034 		    KMF_TOKEN_LABEL_ATTR, slotlabel, strlen(slotlabel));
2035 		fc_numattr++;
2036 	}
2037 
2038 	if (*kstype == KMF_KEYSTORE_OPENSSL) {
2039 		if (dirpath == NULL) {
2040 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2041 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
2042 			fc_numattr++;
2043 		} else {
2044 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2045 			    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2046 			fc_numattr++;
2047 		}
2048 	}
2049 
2050 	num = 0;
2051 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2052 	    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
2053 	fc_numattr++;
2054 
2055 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2056 
2057 	if (ret == KMF_OK && num > 0) {
2058 		certlist = (KMF_X509_DER_CERT *)malloc(num *
2059 		    sizeof (KMF_X509_DER_CERT));
2060 
2061 		if (certlist == NULL) {
2062 			ret = KMF_ERR_MEMORY;
2063 			goto out;
2064 		}
2065 
2066 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2067 		    KMF_X509_DER_CERT_ATTR, certlist,
2068 		    sizeof (KMF_X509_DER_CERT));
2069 		fc_numattr++;
2070 
2071 		ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2072 		if (ret != KMF_OK) {
2073 			free(certlist);
2074 			certlist = NULL;
2075 			goto out;
2076 		}
2077 	} else {
2078 		goto out;
2079 	}
2080 
2081 	if (num == 1) {
2082 		/* only one issuer cert is found */
2083 		tmp_cert.Length = certlist[0].certificate.Length;
2084 		tmp_cert.Data = certlist[0].certificate.Data;
2085 	} else {
2086 		/*
2087 		 * More than one issuer certs are found. We will
2088 		 * pick the latest one.
2089 		 */
2090 		latest = 0;
2091 		for (i = 0; i < num; i++) {
2092 			ret = kmf_get_cert_validity(&certlist[i].certificate,
2093 			    &t_notbefore, &t_notafter);
2094 			if (ret != KMF_OK) {
2095 				ret = KMF_ERR_VALIDITY_PERIOD;
2096 				goto out;
2097 			}
2098 
2099 			if (t_notbefore > latest) {
2100 				tmp_cert.Length =
2101 				    certlist[i].certificate.Length;
2102 				tmp_cert.Data =
2103 				    certlist[i].certificate.Data;
2104 				latest = t_notbefore;
2105 			}
2106 
2107 		}
2108 	}
2109 
2110 	issuer_cert->Length = tmp_cert.Length;
2111 	issuer_cert->Data = malloc(tmp_cert.Length);
2112 	if (issuer_cert->Data == NULL) {
2113 		ret = KMF_ERR_MEMORY;
2114 		goto out;
2115 	}
2116 	(void) memcpy(issuer_cert->Data, tmp_cert.Data,
2117 	    tmp_cert.Length);
2118 
2119 out:
2120 	if (certlist != NULL) {
2121 		for (i = 0; i < num; i++)
2122 			kmf_free_kmf_cert(handle, &certlist[i]);
2123 		free(certlist);
2124 	}
2125 
2126 	return (ret);
2127 
2128 }
2129 
2130 static KMF_RETURN
2131 find_ta_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
2132 	KMF_DATA *ta_cert, KMF_X509_NAME *user_issuerDN,
2133 	char *slotlabel, char *dirpath)
2134 {
2135 	KMF_POLICY_RECORD *policy;
2136 	KMF_RETURN ret = KMF_OK;
2137 	uint32_t num = 0;
2138 	char *ta_name;
2139 	KMF_BIGINT serial = { NULL, 0 };
2140 	uchar_t *bytes = NULL;
2141 	size_t bytelen;
2142 	KMF_X509_DER_CERT ta_retrCert;
2143 	char *ta_subject = NULL;
2144 	KMF_X509_NAME ta_subjectDN;
2145 	KMF_ATTRIBUTE fc_attrlist[16];
2146 	int fc_numattr = 0;
2147 	char *dir = "./";
2148 
2149 	if (handle == NULL || kstype == NULL || ta_cert == NULL ||
2150 	    user_issuerDN == NULL)
2151 		return (KMF_ERR_BAD_PARAMETER);
2152 
2153 	if (!is_valid_keystore_type(*kstype))
2154 		return (KMF_ERR_BAD_PARAMETER);
2155 
2156 	/* Get the TA name and serial number from the policy */
2157 	policy = handle->policy;
2158 	ta_name = policy->ta_name;
2159 	ret = kmf_hexstr_to_bytes((uchar_t *)policy->ta_serial,
2160 	    &bytes, &bytelen);
2161 	if (ret != KMF_OK || bytes == NULL) {
2162 		ret = KMF_ERR_TA_POLICY;
2163 		goto out;
2164 	}
2165 	serial.val = bytes;
2166 	serial.len = bytelen;
2167 
2168 	/* set up fc_attrlist for kmf_find_cert */
2169 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_KEYSTORE_TYPE_ATTR,
2170 	    kstype, sizeof (KMF_KEYSTORE_TYPE));
2171 	fc_numattr++;
2172 
2173 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_SUBJECT_NAME_ATTR,
2174 	    ta_name, strlen(ta_name));
2175 	fc_numattr++;
2176 
2177 	kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_BIGINT_ATTR,
2178 	    &serial, sizeof (KMF_BIGINT));
2179 	fc_numattr++;
2180 
2181 	if (*kstype == KMF_KEYSTORE_NSS && slotlabel != NULL) {
2182 		kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2183 		    KMF_TOKEN_LABEL_ATTR, slotlabel, strlen(slotlabel));
2184 		fc_numattr++;
2185 	}
2186 
2187 	if (*kstype == KMF_KEYSTORE_OPENSSL) {
2188 		if (dirpath == NULL) {
2189 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2190 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
2191 			fc_numattr++;
2192 		} else {
2193 			kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2194 			    KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2195 			fc_numattr++;
2196 		}
2197 	}
2198 
2199 	num = 0;
2200 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2201 	    KMF_COUNT_ATTR, &num, sizeof (uint32_t));
2202 	fc_numattr++;
2203 
2204 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2205 	if (ret != KMF_OK || num != 1)  {
2206 		if (num == 0)
2207 			ret = KMF_ERR_CERT_NOT_FOUND;
2208 		if (num > 1)
2209 			ret = KMF_ERR_CERT_MULTIPLE_FOUND;
2210 		goto out;
2211 	}
2212 
2213 	kmf_set_attr_at_index(fc_attrlist, fc_numattr,
2214 	    KMF_X509_DER_CERT_ATTR, &ta_retrCert, sizeof (KMF_X509_DER_CERT));
2215 	fc_numattr++;
2216 
2217 	ret = kmf_find_cert(handle, fc_numattr, fc_attrlist);
2218 	if (ret == KMF_OK)  {
2219 		ta_cert->Length = ta_retrCert.certificate.Length;
2220 		ta_cert->Data = malloc(ta_retrCert.certificate.Length);
2221 		if (ta_cert->Data == NULL) {
2222 			ret = KMF_ERR_MEMORY;
2223 			goto out;
2224 		}
2225 		(void) memcpy(ta_cert->Data, ta_retrCert.certificate.Data,
2226 		    ta_retrCert.certificate.Length);
2227 	} else {
2228 		goto out;
2229 	}
2230 
2231 	/*
2232 	 * The found TA's name must be matching with issuer name in
2233 	 * subscriber's certificate.
2234 	 */
2235 	(void) memset(&ta_subjectDN, 0, sizeof (ta_subjectDN));
2236 
2237 	ret = kmf_get_cert_subject_str(handle, ta_cert, &ta_subject);
2238 	if (ret != KMF_OK)
2239 		goto out;
2240 
2241 	ret = kmf_dn_parser(ta_subject,  &ta_subjectDN);
2242 	if (ret != KMF_OK)
2243 		goto out;
2244 
2245 	if (kmf_compare_rdns(user_issuerDN, &ta_subjectDN) != 0)
2246 		ret = KMF_ERR_CERT_NOT_FOUND;
2247 
2248 	kmf_free_dn(&ta_subjectDN);
2249 
2250 	/* Make sure the TA cert has the correct extensions */
2251 	if (ret == KMF_OK)
2252 		ret = check_key_usage(handle, ta_cert, KMF_KU_SIGN_CERT);
2253 out:
2254 	if (ta_retrCert.certificate.Data)
2255 		kmf_free_kmf_cert(handle, &ta_retrCert);
2256 
2257 	if ((ret != KMF_OK) && (ta_cert->Data != NULL))
2258 		free(ta_cert->Data);
2259 
2260 	if (serial.val != NULL)
2261 		free(serial.val);
2262 
2263 	if (ta_subject)
2264 		free(ta_subject);
2265 
2266 	return (ret);
2267 }
2268 
2269 KMF_RETURN
2270 kmf_validate_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2271 {
2272 	KMF_RETURN ret = KMF_OK;
2273 	KMF_KEYSTORE_TYPE *kstype = NULL;
2274 	KMF_DATA *pcert = NULL;
2275 	int *result = NULL;
2276 	char *slotlabel = NULL;
2277 	char *dirpath = NULL;
2278 	KMF_DATA *ocsp_response = NULL;
2279 	KMF_DATA ta_cert = {0, NULL};
2280 	KMF_DATA issuer_cert = {0, NULL};
2281 	char *user_issuer = NULL, *user_subject = NULL;
2282 	KMF_X509_NAME user_issuerDN, user_subjectDN;
2283 	boolean_t	self_signed = B_FALSE;
2284 	KMF_POLICY_RECORD *policy;
2285 
2286 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
2287 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
2288 	    {KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)},
2289 	    {KMF_VALIDATE_RESULT_ATTR, FALSE, 1, sizeof (int)}
2290 	};
2291 	int num_req_attrs = sizeof (required_attrs) /
2292 	    sizeof (KMF_ATTRIBUTE_TESTER);
2293 
2294 	if (handle == NULL)
2295 		return (KMF_ERR_BAD_PARAMETER);
2296 
2297 	CLEAR_ERROR(handle, ret);
2298 
2299 	ret = test_attributes(num_req_attrs, required_attrs,
2300 	    0, NULL, numattr, attrlist);
2301 	if (ret != KMF_OK)
2302 		return (ret);
2303 
2304 	policy = handle->policy;
2305 
2306 	/* Get the attribute values */
2307 	kstype = kmf_get_attr_ptr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr);
2308 	pcert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2309 	result = kmf_get_attr_ptr(KMF_VALIDATE_RESULT_ATTR, attrlist, numattr);
2310 	if (kstype == NULL || pcert == NULL || result == NULL)
2311 		return (KMF_ERR_BAD_PARAMETER);
2312 
2313 	slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
2314 	dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2315 	ocsp_response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR, attrlist,
2316 	    numattr);
2317 
2318 	/* Initialize the returned result */
2319 	*result = KMF_CERT_VALIDATE_OK;
2320 
2321 	/*
2322 	 * Get the issuer information from the input certficate first.
2323 	 */
2324 	if ((ret = kmf_get_cert_issuer_str(handle, pcert,
2325 	    &user_issuer)) != KMF_OK) {
2326 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2327 		goto out;
2328 	}
2329 
2330 	if ((ret = kmf_dn_parser(user_issuer,  &user_issuerDN)) != KMF_OK) {
2331 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2332 		goto out;
2333 	}
2334 
2335 	/*
2336 	 * Check if the certificate is a self-signed cert.
2337 	 */
2338 	if ((ret = kmf_get_cert_subject_str(handle, pcert,
2339 	    &user_subject)) != KMF_OK) {
2340 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2341 		kmf_free_dn(&user_issuerDN);
2342 		goto out;
2343 	}
2344 
2345 	if ((ret = kmf_dn_parser(user_subject,  &user_subjectDN)) != KMF_OK) {
2346 		*result |= KMF_CERT_VALIDATE_ERR_USER;
2347 		kmf_free_dn(&user_issuerDN);
2348 		goto out;
2349 	}
2350 
2351 	if ((kmf_compare_rdns(&user_issuerDN, &user_subjectDN)) == 0) {
2352 		/*
2353 		 * this is a self-signed cert
2354 		 */
2355 		self_signed = B_TRUE;
2356 	}
2357 
2358 	kmf_free_dn(&user_subjectDN);
2359 
2360 	/*
2361 	 * Check KeyUsage extension of the subscriber's certificate
2362 	 */
2363 	ret = cert_ku_check(handle, pcert);
2364 	if (ret != KMF_OK)  {
2365 		*result |= KMF_CERT_VALIDATE_ERR_KEYUSAGE;
2366 		goto out;
2367 	}
2368 
2369 	/*
2370 	 * Validate Extended KeyUsage extension
2371 	 */
2372 	ret = cert_eku_check(handle, pcert);
2373 	if (ret != KMF_OK)  {
2374 		*result |= KMF_CERT_VALIDATE_ERR_EXT_KEYUSAGE;
2375 		goto out;
2376 	}
2377 
2378 	/*
2379 	 * Check the certificate's validity period
2380 	 *
2381 	 * This step is needed when "ignore_date" in policy is set
2382 	 * to false.
2383 	 */
2384 	if (!policy->ignore_date) {
2385 		/*
2386 		 * Validate expiration date
2387 		 */
2388 		ret = kmf_check_cert_date(handle, pcert);
2389 		if (ret != KMF_OK)  {
2390 			*result |= KMF_CERT_VALIDATE_ERR_TIME;
2391 			goto out;
2392 		}
2393 	}
2394 
2395 	/*
2396 	 * When "ignore_trust_anchor" in policy is set to FALSE,
2397 	 * we will try to find the TA cert based on the TA policy
2398 	 * attributes.
2399 	 *
2400 	 * TA's subject name (ta_name) and serial number (ta_serial)
2401 	 * are defined as optional attributes in policy dtd, but they
2402 	 * should exist in policy when "ignore_trust_anchor" is set
2403 	 * to FALSE. The policy verification code has enforced that.
2404 	 */
2405 	if (policy->ignore_trust_anchor) {
2406 		goto check_revocation;
2407 	}
2408 
2409 	/*
2410 	 * Verify the signature of subscriber's certificate using
2411 	 * TA certificate.
2412 	 */
2413 	if (self_signed) {
2414 		ret = verify_cert_with_cert(handle, pcert, pcert);
2415 	} else {
2416 		ret = find_ta_cert(handle, kstype, &ta_cert,
2417 		    &user_issuerDN, slotlabel, dirpath);
2418 		if (ret != KMF_OK)  {
2419 			*result |= KMF_CERT_VALIDATE_ERR_TA;
2420 			goto out;
2421 		}
2422 
2423 		ret = check_key_usage(handle, &ta_cert, KMF_KU_SIGN_CERT);
2424 		if (ret != KMF_OK)
2425 			goto out;
2426 
2427 		ret = verify_cert_with_cert(handle, pcert, &ta_cert);
2428 	}
2429 	if (ret != KMF_OK)  {
2430 		*result |= KMF_CERT_VALIDATE_ERR_SIGNATURE;
2431 		goto out;
2432 	}
2433 
2434 check_revocation:
2435 	/*
2436 	 * Check certificate revocation
2437 	 */
2438 	if (self_signed) {
2439 		/* skip revocation checking */
2440 		goto out;
2441 	}
2442 
2443 	/*
2444 	 * When CRL or OCSP revocation method is set in the policy,
2445 	 * we will try to find the issuer of the subscriber certificate
2446 	 * using the issuer name of the subscriber certificate. The
2447 	 * issuer certificate will be used to do the CRL checking
2448 	 * and OCSP checking.
2449 	 */
2450 	if (!(policy->revocation & KMF_REVOCATION_METHOD_CRL) &&
2451 	    !(policy->revocation & KMF_REVOCATION_METHOD_OCSP)) {
2452 		goto out;
2453 	}
2454 
2455 	ret = find_issuer_cert(handle, kstype, user_issuer, &issuer_cert,
2456 	    slotlabel, dirpath);
2457 	if (ret != KMF_OK)  {
2458 		*result |= KMF_CERT_VALIDATE_ERR_ISSUER;
2459 		goto out;
2460 	}
2461 
2462 	if (policy->revocation & KMF_REVOCATION_METHOD_CRL) {
2463 		ret = cert_crl_check(handle, kstype, pcert, &issuer_cert);
2464 		if (ret != KMF_OK)  {
2465 			*result |= KMF_CERT_VALIDATE_ERR_CRL;
2466 			goto out;
2467 		}
2468 	}
2469 
2470 	if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) {
2471 		ret = cert_ocsp_check(handle, kstype, pcert, &issuer_cert,
2472 		    ocsp_response, slotlabel, dirpath);
2473 		if (ret != KMF_OK)  {
2474 			*result |= KMF_CERT_VALIDATE_ERR_OCSP;
2475 			goto out;
2476 		}
2477 	}
2478 
2479 out:
2480 	if (user_issuer) {
2481 		kmf_free_dn(&user_issuerDN);
2482 		free(user_issuer);
2483 	}
2484 
2485 	if (user_subject)
2486 		free(user_subject);
2487 
2488 	if (ta_cert.Data)
2489 		free(ta_cert.Data);
2490 
2491 	if (issuer_cert.Data)
2492 		free(issuer_cert.Data);
2493 
2494 	return (ret);
2495 
2496 }
2497 
2498 KMF_RETURN
2499 kmf_create_cert_file(const KMF_DATA *certdata, KMF_ENCODE_FORMAT format,
2500 	char *certfile)
2501 {
2502 	KMF_RETURN rv = KMF_OK;
2503 	int fd = -1;
2504 	KMF_DATA pemdata = {NULL, 0};
2505 
2506 	if (certdata == NULL || certfile == NULL)
2507 		return (KMF_ERR_BAD_PARAMETER);
2508 
2509 	if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1)
2510 		return (KMF_ERR_BAD_PARAMETER);
2511 
2512 	if (format == KMF_FORMAT_PEM) {
2513 		int len;
2514 		rv = kmf_der_to_pem(KMF_CERT,
2515 		    certdata->Data, certdata->Length,
2516 		    &pemdata.Data, &len);
2517 		if (rv != KMF_OK)
2518 			goto cleanup;
2519 		pemdata.Length = (size_t)len;
2520 	}
2521 
2522 	if ((fd = open(certfile, O_CREAT | O_RDWR | O_TRUNC, 0644)) == -1) {
2523 		rv = KMF_ERR_OPEN_FILE;
2524 		goto cleanup;
2525 	}
2526 
2527 	if (format == KMF_FORMAT_PEM) {
2528 		if (write(fd, pemdata.Data, pemdata.Length) !=
2529 		    pemdata.Length) {
2530 			rv = KMF_ERR_WRITE_FILE;
2531 		}
2532 	} else {
2533 		if (write(fd, certdata->Data, certdata->Length) !=
2534 		    certdata->Length) {
2535 			rv = KMF_ERR_WRITE_FILE;
2536 		}
2537 	}
2538 
2539 cleanup:
2540 	if (fd != -1)
2541 		(void) close(fd);
2542 
2543 	kmf_free_data(&pemdata);
2544 
2545 	return (rv);
2546 }
2547 
2548 KMF_RETURN
2549 kmf_is_cert_file(KMF_HANDLE_T handle, char *filename,
2550 	KMF_ENCODE_FORMAT *pformat)
2551 {
2552 	KMF_PLUGIN *plugin;
2553 	KMF_RETURN (*IsCertFileFn)(void *, char *, KMF_ENCODE_FORMAT *);
2554 
2555 	KMF_RETURN ret;
2556 
2557 	CLEAR_ERROR(handle, ret);
2558 	if (ret != KMF_OK)
2559 		return (ret);
2560 
2561 	if (filename  == NULL || pformat == NULL) {
2562 		return (KMF_ERR_BAD_PARAMETER);
2563 	}
2564 
2565 	/*
2566 	 * This framework function is actually implemented in the openssl
2567 	 * plugin library, so we find the function address and call it.
2568 	 */
2569 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2570 	if (plugin == NULL || plugin->dldesc == NULL) {
2571 		return (KMF_ERR_PLUGIN_NOTFOUND);
2572 	}
2573 
2574 	IsCertFileFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2575 	    "OpenSSL_IsCertFile");
2576 	if (IsCertFileFn == NULL) {
2577 		return (KMF_ERR_FUNCTION_NOT_FOUND);
2578 	}
2579 
2580 	return (IsCertFileFn(handle, filename, pformat));
2581 }
2582 
2583 /*
2584  * This function checks the validity period of a der-encoded certificate.
2585  */
2586 KMF_RETURN
2587 kmf_check_cert_date(KMF_HANDLE_T handle, const KMF_DATA *cert)
2588 {
2589 	KMF_RETURN rv;
2590 	struct tm *gmt;
2591 	time_t t_now;
2592 	time_t t_notbefore;
2593 	time_t t_notafter;
2594 	KMF_POLICY_RECORD *policy;
2595 	uint32_t adj;
2596 
2597 	CLEAR_ERROR(handle, rv);
2598 	if (rv != KMF_OK)
2599 		return (rv);
2600 
2601 	if (cert == NULL || cert->Data == NULL || cert->Length == 0)
2602 		return (KMF_ERR_BAD_PARAMETER);
2603 
2604 	policy = handle->policy;
2605 	rv = kmf_get_cert_validity(cert, &t_notbefore, &t_notafter);
2606 	if (rv != KMF_OK)
2607 		return (rv);
2608 
2609 	/*
2610 	 * Get the current time. The time returned from time() is local which
2611 	 * cannot be used directly. It must be converted to UTC/GMT first.
2612 	 */
2613 	t_now = time(NULL);
2614 	gmt = gmtime(&t_now);
2615 	t_now = mktime(gmt);
2616 
2617 	/*
2618 	 * Adjust the validity time
2619 	 */
2620 	if (policy->validity_adjusttime != NULL) {
2621 		if (str2lifetime(policy->validity_adjusttime, &adj) < 0)
2622 			return (KMF_ERR_VALIDITY_PERIOD);
2623 	} else {
2624 		adj = 0;
2625 	}
2626 
2627 	t_notafter += adj;
2628 	t_notbefore -= adj;
2629 
2630 	if (t_now <= t_notafter && t_now >= t_notbefore) {
2631 		rv = KMF_OK;
2632 	} else {
2633 		rv = KMF_ERR_VALIDITY_PERIOD;
2634 	}
2635 
2636 	return (rv);
2637 }
2638 
2639 KMF_RETURN
2640 kmf_export_pk12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2641 {
2642 	KMF_PLUGIN *plugin;
2643 	KMF_RETURN ret = KMF_OK;
2644 	KMF_KEYSTORE_TYPE kstype;
2645 
2646 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
2647 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
2648 	    {KMF_OUTPUT_FILENAME_ATTR, TRUE, 1, 0},
2649 	};
2650 
2651 	int num_req_attrs = sizeof (required_attrs) /
2652 	    sizeof (KMF_ATTRIBUTE_TESTER);
2653 
2654 	if (handle == NULL)
2655 		return (KMF_ERR_BAD_PARAMETER);
2656 
2657 	CLEAR_ERROR(handle, ret);
2658 
2659 	ret = test_attributes(num_req_attrs, required_attrs, 0, NULL,
2660 	    numattr, attrlist);
2661 	if (ret != KMF_OK)
2662 		return (ret);
2663 
2664 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
2665 	    &kstype, NULL);
2666 	if (ret != KMF_OK)
2667 		return (ret);
2668 
2669 	plugin = FindPlugin(handle, kstype);
2670 	if (plugin == NULL || plugin->funclist->ExportPK12 == NULL)
2671 		return (KMF_ERR_PLUGIN_NOTFOUND);
2672 
2673 	return (plugin->funclist->ExportPK12(handle, numattr, attrlist));
2674 }
2675 
2676 
2677 KMF_RETURN
2678 kmf_build_pk12(KMF_HANDLE_T handle, int numcerts,
2679     KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
2680     KMF_CREDENTIAL *p12cred, char *filename)
2681 {
2682 	KMF_RETURN rv;
2683 	KMF_PLUGIN *plugin;
2684 	KMF_RETURN (*buildpk12)(KMF_HANDLE *, int, KMF_X509_DER_CERT *,
2685 	    int, KMF_KEY_HANDLE *, KMF_CREDENTIAL *, char *);
2686 
2687 	CLEAR_ERROR(handle, rv);
2688 	if (rv != KMF_OK)
2689 		return (rv);
2690 
2691 	if (filename == NULL ||	p12cred == NULL ||
2692 	    (certlist == NULL && keylist == NULL))
2693 		return (KMF_ERR_BAD_PARAMETER);
2694 
2695 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2696 	if (plugin == NULL || plugin->dldesc == NULL) {
2697 		return (KMF_ERR_PLUGIN_NOTFOUND);
2698 	}
2699 
2700 	buildpk12 = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2701 	    "openssl_build_pk12");
2702 	if (buildpk12 == NULL) {
2703 		return (KMF_ERR_FUNCTION_NOT_FOUND);
2704 	}
2705 
2706 	rv = buildpk12(handle, numcerts, certlist, numkeys, keylist, p12cred,
2707 	    filename);
2708 
2709 	return (rv);
2710 }
2711 
2712 
2713 KMF_RETURN
2714 kmf_import_objects(KMF_HANDLE_T handle, char *filename,
2715 	KMF_CREDENTIAL *cred,
2716 	KMF_X509_DER_CERT **certs, int *ncerts,
2717 	KMF_RAW_KEY_DATA **rawkeys, int *nkeys)
2718 {
2719 	KMF_RETURN rv;
2720 	KMF_PLUGIN *plugin;
2721 	KMF_RETURN (*import_objects)(KMF_HANDLE *, char *, KMF_CREDENTIAL *,
2722 	    KMF_X509_DER_CERT **, int *, KMF_RAW_KEY_DATA **, int *);
2723 
2724 	CLEAR_ERROR(handle, rv);
2725 	if (rv != KMF_OK)
2726 		return (rv);
2727 
2728 	if (filename == NULL ||	cred == NULL ||	certs == NULL ||
2729 	    ncerts == NULL ||rawkeys == NULL || nkeys == NULL)
2730 		return (KMF_ERR_BAD_PARAMETER);
2731 
2732 	/*
2733 	 * Use the Keypair reader from the OpenSSL plugin.
2734 	 */
2735 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
2736 	if (plugin == NULL || plugin->dldesc == NULL) {
2737 		return (KMF_ERR_PLUGIN_NOTFOUND);
2738 	}
2739 
2740 	import_objects = (KMF_RETURN(*)())dlsym(plugin->dldesc,
2741 	    "openssl_import_objects");
2742 	if (import_objects == NULL) {
2743 		return (KMF_ERR_FUNCTION_NOT_FOUND);
2744 	}
2745 
2746 	/* Use OpenSSL interfaces to get raw key and cert data */
2747 	rv = import_objects(handle, filename, cred, certs, ncerts,
2748 	    rawkeys, nkeys);
2749 
2750 	return (rv);
2751 }
2752 
2753 KMF_BOOL
2754 IsEqualOid(KMF_OID *Oid1, KMF_OID *Oid2)
2755 {
2756 	return ((Oid1->Length == Oid2->Length) &&
2757 	    !memcmp(Oid1->Data, Oid2->Data, Oid1->Length));
2758 }
2759 
2760 KMF_RETURN
2761 copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
2762 	KMF_X509_ALGORITHM_IDENTIFIER *srcid)
2763 {
2764 	KMF_RETURN ret = KMF_OK;
2765 	if (!destid || !srcid)
2766 		return (KMF_ERR_BAD_PARAMETER);
2767 
2768 	destid->algorithm.Length = srcid->algorithm.Length;
2769 	destid->algorithm.Data = malloc(destid->algorithm.Length);
2770 	if (destid->algorithm.Data == NULL)
2771 		return (KMF_ERR_MEMORY);
2772 
2773 	(void) memcpy(destid->algorithm.Data, srcid->algorithm.Data,
2774 	    destid->algorithm.Length);
2775 
2776 	destid->parameters.Length = srcid->parameters.Length;
2777 	if (destid->parameters.Length > 0) {
2778 		destid->parameters.Data = malloc(destid->parameters.Length);
2779 		if (destid->parameters.Data == NULL)
2780 			return (KMF_ERR_MEMORY);
2781 
2782 		(void) memcpy(destid->parameters.Data, srcid->parameters.Data,
2783 		    destid->parameters.Length);
2784 	} else {
2785 		destid->parameters.Data = NULL;
2786 	}
2787 	return (ret);
2788 }
2789 
2790 static KMF_RETURN
2791 sign_cert(KMF_HANDLE_T handle,
2792 	const KMF_DATA *SubjectCert,
2793 	KMF_KEY_HANDLE	*Signkey,
2794 	KMF_DATA	*SignedCert)
2795 {
2796 	KMF_X509_CERTIFICATE	*subj_cert = NULL;
2797 	KMF_DATA		data_to_sign = {0, NULL};
2798 	KMF_DATA		signed_data = {0, NULL};
2799 	KMF_RETURN		ret = KMF_OK;
2800 	KMF_ALGORITHM_INDEX	algid;
2801 	int i = 0;
2802 	KMF_ATTRIBUTE attrlist[8];
2803 	KMF_OID *oid;
2804 
2805 	if (!SignedCert)
2806 		return (KMF_ERR_BAD_PARAMETER);
2807 
2808 	SignedCert->Length = 0;
2809 	SignedCert->Data = NULL;
2810 
2811 	if (!SubjectCert)
2812 		return (KMF_ERR_BAD_PARAMETER);
2813 
2814 	if (!SubjectCert->Data || !SubjectCert->Length)
2815 		return (KMF_ERR_BAD_PARAMETER);
2816 
2817 	/*
2818 	 * Shortcut - just extract the already encoded TBS cert data from
2819 	 * the original data buffer.  Since we haven't changed anything,
2820 	 * there is no need to re-encode it.
2821 	 */
2822 	ret = ExtractX509CertParts((KMF_DATA *)SubjectCert,
2823 	    &data_to_sign, NULL);
2824 	if (ret != KMF_OK) {
2825 		goto cleanup;
2826 	}
2827 
2828 	/* Estimate the signed data length generously */
2829 	signed_data.Length = data_to_sign.Length*2;
2830 	signed_data.Data = calloc(1, signed_data.Length);
2831 	if (!signed_data.Data) {
2832 		ret = KMF_ERR_MEMORY;
2833 		goto cleanup;
2834 	}
2835 
2836 	/*
2837 	 * If we got here OK, decode into a structure and then re-encode
2838 	 * the complete certificate.
2839 	 */
2840 	ret = DerDecodeSignedCertificate(SubjectCert, &subj_cert);
2841 	if (ret != KMF_OK) {
2842 		goto cleanup;
2843 	}
2844 
2845 	/* We are re-signing this cert, so clear out old signature data */
2846 	if (subj_cert->signature.algorithmIdentifier.algorithm.Length == 0) {
2847 		kmf_free_algoid(&subj_cert->signature.algorithmIdentifier);
2848 		ret = copy_algoid(&subj_cert->signature.algorithmIdentifier,
2849 		    &subj_cert->certificate.signature);
2850 	}
2851 
2852 	if (ret)
2853 		goto cleanup;
2854 
2855 	kmf_set_attr_at_index(attrlist, i, KMF_KEYSTORE_TYPE_ATTR,
2856 	    &Signkey->kstype, sizeof (KMF_KEYSTORE_TYPE));
2857 	i++;
2858 	kmf_set_attr_at_index(attrlist, i, KMF_KEY_HANDLE_ATTR,
2859 	    Signkey, sizeof (KMF_KEY_HANDLE));
2860 	i++;
2861 	kmf_set_attr_at_index(attrlist, i, KMF_DATA_ATTR,
2862 	    &data_to_sign, sizeof (KMF_DATA));
2863 	i++;
2864 	kmf_set_attr_at_index(attrlist, i, KMF_OUT_DATA_ATTR,
2865 	    &signed_data, sizeof (KMF_DATA));
2866 	i++;
2867 	oid = CERT_ALG_OID(subj_cert);
2868 	kmf_set_attr_at_index(attrlist, i, KMF_OID_ATTR,
2869 	    oid, sizeof (KMF_OID));
2870 	i++;
2871 
2872 	/* Sign the data */
2873 	ret = kmf_sign_data(handle, i, attrlist);
2874 
2875 	if (ret != KMF_OK)
2876 		goto cleanup;
2877 
2878 	algid = x509_algoid_to_algid(CERT_SIG_OID(subj_cert));
2879 
2880 	/*
2881 	 * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded
2882 	 * signature. So we must encode the signature correctly.
2883 	 */
2884 	if (algid == KMF_ALGID_SHA1WithDSA) {
2885 
2886 		KMF_DATA signature;
2887 
2888 		ret = DerEncodeDSASignature(&signed_data, &signature);
2889 		kmf_free_data(&signed_data);
2890 
2891 		if (ret != KMF_OK)
2892 			goto cleanup;
2893 
2894 		subj_cert->signature.encrypted = signature;
2895 	} else {
2896 		subj_cert->signature.encrypted = signed_data;
2897 	}
2898 
2899 	/* Now, re-encode the cert with the new signature */
2900 	ret = DerEncodeSignedCertificate(subj_cert, SignedCert);
2901 
2902 cleanup:
2903 	/* Cleanup & return */
2904 	if (ret != KMF_OK)
2905 		kmf_free_data(SignedCert);
2906 
2907 	kmf_free_data(&data_to_sign);
2908 
2909 	if (subj_cert != NULL) {
2910 		kmf_free_signed_cert(subj_cert);
2911 		free(subj_cert);
2912 	}
2913 
2914 	return (ret);
2915 }
2916 
2917 static KMF_RETURN
2918 verify_cert_with_key(KMF_HANDLE_T handle,
2919 	KMF_DATA *derkey,
2920 	const KMF_DATA *CertToBeVerified)
2921 {
2922 	KMF_RETURN ret = KMF_OK;
2923 	KMF_X509_CERTIFICATE *signed_cert = NULL;
2924 	KMF_X509_SPKI	spki;
2925 	KMF_DATA	data_to_verify = {0, NULL};
2926 	KMF_DATA	signed_data = {0, NULL};
2927 	KMF_DATA	signature = { 0, NULL };
2928 	KMF_ALGORITHM_INDEX	algid;
2929 
2930 	/* check the caller and do other setup for this SPI call */
2931 	if (handle == NULL || CertToBeVerified == NULL ||
2932 	    derkey == NULL || derkey->Data == NULL)
2933 		return (KMF_ERR_BAD_PARAMETER);
2934 
2935 	(void) memset(&spki, 0, sizeof (KMF_X509_SPKI));
2936 
2937 	ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerified,
2938 	    &data_to_verify, &signed_data);
2939 
2940 	if (ret != KMF_OK)
2941 		goto cleanup;
2942 
2943 	ret = DerDecodeSPKI(derkey, &spki);
2944 	if (ret != KMF_OK)
2945 		goto cleanup;
2946 
2947 	/* Decode the signer cert so we can get the Algorithm data */
2948 	ret = DerDecodeSignedCertificate(CertToBeVerified, &signed_cert);
2949 	if (ret != KMF_OK)
2950 		return (ret);
2951 
2952 	algid = x509_algoid_to_algid(CERT_SIG_OID(signed_cert));
2953 
2954 	if (algid == KMF_ALGID_NONE)
2955 		return (KMF_ERR_BAD_ALGORITHM);
2956 
2957 	if (algid == KMF_ALGID_SHA1WithDSA) {
2958 		ret = DerDecodeDSASignature(&signed_data, &signature);
2959 		if (ret != KMF_OK)
2960 			goto cleanup;
2961 	} else {
2962 		signature.Data = signed_data.Data;
2963 		signature.Length = signed_data.Length;
2964 	}
2965 
2966 	ret = PKCS_VerifyData(handle, algid, &spki,
2967 	    &data_to_verify, &signature);
2968 
2969 cleanup:
2970 	if (data_to_verify.Data != NULL)
2971 		free(data_to_verify.Data);
2972 
2973 	if (signed_data.Data != NULL)
2974 		free(signed_data.Data);
2975 
2976 	if (signed_cert) {
2977 		kmf_free_signed_cert(signed_cert);
2978 		free(signed_cert);
2979 	}
2980 	if (algid == KMF_ALGID_SHA1WithDSA) {
2981 		free(signature.Data);
2982 	}
2983 
2984 	kmf_free_algoid(&spki.algorithm);
2985 	kmf_free_data(&spki.subjectPublicKey);
2986 
2987 	return (ret);
2988 }
2989 
2990 /*
2991  * Use a signer cert to verify another certificate's signature.
2992  * This code forces the use of the OPENSSL mechanism
2993  * for the verify operation to avoid a circular dependency
2994  * with libelfsign when it attempts to verify the PKCS#11 libraries.
2995  */
2996 static KMF_RETURN
2997 verify_cert_with_cert(KMF_HANDLE_T handle,
2998 	const KMF_DATA *CertToBeVerifiedData,
2999 	const KMF_DATA *SignerCertData)
3000 {
3001 	KMF_RETURN ret = KMF_OK;
3002 	KMF_X509_CERTIFICATE *SignerCert = NULL;
3003 	KMF_X509_CERTIFICATE *ToBeVerifiedCert = NULL;
3004 	KMF_DATA	data_to_verify = {0, NULL};
3005 	KMF_DATA	signed_data = {0, NULL};
3006 	KMF_DATA	signature;
3007 	KMF_ALGORITHM_INDEX	algid;
3008 
3009 	if (!CertToBeVerifiedData ||
3010 	    !CertToBeVerifiedData->Data ||
3011 	    !CertToBeVerifiedData->Length)
3012 		return (KMF_ERR_BAD_PARAMETER);
3013 
3014 	if (!SignerCertData ||
3015 	    !SignerCertData->Data ||
3016 	    !SignerCertData->Length)
3017 		return (KMF_ERR_BAD_PARAMETER);
3018 
3019 	/* Make sure the signer has proper key usage bits */
3020 	ret = check_key_usage(handle, SignerCertData, KMF_KU_SIGN_CERT);
3021 	if (ret != KMF_OK)
3022 		return (ret);
3023 
3024 	/* Decode the cert into parts for verification */
3025 	ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerifiedData,
3026 	    &data_to_verify, &signed_data);
3027 	if (ret != KMF_OK)
3028 		goto cleanup;
3029 
3030 	/* Decode the to-be-verified cert so we know what algorithm to use */
3031 	ret = DerDecodeSignedCertificate(CertToBeVerifiedData,
3032 	    &ToBeVerifiedCert);
3033 
3034 	if (ret != KMF_OK)
3035 		goto cleanup;
3036 
3037 	algid = x509_algoid_to_algid(CERT_SIG_OID(ToBeVerifiedCert));
3038 
3039 	if (algid == KMF_ALGID_SHA1WithDSA) {
3040 		ret = DerDecodeDSASignature(&signed_data, &signature);
3041 		if (ret != KMF_OK)
3042 			goto cleanup;
3043 	} else {
3044 		signature.Data = signed_data.Data;
3045 		signature.Length = signed_data.Length;
3046 	}
3047 
3048 	/*
3049 	 * To avoid recursion with kcfd consumer and libpkcs11,
3050 	 * do the certificate verification using the OpenSSL
3051 	 * plugin algorithms instead of the crypto framework.
3052 	 */
3053 	ret = plugin_verify_data_with_cert(handle, KMF_KEYSTORE_OPENSSL,
3054 	    algid, &data_to_verify, &signature,	SignerCertData);
3055 
3056 cleanup:
3057 	kmf_free_data(&data_to_verify);
3058 	kmf_free_data(&signed_data);
3059 
3060 	if (SignerCert) {
3061 		kmf_free_signed_cert(SignerCert);
3062 		free(SignerCert);
3063 	}
3064 
3065 	if (ToBeVerifiedCert) {
3066 		kmf_free_signed_cert(ToBeVerifiedCert);
3067 		free(ToBeVerifiedCert);
3068 	}
3069 
3070 	if (algid == KMF_ALGID_SHA1WithDSA) {
3071 		free(signature.Data);
3072 	}
3073 
3074 	return (ret);
3075 }
3076 
3077 /*
3078  * Phase 1 APIs still needed to maintain compat with elfsign.
3079  */
3080 KMF_RETURN
3081 KMF_VerifyDataWithCert(KMF_HANDLE_T handle,
3082 	KMF_KEYSTORE_TYPE kstype,
3083 	KMF_ALGORITHM_INDEX algid,
3084 	KMF_DATA *indata,
3085 	KMF_DATA *insig,
3086 	const KMF_DATA *SignerCert)
3087 {
3088 	KMF_ATTRIBUTE attrlist[8];
3089 	int numattr = 0;
3090 
3091 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3092 	    &kstype,  sizeof (kstype));
3093 	numattr++;
3094 
3095 	kmf_set_attr_at_index(attrlist, numattr, KMF_DATA_ATTR,
3096 	    indata, sizeof (KMF_DATA));
3097 	numattr++;
3098 
3099 	kmf_set_attr_at_index(attrlist, numattr, KMF_IN_SIGN_ATTR,
3100 	    insig, sizeof (KMF_DATA));
3101 	numattr++;
3102 
3103 	kmf_set_attr_at_index(attrlist, numattr, KMF_SIGNER_CERT_DATA_ATTR,
3104 	    (KMF_DATA *)SignerCert, sizeof (KMF_DATA));
3105 	numattr++;
3106 
3107 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
3108 	    &algid, sizeof (algid));
3109 	numattr++;
3110 
3111 	return (kmf_verify_data(handle, numattr, attrlist));
3112 }
3113 
3114 KMF_RETURN
3115 KMF_VerifyCertWithCert(KMF_HANDLE_T handle,
3116 	const KMF_DATA *CertToBeVerified,
3117 	const KMF_DATA *SignerCert)
3118 {
3119 	KMF_RETURN ret;
3120 	if (CertToBeVerified == NULL || SignerCert == NULL)
3121 		return (KMF_ERR_BAD_PARAMETER);
3122 
3123 	/* check the keyUsage of signer's certificate */
3124 	ret = check_key_usage(handle, SignerCert, KMF_KU_SIGN_CERT);
3125 	if (ret != KMF_OK)
3126 		return (ret);
3127 
3128 	return (verify_cert_with_cert(handle, CertToBeVerified,
3129 	    SignerCert));
3130 }
3131 
3132 KMF_RETURN
3133 KMF_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *target,
3134 		KMF_X509_DER_CERT *kmf_cert,
3135 		uint32_t *num_certs)
3136 {
3137 	KMF_ATTRIBUTE attrlist[32];
3138 	int i = 0;
3139 
3140 	if (target == NULL || num_certs == NULL)
3141 		return (KMF_ERR_BAD_PARAMETER); /* ILLEGAL ARGS ERROR */
3142 
3143 	if ((target->find_cert_validity < KMF_ALL_CERTS) ||
3144 	    (target->find_cert_validity > KMF_EXPIRED_CERTS))
3145 		return (KMF_ERR_BAD_PARAMETER);
3146 
3147 	kmf_set_attr_at_index(attrlist, i,
3148 	    KMF_KEYSTORE_TYPE_ATTR, &target->kstype, sizeof (target->kstype));
3149 	i++;
3150 
3151 	if (kmf_cert != NULL) {
3152 		kmf_set_attr_at_index(attrlist, i,
3153 		    KMF_X509_DER_CERT_ATTR, kmf_cert,
3154 		    sizeof (KMF_X509_DER_CERT));
3155 		i++;
3156 	}
3157 
3158 	kmf_set_attr_at_index(attrlist, i,
3159 	    KMF_COUNT_ATTR, num_certs, sizeof (uint32_t));
3160 	i++;
3161 
3162 	/* Set the optional searching attributes for all 3 plugins. */
3163 	if (target->issuer != NULL) {
3164 		kmf_set_attr_at_index(attrlist, i, KMF_ISSUER_NAME_ATTR,
3165 		    target->issuer, strlen(target->issuer));
3166 		i++;
3167 	}
3168 	if (target->subject != NULL) {
3169 		kmf_set_attr_at_index(attrlist, i, KMF_SUBJECT_NAME_ATTR,
3170 		    target->subject, strlen(target->subject));
3171 		i++;
3172 	}
3173 	if (target->serial != NULL) {
3174 		kmf_set_attr_at_index(attrlist, i, KMF_BIGINT_ATTR,
3175 		    target->serial, sizeof (KMF_BIGINT));
3176 		i++;
3177 	}
3178 
3179 	kmf_set_attr_at_index(attrlist, i, KMF_CERT_VALIDITY_ATTR,
3180 	    &target->find_cert_validity, sizeof (KMF_CERT_VALIDITY));
3181 	i++;
3182 
3183 	if (target->kstype == KMF_KEYSTORE_NSS) {
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 		if (target->nssparms.slotlabel != NULL) {
3192 			kmf_set_attr_at_index(attrlist, i,
3193 			    KMF_TOKEN_LABEL_ATTR,
3194 			    target->nssparms.slotlabel,
3195 			    strlen(target->nssparms.slotlabel));
3196 			i++;
3197 		}
3198 
3199 	} else if (target->kstype == KMF_KEYSTORE_OPENSSL) {
3200 		if (target->sslparms.certfile != NULL) {
3201 			kmf_set_attr_at_index(attrlist, i,
3202 			    KMF_CERT_FILENAME_ATTR,
3203 			    target->sslparms.certfile,
3204 			    strlen(target->sslparms.certfile));
3205 			i++;
3206 		}
3207 
3208 		if (target->sslparms.dirpath != NULL) {
3209 			kmf_set_attr_at_index(attrlist, i,
3210 			    KMF_DIRPATH_ATTR,
3211 			    target->sslparms.dirpath,
3212 			    strlen(target->sslparms.dirpath));
3213 			i++;
3214 		}
3215 
3216 	} else if (target->kstype == KMF_KEYSTORE_PK11TOKEN) {
3217 		if (target->certLabel != NULL) {
3218 			kmf_set_attr_at_index(attrlist, i,
3219 			    KMF_CERT_LABEL_ATTR,
3220 			    target->certLabel, strlen(target->certLabel));
3221 			i++;
3222 		}
3223 
3224 		kmf_set_attr_at_index(attrlist, i, KMF_PRIVATE_BOOL_ATTR,
3225 		    &target->pkcs11parms.private,
3226 		    sizeof (target->pkcs11parms.private));
3227 		i++;
3228 	}
3229 
3230 	return (kmf_find_cert(handle, i, attrlist));
3231 }
3232