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