xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencsr.c (revision 12234:cd6642d6b7dd)
13089Swyllys /*
23089Swyllys  * CDDL HEADER START
33089Swyllys  *
43089Swyllys  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
73089Swyllys  *
83089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93089Swyllys  * or http://www.opensolaris.org/os/licensing.
103089Swyllys  * See the License for the specific language governing permissions
113089Swyllys  * and limitations under the License.
123089Swyllys  *
133089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
143089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
163089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
173089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
183089Swyllys  *
193089Swyllys  * CDDL HEADER END
203089Swyllys  *
21*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
223089Swyllys  */
233089Swyllys 
243089Swyllys #include <stdio.h>
253089Swyllys #include <string.h>
263089Swyllys #include <ctype.h>
273089Swyllys #include <malloc.h>
283089Swyllys #include <libgen.h>
293089Swyllys #include <errno.h>
303089Swyllys #include <cryptoutil.h>
313089Swyllys #include <security/cryptoki.h>
323089Swyllys #include "common.h"
333089Swyllys 
343089Swyllys #include <kmfapi.h>
353089Swyllys 
363089Swyllys #define	SET_VALUE(f, s) \
373089Swyllys 	kmfrv = f; \
383089Swyllys 	if (kmfrv != KMF_OK) { \
393089Swyllys 		cryptoerror(LOG_STDERR, \
403089Swyllys 			gettext("Failed to %s: 0x%02\n"), \
413089Swyllys 			s, kmfrv); \
423089Swyllys 		goto cleanup; \
433089Swyllys 	}
443089Swyllys 
453089Swyllys static KMF_RETURN
gencsr_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * certlabel,KMF_KEY_ALG keyAlg,int keylen,uint16_t kubits,int kucrit,KMF_ENCODE_FORMAT fmt,char * csrfile,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg,KMF_OID * curveoid)463089Swyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
473089Swyllys 	char *token, char *subject, char *altname,
483089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
493089Swyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
506051Swyllys 	int keylen, uint16_t kubits, int kucrit,
513089Swyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
5211973Swyllys.ingersoll@sun.com 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
5311973Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
543089Swyllys {
553089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
563089Swyllys 	KMF_KEY_HANDLE pubk, prik;
573089Swyllys 	KMF_X509_NAME	csrSubject;
583089Swyllys 	KMF_CSR_DATA	csr;
593089Swyllys 	KMF_DATA signedCsr = {NULL, 0};
603089Swyllys 
615051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
625051Swyllys 	int numattr = 0;
635051Swyllys 	KMF_ATTRIBUTE attrlist[16];
645051Swyllys 
653089Swyllys 	(void) memset(&csr, 0, sizeof (csr));
663089Swyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
673089Swyllys 
683089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
6911973Swyllys.ingersoll@sun.com 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK)
703089Swyllys 		return (kmfrv);
713089Swyllys 
723089Swyllys 	/* Select a PKCS11 token */
733089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
7411973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
753089Swyllys 		return (kmfrv);
7611973Swyllys.ingersoll@sun.com 	/*
7711973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
7811973Swyllys.ingersoll@sun.com 	 */
7911973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
8011973Swyllys.ingersoll@sun.com 	    keyAlg, keylen, tokencred, curveoid, &prik, &pubk);
8111973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
823089Swyllys 		return (kmfrv);
833089Swyllys 
845051Swyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
853089Swyllys 
865051Swyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
873089Swyllys 
885051Swyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
893089Swyllys 
905051Swyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
915051Swyllys 	    "SignatureAlgorithm");
923089Swyllys 
933089Swyllys 	if (altname != NULL) {
945051Swyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
955051Swyllys 		    alttype), "SetCSRSubjectAltName");
963089Swyllys 	}
973089Swyllys 
983089Swyllys 	if (kubits != 0) {
995051Swyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
1005051Swyllys 		    "SetCSRKeyUsage");
1013089Swyllys 	}
1026051Swyllys 	if (ekulist != NULL) {
1036051Swyllys 		int i;
1046051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1056051Swyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
1066051Swyllys 			    &ekulist->ekulist[i],
1076051Swyllys 			    ekulist->critlist[i]),
1086051Swyllys 			    "Extended Key Usage");
1096051Swyllys 		}
1106051Swyllys 	}
1115051Swyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
1125051Swyllys 	    KMF_OK) {
1135051Swyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
1143089Swyllys 	}
1153089Swyllys 
1163089Swyllys cleanup:
1175051Swyllys 	(void) kmf_free_data(&signedCsr);
1189145SHuie-Ying.Lee@Sun.COM 	(void) kmf_free_signed_csr(&csr);
1199145SHuie-Ying.Lee@Sun.COM 
1209145SHuie-Ying.Lee@Sun.COM 	/* delete the public key */
1215051Swyllys 	numattr = 0;
1225051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1235051Swyllys 	    &kstype, sizeof (kstype));
1245051Swyllys 	numattr++;
1255051Swyllys 
1265051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
1275051Swyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
1285051Swyllys 	numattr++;
1295051Swyllys 
1309145SHuie-Ying.Lee@Sun.COM 	if (tokencred != NULL && tokencred->cred != NULL) {
1319145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
1329145SHuie-Ying.Lee@Sun.COM 		    tokencred, sizeof (KMF_CREDENTIAL));
1339145SHuie-Ying.Lee@Sun.COM 		numattr++;
1349145SHuie-Ying.Lee@Sun.COM 	}
1359145SHuie-Ying.Lee@Sun.COM 
1365051Swyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
1375051Swyllys 
1389145SHuie-Ying.Lee@Sun.COM 	/*
1399145SHuie-Ying.Lee@Sun.COM 	 * If there is an error, then we need to remove the private key
1409145SHuie-Ying.Lee@Sun.COM 	 * from the token.
1419145SHuie-Ying.Lee@Sun.COM 	 */
1429145SHuie-Ying.Lee@Sun.COM 	if (kmfrv != KMF_OK) {
1439145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
1449145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
1459145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
1469145SHuie-Ying.Lee@Sun.COM 		numattr++;
1473089Swyllys 
1489145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
1499145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
1509145SHuie-Ying.Lee@Sun.COM 		numattr++;
1519145SHuie-Ying.Lee@Sun.COM 
1529145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
1539145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
1549145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
1559145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
1569145SHuie-Ying.Lee@Sun.COM 			numattr++;
1579145SHuie-Ying.Lee@Sun.COM 		}
1589145SHuie-Ying.Lee@Sun.COM 
1599145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
1609145SHuie-Ying.Lee@Sun.COM 		    attrlist);
1619145SHuie-Ying.Lee@Sun.COM 	}
1629145SHuie-Ying.Lee@Sun.COM 
1639145SHuie-Ying.Lee@Sun.COM 	(void) kmf_free_kmf_key(kmfhandle, &prik);
1643089Swyllys 	return (kmfrv);
1653089Swyllys }
1663089Swyllys 
1673089Swyllys static KMF_RETURN
gencsr_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,int keylen,KMF_ENCODE_FORMAT fmt,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,uint16_t kubits,int kucrit,char * outcsr,char * outkey,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg)1683089Swyllys gencsr_file(KMF_HANDLE_T kmfhandle,
1693089Swyllys 	KMF_KEY_ALG keyAlg,
1703089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
1713089Swyllys 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
1723089Swyllys 	int altcrit, uint16_t kubits, int kucrit,
17311973Swyllys.ingersoll@sun.com 	char *outcsr, char *outkey, EKU_LIST *ekulist,
17411973Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg)
1753089Swyllys {
1763089Swyllys 	KMF_RETURN kmfrv;
1773089Swyllys 	KMF_KEY_HANDLE pubk, prik;
1783089Swyllys 	KMF_X509_NAME	csrSubject;
1793089Swyllys 	KMF_CSR_DATA	csr;
1803089Swyllys 	KMF_DATA signedCsr = {NULL, 0};
1813089Swyllys 	char *fullcsrpath = NULL;
1823089Swyllys 	char *fullkeypath = NULL;
1833089Swyllys 
1845051Swyllys 
1853089Swyllys 	(void) memset(&csr, 0, sizeof (csr));
1863089Swyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
1873089Swyllys 
1883089Swyllys 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
1893089Swyllys 		cryptoerror(LOG_STDERR,
1905051Swyllys 		    gettext("No output file was specified for "
1915051Swyllys 		    "the csr or key\n"));
1923089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
1933089Swyllys 	}
1946669Swyllys 	fullcsrpath = strdup(outcsr);
1953089Swyllys 	if (verify_file(fullcsrpath)) {
1963089Swyllys 		cryptoerror(LOG_STDERR,
1975051Swyllys 		    gettext("Cannot write the indicated output "
1985051Swyllys 		    "certificate file (%s).\n"), fullcsrpath);
1993089Swyllys 		free(fullcsrpath);
2003089Swyllys 		return (PK_ERR_USAGE);
2013089Swyllys 	}
2026669Swyllys 
2033089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
2045051Swyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
2053089Swyllys 		return (kmfrv);
2063089Swyllys 	}
20711973Swyllys.ingersoll@sun.com 	/*
20811973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
20911973Swyllys.ingersoll@sun.com 	 */
21011973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
21111973Swyllys.ingersoll@sun.com 	    fmt, outkey, &prik, &pubk);
21211973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
21311973Swyllys.ingersoll@sun.com 		return (kmfrv);
2143089Swyllys 
2155051Swyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
2165051Swyllys 	    "SetCSRPubKey");
2173089Swyllys 
2185051Swyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
2193089Swyllys 
2205051Swyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
2215051Swyllys 	    "kmf_set_csr_subject");
2223089Swyllys 
2235051Swyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
2243089Swyllys 
2253089Swyllys 	if (altname != NULL) {
2265051Swyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
2275051Swyllys 		    alttype), "kmf_set_csr_subject_altname");
2283089Swyllys 	}
2293089Swyllys 	if (kubits != NULL) {
2305051Swyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
2315051Swyllys 		    "kmf_set_csr_ku");
2323089Swyllys 	}
2336051Swyllys 	if (ekulist != NULL) {
2346051Swyllys 		int i;
2356051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
2366051Swyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
2376051Swyllys 			    &ekulist->ekulist[i],
2386051Swyllys 			    ekulist->critlist[i]),
2396051Swyllys 			    "Extended Key Usage");
2406051Swyllys 		}
2416051Swyllys 	}
2425051Swyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
2435051Swyllys 	    KMF_OK) {
2445051Swyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
2453089Swyllys 	}
2463089Swyllys 
2473089Swyllys cleanup:
2483089Swyllys 	if (fullkeypath)
2493089Swyllys 		free(fullkeypath);
2503089Swyllys 	if (fullcsrpath)
2513089Swyllys 		free(fullcsrpath);
2523089Swyllys 
2535051Swyllys 	kmf_free_data(&signedCsr);
2545051Swyllys 	kmf_free_kmf_key(kmfhandle, &prik);
2555051Swyllys 	kmf_free_signed_csr(&csr);
2563089Swyllys 
2573089Swyllys 	return (kmfrv);
2583089Swyllys }
2593089Swyllys 
2603089Swyllys static KMF_RETURN
gencsr_nss(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * nickname,char * dir,char * prefix,KMF_KEY_ALG keyAlg,int keylen,uint16_t kubits,int kucrit,KMF_ENCODE_FORMAT fmt,char * csrfile,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg,KMF_OID * curveoid)2613089Swyllys gencsr_nss(KMF_HANDLE_T kmfhandle,
2623089Swyllys 	char *token, char *subject, char *altname,
2633089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2643089Swyllys 	char *nickname, char *dir, char *prefix,
2653089Swyllys 	KMF_KEY_ALG keyAlg, int keylen,
2663089Swyllys 	uint16_t kubits, int kucrit,
2673089Swyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
26811973Swyllys.ingersoll@sun.com 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
26911973Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
2703089Swyllys {
2713089Swyllys 	KMF_RETURN kmfrv;
2723089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2733089Swyllys 	KMF_X509_NAME	csrSubject;
2743089Swyllys 	KMF_CSR_DATA	csr;
2753089Swyllys 	KMF_DATA signedCsr = {NULL, 0};
2765051Swyllys 
2775051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
2785051Swyllys 	int numattr = 0;
2795051Swyllys 	KMF_ATTRIBUTE attrlist[16];
2803089Swyllys 
2813089Swyllys 	if (token == NULL)
2823089Swyllys 		token = DEFAULT_NSS_TOKEN;
2833089Swyllys 
2843089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
2853089Swyllys 	if (kmfrv != KMF_OK)
2863089Swyllys 		return (kmfrv);
2873089Swyllys 
2883089Swyllys 	(void) memset(&csr, 0, sizeof (csr));
2893089Swyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
2906669Swyllys 	(void) memset(&pubk, 0, sizeof (pubk));
2916669Swyllys 	(void) memset(&prik, 0, sizeof (prik));
2923089Swyllys 
2933089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
2945051Swyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
2953089Swyllys 		return (kmfrv);
2963089Swyllys 	}
2973089Swyllys 
29811973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
29911973Swyllys.ingersoll@sun.com 	    prefix, keyAlg, keylen, tokencred, curveoid,
30011973Swyllys.ingersoll@sun.com 	    &prik, &pubk);
30111973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
30211973Swyllys.ingersoll@sun.com 		return (kmfrv);
3033089Swyllys 
3045051Swyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
3055051Swyllys 	    "kmf_set_csr_pubkey");
3065051Swyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
3075051Swyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
3085051Swyllys 	    "kmf_set_csr_subject");
3095051Swyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
3103089Swyllys 
3113089Swyllys 	if (altname != NULL) {
3125051Swyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
3135051Swyllys 		    alttype), "kmf_set_csr_subject_altname");
3143089Swyllys 	}
3153089Swyllys 	if (kubits != NULL) {
3165051Swyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
3175051Swyllys 		    "kmf_set_csr_ku");
3183089Swyllys 	}
3196051Swyllys 	if (ekulist != NULL) {
3206051Swyllys 		int i;
3216051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
3226051Swyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
3236051Swyllys 			    &ekulist->ekulist[i],
3246051Swyllys 			    ekulist->critlist[i]),
3256051Swyllys 			    "Extended Key Usage");
3266051Swyllys 		}
3276051Swyllys 	}
3285051Swyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
3295051Swyllys 	    KMF_OK) {
3305051Swyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
3313089Swyllys 	}
3323089Swyllys 
3333089Swyllys cleanup:
3345051Swyllys 	(void) kmf_free_data(&signedCsr);
3355051Swyllys 	(void) kmf_free_kmf_key(kmfhandle, &prik);
3365051Swyllys 
3373089Swyllys 	/* delete the key */
3385051Swyllys 	numattr = 0;
3395051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3405051Swyllys 	    &kstype, sizeof (kstype));
3415051Swyllys 	numattr++;
3425051Swyllys 
3435051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
3445051Swyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
3455051Swyllys 	numattr++;
3465051Swyllys 
3475051Swyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
3485051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
3495051Swyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
3505051Swyllys 		numattr++;
3515051Swyllys 	}
3525051Swyllys 
3535051Swyllys 	if (token && strlen(token)) {
3545051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
3555051Swyllys 		    token, strlen(token));
3565051Swyllys 		numattr++;
3575051Swyllys 	}
3585051Swyllys 
3595051Swyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
3605051Swyllys 
3615051Swyllys 	(void) kmf_free_signed_csr(&csr);
3623089Swyllys 
3633089Swyllys 	return (kmfrv);
3643089Swyllys }
3653089Swyllys 
3663089Swyllys int
pk_gencsr(int argc,char * argv[])3673089Swyllys pk_gencsr(int argc, char *argv[])
3683089Swyllys {
3693089Swyllys 	KMF_RETURN rv;
3703089Swyllys 	int opt;
3713089Swyllys 	extern int	optind_av;
3723089Swyllys 	extern char	*optarg_av;
3733089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
3743089Swyllys 	char *subject = NULL;
3753089Swyllys 	char *tokenname = NULL;
3763089Swyllys 	char *dir = NULL;
3773089Swyllys 	char *prefix = NULL;
3783089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
3793089Swyllys 	char *certlabel = NULL;
3803089Swyllys 	char *outcsr = NULL;
3813089Swyllys 	char *outkey = NULL;
3823089Swyllys 	char *format = NULL;
3833089Swyllys 	char *altname = NULL;
3843089Swyllys 	char *kustr = NULL;
3856051Swyllys 	char *ekustr = NULL;
38611973Swyllys.ingersoll@sun.com 	char *hashname = NULL;
3873089Swyllys 	uint16_t kubits = 0;
3883089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
3893089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
3903089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
3913089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
39210744Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
3933089Swyllys 	boolean_t interactive = B_FALSE;
3943089Swyllys 	char *subname = NULL;
3953089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
3963089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
3973089Swyllys 	int altcrit = 0, kucrit = 0;
3986051Swyllys 	EKU_LIST *ekulist = NULL;
39911973Swyllys.ingersoll@sun.com 	KMF_OID *curveoid = NULL; /* ECC */
40011973Swyllys.ingersoll@sun.com 	KMF_OID *hashoid = NULL;
40111973Swyllys.ingersoll@sun.com 	int y_flag = 0;
4023089Swyllys 
4033089Swyllys 	while ((opt = getopt_av(argc, argv,
4045051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
4055051Swyllys 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
40611973Swyllys.ingersoll@sun.com 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
40711973Swyllys.ingersoll@sun.com 	    "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {
4083089Swyllys 
4093089Swyllys 		switch (opt) {
4103089Swyllys 			case 'A':
4113089Swyllys 				altname = optarg_av;
4123089Swyllys 				break;
4133089Swyllys 			case 'i':
41410241Swyllys.ingersoll@sun.com 				if (interactive)
4153089Swyllys 					return (PK_ERR_USAGE);
41610241Swyllys.ingersoll@sun.com 				else if (subject) {
41710241Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
41810241Swyllys.ingersoll@sun.com 					    gettext("Interactive (-i) and "
41910241Swyllys.ingersoll@sun.com 					    "subject options are mutually "
42010241Swyllys.ingersoll@sun.com 					    "exclusive.\n"));
42110241Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
42210241Swyllys.ingersoll@sun.com 				} else
4233089Swyllys 					interactive = B_TRUE;
4243089Swyllys 				break;
4253089Swyllys 			case 'k':
4263089Swyllys 				kstype = KS2Int(optarg_av);
4273089Swyllys 				if (kstype == 0)
4283089Swyllys 					return (PK_ERR_USAGE);
4293089Swyllys 				break;
4303089Swyllys 			case 's':
43110241Swyllys.ingersoll@sun.com 				if (subject)
4323089Swyllys 					return (PK_ERR_USAGE);
43310241Swyllys.ingersoll@sun.com 				else if (interactive) {
43410241Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
43510241Swyllys.ingersoll@sun.com 					    gettext("Interactive (-i) and "
43610241Swyllys.ingersoll@sun.com 					    "subject options are mutually "
43710241Swyllys.ingersoll@sun.com 					    "exclusive.\n"));
43810241Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
43910241Swyllys.ingersoll@sun.com 				} else
4403089Swyllys 					subject = optarg_av;
4413089Swyllys 				break;
4423089Swyllys 			case 'l':
4433089Swyllys 			case 'n':
4443089Swyllys 				if (certlabel)
4453089Swyllys 					return (PK_ERR_USAGE);
4463089Swyllys 				certlabel = optarg_av;
4473089Swyllys 				break;
4483089Swyllys 			case 'T':
4493089Swyllys 				if (tokenname)
4503089Swyllys 					return (PK_ERR_USAGE);
4513089Swyllys 				tokenname = optarg_av;
4523089Swyllys 				break;
4533089Swyllys 			case 'd':
4543089Swyllys 				dir = optarg_av;
4553089Swyllys 				break;
4563089Swyllys 			case 'p':
4573089Swyllys 				if (prefix)
4583089Swyllys 					return (PK_ERR_USAGE);
4593089Swyllys 				prefix = optarg_av;
4603089Swyllys 				break;
4613089Swyllys 			case 't':
4623089Swyllys 				keytype = optarg_av;
4633089Swyllys 				break;
4643089Swyllys 			case 'u':
4653089Swyllys 				kustr = optarg_av;
4663089Swyllys 				break;
4673089Swyllys 			case 'y':
4683089Swyllys 				if (sscanf(optarg_av, "%d",
4695051Swyllys 				    &keylen) != 1) {
4703089Swyllys 					cryptoerror(LOG_STDERR,
4715051Swyllys 					    gettext("Unrecognized "
4725051Swyllys 					    "key length (%s)\n"), optarg_av);
4733089Swyllys 					return (PK_ERR_USAGE);
4743089Swyllys 				}
47511973Swyllys.ingersoll@sun.com 				y_flag++;
4763089Swyllys 				break;
4773089Swyllys 			case 'c':
4783089Swyllys 				if (outcsr)
4793089Swyllys 					return (PK_ERR_USAGE);
4803089Swyllys 				outcsr = optarg_av;
4813089Swyllys 				break;
4823089Swyllys 			case 'K':
4833089Swyllys 				if (outkey)
4843089Swyllys 					return (PK_ERR_USAGE);
4853089Swyllys 				outkey = optarg_av;
4863089Swyllys 				break;
4873089Swyllys 			case 'F':
4883089Swyllys 				if (format)
4893089Swyllys 					return (PK_ERR_USAGE);
4903089Swyllys 				format = optarg_av;
4913089Swyllys 				break;
4926051Swyllys 			case 'e':
4936051Swyllys 				ekustr = optarg_av;
4946051Swyllys 				break;
49511973Swyllys.ingersoll@sun.com 			case 'C':
49611973Swyllys.ingersoll@sun.com 				curveoid = ecc_name_to_oid(optarg_av);
49711973Swyllys.ingersoll@sun.com 				if (curveoid == NULL) {
49811973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
49911973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized ECC "
50011973Swyllys.ingersoll@sun.com 					    "curve.\n"));
50111973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
50211973Swyllys.ingersoll@sun.com 				}
50311973Swyllys.ingersoll@sun.com 				break;
50411973Swyllys.ingersoll@sun.com 			case 'E':
50511973Swyllys.ingersoll@sun.com 				/*
50611973Swyllys.ingersoll@sun.com 				 * This argument is only to be used
50711973Swyllys.ingersoll@sun.com 				 * by itself, no other options should
50811973Swyllys.ingersoll@sun.com 				 * be present.
50911973Swyllys.ingersoll@sun.com 				 */
51011973Swyllys.ingersoll@sun.com 				if (argc != 2) {
51111973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
51211973Swyllys.ingersoll@sun.com 					    gettext("listcurves has no other "
51311973Swyllys.ingersoll@sun.com 					    "options.\n"));
51411973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
51511973Swyllys.ingersoll@sun.com 				}
51611973Swyllys.ingersoll@sun.com 				show_ecc_curves();
51711973Swyllys.ingersoll@sun.com 				return (0);
51811973Swyllys.ingersoll@sun.com 			case 'h':
51911973Swyllys.ingersoll@sun.com 				hashname = optarg_av;
52011973Swyllys.ingersoll@sun.com 				hashoid = ecc_name_to_oid(optarg_av);
52111973Swyllys.ingersoll@sun.com 				if (hashoid == NULL) {
52211973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
52311973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized hash.\n"));
52411973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
52511973Swyllys.ingersoll@sun.com 				}
52611973Swyllys.ingersoll@sun.com 				break;
5273089Swyllys 			default:
5283089Swyllys 				cryptoerror(LOG_STDERR, gettext(
5295051Swyllys 				    "unrecognized gencsr option '%s'\n"),
5305051Swyllys 				    argv[optind_av]);
5313089Swyllys 				return (PK_ERR_USAGE);
5323089Swyllys 		}
5333089Swyllys 	}
5343089Swyllys 	/* No additional args allowed. */
5353089Swyllys 	argc -= optind_av;
5363089Swyllys 	argv += optind_av;
5373089Swyllys 	if (argc) {
5383089Swyllys 		return (PK_ERR_USAGE);
5393089Swyllys 	}
5403089Swyllys 
5413089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
5423089Swyllys 	if (kstype == 0)
5433089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
5443089Swyllys 
5456884Swyllys 	DIR_OPTION_CHECK(kstype, dir);
5466884Swyllys 
5475221Swyllys 	if (EMPTYSTRING(outcsr) && interactive) {
5485221Swyllys 		(void) get_filename("CSR", &outcsr);
5495221Swyllys 	}
5503089Swyllys 	if (EMPTYSTRING(outcsr)) {
5513089Swyllys 		(void) printf(gettext("A filename must be specified to hold"
5525051Swyllys 		    "the final certificate request data.\n"));
5533089Swyllys 		return (PK_ERR_USAGE);
5545221Swyllys 	}
5555221Swyllys 	/*
5565221Swyllys 	 * verify that the outcsr file does not already exist
5575221Swyllys 	 * and that it can be created.
5585221Swyllys 	 */
5595221Swyllys 	rv = verify_file(outcsr);
560*12234Swyllys.ingersoll@sun.com 	if (rv == KMF_ERR_OPEN_FILE) {
561*12234Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR,
562*12234Swyllys.ingersoll@sun.com 		    gettext("Warning: file \"%s\" exists, "
563*12234Swyllys.ingersoll@sun.com 		    "will be overwritten."), outcsr);
564*12234Swyllys.ingersoll@sun.com 		if (yesno(gettext("Continue with gencsr? "),
565*12234Swyllys.ingersoll@sun.com 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
566*12234Swyllys.ingersoll@sun.com 			return (0);
567*12234Swyllys.ingersoll@sun.com 		} else {
568*12234Swyllys.ingersoll@sun.com 			/* remove the file */
569*12234Swyllys.ingersoll@sun.com 			(void) unlink(outcsr);
570*12234Swyllys.ingersoll@sun.com 		}
571*12234Swyllys.ingersoll@sun.com 	} else if (rv != KMF_OK)  {
572*12234Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR,
573*12234Swyllys.ingersoll@sun.com 		    gettext("Warning: error accessing \"%s\""), outcsr);
574*12234Swyllys.ingersoll@sun.com 		return (rv);
5755221Swyllys 	}
5765221Swyllys 
5775221Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
5785221Swyllys 		if (EMPTYSTRING(certlabel) && interactive)
5795221Swyllys 			(void) get_certlabel(&certlabel);
5805221Swyllys 
5815221Swyllys 		if (EMPTYSTRING(certlabel)) {
5825221Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
5835221Swyllys 			    "specified to create a certificate request.\n"));
5843089Swyllys 			return (PK_ERR_USAGE);
5853089Swyllys 		}
5865221Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
5875221Swyllys 		if (EMPTYSTRING(outkey) && interactive)
5885221Swyllys 			(void) get_filename("private key", &outkey);
5893089Swyllys 
5905221Swyllys 		if (EMPTYSTRING(outkey)) {
5915221Swyllys 			cryptoerror(LOG_STDERR, gettext("A key filename "
5925221Swyllys 			    "must be specified to create a certificate "
5935221Swyllys 			    "request.\n"));
5945221Swyllys 			return (PK_ERR_USAGE);
5955221Swyllys 		}
5963089Swyllys 	}
5973089Swyllys 
5983089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
5993089Swyllys 		cryptoerror(LOG_STDERR,
6005051Swyllys 		    gettext("Error parsing format string (%s).\n"), format);
6013089Swyllys 		return (PK_ERR_USAGE);
6023089Swyllys 	}
6033089Swyllys 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
6043089Swyllys 		cryptoerror(LOG_STDERR,
6055051Swyllys 		    gettext("CSR must be DER or PEM format.\n"));
6063089Swyllys 		return (PK_ERR_USAGE);
6073089Swyllys 	}
6083089Swyllys 
6093089Swyllys 	/*
6103089Swyllys 	 * Check the subject name.
6113089Swyllys 	 * If interactive is true, get it now interactively.
6123089Swyllys 	 */
6133089Swyllys 	if (interactive) {
6143089Swyllys 		if (get_subname(&subname) != KMF_OK) {
6153089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
6163089Swyllys 			    "subject name interactively.\n"));
6173089Swyllys 			return (PK_ERR_USAGE);
6183089Swyllys 		}
6193089Swyllys 	} else {
6203089Swyllys 		if (EMPTYSTRING(subject)) {
6213089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
6223089Swyllys 			    "-i must be specified to create a certificate "
6233089Swyllys 			    "request.\n"));
6243089Swyllys 			return (PK_ERR_USAGE);
6253089Swyllys 		} else {
6263089Swyllys 			subname = strdup(subject);
6273089Swyllys 			if (subname == NULL) {
6283089Swyllys 				cryptoerror(LOG_STDERR,
6293089Swyllys 				    gettext("Out of memory.\n"));
6303089Swyllys 				return (PK_ERR_SYSTEM);
6313089Swyllys 			}
6323089Swyllys 		}
6333089Swyllys 	}
6343089Swyllys 	if (altname != NULL) {
6353089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
6363089Swyllys 		if (rv != KMF_OK) {
6373089Swyllys 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
6385051Swyllys 			    "must be specified as a name=value pair. "
6395051Swyllys 			    "See the man page for details."));
6403089Swyllys 			goto end;
6413089Swyllys 		} else {
6423089Swyllys 			/* advance the altname past the '=' sign */
6433089Swyllys 			char *p = strchr(altname, '=');
6443089Swyllys 			if (p != NULL)
6453089Swyllys 				altname = p + 1;
6463089Swyllys 		}
6473089Swyllys 	}
6483089Swyllys 
6493089Swyllys 	if (kustr != NULL) {
6503089Swyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
6513089Swyllys 		if (rv != KMF_OK) {
6523089Swyllys 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
6535051Swyllys 			    "must be specified as a comma-separated list. "
6545051Swyllys 			    "See the man page for details."));
6553089Swyllys 			goto end;
6563089Swyllys 		}
6573089Swyllys 	}
6586051Swyllys 	if (ekustr != NULL) {
6596051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
6606051Swyllys 		if (rv != KMF_OK) {
6616051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
6626051Swyllys 			    "be specified as a comma-separated list. "
6636051Swyllys 			    "See the man page for details.\n"));
6646051Swyllys 			rv = PK_ERR_USAGE;
6656051Swyllys 			goto end;
6666051Swyllys 		}
6676051Swyllys 	}
66811973Swyllys.ingersoll@sun.com 	if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
66911973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR,
67011973Swyllys.ingersoll@sun.com 		    gettext("Unsupported key/hash combination (%s/%s).\n"),
67111973Swyllys.ingersoll@sun.com 		    keytype, (hashname ? hashname : "none"));
6723089Swyllys 		goto end;
6733089Swyllys 	}
67411973Swyllys.ingersoll@sun.com 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
67511973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
67611973Swyllys.ingersoll@sun.com 		    "valid for EC keytypes.\n"));
67711973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
67811973Swyllys.ingersoll@sun.com 	}
67911973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
68011973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("A curve must be "
68111973Swyllys.ingersoll@sun.com 		    "specifed when using EC keys.\n"));
68211973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
68311973Swyllys.ingersoll@sun.com 	}
68411973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
68511973Swyllys.ingersoll@sun.com 		(void) fprintf(stderr, gettext("ECC certificates are"
68611973Swyllys.ingersoll@sun.com 		    "only supported with the pkcs11 and nss keystores\n"));
68711973Swyllys.ingersoll@sun.com 		rv = PK_ERR_USAGE;
68811973Swyllys.ingersoll@sun.com 		goto end;
68911973Swyllys.ingersoll@sun.com 	}
69011973Swyllys.ingersoll@sun.com 
69111973Swyllys.ingersoll@sun.com 	/* Adjust default keylength for NSS and DSA */
69211973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
69311973Swyllys.ingersoll@sun.com 		keylen = 1024;
6943089Swyllys 
6953089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
6963089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
6973089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
6983089Swyllys 				tokenname = "internal";
6993089Swyllys 			} else  {
7003089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
7013089Swyllys 			}
7023089Swyllys 		}
7033089Swyllys 
7043089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
7053089Swyllys 	}
7063089Swyllys 
7076884Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7086884Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
7096884Swyllys 		return (PK_ERR_USAGE);
7106884Swyllys 	}
7116884Swyllys 
7126884Swyllys 
7133089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
7143089Swyllys 		if (dir == NULL)
7153089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
7163089Swyllys 
7173089Swyllys 		rv = gencsr_nss(kmfhandle,
7185051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
7195051Swyllys 		    certlabel, dir, prefix,
7205051Swyllys 		    keyAlg, keylen, kubits, kucrit,
72111973Swyllys.ingersoll@sun.com 		    fmt, outcsr, &tokencred, ekulist,
72211973Swyllys.ingersoll@sun.com 		    sigAlg, curveoid);
7233089Swyllys 
7243089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
7253089Swyllys 		rv = gencsr_pkcs11(kmfhandle,
7265051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
7275051Swyllys 		    certlabel, keyAlg, keylen,
72811973Swyllys.ingersoll@sun.com 		    kubits, kucrit, fmt, outcsr, &tokencred,
72911973Swyllys.ingersoll@sun.com 		    ekulist, sigAlg, curveoid);
7303089Swyllys 
7313089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
7323089Swyllys 		rv = gencsr_file(kmfhandle,
7335051Swyllys 		    keyAlg, keylen, fmt, subname, altname,
7345051Swyllys 		    alttype, altcrit, kubits, kucrit,
73511973Swyllys.ingersoll@sun.com 		    outcsr, outkey, ekulist, sigAlg);
7363089Swyllys 	}
7373089Swyllys 
7383089Swyllys end:
73910241Swyllys.ingersoll@sun.com 	if (rv != KMF_OK) {
7403089Swyllys 		display_error(kmfhandle, rv,
7415051Swyllys 		    gettext("Error creating CSR or keypair"));
7423089Swyllys 
74310241Swyllys.ingersoll@sun.com 		if (rv == KMF_ERR_RDN_PARSER) {
74410241Swyllys.ingersoll@sun.com 			cryptoerror(LOG_STDERR, gettext("subject or "
74510241Swyllys.ingersoll@sun.com 			    "issuer name must be in proper DN format.\n"));
74610241Swyllys.ingersoll@sun.com 		}
74710241Swyllys.ingersoll@sun.com 	}
74810241Swyllys.ingersoll@sun.com 
7496051Swyllys 	if (ekulist != NULL)
7506051Swyllys 		free_eku_list(ekulist);
7516051Swyllys 
7523089Swyllys 	if (subname)
7533089Swyllys 		free(subname);
7543089Swyllys 
7553089Swyllys 	if (tokencred.cred != NULL)
7563089Swyllys 		free(tokencred.cred);
7573089Swyllys 
7585051Swyllys 	(void) kmf_finalize(kmfhandle);
7593089Swyllys 	if (rv != KMF_OK)
7603089Swyllys 		return (PK_ERR_USAGE);
7613089Swyllys 
7623089Swyllys 	return (0);
7633089Swyllys }
764