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