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