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*d00756ccSwyllys  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2399ebb4caSwyllys  * Use is subject to license terms.
2499ebb4caSwyllys  */
2599ebb4caSwyllys 
2699ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
2799ebb4caSwyllys 
2899ebb4caSwyllys #include <stdio.h>
2999ebb4caSwyllys #include <string.h>
3099ebb4caSwyllys #include <ctype.h>
3199ebb4caSwyllys #include <malloc.h>
3299ebb4caSwyllys #include <libgen.h>
3399ebb4caSwyllys #include <errno.h>
3499ebb4caSwyllys #include <cryptoutil.h>
3599ebb4caSwyllys #include <security/cryptoki.h>
3699ebb4caSwyllys #include "common.h"
3799ebb4caSwyllys 
3899ebb4caSwyllys #include <kmfapi.h>
3999ebb4caSwyllys 
4099ebb4caSwyllys #define	SET_VALUE(f, s) \
4199ebb4caSwyllys 	kmfrv = f; \
4299ebb4caSwyllys 	if (kmfrv != KMF_OK) { \
4399ebb4caSwyllys 		cryptoerror(LOG_STDERR, \
4499ebb4caSwyllys 			gettext("Failed to %s: 0x%02\n"), \
4599ebb4caSwyllys 			s, kmfrv); \
4699ebb4caSwyllys 		goto cleanup; \
4799ebb4caSwyllys 	}
4899ebb4caSwyllys 
4999ebb4caSwyllys static KMF_RETURN
5099ebb4caSwyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
5199ebb4caSwyllys 	char *token, char *subject, char *altname,
5299ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
5399ebb4caSwyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
54*d00756ccSwyllys 	int keylen, uint16_t kubits, int kucrit,
5599ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
56*d00756ccSwyllys 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
5799ebb4caSwyllys {
5899ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
5999ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
6099ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
6199ebb4caSwyllys 	KMF_CSR_DATA	csr;
6299ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
6399ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
6499ebb4caSwyllys 
6530a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
6630a5e8faSwyllys 	int numattr = 0;
6730a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
6830a5e8faSwyllys 	boolean_t storekey = TRUE;
6930a5e8faSwyllys 
7099ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
7199ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
7299ebb4caSwyllys 
7399ebb4caSwyllys 	if (keyAlg == KMF_DSA)
7499ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
7599ebb4caSwyllys 	else
7699ebb4caSwyllys 		sigAlg = KMF_ALGID_MD5WithRSA;
7799ebb4caSwyllys 
7899ebb4caSwyllys 
7999ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
8030a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
8199ebb4caSwyllys 		return (kmfrv);
8299ebb4caSwyllys 	}
8399ebb4caSwyllys 
8499ebb4caSwyllys 	/* Select a PKCS11 token */
8599ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
8699ebb4caSwyllys 	if (kmfrv != KMF_OK) {
8799ebb4caSwyllys 		return (kmfrv);
8899ebb4caSwyllys 	}
8999ebb4caSwyllys 
9030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
9130a5e8faSwyllys 	    &kstype, sizeof (kstype));
9230a5e8faSwyllys 	numattr++;
9330a5e8faSwyllys 
9430a5e8faSwyllys 	if (certlabel != NULL && strlen(certlabel)) {
9530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
9630a5e8faSwyllys 		    certlabel, strlen(certlabel));
9730a5e8faSwyllys 		numattr++;
9830a5e8faSwyllys 	}
9930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
10030a5e8faSwyllys 	    &keylen, sizeof (keylen));
10130a5e8faSwyllys 	numattr++;
10230a5e8faSwyllys 
10330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
10430a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
10530a5e8faSwyllys 	numattr++;
10630a5e8faSwyllys 
10730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
10830a5e8faSwyllys 	    tokencred, sizeof (KMF_CREDENTIAL));
10930a5e8faSwyllys 	numattr++;
11030a5e8faSwyllys 
11130a5e8faSwyllys 	if (token && strlen(token)) {
11230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
11330a5e8faSwyllys 		    token, strlen(token));
11430a5e8faSwyllys 		numattr++;
11530a5e8faSwyllys 	}
11630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
11730a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
11830a5e8faSwyllys 	numattr++;
11930a5e8faSwyllys 
12030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
12130a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
12230a5e8faSwyllys 	numattr++;
12330a5e8faSwyllys 
12430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
12530a5e8faSwyllys 	    &storekey, sizeof (storekey));
12630a5e8faSwyllys 	numattr++;
12730a5e8faSwyllys 
12830a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
12999ebb4caSwyllys 	if (kmfrv != KMF_OK) {
13099ebb4caSwyllys 		return (kmfrv);
13199ebb4caSwyllys 	}
13299ebb4caSwyllys 
13330a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
13499ebb4caSwyllys 
13530a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
13699ebb4caSwyllys 
13730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
13899ebb4caSwyllys 
13930a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
14030a5e8faSwyllys 	    "SignatureAlgorithm");
14199ebb4caSwyllys 
14299ebb4caSwyllys 	if (altname != NULL) {
14330a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
14430a5e8faSwyllys 		    alttype), "SetCSRSubjectAltName");
14599ebb4caSwyllys 	}
14699ebb4caSwyllys 
14799ebb4caSwyllys 	if (kubits != 0) {
14830a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
14930a5e8faSwyllys 		    "SetCSRKeyUsage");
15099ebb4caSwyllys 	}
151*d00756ccSwyllys 	if (ekulist != NULL) {
152*d00756ccSwyllys 		int i;
153*d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
154*d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
155*d00756ccSwyllys 			    &ekulist->ekulist[i],
156*d00756ccSwyllys 			    ekulist->critlist[i]),
157*d00756ccSwyllys 			    "Extended Key Usage");
158*d00756ccSwyllys 		}
159*d00756ccSwyllys 	}
16030a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
16130a5e8faSwyllys 	    KMF_OK) {
16230a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
16399ebb4caSwyllys 	}
16499ebb4caSwyllys 
16599ebb4caSwyllys cleanup:
16630a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
16730a5e8faSwyllys 	(void) kmf_free_kmf_key(kmfhandle, &prik);
16899ebb4caSwyllys 	/* delete the key */
16930a5e8faSwyllys 	numattr = 0;
17030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
17130a5e8faSwyllys 	    &kstype, sizeof (kstype));
17230a5e8faSwyllys 	numattr++;
17330a5e8faSwyllys 
17430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
17530a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
17630a5e8faSwyllys 	numattr++;
17730a5e8faSwyllys 
17830a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
17930a5e8faSwyllys 
18030a5e8faSwyllys 	(void) kmf_free_signed_csr(&csr);
18199ebb4caSwyllys 
18299ebb4caSwyllys 	return (kmfrv);
18399ebb4caSwyllys }
18499ebb4caSwyllys 
18599ebb4caSwyllys static KMF_RETURN
18699ebb4caSwyllys gencsr_file(KMF_HANDLE_T kmfhandle,
18799ebb4caSwyllys 	KMF_KEY_ALG keyAlg,
18899ebb4caSwyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
18999ebb4caSwyllys 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
19099ebb4caSwyllys 	int altcrit, uint16_t kubits, int kucrit,
191*d00756ccSwyllys 	char *dir, char *outcsr, char *outkey, EKU_LIST *ekulist)
19299ebb4caSwyllys {
19399ebb4caSwyllys 	KMF_RETURN kmfrv;
19499ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
19599ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
19699ebb4caSwyllys 	KMF_CSR_DATA	csr;
19799ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
19899ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
19999ebb4caSwyllys 	char *fullcsrpath = NULL;
20099ebb4caSwyllys 	char *fullkeypath = NULL;
20199ebb4caSwyllys 
20230a5e8faSwyllys 	int numattr = 0;
20330a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
20430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
20530a5e8faSwyllys 	boolean_t	storekey = TRUE;
20630a5e8faSwyllys 
20799ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
20899ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
20999ebb4caSwyllys 
21099ebb4caSwyllys 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
21199ebb4caSwyllys 		cryptoerror(LOG_STDERR,
21230a5e8faSwyllys 		    gettext("No output file was specified for "
21330a5e8faSwyllys 		    "the csr or key\n"));
21499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
21599ebb4caSwyllys 	}
21699ebb4caSwyllys 	if (dir != NULL) {
21799ebb4caSwyllys 		fullcsrpath = get_fullpath(dir, outcsr);
21899ebb4caSwyllys 		if (fullcsrpath == NULL) {
21999ebb4caSwyllys 			cryptoerror(LOG_STDERR,
22030a5e8faSwyllys 			    gettext("Cannot create file %s in "
22130a5e8faSwyllys 			    "directory %s\n"), dir, outcsr);
22299ebb4caSwyllys 			return (PK_ERR_USAGE);
22399ebb4caSwyllys 		}
22499ebb4caSwyllys 	} else {
22599ebb4caSwyllys 		fullcsrpath = strdup(outcsr);
22699ebb4caSwyllys 	}
22799ebb4caSwyllys 	if (verify_file(fullcsrpath)) {
22899ebb4caSwyllys 		cryptoerror(LOG_STDERR,
22930a5e8faSwyllys 		    gettext("Cannot write the indicated output "
23030a5e8faSwyllys 		    "certificate file (%s).\n"), fullcsrpath);
23199ebb4caSwyllys 		free(fullcsrpath);
23299ebb4caSwyllys 		return (PK_ERR_USAGE);
23399ebb4caSwyllys 	}
23499ebb4caSwyllys 	if (dir != NULL) {
23599ebb4caSwyllys 		fullkeypath = get_fullpath(dir, outkey);
23699ebb4caSwyllys 		if (fullkeypath == NULL) {
23799ebb4caSwyllys 			cryptoerror(LOG_STDERR,
23830a5e8faSwyllys 			    gettext("Cannot create file %s in "
23930a5e8faSwyllys 			    "directory %s\n"), dir, outkey);
24099ebb4caSwyllys 			free(fullcsrpath);
24199ebb4caSwyllys 			return (PK_ERR_USAGE);
24299ebb4caSwyllys 		}
24399ebb4caSwyllys 	} else {
24499ebb4caSwyllys 		fullkeypath = strdup(outkey);
24599ebb4caSwyllys 	}
24699ebb4caSwyllys 	if (verify_file(fullcsrpath)) {
24799ebb4caSwyllys 		cryptoerror(LOG_STDERR,
24830a5e8faSwyllys 		    gettext("Cannot write the indicated output "
24930a5e8faSwyllys 		    "key file (%s).\n"), fullkeypath);
25099ebb4caSwyllys 		free(fullcsrpath);
25199ebb4caSwyllys 		return (PK_ERR_USAGE);
25299ebb4caSwyllys 	}
25399ebb4caSwyllys 
25499ebb4caSwyllys 	if (keyAlg == KMF_DSA)
25599ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
25699ebb4caSwyllys 	else
25799ebb4caSwyllys 		sigAlg = KMF_ALGID_MD5WithRSA;
25899ebb4caSwyllys 
25999ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
26030a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
26199ebb4caSwyllys 		return (kmfrv);
26299ebb4caSwyllys 	}
26399ebb4caSwyllys 
26430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
26530a5e8faSwyllys 	    &kstype, sizeof (kstype));
26630a5e8faSwyllys 	numattr++;
26730a5e8faSwyllys 
26830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
26930a5e8faSwyllys 	    fullkeypath, strlen(fullkeypath));
27030a5e8faSwyllys 	numattr++;
27130a5e8faSwyllys 
27230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
27330a5e8faSwyllys 	    &keylen, sizeof (keylen));
27430a5e8faSwyllys 	numattr++;
27530a5e8faSwyllys 
27630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
27730a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
27830a5e8faSwyllys 	numattr++;
27930a5e8faSwyllys 
28030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
28130a5e8faSwyllys 	    &fmt, sizeof (fmt));
28230a5e8faSwyllys 	numattr++;
28399ebb4caSwyllys 
28430a5e8faSwyllys 	(void) memset(&prik, 0, sizeof (prik));
28530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
28630a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
28730a5e8faSwyllys 	numattr++;
28899ebb4caSwyllys 
28930a5e8faSwyllys 	(void) memset(&pubk, 0, sizeof (pubk));
29030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
29130a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
29230a5e8faSwyllys 	numattr++;
29330a5e8faSwyllys 
29430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
29530a5e8faSwyllys 	    &storekey, sizeof (storekey));
29630a5e8faSwyllys 	numattr++;
29730a5e8faSwyllys 
29830a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
29999ebb4caSwyllys 	if (kmfrv != KMF_OK) {
30099ebb4caSwyllys 		goto cleanup;
30199ebb4caSwyllys 	}
30230a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
30330a5e8faSwyllys 	    "SetCSRPubKey");
30499ebb4caSwyllys 
30530a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
30699ebb4caSwyllys 
30730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
30830a5e8faSwyllys 	    "kmf_set_csr_subject");
30999ebb4caSwyllys 
31030a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
31199ebb4caSwyllys 
31299ebb4caSwyllys 	if (altname != NULL) {
31330a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
31430a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
31599ebb4caSwyllys 	}
31699ebb4caSwyllys 	if (kubits != NULL) {
31730a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
31830a5e8faSwyllys 		    "kmf_set_csr_ku");
31999ebb4caSwyllys 	}
320*d00756ccSwyllys 	if (ekulist != NULL) {
321*d00756ccSwyllys 		int i;
322*d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
323*d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
324*d00756ccSwyllys 			    &ekulist->ekulist[i],
325*d00756ccSwyllys 			    ekulist->critlist[i]),
326*d00756ccSwyllys 			    "Extended Key Usage");
327*d00756ccSwyllys 		}
328*d00756ccSwyllys 	}
32930a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
33030a5e8faSwyllys 	    KMF_OK) {
33130a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
33299ebb4caSwyllys 	}
33399ebb4caSwyllys 
33499ebb4caSwyllys cleanup:
33599ebb4caSwyllys 	if (fullkeypath)
33699ebb4caSwyllys 		free(fullkeypath);
33799ebb4caSwyllys 	if (fullcsrpath)
33899ebb4caSwyllys 		free(fullcsrpath);
33999ebb4caSwyllys 
34030a5e8faSwyllys 	kmf_free_data(&signedCsr);
34130a5e8faSwyllys 	kmf_free_kmf_key(kmfhandle, &prik);
34230a5e8faSwyllys 	kmf_free_signed_csr(&csr);
34399ebb4caSwyllys 
34499ebb4caSwyllys 	return (kmfrv);
34599ebb4caSwyllys }
34699ebb4caSwyllys 
34799ebb4caSwyllys static KMF_RETURN
34899ebb4caSwyllys gencsr_nss(KMF_HANDLE_T kmfhandle,
34999ebb4caSwyllys 	char *token, char *subject, char *altname,
35099ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
35199ebb4caSwyllys 	char *nickname, char *dir, char *prefix,
35299ebb4caSwyllys 	KMF_KEY_ALG keyAlg, int keylen,
35399ebb4caSwyllys 	uint16_t kubits, int kucrit,
35499ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
355*d00756ccSwyllys 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
35699ebb4caSwyllys {
35799ebb4caSwyllys 	KMF_RETURN kmfrv;
35899ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
35999ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
36099ebb4caSwyllys 	KMF_CSR_DATA	csr;
36199ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
36299ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
36330a5e8faSwyllys 
36430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
36530a5e8faSwyllys 	int numattr = 0;
36630a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
36730a5e8faSwyllys 	boolean_t storekey = TRUE;
36899ebb4caSwyllys 
36999ebb4caSwyllys 	if (token == NULL)
37099ebb4caSwyllys 		token = DEFAULT_NSS_TOKEN;
37199ebb4caSwyllys 
37299ebb4caSwyllys 	if (keyAlg == KMF_DSA)
37399ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
37499ebb4caSwyllys 	else
37599ebb4caSwyllys 		sigAlg = KMF_ALGID_MD5WithRSA;
37699ebb4caSwyllys 
37799ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
37899ebb4caSwyllys 	if (kmfrv != KMF_OK)
37999ebb4caSwyllys 		return (kmfrv);
38099ebb4caSwyllys 
38199ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
38299ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
38399ebb4caSwyllys 
38499ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
38530a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
38699ebb4caSwyllys 		return (kmfrv);
38799ebb4caSwyllys 	}
38899ebb4caSwyllys 
38930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
39030a5e8faSwyllys 	    &kstype, sizeof (kstype));
39130a5e8faSwyllys 	numattr++;
39230a5e8faSwyllys 
39330a5e8faSwyllys 	if (nickname != NULL && strlen(nickname)) {
39430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
39530a5e8faSwyllys 		    nickname, strlen(nickname));
39630a5e8faSwyllys 		numattr++;
39730a5e8faSwyllys 	}
39830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
39930a5e8faSwyllys 	    &keylen, sizeof (keylen));
40030a5e8faSwyllys 	numattr++;
40130a5e8faSwyllys 
40230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
40330a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
40430a5e8faSwyllys 	numattr++;
40530a5e8faSwyllys 
40630a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
40730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
40830a5e8faSwyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
40930a5e8faSwyllys 		numattr++;
41030a5e8faSwyllys 	}
41130a5e8faSwyllys 
41230a5e8faSwyllys 	if (token && strlen(token)) {
41330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
41430a5e8faSwyllys 		    token, strlen(token));
41530a5e8faSwyllys 		numattr++;
41630a5e8faSwyllys 	}
41730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
41830a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
41930a5e8faSwyllys 	numattr++;
42099ebb4caSwyllys 
42130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
42230a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
42330a5e8faSwyllys 	numattr++;
42499ebb4caSwyllys 
42530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
42630a5e8faSwyllys 	    &storekey, sizeof (storekey));
42730a5e8faSwyllys 	numattr++;
42830a5e8faSwyllys 
42930a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
43099ebb4caSwyllys 	if (kmfrv != KMF_OK) {
43199ebb4caSwyllys 		goto cleanup;
43299ebb4caSwyllys 	}
43399ebb4caSwyllys 
43430a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
43530a5e8faSwyllys 	    "kmf_set_csr_pubkey");
43630a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
43730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
43830a5e8faSwyllys 	    "kmf_set_csr_subject");
43930a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
44099ebb4caSwyllys 
44199ebb4caSwyllys 	if (altname != NULL) {
44230a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
44330a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
44499ebb4caSwyllys 	}
44599ebb4caSwyllys 	if (kubits != NULL) {
44630a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
44730a5e8faSwyllys 		    "kmf_set_csr_ku");
44899ebb4caSwyllys 	}
449*d00756ccSwyllys 	if (ekulist != NULL) {
450*d00756ccSwyllys 		int i;
451*d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
452*d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
453*d00756ccSwyllys 			    &ekulist->ekulist[i],
454*d00756ccSwyllys 			    ekulist->critlist[i]),
455*d00756ccSwyllys 			    "Extended Key Usage");
456*d00756ccSwyllys 		}
457*d00756ccSwyllys 	}
45830a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
45930a5e8faSwyllys 	    KMF_OK) {
46030a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
46199ebb4caSwyllys 	}
46299ebb4caSwyllys 
46399ebb4caSwyllys cleanup:
46430a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
46530a5e8faSwyllys 	(void) kmf_free_kmf_key(kmfhandle, &prik);
46630a5e8faSwyllys 
46799ebb4caSwyllys 	/* delete the key */
46830a5e8faSwyllys 	numattr = 0;
46930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
47030a5e8faSwyllys 	    &kstype, sizeof (kstype));
47130a5e8faSwyllys 	numattr++;
47230a5e8faSwyllys 
47330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
47430a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
47530a5e8faSwyllys 	numattr++;
47630a5e8faSwyllys 
47730a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
47830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
47930a5e8faSwyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
48030a5e8faSwyllys 		numattr++;
48130a5e8faSwyllys 	}
48230a5e8faSwyllys 
48330a5e8faSwyllys 	if (token && strlen(token)) {
48430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
48530a5e8faSwyllys 		    token, strlen(token));
48630a5e8faSwyllys 		numattr++;
48730a5e8faSwyllys 	}
48830a5e8faSwyllys 
48930a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
49030a5e8faSwyllys 
49130a5e8faSwyllys 	(void) kmf_free_signed_csr(&csr);
49299ebb4caSwyllys 
49399ebb4caSwyllys 	return (kmfrv);
49499ebb4caSwyllys }
49599ebb4caSwyllys 
49699ebb4caSwyllys int
49799ebb4caSwyllys pk_gencsr(int argc, char *argv[])
49899ebb4caSwyllys {
49999ebb4caSwyllys 	KMF_RETURN rv;
50099ebb4caSwyllys 	int opt;
50199ebb4caSwyllys 	extern int	optind_av;
50299ebb4caSwyllys 	extern char	*optarg_av;
50399ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = 0;
50499ebb4caSwyllys 	char *subject = NULL;
50599ebb4caSwyllys 	char *tokenname = NULL;
50699ebb4caSwyllys 	char *dir = NULL;
50799ebb4caSwyllys 	char *prefix = NULL;
50899ebb4caSwyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
50999ebb4caSwyllys 	char *certlabel = NULL;
51099ebb4caSwyllys 	char *outcsr = NULL;
51199ebb4caSwyllys 	char *outkey = NULL;
51299ebb4caSwyllys 	char *format = NULL;
51399ebb4caSwyllys 	char *altname = NULL;
51499ebb4caSwyllys 	char *kustr = NULL;
515*d00756ccSwyllys 	char *ekustr = NULL;
51699ebb4caSwyllys 	uint16_t kubits = 0;
51799ebb4caSwyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
51899ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
51999ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
52099ebb4caSwyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
52199ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
52299ebb4caSwyllys 	boolean_t interactive = B_FALSE;
52399ebb4caSwyllys 	char *subname = NULL;
52499ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
52599ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype = 0;
52699ebb4caSwyllys 	int altcrit = 0, kucrit = 0;
527*d00756ccSwyllys 	EKU_LIST *ekulist = NULL;
52899ebb4caSwyllys 
52999ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
53030a5e8faSwyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
53130a5e8faSwyllys 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
532*d00756ccSwyllys 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)"
53330a5e8faSwyllys 	    "K:(outkey)F:(format)")) != EOF) {
53499ebb4caSwyllys 
53599ebb4caSwyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
53699ebb4caSwyllys 			return (PK_ERR_USAGE);
53799ebb4caSwyllys 
53899ebb4caSwyllys 		switch (opt) {
53999ebb4caSwyllys 			case 'A':
54099ebb4caSwyllys 				altname = optarg_av;
54199ebb4caSwyllys 				break;
54299ebb4caSwyllys 			case 'i':
54399ebb4caSwyllys 				if (interactive || subject)
54499ebb4caSwyllys 					return (PK_ERR_USAGE);
54599ebb4caSwyllys 				else
54699ebb4caSwyllys 					interactive = B_TRUE;
54799ebb4caSwyllys 				break;
54899ebb4caSwyllys 			case 'k':
54999ebb4caSwyllys 				kstype = KS2Int(optarg_av);
55099ebb4caSwyllys 				if (kstype == 0)
55199ebb4caSwyllys 					return (PK_ERR_USAGE);
55299ebb4caSwyllys 				break;
55399ebb4caSwyllys 			case 's':
55499ebb4caSwyllys 				if (interactive || subject)
55599ebb4caSwyllys 					return (PK_ERR_USAGE);
55699ebb4caSwyllys 				else
55799ebb4caSwyllys 					subject = optarg_av;
55899ebb4caSwyllys 				break;
55999ebb4caSwyllys 			case 'l':
56099ebb4caSwyllys 			case 'n':
56199ebb4caSwyllys 				if (certlabel)
56299ebb4caSwyllys 					return (PK_ERR_USAGE);
56399ebb4caSwyllys 				certlabel = optarg_av;
56499ebb4caSwyllys 				break;
56599ebb4caSwyllys 			case 'T':
56699ebb4caSwyllys 				if (tokenname)
56799ebb4caSwyllys 					return (PK_ERR_USAGE);
56899ebb4caSwyllys 				tokenname = optarg_av;
56999ebb4caSwyllys 				break;
57099ebb4caSwyllys 			case 'd':
57199ebb4caSwyllys 				dir = optarg_av;
57299ebb4caSwyllys 				break;
57399ebb4caSwyllys 			case 'p':
57499ebb4caSwyllys 				if (prefix)
57599ebb4caSwyllys 					return (PK_ERR_USAGE);
57699ebb4caSwyllys 				prefix = optarg_av;
57799ebb4caSwyllys 				break;
57899ebb4caSwyllys 			case 't':
57999ebb4caSwyllys 				keytype = optarg_av;
58099ebb4caSwyllys 				break;
58199ebb4caSwyllys 			case 'u':
58299ebb4caSwyllys 				kustr = optarg_av;
58399ebb4caSwyllys 				break;
58499ebb4caSwyllys 			case 'y':
58599ebb4caSwyllys 				if (sscanf(optarg_av, "%d",
58630a5e8faSwyllys 				    &keylen) != 1) {
58799ebb4caSwyllys 					cryptoerror(LOG_STDERR,
58830a5e8faSwyllys 					    gettext("Unrecognized "
58930a5e8faSwyllys 					    "key length (%s)\n"), optarg_av);
59099ebb4caSwyllys 					return (PK_ERR_USAGE);
59199ebb4caSwyllys 				}
59299ebb4caSwyllys 				break;
59399ebb4caSwyllys 			case 'c':
59499ebb4caSwyllys 				if (outcsr)
59599ebb4caSwyllys 					return (PK_ERR_USAGE);
59699ebb4caSwyllys 				outcsr = optarg_av;
59799ebb4caSwyllys 				break;
59899ebb4caSwyllys 			case 'K':
59999ebb4caSwyllys 				if (outkey)
60099ebb4caSwyllys 					return (PK_ERR_USAGE);
60199ebb4caSwyllys 				outkey = optarg_av;
60299ebb4caSwyllys 				break;
60399ebb4caSwyllys 			case 'F':
60499ebb4caSwyllys 				if (format)
60599ebb4caSwyllys 					return (PK_ERR_USAGE);
60699ebb4caSwyllys 				format = optarg_av;
60799ebb4caSwyllys 				break;
608*d00756ccSwyllys 			case 'e':
609*d00756ccSwyllys 				ekustr = optarg_av;
610*d00756ccSwyllys 				break;
61199ebb4caSwyllys 			default:
61299ebb4caSwyllys 				cryptoerror(LOG_STDERR, gettext(
61330a5e8faSwyllys 				    "unrecognized gencsr option '%s'\n"),
61430a5e8faSwyllys 				    argv[optind_av]);
61599ebb4caSwyllys 				return (PK_ERR_USAGE);
61699ebb4caSwyllys 		}
61799ebb4caSwyllys 	}
61899ebb4caSwyllys 	/* No additional args allowed. */
61999ebb4caSwyllys 	argc -= optind_av;
62099ebb4caSwyllys 	argv += optind_av;
62199ebb4caSwyllys 	if (argc) {
62299ebb4caSwyllys 		return (PK_ERR_USAGE);
62399ebb4caSwyllys 	}
62499ebb4caSwyllys 
62530a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
62699ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
62799ebb4caSwyllys 		return (PK_ERR_USAGE);
62899ebb4caSwyllys 	}
62999ebb4caSwyllys 
63099ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
63199ebb4caSwyllys 	if (kstype == 0)
63299ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
63399ebb4caSwyllys 
6342cbed729Swyllys 	if (EMPTYSTRING(outcsr) && interactive) {
6352cbed729Swyllys 		(void) get_filename("CSR", &outcsr);
6362cbed729Swyllys 	}
63799ebb4caSwyllys 	if (EMPTYSTRING(outcsr)) {
63899ebb4caSwyllys 		(void) printf(gettext("A filename must be specified to hold"
63930a5e8faSwyllys 		    "the final certificate request data.\n"));
64099ebb4caSwyllys 		return (PK_ERR_USAGE);
64199ebb4caSwyllys 	}
6422cbed729Swyllys 	/*
6432cbed729Swyllys 	 * verify that the outcsr file does not already exist
6442cbed729Swyllys 	 * and that it can be created.
6452cbed729Swyllys 	 */
6462cbed729Swyllys 	rv = verify_file(outcsr);
6472cbed729Swyllys 	if (rv != KMF_OK) {
6482cbed729Swyllys 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
6492cbed729Swyllys 		    "cannot be created.\n"), outcsr);
65099ebb4caSwyllys 		return (PK_ERR_USAGE);
65199ebb4caSwyllys 	}
65299ebb4caSwyllys 
6532cbed729Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
6542cbed729Swyllys 		if (EMPTYSTRING(certlabel) && interactive)
6552cbed729Swyllys 			(void) get_certlabel(&certlabel);
6562cbed729Swyllys 
6572cbed729Swyllys 		if (EMPTYSTRING(certlabel)) {
6582cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
6592cbed729Swyllys 			    "specified to create a certificate request.\n"));
6602cbed729Swyllys 			return (PK_ERR_USAGE);
6612cbed729Swyllys 		}
6622cbed729Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
6632cbed729Swyllys 		if (EMPTYSTRING(outkey) && interactive)
6642cbed729Swyllys 			(void) get_filename("private key", &outkey);
6652cbed729Swyllys 
6662cbed729Swyllys 		if (EMPTYSTRING(outkey)) {
6672cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A key filename "
6682cbed729Swyllys 			    "must be specified to create a certificate "
6692cbed729Swyllys 			    "request.\n"));
6702cbed729Swyllys 			return (PK_ERR_USAGE);
6712cbed729Swyllys 		}
6722cbed729Swyllys 	}
6732cbed729Swyllys 
67499ebb4caSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
67599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
67630a5e8faSwyllys 		    gettext("Error parsing format string (%s).\n"), format);
67799ebb4caSwyllys 		return (PK_ERR_USAGE);
67899ebb4caSwyllys 	}
67999ebb4caSwyllys 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
68099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
68130a5e8faSwyllys 		    gettext("CSR must be DER or PEM format.\n"));
68299ebb4caSwyllys 		return (PK_ERR_USAGE);
68399ebb4caSwyllys 	}
68499ebb4caSwyllys 
68599ebb4caSwyllys 	/*
68699ebb4caSwyllys 	 * Check the subject name.
68799ebb4caSwyllys 	 * If interactive is true, get it now interactively.
68899ebb4caSwyllys 	 */
68999ebb4caSwyllys 	if (interactive) {
69099ebb4caSwyllys 		if (get_subname(&subname) != KMF_OK) {
69199ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
69299ebb4caSwyllys 			    "subject name interactively.\n"));
69399ebb4caSwyllys 			return (PK_ERR_USAGE);
69499ebb4caSwyllys 		}
69599ebb4caSwyllys 	} else {
69699ebb4caSwyllys 		if (EMPTYSTRING(subject)) {
69799ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
69899ebb4caSwyllys 			    "-i must be specified to create a certificate "
69999ebb4caSwyllys 			    "request.\n"));
70099ebb4caSwyllys 			return (PK_ERR_USAGE);
70199ebb4caSwyllys 		} else {
70299ebb4caSwyllys 			subname = strdup(subject);
70399ebb4caSwyllys 			if (subname == NULL) {
70499ebb4caSwyllys 				cryptoerror(LOG_STDERR,
70599ebb4caSwyllys 				    gettext("Out of memory.\n"));
70699ebb4caSwyllys 				return (PK_ERR_SYSTEM);
70799ebb4caSwyllys 			}
70899ebb4caSwyllys 		}
70999ebb4caSwyllys 	}
71099ebb4caSwyllys 	if (altname != NULL) {
71199ebb4caSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
71299ebb4caSwyllys 		if (rv != KMF_OK) {
71399ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
71430a5e8faSwyllys 			    "must be specified as a name=value pair. "
71530a5e8faSwyllys 			    "See the man page for details."));
71699ebb4caSwyllys 			goto end;
71799ebb4caSwyllys 		} else {
71899ebb4caSwyllys 			/* advance the altname past the '=' sign */
71999ebb4caSwyllys 			char *p = strchr(altname, '=');
72099ebb4caSwyllys 			if (p != NULL)
72199ebb4caSwyllys 				altname = p + 1;
72299ebb4caSwyllys 		}
72399ebb4caSwyllys 	}
72499ebb4caSwyllys 
72599ebb4caSwyllys 	if (kustr != NULL) {
72699ebb4caSwyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
72799ebb4caSwyllys 		if (rv != KMF_OK) {
72899ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
72930a5e8faSwyllys 			    "must be specified as a comma-separated list. "
73030a5e8faSwyllys 			    "See the man page for details."));
73199ebb4caSwyllys 			goto end;
73299ebb4caSwyllys 		}
73399ebb4caSwyllys 	}
734*d00756ccSwyllys 	if (ekustr != NULL) {
735*d00756ccSwyllys 		rv = verify_ekunames(ekustr, &ekulist);
736*d00756ccSwyllys 		if (rv != KMF_OK) {
737*d00756ccSwyllys 			(void) fprintf(stderr, gettext("EKUs must "
738*d00756ccSwyllys 			    "be specified as a comma-separated list. "
739*d00756ccSwyllys 			    "See the man page for details.\n"));
740*d00756ccSwyllys 			rv = PK_ERR_USAGE;
741*d00756ccSwyllys 			goto end;
742*d00756ccSwyllys 		}
743*d00756ccSwyllys 	}
744*d00756ccSwyllys 
745*d00756ccSwyllys 
74699ebb4caSwyllys 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
74799ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
74830a5e8faSwyllys 		    keytype);
74999ebb4caSwyllys 		goto end;
75099ebb4caSwyllys 	}
75199ebb4caSwyllys 
75299ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
75399ebb4caSwyllys 		if (tokenname == NULL || !strlen(tokenname)) {
75499ebb4caSwyllys 			if (kstype == KMF_KEYSTORE_NSS) {
75599ebb4caSwyllys 				tokenname = "internal";
75699ebb4caSwyllys 			} else  {
75799ebb4caSwyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
75899ebb4caSwyllys 			}
75999ebb4caSwyllys 		}
76099ebb4caSwyllys 
76199ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
76299ebb4caSwyllys 	}
76399ebb4caSwyllys 
76499ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
76599ebb4caSwyllys 		if (dir == NULL)
76699ebb4caSwyllys 			dir = PK_DEFAULT_DIRECTORY;
76799ebb4caSwyllys 
76899ebb4caSwyllys 		rv = gencsr_nss(kmfhandle,
76930a5e8faSwyllys 		    tokenname, subname, altname, alttype, altcrit,
77030a5e8faSwyllys 		    certlabel, dir, prefix,
77130a5e8faSwyllys 		    keyAlg, keylen, kubits, kucrit,
772*d00756ccSwyllys 		    fmt, outcsr, &tokencred, ekulist);
77399ebb4caSwyllys 
77499ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
77599ebb4caSwyllys 		rv = gencsr_pkcs11(kmfhandle,
77630a5e8faSwyllys 		    tokenname, subname, altname, alttype, altcrit,
77730a5e8faSwyllys 		    certlabel, keyAlg, keylen,
778*d00756ccSwyllys 		    kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
77999ebb4caSwyllys 
78099ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
78199ebb4caSwyllys 		rv = gencsr_file(kmfhandle,
78230a5e8faSwyllys 		    keyAlg, keylen, fmt, subname, altname,
78330a5e8faSwyllys 		    alttype, altcrit, kubits, kucrit,
784*d00756ccSwyllys 		    dir, outcsr, outkey, ekulist);
78599ebb4caSwyllys 	}
78699ebb4caSwyllys 
78799ebb4caSwyllys end:
78899ebb4caSwyllys 	if (rv != KMF_OK)
78999ebb4caSwyllys 		display_error(kmfhandle, rv,
79030a5e8faSwyllys 		    gettext("Error creating CSR or keypair"));
79199ebb4caSwyllys 
792*d00756ccSwyllys 	if (ekulist != NULL)
793*d00756ccSwyllys 		free_eku_list(ekulist);
794*d00756ccSwyllys 
79599ebb4caSwyllys 	if (subname)
79699ebb4caSwyllys 		free(subname);
79799ebb4caSwyllys 
79899ebb4caSwyllys 	if (tokencred.cred != NULL)
79999ebb4caSwyllys 		free(tokencred.cred);
80099ebb4caSwyllys 
80130a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
80299ebb4caSwyllys 	if (rv != KMF_OK)
80399ebb4caSwyllys 		return (PK_ERR_USAGE);
80499ebb4caSwyllys 
80599ebb4caSwyllys 	return (0);
80699ebb4caSwyllys }
807