xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/gencsr.c (revision e65e5c2d2f32a99e8c5f740cabae9075dab03ce7)
199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
2099ebb4caSwyllys  *
2199ebb4caSwyllys  *
22*e65e5c2dSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2399ebb4caSwyllys  * Use is subject to license terms.
2499ebb4caSwyllys  */
2599ebb4caSwyllys 
2699ebb4caSwyllys #include <stdio.h>
2799ebb4caSwyllys #include <string.h>
2899ebb4caSwyllys #include <ctype.h>
2999ebb4caSwyllys #include <malloc.h>
3099ebb4caSwyllys #include <libgen.h>
3199ebb4caSwyllys #include <errno.h>
3299ebb4caSwyllys #include <cryptoutil.h>
3399ebb4caSwyllys #include <security/cryptoki.h>
3499ebb4caSwyllys #include "common.h"
3599ebb4caSwyllys 
3699ebb4caSwyllys #include <kmfapi.h>
3799ebb4caSwyllys 
3899ebb4caSwyllys #define	SET_VALUE(f, s) \
3999ebb4caSwyllys 	kmfrv = f; \
4099ebb4caSwyllys 	if (kmfrv != KMF_OK) { \
4199ebb4caSwyllys 		cryptoerror(LOG_STDERR, \
4299ebb4caSwyllys 			gettext("Failed to %s: 0x%02\n"), \
4399ebb4caSwyllys 			s, kmfrv); \
4499ebb4caSwyllys 		goto cleanup; \
4599ebb4caSwyllys 	}
4699ebb4caSwyllys 
4799ebb4caSwyllys static KMF_RETURN
4899ebb4caSwyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
4999ebb4caSwyllys 	char *token, char *subject, char *altname,
5099ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
5199ebb4caSwyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
52d00756ccSwyllys 	int keylen, uint16_t kubits, int kucrit,
5399ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
54*e65e5c2dSWyllys Ingersoll 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
55*e65e5c2dSWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
5699ebb4caSwyllys {
5799ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
5899ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
5999ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
6099ebb4caSwyllys 	KMF_CSR_DATA	csr;
6199ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
6299ebb4caSwyllys 
6330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
6430a5e8faSwyllys 	int numattr = 0;
6530a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
6630a5e8faSwyllys 
6799ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
6899ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
6999ebb4caSwyllys 
7099ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
71*e65e5c2dSWyllys Ingersoll 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK)
7299ebb4caSwyllys 		return (kmfrv);
7399ebb4caSwyllys 
7499ebb4caSwyllys 	/* Select a PKCS11 token */
7599ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
76*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
7799ebb4caSwyllys 		return (kmfrv);
78*e65e5c2dSWyllys Ingersoll 	/*
79*e65e5c2dSWyllys Ingersoll 	 * Share the "genkeypair" routine for creating the keypair.
80*e65e5c2dSWyllys Ingersoll 	 */
81*e65e5c2dSWyllys Ingersoll 	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
82*e65e5c2dSWyllys Ingersoll 	    keyAlg, keylen, tokencred, curveoid, &prik, &pubk);
83*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
8499ebb4caSwyllys 		return (kmfrv);
8599ebb4caSwyllys 
8630a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
8799ebb4caSwyllys 
8830a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
8999ebb4caSwyllys 
9030a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
9199ebb4caSwyllys 
9230a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
9399ebb4caSwyllys 	    "SignatureAlgorithm");
9499ebb4caSwyllys 
9599ebb4caSwyllys 	if (altname != NULL) {
9630a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
9799ebb4caSwyllys 		    alttype), "SetCSRSubjectAltName");
9899ebb4caSwyllys 	}
9999ebb4caSwyllys 
10099ebb4caSwyllys 	if (kubits != 0) {
10130a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
10299ebb4caSwyllys 		    "SetCSRKeyUsage");
10399ebb4caSwyllys 	}
104d00756ccSwyllys 	if (ekulist != NULL) {
105d00756ccSwyllys 		int i;
106d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
107d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
108d00756ccSwyllys 			    &ekulist->ekulist[i],
109d00756ccSwyllys 			    ekulist->critlist[i]),
110d00756ccSwyllys 			    "Extended Key Usage");
111d00756ccSwyllys 		}
112d00756ccSwyllys 	}
11330a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
11499ebb4caSwyllys 	    KMF_OK) {
11530a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
11699ebb4caSwyllys 	}
11799ebb4caSwyllys 
11899ebb4caSwyllys cleanup:
11930a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
120a44b45c8SHuie-Ying Lee 	(void) kmf_free_signed_csr(&csr);
121a44b45c8SHuie-Ying Lee 
122a44b45c8SHuie-Ying Lee 	/* delete the public key */
12330a5e8faSwyllys 	numattr = 0;
12430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
12530a5e8faSwyllys 	    &kstype, sizeof (kstype));
12630a5e8faSwyllys 	numattr++;
12730a5e8faSwyllys 
12830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
12930a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
13030a5e8faSwyllys 	numattr++;
13130a5e8faSwyllys 
132a44b45c8SHuie-Ying Lee 	if (tokencred != NULL && tokencred->cred != NULL) {
133a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
134a44b45c8SHuie-Ying Lee 		    tokencred, sizeof (KMF_CREDENTIAL));
135a44b45c8SHuie-Ying Lee 		numattr++;
136a44b45c8SHuie-Ying Lee 	}
137a44b45c8SHuie-Ying Lee 
13830a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
13930a5e8faSwyllys 
140a44b45c8SHuie-Ying Lee 	/*
141a44b45c8SHuie-Ying Lee 	 * If there is an error, then we need to remove the private key
142a44b45c8SHuie-Ying Lee 	 * from the token.
143a44b45c8SHuie-Ying Lee 	 */
144a44b45c8SHuie-Ying Lee 	if (kmfrv != KMF_OK) {
145a44b45c8SHuie-Ying Lee 		numattr = 0;
146a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr,
147a44b45c8SHuie-Ying Lee 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
148a44b45c8SHuie-Ying Lee 		numattr++;
14999ebb4caSwyllys 
150a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr,
151a44b45c8SHuie-Ying Lee 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
152a44b45c8SHuie-Ying Lee 		numattr++;
153a44b45c8SHuie-Ying Lee 
154a44b45c8SHuie-Ying Lee 		if (tokencred != NULL && tokencred->cred != NULL) {
155a44b45c8SHuie-Ying Lee 			kmf_set_attr_at_index(attrlist, numattr,
156a44b45c8SHuie-Ying Lee 			    KMF_CREDENTIAL_ATTR, tokencred,
157a44b45c8SHuie-Ying Lee 			    sizeof (KMF_CREDENTIAL));
158a44b45c8SHuie-Ying Lee 			numattr++;
159a44b45c8SHuie-Ying Lee 		}
160a44b45c8SHuie-Ying Lee 
161a44b45c8SHuie-Ying Lee 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
162a44b45c8SHuie-Ying Lee 		    attrlist);
163a44b45c8SHuie-Ying Lee 	}
164a44b45c8SHuie-Ying Lee 
165a44b45c8SHuie-Ying Lee 	(void) kmf_free_kmf_key(kmfhandle, &prik);
16699ebb4caSwyllys 	return (kmfrv);
16799ebb4caSwyllys }
16899ebb4caSwyllys 
16999ebb4caSwyllys static KMF_RETURN
17099ebb4caSwyllys gencsr_file(KMF_HANDLE_T kmfhandle,
17199ebb4caSwyllys 	KMF_KEY_ALG keyAlg,
17299ebb4caSwyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
17399ebb4caSwyllys 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
17499ebb4caSwyllys 	int altcrit, uint16_t kubits, int kucrit,
175*e65e5c2dSWyllys Ingersoll 	char *outcsr, char *outkey, EKU_LIST *ekulist,
176*e65e5c2dSWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg)
17799ebb4caSwyllys {
17899ebb4caSwyllys 	KMF_RETURN kmfrv;
17999ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
18099ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
18199ebb4caSwyllys 	KMF_CSR_DATA	csr;
18299ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
18399ebb4caSwyllys 	char *fullcsrpath = NULL;
18499ebb4caSwyllys 	char *fullkeypath = NULL;
18599ebb4caSwyllys 
18630a5e8faSwyllys 
18799ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
18899ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
18999ebb4caSwyllys 
19099ebb4caSwyllys 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
19199ebb4caSwyllys 		cryptoerror(LOG_STDERR,
19299ebb4caSwyllys 		    gettext("No output file was specified for "
19399ebb4caSwyllys 		    "the csr or key\n"));
19499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
19599ebb4caSwyllys 	}
19699ebb4caSwyllys 	fullcsrpath = strdup(outcsr);
19799ebb4caSwyllys 	if (verify_file(fullcsrpath)) {
19899ebb4caSwyllys 		cryptoerror(LOG_STDERR,
19999ebb4caSwyllys 		    gettext("Cannot write the indicated output "
20099ebb4caSwyllys 		    "certificate file (%s).\n"), fullcsrpath);
20199ebb4caSwyllys 		free(fullcsrpath);
20299ebb4caSwyllys 		return (PK_ERR_USAGE);
20399ebb4caSwyllys 	}
204448b8615Swyllys 
20599ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
20630a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
20799ebb4caSwyllys 		return (kmfrv);
20899ebb4caSwyllys 	}
209*e65e5c2dSWyllys Ingersoll 	/*
210*e65e5c2dSWyllys Ingersoll 	 * Share the "genkeypair" routine for creating the keypair.
211*e65e5c2dSWyllys Ingersoll 	 */
212*e65e5c2dSWyllys Ingersoll 	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
213*e65e5c2dSWyllys Ingersoll 	    fmt, outkey, &prik, &pubk);
214*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
215*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
21699ebb4caSwyllys 
21730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
21899ebb4caSwyllys 	    "SetCSRPubKey");
21999ebb4caSwyllys 
22030a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
22199ebb4caSwyllys 
22230a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
22330a5e8faSwyllys 	    "kmf_set_csr_subject");
22499ebb4caSwyllys 
22530a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
22699ebb4caSwyllys 
22799ebb4caSwyllys 	if (altname != NULL) {
22830a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
22930a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
23099ebb4caSwyllys 	}
23199ebb4caSwyllys 	if (kubits != NULL) {
23230a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
23330a5e8faSwyllys 		    "kmf_set_csr_ku");
23499ebb4caSwyllys 	}
235d00756ccSwyllys 	if (ekulist != NULL) {
236d00756ccSwyllys 		int i;
237d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
238d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
239d00756ccSwyllys 			    &ekulist->ekulist[i],
240d00756ccSwyllys 			    ekulist->critlist[i]),
241d00756ccSwyllys 			    "Extended Key Usage");
242d00756ccSwyllys 		}
243d00756ccSwyllys 	}
24430a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
24599ebb4caSwyllys 	    KMF_OK) {
24630a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
24799ebb4caSwyllys 	}
24899ebb4caSwyllys 
24999ebb4caSwyllys cleanup:
25099ebb4caSwyllys 	if (fullkeypath)
25199ebb4caSwyllys 		free(fullkeypath);
25299ebb4caSwyllys 	if (fullcsrpath)
25399ebb4caSwyllys 		free(fullcsrpath);
25499ebb4caSwyllys 
25530a5e8faSwyllys 	kmf_free_data(&signedCsr);
25630a5e8faSwyllys 	kmf_free_kmf_key(kmfhandle, &prik);
25730a5e8faSwyllys 	kmf_free_signed_csr(&csr);
25899ebb4caSwyllys 
25999ebb4caSwyllys 	return (kmfrv);
26099ebb4caSwyllys }
26199ebb4caSwyllys 
26299ebb4caSwyllys static KMF_RETURN
26399ebb4caSwyllys gencsr_nss(KMF_HANDLE_T kmfhandle,
26499ebb4caSwyllys 	char *token, char *subject, char *altname,
26599ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
26699ebb4caSwyllys 	char *nickname, char *dir, char *prefix,
26799ebb4caSwyllys 	KMF_KEY_ALG keyAlg, int keylen,
26899ebb4caSwyllys 	uint16_t kubits, int kucrit,
26999ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
270*e65e5c2dSWyllys Ingersoll 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
271*e65e5c2dSWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
27299ebb4caSwyllys {
27399ebb4caSwyllys 	KMF_RETURN kmfrv;
27499ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
27599ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
27699ebb4caSwyllys 	KMF_CSR_DATA	csr;
27799ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
27830a5e8faSwyllys 
27930a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
28030a5e8faSwyllys 	int numattr = 0;
28130a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
28299ebb4caSwyllys 
28399ebb4caSwyllys 	if (token == NULL)
28499ebb4caSwyllys 		token = DEFAULT_NSS_TOKEN;
28599ebb4caSwyllys 
28699ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
28799ebb4caSwyllys 	if (kmfrv != KMF_OK)
28899ebb4caSwyllys 		return (kmfrv);
28999ebb4caSwyllys 
29099ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
29199ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
292448b8615Swyllys 	(void) memset(&pubk, 0, sizeof (pubk));
293448b8615Swyllys 	(void) memset(&prik, 0, sizeof (prik));
29499ebb4caSwyllys 
29599ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
29630a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
29799ebb4caSwyllys 		return (kmfrv);
29899ebb4caSwyllys 	}
29999ebb4caSwyllys 
300*e65e5c2dSWyllys Ingersoll 	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
301*e65e5c2dSWyllys Ingersoll 	    prefix, keyAlg, keylen, tokencred, curveoid,
302*e65e5c2dSWyllys Ingersoll 	    &prik, &pubk);
303*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
304*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
30599ebb4caSwyllys 
30630a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
30730a5e8faSwyllys 	    "kmf_set_csr_pubkey");
30830a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
30930a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
31030a5e8faSwyllys 	    "kmf_set_csr_subject");
31130a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
31299ebb4caSwyllys 
31399ebb4caSwyllys 	if (altname != NULL) {
31430a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
31530a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
31699ebb4caSwyllys 	}
31799ebb4caSwyllys 	if (kubits != NULL) {
31830a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
31930a5e8faSwyllys 		    "kmf_set_csr_ku");
32099ebb4caSwyllys 	}
321d00756ccSwyllys 	if (ekulist != NULL) {
322d00756ccSwyllys 		int i;
323d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
324d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
325d00756ccSwyllys 			    &ekulist->ekulist[i],
326d00756ccSwyllys 			    ekulist->critlist[i]),
327d00756ccSwyllys 			    "Extended Key Usage");
328d00756ccSwyllys 		}
329d00756ccSwyllys 	}
33030a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
33199ebb4caSwyllys 	    KMF_OK) {
33230a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
33399ebb4caSwyllys 	}
33499ebb4caSwyllys 
33599ebb4caSwyllys cleanup:
33630a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
33730a5e8faSwyllys 	(void) kmf_free_kmf_key(kmfhandle, &prik);
33830a5e8faSwyllys 
33999ebb4caSwyllys 	/* delete the key */
34030a5e8faSwyllys 	numattr = 0;
34130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
34230a5e8faSwyllys 	    &kstype, sizeof (kstype));
34330a5e8faSwyllys 	numattr++;
34430a5e8faSwyllys 
34530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
34630a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
34730a5e8faSwyllys 	numattr++;
34830a5e8faSwyllys 
34930a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
35030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
35130a5e8faSwyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
35230a5e8faSwyllys 		numattr++;
35330a5e8faSwyllys 	}
35430a5e8faSwyllys 
35530a5e8faSwyllys 	if (token && strlen(token)) {
35630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
35730a5e8faSwyllys 		    token, strlen(token));
35830a5e8faSwyllys 		numattr++;
35930a5e8faSwyllys 	}
36030a5e8faSwyllys 
36130a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
36230a5e8faSwyllys 
36330a5e8faSwyllys 	(void) kmf_free_signed_csr(&csr);
36499ebb4caSwyllys 
36599ebb4caSwyllys 	return (kmfrv);
36699ebb4caSwyllys }
36799ebb4caSwyllys 
36899ebb4caSwyllys int
36999ebb4caSwyllys pk_gencsr(int argc, char *argv[])
37099ebb4caSwyllys {
37199ebb4caSwyllys 	KMF_RETURN rv;
37299ebb4caSwyllys 	int opt;
37399ebb4caSwyllys 	extern int	optind_av;
37499ebb4caSwyllys 	extern char	*optarg_av;
37599ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = 0;
37699ebb4caSwyllys 	char *subject = NULL;
37799ebb4caSwyllys 	char *tokenname = NULL;
37899ebb4caSwyllys 	char *dir = NULL;
37999ebb4caSwyllys 	char *prefix = NULL;
38099ebb4caSwyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
38199ebb4caSwyllys 	char *certlabel = NULL;
38299ebb4caSwyllys 	char *outcsr = NULL;
38399ebb4caSwyllys 	char *outkey = NULL;
38499ebb4caSwyllys 	char *format = NULL;
38599ebb4caSwyllys 	char *altname = NULL;
38699ebb4caSwyllys 	char *kustr = NULL;
387d00756ccSwyllys 	char *ekustr = NULL;
388*e65e5c2dSWyllys Ingersoll 	char *hashname = NULL;
38999ebb4caSwyllys 	uint16_t kubits = 0;
39099ebb4caSwyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
39199ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
39299ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
39399ebb4caSwyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
3944165f465SWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
39599ebb4caSwyllys 	boolean_t interactive = B_FALSE;
39699ebb4caSwyllys 	char *subname = NULL;
39799ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
39899ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype = 0;
39999ebb4caSwyllys 	int altcrit = 0, kucrit = 0;
400d00756ccSwyllys 	EKU_LIST *ekulist = NULL;
401*e65e5c2dSWyllys Ingersoll 	KMF_OID *curveoid = NULL; /* ECC */
402*e65e5c2dSWyllys Ingersoll 	KMF_OID *hashoid = NULL;
403*e65e5c2dSWyllys Ingersoll 	int y_flag = 0;
40499ebb4caSwyllys 
40599ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
40699ebb4caSwyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
40799ebb4caSwyllys 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
408*e65e5c2dSWyllys Ingersoll 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
409*e65e5c2dSWyllys Ingersoll 	    "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {
41099ebb4caSwyllys 
41199ebb4caSwyllys 		switch (opt) {
41299ebb4caSwyllys 			case 'A':
41399ebb4caSwyllys 				altname = optarg_av;
41499ebb4caSwyllys 				break;
41599ebb4caSwyllys 			case 'i':
416592106a2SWyllys Ingersoll 				if (interactive)
41799ebb4caSwyllys 					return (PK_ERR_USAGE);
418592106a2SWyllys Ingersoll 				else if (subject) {
419592106a2SWyllys Ingersoll 					cryptoerror(LOG_STDERR,
420592106a2SWyllys Ingersoll 					    gettext("Interactive (-i) and "
421592106a2SWyllys Ingersoll 					    "subject options are mutually "
422592106a2SWyllys Ingersoll 					    "exclusive.\n"));
423592106a2SWyllys Ingersoll 					return (PK_ERR_USAGE);
424592106a2SWyllys Ingersoll 				} else
42599ebb4caSwyllys 					interactive = B_TRUE;
42699ebb4caSwyllys 				break;
42799ebb4caSwyllys 			case 'k':
42899ebb4caSwyllys 				kstype = KS2Int(optarg_av);
42999ebb4caSwyllys 				if (kstype == 0)
43099ebb4caSwyllys 					return (PK_ERR_USAGE);
43199ebb4caSwyllys 				break;
43299ebb4caSwyllys 			case 's':
433592106a2SWyllys Ingersoll 				if (subject)
43499ebb4caSwyllys 					return (PK_ERR_USAGE);
435592106a2SWyllys Ingersoll 				else if (interactive) {
436592106a2SWyllys Ingersoll 					cryptoerror(LOG_STDERR,
437592106a2SWyllys Ingersoll 					    gettext("Interactive (-i) and "
438592106a2SWyllys Ingersoll 					    "subject options are mutually "
439592106a2SWyllys Ingersoll 					    "exclusive.\n"));
440592106a2SWyllys Ingersoll 					return (PK_ERR_USAGE);
441592106a2SWyllys Ingersoll 				} else
44299ebb4caSwyllys 					subject = optarg_av;
44399ebb4caSwyllys 				break;
44499ebb4caSwyllys 			case 'l':
44599ebb4caSwyllys 			case 'n':
44699ebb4caSwyllys 				if (certlabel)
44799ebb4caSwyllys 					return (PK_ERR_USAGE);
44899ebb4caSwyllys 				certlabel = optarg_av;
44999ebb4caSwyllys 				break;
45099ebb4caSwyllys 			case 'T':
45199ebb4caSwyllys 				if (tokenname)
45299ebb4caSwyllys 					return (PK_ERR_USAGE);
45399ebb4caSwyllys 				tokenname = optarg_av;
45499ebb4caSwyllys 				break;
45599ebb4caSwyllys 			case 'd':
45699ebb4caSwyllys 				dir = optarg_av;
45799ebb4caSwyllys 				break;
45899ebb4caSwyllys 			case 'p':
45999ebb4caSwyllys 				if (prefix)
46099ebb4caSwyllys 					return (PK_ERR_USAGE);
46199ebb4caSwyllys 				prefix = optarg_av;
46299ebb4caSwyllys 				break;
46399ebb4caSwyllys 			case 't':
46499ebb4caSwyllys 				keytype = optarg_av;
46599ebb4caSwyllys 				break;
46699ebb4caSwyllys 			case 'u':
46799ebb4caSwyllys 				kustr = optarg_av;
46899ebb4caSwyllys 				break;
46999ebb4caSwyllys 			case 'y':
47099ebb4caSwyllys 				if (sscanf(optarg_av, "%d",
47199ebb4caSwyllys 				    &keylen) != 1) {
47299ebb4caSwyllys 					cryptoerror(LOG_STDERR,
47399ebb4caSwyllys 					    gettext("Unrecognized "
47430a5e8faSwyllys 					    "key length (%s)\n"), optarg_av);
47599ebb4caSwyllys 					return (PK_ERR_USAGE);
47699ebb4caSwyllys 				}
477*e65e5c2dSWyllys Ingersoll 				y_flag++;
47899ebb4caSwyllys 				break;
47999ebb4caSwyllys 			case 'c':
48099ebb4caSwyllys 				if (outcsr)
48199ebb4caSwyllys 					return (PK_ERR_USAGE);
48299ebb4caSwyllys 				outcsr = optarg_av;
48399ebb4caSwyllys 				break;
48499ebb4caSwyllys 			case 'K':
48599ebb4caSwyllys 				if (outkey)
48699ebb4caSwyllys 					return (PK_ERR_USAGE);
48799ebb4caSwyllys 				outkey = optarg_av;
48899ebb4caSwyllys 				break;
48999ebb4caSwyllys 			case 'F':
49099ebb4caSwyllys 				if (format)
49199ebb4caSwyllys 					return (PK_ERR_USAGE);
49299ebb4caSwyllys 				format = optarg_av;
49399ebb4caSwyllys 				break;
494d00756ccSwyllys 			case 'e':
495d00756ccSwyllys 				ekustr = optarg_av;
496d00756ccSwyllys 				break;
497*e65e5c2dSWyllys Ingersoll 			case 'C':
498*e65e5c2dSWyllys Ingersoll 				curveoid = ecc_name_to_oid(optarg_av);
499*e65e5c2dSWyllys Ingersoll 				if (curveoid == NULL) {
500*e65e5c2dSWyllys Ingersoll 					cryptoerror(LOG_STDERR,
501*e65e5c2dSWyllys Ingersoll 					    gettext("Unrecognized ECC "
502*e65e5c2dSWyllys Ingersoll 					    "curve.\n"));
503*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
504*e65e5c2dSWyllys Ingersoll 				}
505*e65e5c2dSWyllys Ingersoll 				break;
506*e65e5c2dSWyllys Ingersoll 			case 'E':
507*e65e5c2dSWyllys Ingersoll 				/*
508*e65e5c2dSWyllys Ingersoll 				 * This argument is only to be used
509*e65e5c2dSWyllys Ingersoll 				 * by itself, no other options should
510*e65e5c2dSWyllys Ingersoll 				 * be present.
511*e65e5c2dSWyllys Ingersoll 				 */
512*e65e5c2dSWyllys Ingersoll 				if (argc != 2) {
513*e65e5c2dSWyllys Ingersoll 					cryptoerror(LOG_STDERR,
514*e65e5c2dSWyllys Ingersoll 					    gettext("listcurves has no other "
515*e65e5c2dSWyllys Ingersoll 					    "options.\n"));
516*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
517*e65e5c2dSWyllys Ingersoll 				}
518*e65e5c2dSWyllys Ingersoll 				show_ecc_curves();
519*e65e5c2dSWyllys Ingersoll 				return (0);
520*e65e5c2dSWyllys Ingersoll 			case 'h':
521*e65e5c2dSWyllys Ingersoll 				hashname = optarg_av;
522*e65e5c2dSWyllys Ingersoll 				hashoid = ecc_name_to_oid(optarg_av);
523*e65e5c2dSWyllys Ingersoll 				if (hashoid == NULL) {
524*e65e5c2dSWyllys Ingersoll 					cryptoerror(LOG_STDERR,
525*e65e5c2dSWyllys Ingersoll 					    gettext("Unrecognized hash.\n"));
526*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
527*e65e5c2dSWyllys Ingersoll 				}
528*e65e5c2dSWyllys Ingersoll 				break;
52999ebb4caSwyllys 			default:
53099ebb4caSwyllys 				cryptoerror(LOG_STDERR, gettext(
53199ebb4caSwyllys 				    "unrecognized gencsr option '%s'\n"),
53299ebb4caSwyllys 				    argv[optind_av]);
53399ebb4caSwyllys 				return (PK_ERR_USAGE);
53499ebb4caSwyllys 		}
53599ebb4caSwyllys 	}
53699ebb4caSwyllys 	/* No additional args allowed. */
53799ebb4caSwyllys 	argc -= optind_av;
53899ebb4caSwyllys 	argv += optind_av;
53999ebb4caSwyllys 	if (argc) {
54099ebb4caSwyllys 		return (PK_ERR_USAGE);
54199ebb4caSwyllys 	}
54299ebb4caSwyllys 
54399ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
54499ebb4caSwyllys 	if (kstype == 0)
54599ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
54699ebb4caSwyllys 
547577f4726Swyllys 	DIR_OPTION_CHECK(kstype, dir);
548577f4726Swyllys 
5492cbed729Swyllys 	if (EMPTYSTRING(outcsr) && interactive) {
5502cbed729Swyllys 		(void) get_filename("CSR", &outcsr);
5512cbed729Swyllys 	}
55299ebb4caSwyllys 	if (EMPTYSTRING(outcsr)) {
55399ebb4caSwyllys 		(void) printf(gettext("A filename must be specified to hold"
55499ebb4caSwyllys 		    "the final certificate request data.\n"));
55599ebb4caSwyllys 		return (PK_ERR_USAGE);
5562cbed729Swyllys 	}
55799ebb4caSwyllys 	/*
55899ebb4caSwyllys 	 * verify that the outcsr file does not already exist
55999ebb4caSwyllys 	 * and that it can be created.
56099ebb4caSwyllys 	 */
56199ebb4caSwyllys 	rv = verify_file(outcsr);
56299ebb4caSwyllys 	if (rv != KMF_OK) {
56399ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
56499ebb4caSwyllys 		    "cannot be created.\n"), outcsr);
56599ebb4caSwyllys 		return (PK_ERR_USAGE);
56699ebb4caSwyllys 	}
56799ebb4caSwyllys 
5682cbed729Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
5692cbed729Swyllys 		if (EMPTYSTRING(certlabel) && interactive)
5702cbed729Swyllys 			(void) get_certlabel(&certlabel);
5712cbed729Swyllys 
5722cbed729Swyllys 		if (EMPTYSTRING(certlabel)) {
5732cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
57499ebb4caSwyllys 			    "specified to create a certificate request.\n"));
57599ebb4caSwyllys 			return (PK_ERR_USAGE);
57699ebb4caSwyllys 		}
5772cbed729Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
5782cbed729Swyllys 		if (EMPTYSTRING(outkey) && interactive)
5792cbed729Swyllys 			(void) get_filename("private key", &outkey);
5802cbed729Swyllys 
5812cbed729Swyllys 		if (EMPTYSTRING(outkey)) {
5822cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A key filename "
5832cbed729Swyllys 			    "must be specified to create a certificate "
5842cbed729Swyllys 			    "request.\n"));
5852cbed729Swyllys 			return (PK_ERR_USAGE);
5862cbed729Swyllys 		}
5872cbed729Swyllys 	}
58899ebb4caSwyllys 
58999ebb4caSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
59099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
59130a5e8faSwyllys 		    gettext("Error parsing format string (%s).\n"), format);
59299ebb4caSwyllys 		return (PK_ERR_USAGE);
59399ebb4caSwyllys 	}
59499ebb4caSwyllys 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
59599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
59699ebb4caSwyllys 		    gettext("CSR must be DER or PEM format.\n"));
59799ebb4caSwyllys 		return (PK_ERR_USAGE);
59899ebb4caSwyllys 	}
59999ebb4caSwyllys 
60099ebb4caSwyllys 	/*
60199ebb4caSwyllys 	 * Check the subject name.
60299ebb4caSwyllys 	 * If interactive is true, get it now interactively.
60399ebb4caSwyllys 	 */
60499ebb4caSwyllys 	if (interactive) {
60599ebb4caSwyllys 		if (get_subname(&subname) != KMF_OK) {
60699ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
60799ebb4caSwyllys 			    "subject name interactively.\n"));
60899ebb4caSwyllys 			return (PK_ERR_USAGE);
60999ebb4caSwyllys 		}
61099ebb4caSwyllys 	} else {
61199ebb4caSwyllys 		if (EMPTYSTRING(subject)) {
61299ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
61399ebb4caSwyllys 			    "-i must be specified to create a certificate "
61499ebb4caSwyllys 			    "request.\n"));
61599ebb4caSwyllys 			return (PK_ERR_USAGE);
61699ebb4caSwyllys 		} else {
61799ebb4caSwyllys 			subname = strdup(subject);
61899ebb4caSwyllys 			if (subname == NULL) {
61999ebb4caSwyllys 				cryptoerror(LOG_STDERR,
62099ebb4caSwyllys 				    gettext("Out of memory.\n"));
62199ebb4caSwyllys 				return (PK_ERR_SYSTEM);
62299ebb4caSwyllys 			}
62399ebb4caSwyllys 		}
62499ebb4caSwyllys 	}
62599ebb4caSwyllys 	if (altname != NULL) {
62699ebb4caSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
62799ebb4caSwyllys 		if (rv != KMF_OK) {
62899ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
62999ebb4caSwyllys 			    "must be specified as a name=value pair. "
63099ebb4caSwyllys 			    "See the man page for details."));
63199ebb4caSwyllys 			goto end;
63299ebb4caSwyllys 		} else {
63399ebb4caSwyllys 			/* advance the altname past the '=' sign */
63499ebb4caSwyllys 			char *p = strchr(altname, '=');
63599ebb4caSwyllys 			if (p != NULL)
63699ebb4caSwyllys 				altname = p + 1;
63799ebb4caSwyllys 		}
63899ebb4caSwyllys 	}
63999ebb4caSwyllys 
64099ebb4caSwyllys 	if (kustr != NULL) {
64199ebb4caSwyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
64299ebb4caSwyllys 		if (rv != KMF_OK) {
64399ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
64499ebb4caSwyllys 			    "must be specified as a comma-separated list. "
64599ebb4caSwyllys 			    "See the man page for details."));
64699ebb4caSwyllys 			goto end;
64799ebb4caSwyllys 		}
64899ebb4caSwyllys 	}
649d00756ccSwyllys 	if (ekustr != NULL) {
650d00756ccSwyllys 		rv = verify_ekunames(ekustr, &ekulist);
651d00756ccSwyllys 		if (rv != KMF_OK) {
652d00756ccSwyllys 			(void) fprintf(stderr, gettext("EKUs must "
653d00756ccSwyllys 			    "be specified as a comma-separated list. "
654d00756ccSwyllys 			    "See the man page for details.\n"));
655d00756ccSwyllys 			rv = PK_ERR_USAGE;
656d00756ccSwyllys 			goto end;
657d00756ccSwyllys 		}
658d00756ccSwyllys 	}
659*e65e5c2dSWyllys Ingersoll 	if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
660*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR,
661*e65e5c2dSWyllys Ingersoll 		    gettext("Unsupported key/hash combination (%s/%s).\n"),
662*e65e5c2dSWyllys Ingersoll 		    keytype, (hashname ? hashname : "none"));
66399ebb4caSwyllys 		goto end;
66499ebb4caSwyllys 	}
665*e65e5c2dSWyllys Ingersoll 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
666*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
667*e65e5c2dSWyllys Ingersoll 		    "valid for EC keytypes.\n"));
668*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
669*e65e5c2dSWyllys Ingersoll 	}
670*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
671*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("A curve must be "
672*e65e5c2dSWyllys Ingersoll 		    "specifed when using EC keys.\n"));
673*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
674*e65e5c2dSWyllys Ingersoll 	}
675*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
676*e65e5c2dSWyllys Ingersoll 		(void) fprintf(stderr, gettext("ECC certificates are"
677*e65e5c2dSWyllys Ingersoll 		    "only supported with the pkcs11 and nss keystores\n"));
678*e65e5c2dSWyllys Ingersoll 		rv = PK_ERR_USAGE;
679*e65e5c2dSWyllys Ingersoll 		goto end;
680*e65e5c2dSWyllys Ingersoll 	}
681*e65e5c2dSWyllys Ingersoll 
682*e65e5c2dSWyllys Ingersoll 	/* Adjust default keylength for NSS and DSA */
683*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
684*e65e5c2dSWyllys Ingersoll 		keylen = 1024;
68599ebb4caSwyllys 
68699ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
68799ebb4caSwyllys 		if (tokenname == NULL || !strlen(tokenname)) {
68899ebb4caSwyllys 			if (kstype == KMF_KEYSTORE_NSS) {
68999ebb4caSwyllys 				tokenname = "internal";
69099ebb4caSwyllys 			} else  {
69199ebb4caSwyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
69299ebb4caSwyllys 			}
69399ebb4caSwyllys 		}
69499ebb4caSwyllys 
69599ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
69699ebb4caSwyllys 	}
69799ebb4caSwyllys 
698577f4726Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
699577f4726Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
700577f4726Swyllys 		return (PK_ERR_USAGE);
701577f4726Swyllys 	}
702577f4726Swyllys 
703577f4726Swyllys 
70499ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
70599ebb4caSwyllys 		if (dir == NULL)
70699ebb4caSwyllys 			dir = PK_DEFAULT_DIRECTORY;
70799ebb4caSwyllys 
70899ebb4caSwyllys 		rv = gencsr_nss(kmfhandle,
70999ebb4caSwyllys 		    tokenname, subname, altname, alttype, altcrit,
71099ebb4caSwyllys 		    certlabel, dir, prefix,
71199ebb4caSwyllys 		    keyAlg, keylen, kubits, kucrit,
712*e65e5c2dSWyllys Ingersoll 		    fmt, outcsr, &tokencred, ekulist,
713*e65e5c2dSWyllys Ingersoll 		    sigAlg, curveoid);
71499ebb4caSwyllys 
71599ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
71699ebb4caSwyllys 		rv = gencsr_pkcs11(kmfhandle,
71799ebb4caSwyllys 		    tokenname, subname, altname, alttype, altcrit,
71899ebb4caSwyllys 		    certlabel, keyAlg, keylen,
719*e65e5c2dSWyllys Ingersoll 		    kubits, kucrit, fmt, outcsr, &tokencred,
720*e65e5c2dSWyllys Ingersoll 		    ekulist, sigAlg, curveoid);
72199ebb4caSwyllys 
72299ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
72399ebb4caSwyllys 		rv = gencsr_file(kmfhandle,
72499ebb4caSwyllys 		    keyAlg, keylen, fmt, subname, altname,
72599ebb4caSwyllys 		    alttype, altcrit, kubits, kucrit,
726*e65e5c2dSWyllys Ingersoll 		    outcsr, outkey, ekulist, sigAlg);
72799ebb4caSwyllys 	}
72899ebb4caSwyllys 
72999ebb4caSwyllys end:
730592106a2SWyllys Ingersoll 	if (rv != KMF_OK) {
73199ebb4caSwyllys 		display_error(kmfhandle, rv,
73299ebb4caSwyllys 		    gettext("Error creating CSR or keypair"));
73399ebb4caSwyllys 
734592106a2SWyllys Ingersoll 		if (rv == KMF_ERR_RDN_PARSER) {
735592106a2SWyllys Ingersoll 			cryptoerror(LOG_STDERR, gettext("subject or "
736592106a2SWyllys Ingersoll 			    "issuer name must be in proper DN format.\n"));
737592106a2SWyllys Ingersoll 		}
738592106a2SWyllys Ingersoll 	}
739592106a2SWyllys Ingersoll 
740d00756ccSwyllys 	if (ekulist != NULL)
741d00756ccSwyllys 		free_eku_list(ekulist);
742d00756ccSwyllys 
74399ebb4caSwyllys 	if (subname)
74499ebb4caSwyllys 		free(subname);
74599ebb4caSwyllys 
74699ebb4caSwyllys 	if (tokencred.cred != NULL)
74799ebb4caSwyllys 		free(tokencred.cred);
74899ebb4caSwyllys 
74930a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
75099ebb4caSwyllys 	if (rv != KMF_OK)
75199ebb4caSwyllys 		return (PK_ERR_USAGE);
75299ebb4caSwyllys 
75399ebb4caSwyllys 	return (0);
75499ebb4caSwyllys }
755