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