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