xref: /titanic_51/usr/src/cmd/cmd-crypto/pktool/gencsr.c (revision 4165f46543b20d435f7ef0aced6239f7e97b12ff)
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  *
22a44b45c8SHuie-Ying Lee  * Copyright 2009 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,
54d00756ccSwyllys 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
5599ebb4caSwyllys {
5699ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
5799ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
5899ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
5999ebb4caSwyllys 	KMF_CSR_DATA	csr;
6099ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
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 	boolean_t storekey = TRUE;
6730a5e8faSwyllys 
6899ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
6999ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
7099ebb4caSwyllys 
7199ebb4caSwyllys 	if (keyAlg == KMF_DSA)
7299ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
7399ebb4caSwyllys 	else
74*4165f465SWyllys Ingersoll 		sigAlg = KMF_ALGID_SHA1WithRSA;
7599ebb4caSwyllys 
7699ebb4caSwyllys 
7799ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
7830a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
7999ebb4caSwyllys 		return (kmfrv);
8099ebb4caSwyllys 	}
8199ebb4caSwyllys 
8299ebb4caSwyllys 	/* Select a PKCS11 token */
8399ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
8499ebb4caSwyllys 	if (kmfrv != KMF_OK) {
8599ebb4caSwyllys 		return (kmfrv);
8699ebb4caSwyllys 	}
8799ebb4caSwyllys 
8830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
8930a5e8faSwyllys 	    &kstype, sizeof (kstype));
9030a5e8faSwyllys 	numattr++;
9130a5e8faSwyllys 
9230a5e8faSwyllys 	if (certlabel != NULL && strlen(certlabel)) {
9330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
9430a5e8faSwyllys 		    certlabel, strlen(certlabel));
9530a5e8faSwyllys 		numattr++;
9630a5e8faSwyllys 	}
9730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
9830a5e8faSwyllys 	    &keylen, sizeof (keylen));
9930a5e8faSwyllys 	numattr++;
10030a5e8faSwyllys 
10130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
10230a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
10330a5e8faSwyllys 	numattr++;
10430a5e8faSwyllys 
10530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
10630a5e8faSwyllys 	    tokencred, sizeof (KMF_CREDENTIAL));
10730a5e8faSwyllys 	numattr++;
10830a5e8faSwyllys 
10930a5e8faSwyllys 	if (token && strlen(token)) {
11030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
11130a5e8faSwyllys 		    token, strlen(token));
11230a5e8faSwyllys 		numattr++;
11330a5e8faSwyllys 	}
11430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
11530a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
11630a5e8faSwyllys 	numattr++;
11730a5e8faSwyllys 
11830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
11930a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
12030a5e8faSwyllys 	numattr++;
12130a5e8faSwyllys 
12230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
12330a5e8faSwyllys 	    &storekey, sizeof (storekey));
12430a5e8faSwyllys 	numattr++;
12530a5e8faSwyllys 
12630a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
12799ebb4caSwyllys 	if (kmfrv != KMF_OK) {
12899ebb4caSwyllys 		return (kmfrv);
12999ebb4caSwyllys 	}
13099ebb4caSwyllys 
13130a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
13299ebb4caSwyllys 
13330a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
13499ebb4caSwyllys 
13530a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
13699ebb4caSwyllys 
13730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
13899ebb4caSwyllys 	    "SignatureAlgorithm");
13999ebb4caSwyllys 
14099ebb4caSwyllys 	if (altname != NULL) {
14130a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
14299ebb4caSwyllys 		    alttype), "SetCSRSubjectAltName");
14399ebb4caSwyllys 	}
14499ebb4caSwyllys 
14599ebb4caSwyllys 	if (kubits != 0) {
14630a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
14799ebb4caSwyllys 		    "SetCSRKeyUsage");
14899ebb4caSwyllys 	}
149d00756ccSwyllys 	if (ekulist != NULL) {
150d00756ccSwyllys 		int i;
151d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
152d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
153d00756ccSwyllys 			    &ekulist->ekulist[i],
154d00756ccSwyllys 			    ekulist->critlist[i]),
155d00756ccSwyllys 			    "Extended Key Usage");
156d00756ccSwyllys 		}
157d00756ccSwyllys 	}
15830a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
15999ebb4caSwyllys 	    KMF_OK) {
16030a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
16199ebb4caSwyllys 	}
16299ebb4caSwyllys 
16399ebb4caSwyllys cleanup:
16430a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
165a44b45c8SHuie-Ying Lee 	(void) kmf_free_signed_csr(&csr);
166a44b45c8SHuie-Ying Lee 
167a44b45c8SHuie-Ying Lee 	/* delete the public key */
16830a5e8faSwyllys 	numattr = 0;
16930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
17030a5e8faSwyllys 	    &kstype, sizeof (kstype));
17130a5e8faSwyllys 	numattr++;
17230a5e8faSwyllys 
17330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
17430a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
17530a5e8faSwyllys 	numattr++;
17630a5e8faSwyllys 
177a44b45c8SHuie-Ying Lee 	if (tokencred != NULL && tokencred->cred != NULL) {
178a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
179a44b45c8SHuie-Ying Lee 		    tokencred, sizeof (KMF_CREDENTIAL));
180a44b45c8SHuie-Ying Lee 		numattr++;
181a44b45c8SHuie-Ying Lee 	}
182a44b45c8SHuie-Ying Lee 
18330a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
18430a5e8faSwyllys 
185a44b45c8SHuie-Ying Lee 	/*
186a44b45c8SHuie-Ying Lee 	 * If there is an error, then we need to remove the private key
187a44b45c8SHuie-Ying Lee 	 * from the token.
188a44b45c8SHuie-Ying Lee 	 */
189a44b45c8SHuie-Ying Lee 	if (kmfrv != KMF_OK) {
190a44b45c8SHuie-Ying Lee 		numattr = 0;
191a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr,
192a44b45c8SHuie-Ying Lee 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
193a44b45c8SHuie-Ying Lee 		numattr++;
19499ebb4caSwyllys 
195a44b45c8SHuie-Ying Lee 		kmf_set_attr_at_index(attrlist, numattr,
196a44b45c8SHuie-Ying Lee 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
197a44b45c8SHuie-Ying Lee 		numattr++;
198a44b45c8SHuie-Ying Lee 
199a44b45c8SHuie-Ying Lee 		if (tokencred != NULL && tokencred->cred != NULL) {
200a44b45c8SHuie-Ying Lee 			kmf_set_attr_at_index(attrlist, numattr,
201a44b45c8SHuie-Ying Lee 			    KMF_CREDENTIAL_ATTR, tokencred,
202a44b45c8SHuie-Ying Lee 			    sizeof (KMF_CREDENTIAL));
203a44b45c8SHuie-Ying Lee 			numattr++;
204a44b45c8SHuie-Ying Lee 		}
205a44b45c8SHuie-Ying Lee 
206a44b45c8SHuie-Ying Lee 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
207a44b45c8SHuie-Ying Lee 		    attrlist);
208a44b45c8SHuie-Ying Lee 	}
209a44b45c8SHuie-Ying Lee 
210a44b45c8SHuie-Ying Lee 	(void) kmf_free_kmf_key(kmfhandle, &prik);
21199ebb4caSwyllys 	return (kmfrv);
21299ebb4caSwyllys }
21399ebb4caSwyllys 
21499ebb4caSwyllys static KMF_RETURN
21599ebb4caSwyllys gencsr_file(KMF_HANDLE_T kmfhandle,
21699ebb4caSwyllys 	KMF_KEY_ALG keyAlg,
21799ebb4caSwyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
21899ebb4caSwyllys 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
21999ebb4caSwyllys 	int altcrit, uint16_t kubits, int kucrit,
220448b8615Swyllys 	char *outcsr, char *outkey, EKU_LIST *ekulist)
22199ebb4caSwyllys {
22299ebb4caSwyllys 	KMF_RETURN kmfrv;
22399ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
22499ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
22599ebb4caSwyllys 	KMF_CSR_DATA	csr;
22699ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
22799ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
22899ebb4caSwyllys 	char *fullcsrpath = NULL;
22999ebb4caSwyllys 	char *fullkeypath = NULL;
23099ebb4caSwyllys 
23130a5e8faSwyllys 	int numattr = 0;
23230a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
23330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
23430a5e8faSwyllys 	boolean_t	storekey = TRUE;
23530a5e8faSwyllys 
23699ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
23799ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
23899ebb4caSwyllys 
23999ebb4caSwyllys 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
24099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
24199ebb4caSwyllys 		    gettext("No output file was specified for "
24299ebb4caSwyllys 		    "the csr or key\n"));
24399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
24499ebb4caSwyllys 	}
24599ebb4caSwyllys 	fullcsrpath = strdup(outcsr);
24699ebb4caSwyllys 	if (verify_file(fullcsrpath)) {
24799ebb4caSwyllys 		cryptoerror(LOG_STDERR,
24899ebb4caSwyllys 		    gettext("Cannot write the indicated output "
24999ebb4caSwyllys 		    "certificate file (%s).\n"), fullcsrpath);
25099ebb4caSwyllys 		free(fullcsrpath);
25199ebb4caSwyllys 		return (PK_ERR_USAGE);
25299ebb4caSwyllys 	}
253448b8615Swyllys 
25499ebb4caSwyllys 	fullkeypath = strdup(outkey);
25599ebb4caSwyllys 	if (verify_file(fullcsrpath)) {
25699ebb4caSwyllys 		cryptoerror(LOG_STDERR,
25799ebb4caSwyllys 		    gettext("Cannot write the indicated output "
25899ebb4caSwyllys 		    "key file (%s).\n"), fullkeypath);
25999ebb4caSwyllys 		free(fullcsrpath);
26099ebb4caSwyllys 		return (PK_ERR_USAGE);
26199ebb4caSwyllys 	}
26299ebb4caSwyllys 
26399ebb4caSwyllys 	if (keyAlg == KMF_DSA)
26499ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
26599ebb4caSwyllys 	else
266*4165f465SWyllys Ingersoll 		sigAlg = KMF_ALGID_SHA1WithRSA;
26799ebb4caSwyllys 
26899ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
26930a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
27099ebb4caSwyllys 		return (kmfrv);
27199ebb4caSwyllys 	}
27299ebb4caSwyllys 
27330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
27430a5e8faSwyllys 	    &kstype, sizeof (kstype));
27530a5e8faSwyllys 	numattr++;
27699ebb4caSwyllys 
27730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
27830a5e8faSwyllys 	    fullkeypath, strlen(fullkeypath));
27930a5e8faSwyllys 	numattr++;
28099ebb4caSwyllys 
28130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
28230a5e8faSwyllys 	    &keylen, sizeof (keylen));
28330a5e8faSwyllys 	numattr++;
28430a5e8faSwyllys 
28530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
28630a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
28730a5e8faSwyllys 	numattr++;
28830a5e8faSwyllys 
28930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
29030a5e8faSwyllys 	    &fmt, sizeof (fmt));
29130a5e8faSwyllys 	numattr++;
29230a5e8faSwyllys 
29330a5e8faSwyllys 	(void) memset(&prik, 0, sizeof (prik));
29430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
29530a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
29630a5e8faSwyllys 	numattr++;
29730a5e8faSwyllys 
29830a5e8faSwyllys 	(void) memset(&pubk, 0, sizeof (pubk));
29930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
30030a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
30130a5e8faSwyllys 	numattr++;
30230a5e8faSwyllys 
30330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
30430a5e8faSwyllys 	    &storekey, sizeof (storekey));
30530a5e8faSwyllys 	numattr++;
30630a5e8faSwyllys 
30730a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
30899ebb4caSwyllys 	if (kmfrv != KMF_OK) {
30999ebb4caSwyllys 		goto cleanup;
31099ebb4caSwyllys 	}
31130a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
31299ebb4caSwyllys 	    "SetCSRPubKey");
31399ebb4caSwyllys 
31430a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
31599ebb4caSwyllys 
31630a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
31730a5e8faSwyllys 	    "kmf_set_csr_subject");
31899ebb4caSwyllys 
31930a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
32099ebb4caSwyllys 
32199ebb4caSwyllys 	if (altname != NULL) {
32230a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
32330a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
32499ebb4caSwyllys 	}
32599ebb4caSwyllys 	if (kubits != NULL) {
32630a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
32730a5e8faSwyllys 		    "kmf_set_csr_ku");
32899ebb4caSwyllys 	}
329d00756ccSwyllys 	if (ekulist != NULL) {
330d00756ccSwyllys 		int i;
331d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
332d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
333d00756ccSwyllys 			    &ekulist->ekulist[i],
334d00756ccSwyllys 			    ekulist->critlist[i]),
335d00756ccSwyllys 			    "Extended Key Usage");
336d00756ccSwyllys 		}
337d00756ccSwyllys 	}
33830a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
33999ebb4caSwyllys 	    KMF_OK) {
34030a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
34199ebb4caSwyllys 	}
34299ebb4caSwyllys 
34399ebb4caSwyllys cleanup:
34499ebb4caSwyllys 	if (fullkeypath)
34599ebb4caSwyllys 		free(fullkeypath);
34699ebb4caSwyllys 	if (fullcsrpath)
34799ebb4caSwyllys 		free(fullcsrpath);
34899ebb4caSwyllys 
34930a5e8faSwyllys 	kmf_free_data(&signedCsr);
35030a5e8faSwyllys 	kmf_free_kmf_key(kmfhandle, &prik);
35130a5e8faSwyllys 	kmf_free_signed_csr(&csr);
35299ebb4caSwyllys 
35399ebb4caSwyllys 	return (kmfrv);
35499ebb4caSwyllys }
35599ebb4caSwyllys 
35699ebb4caSwyllys static KMF_RETURN
35799ebb4caSwyllys gencsr_nss(KMF_HANDLE_T kmfhandle,
35899ebb4caSwyllys 	char *token, char *subject, char *altname,
35999ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
36099ebb4caSwyllys 	char *nickname, char *dir, char *prefix,
36199ebb4caSwyllys 	KMF_KEY_ALG keyAlg, int keylen,
36299ebb4caSwyllys 	uint16_t kubits, int kucrit,
36399ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt, char *csrfile,
364d00756ccSwyllys 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
36599ebb4caSwyllys {
36699ebb4caSwyllys 	KMF_RETURN kmfrv;
36799ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
36899ebb4caSwyllys 	KMF_X509_NAME	csrSubject;
36999ebb4caSwyllys 	KMF_CSR_DATA	csr;
37099ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg;
37199ebb4caSwyllys 	KMF_DATA signedCsr = {NULL, 0};
37230a5e8faSwyllys 
37330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
37430a5e8faSwyllys 	int numattr = 0;
37530a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
37630a5e8faSwyllys 	boolean_t storekey = TRUE;
37799ebb4caSwyllys 
37899ebb4caSwyllys 	if (token == NULL)
37999ebb4caSwyllys 		token = DEFAULT_NSS_TOKEN;
38099ebb4caSwyllys 
38199ebb4caSwyllys 	if (keyAlg == KMF_DSA)
38299ebb4caSwyllys 		sigAlg = KMF_ALGID_SHA1WithDSA;
38399ebb4caSwyllys 	else
384*4165f465SWyllys Ingersoll 		sigAlg = KMF_ALGID_SHA1WithRSA;
38599ebb4caSwyllys 
38699ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
38799ebb4caSwyllys 	if (kmfrv != KMF_OK)
38899ebb4caSwyllys 		return (kmfrv);
38999ebb4caSwyllys 
39099ebb4caSwyllys 	(void) memset(&csr, 0, sizeof (csr));
39199ebb4caSwyllys 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
392448b8615Swyllys 	(void) memset(&pubk, 0, sizeof (pubk));
393448b8615Swyllys 	(void) memset(&prik, 0, sizeof (prik));
39499ebb4caSwyllys 
39599ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
39630a5e8faSwyllys 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
39799ebb4caSwyllys 		return (kmfrv);
39899ebb4caSwyllys 	}
39999ebb4caSwyllys 
40030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
40130a5e8faSwyllys 	    &kstype, sizeof (kstype));
40230a5e8faSwyllys 	numattr++;
40399ebb4caSwyllys 
40430a5e8faSwyllys 	if (nickname != NULL && strlen(nickname)) {
40530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
40630a5e8faSwyllys 		    nickname, strlen(nickname));
40730a5e8faSwyllys 		numattr++;
40830a5e8faSwyllys 	}
40930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
41030a5e8faSwyllys 	    &keylen, sizeof (keylen));
41130a5e8faSwyllys 	numattr++;
41299ebb4caSwyllys 
41330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
41430a5e8faSwyllys 	    &keyAlg, sizeof (keyAlg));
41530a5e8faSwyllys 	numattr++;
41630a5e8faSwyllys 
41730a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
41830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
41930a5e8faSwyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
42030a5e8faSwyllys 		numattr++;
42130a5e8faSwyllys 	}
42230a5e8faSwyllys 
42330a5e8faSwyllys 	if (token && strlen(token)) {
42430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
42530a5e8faSwyllys 		    token, strlen(token));
42630a5e8faSwyllys 		numattr++;
42730a5e8faSwyllys 	}
42830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
42930a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
43030a5e8faSwyllys 	numattr++;
43130a5e8faSwyllys 
43230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
43330a5e8faSwyllys 	    &prik, sizeof (KMF_KEY_HANDLE));
43430a5e8faSwyllys 	numattr++;
43530a5e8faSwyllys 
43630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
43730a5e8faSwyllys 	    &storekey, sizeof (storekey));
43830a5e8faSwyllys 	numattr++;
43930a5e8faSwyllys 
44030a5e8faSwyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
44199ebb4caSwyllys 	if (kmfrv != KMF_OK) {
44299ebb4caSwyllys 		goto cleanup;
44399ebb4caSwyllys 	}
44499ebb4caSwyllys 
44530a5e8faSwyllys 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
44630a5e8faSwyllys 	    "kmf_set_csr_pubkey");
44730a5e8faSwyllys 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
44830a5e8faSwyllys 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
44930a5e8faSwyllys 	    "kmf_set_csr_subject");
45030a5e8faSwyllys 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
45199ebb4caSwyllys 
45299ebb4caSwyllys 	if (altname != NULL) {
45330a5e8faSwyllys 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
45430a5e8faSwyllys 		    alttype), "kmf_set_csr_subject_altname");
45599ebb4caSwyllys 	}
45699ebb4caSwyllys 	if (kubits != NULL) {
45730a5e8faSwyllys 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
45830a5e8faSwyllys 		    "kmf_set_csr_ku");
45999ebb4caSwyllys 	}
460d00756ccSwyllys 	if (ekulist != NULL) {
461d00756ccSwyllys 		int i;
462d00756ccSwyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
463d00756ccSwyllys 			SET_VALUE(kmf_add_csr_eku(&csr,
464d00756ccSwyllys 			    &ekulist->ekulist[i],
465d00756ccSwyllys 			    ekulist->critlist[i]),
466d00756ccSwyllys 			    "Extended Key Usage");
467d00756ccSwyllys 		}
468d00756ccSwyllys 	}
46930a5e8faSwyllys 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
47099ebb4caSwyllys 	    KMF_OK) {
47130a5e8faSwyllys 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
47299ebb4caSwyllys 	}
47399ebb4caSwyllys 
47499ebb4caSwyllys cleanup:
47530a5e8faSwyllys 	(void) kmf_free_data(&signedCsr);
47630a5e8faSwyllys 	(void) kmf_free_kmf_key(kmfhandle, &prik);
47730a5e8faSwyllys 
47899ebb4caSwyllys 	/* delete the key */
47930a5e8faSwyllys 	numattr = 0;
48030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
48130a5e8faSwyllys 	    &kstype, sizeof (kstype));
48230a5e8faSwyllys 	numattr++;
48330a5e8faSwyllys 
48430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
48530a5e8faSwyllys 	    &pubk, sizeof (KMF_KEY_HANDLE));
48630a5e8faSwyllys 	numattr++;
48730a5e8faSwyllys 
48830a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
48930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
49030a5e8faSwyllys 		    tokencred, sizeof (KMF_CREDENTIAL));
49130a5e8faSwyllys 		numattr++;
49230a5e8faSwyllys 	}
49330a5e8faSwyllys 
49430a5e8faSwyllys 	if (token && strlen(token)) {
49530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
49630a5e8faSwyllys 		    token, strlen(token));
49730a5e8faSwyllys 		numattr++;
49830a5e8faSwyllys 	}
49930a5e8faSwyllys 
50030a5e8faSwyllys 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
50130a5e8faSwyllys 
50230a5e8faSwyllys 	(void) kmf_free_signed_csr(&csr);
50399ebb4caSwyllys 
50499ebb4caSwyllys 	return (kmfrv);
50599ebb4caSwyllys }
50699ebb4caSwyllys 
50799ebb4caSwyllys int
50899ebb4caSwyllys pk_gencsr(int argc, char *argv[])
50999ebb4caSwyllys {
51099ebb4caSwyllys 	KMF_RETURN rv;
51199ebb4caSwyllys 	int opt;
51299ebb4caSwyllys 	extern int	optind_av;
51399ebb4caSwyllys 	extern char	*optarg_av;
51499ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = 0;
51599ebb4caSwyllys 	char *subject = NULL;
51699ebb4caSwyllys 	char *tokenname = NULL;
51799ebb4caSwyllys 	char *dir = NULL;
51899ebb4caSwyllys 	char *prefix = NULL;
51999ebb4caSwyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
52099ebb4caSwyllys 	char *certlabel = NULL;
52199ebb4caSwyllys 	char *outcsr = NULL;
52299ebb4caSwyllys 	char *outkey = NULL;
52399ebb4caSwyllys 	char *format = NULL;
52499ebb4caSwyllys 	char *altname = NULL;
52599ebb4caSwyllys 	char *kustr = NULL;
526d00756ccSwyllys 	char *ekustr = NULL;
52799ebb4caSwyllys 	uint16_t kubits = 0;
52899ebb4caSwyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
52999ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
53099ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
53199ebb4caSwyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
532*4165f465SWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
53399ebb4caSwyllys 	boolean_t interactive = B_FALSE;
53499ebb4caSwyllys 	char *subname = NULL;
53599ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
53699ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype = 0;
53799ebb4caSwyllys 	int altcrit = 0, kucrit = 0;
538d00756ccSwyllys 	EKU_LIST *ekulist = NULL;
53999ebb4caSwyllys 
54099ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
54199ebb4caSwyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
54299ebb4caSwyllys 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
543d00756ccSwyllys 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)"
54499ebb4caSwyllys 	    "K:(outkey)F:(format)")) != EOF) {
54599ebb4caSwyllys 
54699ebb4caSwyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
54799ebb4caSwyllys 			return (PK_ERR_USAGE);
54899ebb4caSwyllys 
54999ebb4caSwyllys 		switch (opt) {
55099ebb4caSwyllys 			case 'A':
55199ebb4caSwyllys 				altname = optarg_av;
55299ebb4caSwyllys 				break;
55399ebb4caSwyllys 			case 'i':
554592106a2SWyllys Ingersoll 				if (interactive)
55599ebb4caSwyllys 					return (PK_ERR_USAGE);
556592106a2SWyllys Ingersoll 				else if (subject) {
557592106a2SWyllys Ingersoll 					cryptoerror(LOG_STDERR,
558592106a2SWyllys Ingersoll 					    gettext("Interactive (-i) and "
559592106a2SWyllys Ingersoll 					    "subject options are mutually "
560592106a2SWyllys Ingersoll 					    "exclusive.\n"));
561592106a2SWyllys Ingersoll 					return (PK_ERR_USAGE);
562592106a2SWyllys Ingersoll 				} else
56399ebb4caSwyllys 					interactive = B_TRUE;
56499ebb4caSwyllys 				break;
56599ebb4caSwyllys 			case 'k':
56699ebb4caSwyllys 				kstype = KS2Int(optarg_av);
56799ebb4caSwyllys 				if (kstype == 0)
56899ebb4caSwyllys 					return (PK_ERR_USAGE);
56999ebb4caSwyllys 				break;
57099ebb4caSwyllys 			case 's':
571592106a2SWyllys Ingersoll 				if (subject)
57299ebb4caSwyllys 					return (PK_ERR_USAGE);
573592106a2SWyllys Ingersoll 				else if (interactive) {
574592106a2SWyllys Ingersoll 					cryptoerror(LOG_STDERR,
575592106a2SWyllys Ingersoll 					    gettext("Interactive (-i) and "
576592106a2SWyllys Ingersoll 					    "subject options are mutually "
577592106a2SWyllys Ingersoll 					    "exclusive.\n"));
578592106a2SWyllys Ingersoll 					return (PK_ERR_USAGE);
579592106a2SWyllys Ingersoll 				} else
58099ebb4caSwyllys 					subject = optarg_av;
58199ebb4caSwyllys 				break;
58299ebb4caSwyllys 			case 'l':
58399ebb4caSwyllys 			case 'n':
58499ebb4caSwyllys 				if (certlabel)
58599ebb4caSwyllys 					return (PK_ERR_USAGE);
58699ebb4caSwyllys 				certlabel = optarg_av;
58799ebb4caSwyllys 				break;
58899ebb4caSwyllys 			case 'T':
58999ebb4caSwyllys 				if (tokenname)
59099ebb4caSwyllys 					return (PK_ERR_USAGE);
59199ebb4caSwyllys 				tokenname = optarg_av;
59299ebb4caSwyllys 				break;
59399ebb4caSwyllys 			case 'd':
59499ebb4caSwyllys 				dir = optarg_av;
59599ebb4caSwyllys 				break;
59699ebb4caSwyllys 			case 'p':
59799ebb4caSwyllys 				if (prefix)
59899ebb4caSwyllys 					return (PK_ERR_USAGE);
59999ebb4caSwyllys 				prefix = optarg_av;
60099ebb4caSwyllys 				break;
60199ebb4caSwyllys 			case 't':
60299ebb4caSwyllys 				keytype = optarg_av;
60399ebb4caSwyllys 				break;
60499ebb4caSwyllys 			case 'u':
60599ebb4caSwyllys 				kustr = optarg_av;
60699ebb4caSwyllys 				break;
60799ebb4caSwyllys 			case 'y':
60899ebb4caSwyllys 				if (sscanf(optarg_av, "%d",
60999ebb4caSwyllys 				    &keylen) != 1) {
61099ebb4caSwyllys 					cryptoerror(LOG_STDERR,
61199ebb4caSwyllys 					    gettext("Unrecognized "
61230a5e8faSwyllys 					    "key length (%s)\n"), optarg_av);
61399ebb4caSwyllys 					return (PK_ERR_USAGE);
61499ebb4caSwyllys 				}
61599ebb4caSwyllys 				break;
61699ebb4caSwyllys 			case 'c':
61799ebb4caSwyllys 				if (outcsr)
61899ebb4caSwyllys 					return (PK_ERR_USAGE);
61999ebb4caSwyllys 				outcsr = optarg_av;
62099ebb4caSwyllys 				break;
62199ebb4caSwyllys 			case 'K':
62299ebb4caSwyllys 				if (outkey)
62399ebb4caSwyllys 					return (PK_ERR_USAGE);
62499ebb4caSwyllys 				outkey = optarg_av;
62599ebb4caSwyllys 				break;
62699ebb4caSwyllys 			case 'F':
62799ebb4caSwyllys 				if (format)
62899ebb4caSwyllys 					return (PK_ERR_USAGE);
62999ebb4caSwyllys 				format = optarg_av;
63099ebb4caSwyllys 				break;
631d00756ccSwyllys 			case 'e':
632d00756ccSwyllys 				ekustr = optarg_av;
633d00756ccSwyllys 				break;
63499ebb4caSwyllys 			default:
63599ebb4caSwyllys 				cryptoerror(LOG_STDERR, gettext(
63699ebb4caSwyllys 				    "unrecognized gencsr option '%s'\n"),
63799ebb4caSwyllys 				    argv[optind_av]);
63899ebb4caSwyllys 				return (PK_ERR_USAGE);
63999ebb4caSwyllys 		}
64099ebb4caSwyllys 	}
64199ebb4caSwyllys 	/* No additional args allowed. */
64299ebb4caSwyllys 	argc -= optind_av;
64399ebb4caSwyllys 	argv += optind_av;
64499ebb4caSwyllys 	if (argc) {
64599ebb4caSwyllys 		return (PK_ERR_USAGE);
64699ebb4caSwyllys 	}
64799ebb4caSwyllys 
64899ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
64999ebb4caSwyllys 	if (kstype == 0)
65099ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
65199ebb4caSwyllys 
652577f4726Swyllys 	DIR_OPTION_CHECK(kstype, dir);
653577f4726Swyllys 
6542cbed729Swyllys 	if (EMPTYSTRING(outcsr) && interactive) {
6552cbed729Swyllys 		(void) get_filename("CSR", &outcsr);
6562cbed729Swyllys 	}
65799ebb4caSwyllys 	if (EMPTYSTRING(outcsr)) {
65899ebb4caSwyllys 		(void) printf(gettext("A filename must be specified to hold"
65999ebb4caSwyllys 		    "the final certificate request data.\n"));
66099ebb4caSwyllys 		return (PK_ERR_USAGE);
6612cbed729Swyllys 	}
66299ebb4caSwyllys 	/*
66399ebb4caSwyllys 	 * verify that the outcsr file does not already exist
66499ebb4caSwyllys 	 * and that it can be created.
66599ebb4caSwyllys 	 */
66699ebb4caSwyllys 	rv = verify_file(outcsr);
66799ebb4caSwyllys 	if (rv != KMF_OK) {
66899ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
66999ebb4caSwyllys 		    "cannot be created.\n"), outcsr);
67099ebb4caSwyllys 		return (PK_ERR_USAGE);
67199ebb4caSwyllys 	}
67299ebb4caSwyllys 
6732cbed729Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
6742cbed729Swyllys 		if (EMPTYSTRING(certlabel) && interactive)
6752cbed729Swyllys 			(void) get_certlabel(&certlabel);
6762cbed729Swyllys 
6772cbed729Swyllys 		if (EMPTYSTRING(certlabel)) {
6782cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
67999ebb4caSwyllys 			    "specified to create a certificate request.\n"));
68099ebb4caSwyllys 			return (PK_ERR_USAGE);
68199ebb4caSwyllys 		}
6822cbed729Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
6832cbed729Swyllys 		if (EMPTYSTRING(outkey) && interactive)
6842cbed729Swyllys 			(void) get_filename("private key", &outkey);
6852cbed729Swyllys 
6862cbed729Swyllys 		if (EMPTYSTRING(outkey)) {
6872cbed729Swyllys 			cryptoerror(LOG_STDERR, gettext("A key filename "
6882cbed729Swyllys 			    "must be specified to create a certificate "
6892cbed729Swyllys 			    "request.\n"));
6902cbed729Swyllys 			return (PK_ERR_USAGE);
6912cbed729Swyllys 		}
6922cbed729Swyllys 	}
69399ebb4caSwyllys 
69499ebb4caSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
69599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
69630a5e8faSwyllys 		    gettext("Error parsing format string (%s).\n"), format);
69799ebb4caSwyllys 		return (PK_ERR_USAGE);
69899ebb4caSwyllys 	}
69999ebb4caSwyllys 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
70099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
70199ebb4caSwyllys 		    gettext("CSR must be DER or PEM format.\n"));
70299ebb4caSwyllys 		return (PK_ERR_USAGE);
70399ebb4caSwyllys 	}
70499ebb4caSwyllys 
70599ebb4caSwyllys 	/*
70699ebb4caSwyllys 	 * Check the subject name.
70799ebb4caSwyllys 	 * If interactive is true, get it now interactively.
70899ebb4caSwyllys 	 */
70999ebb4caSwyllys 	if (interactive) {
71099ebb4caSwyllys 		if (get_subname(&subname) != KMF_OK) {
71199ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
71299ebb4caSwyllys 			    "subject name interactively.\n"));
71399ebb4caSwyllys 			return (PK_ERR_USAGE);
71499ebb4caSwyllys 		}
71599ebb4caSwyllys 	} else {
71699ebb4caSwyllys 		if (EMPTYSTRING(subject)) {
71799ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
71899ebb4caSwyllys 			    "-i must be specified to create a certificate "
71999ebb4caSwyllys 			    "request.\n"));
72099ebb4caSwyllys 			return (PK_ERR_USAGE);
72199ebb4caSwyllys 		} else {
72299ebb4caSwyllys 			subname = strdup(subject);
72399ebb4caSwyllys 			if (subname == NULL) {
72499ebb4caSwyllys 				cryptoerror(LOG_STDERR,
72599ebb4caSwyllys 				    gettext("Out of memory.\n"));
72699ebb4caSwyllys 				return (PK_ERR_SYSTEM);
72799ebb4caSwyllys 			}
72899ebb4caSwyllys 		}
72999ebb4caSwyllys 	}
73099ebb4caSwyllys 	if (altname != NULL) {
73199ebb4caSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
73299ebb4caSwyllys 		if (rv != KMF_OK) {
73399ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
73499ebb4caSwyllys 			    "must be specified as a name=value pair. "
73599ebb4caSwyllys 			    "See the man page for details."));
73699ebb4caSwyllys 			goto end;
73799ebb4caSwyllys 		} else {
73899ebb4caSwyllys 			/* advance the altname past the '=' sign */
73999ebb4caSwyllys 			char *p = strchr(altname, '=');
74099ebb4caSwyllys 			if (p != NULL)
74199ebb4caSwyllys 				altname = p + 1;
74299ebb4caSwyllys 		}
74399ebb4caSwyllys 	}
74499ebb4caSwyllys 
74599ebb4caSwyllys 	if (kustr != NULL) {
74699ebb4caSwyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
74799ebb4caSwyllys 		if (rv != KMF_OK) {
74899ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
74999ebb4caSwyllys 			    "must be specified as a comma-separated list. "
75099ebb4caSwyllys 			    "See the man page for details."));
75199ebb4caSwyllys 			goto end;
75299ebb4caSwyllys 		}
75399ebb4caSwyllys 	}
754d00756ccSwyllys 	if (ekustr != NULL) {
755d00756ccSwyllys 		rv = verify_ekunames(ekustr, &ekulist);
756d00756ccSwyllys 		if (rv != KMF_OK) {
757d00756ccSwyllys 			(void) fprintf(stderr, gettext("EKUs must "
758d00756ccSwyllys 			    "be specified as a comma-separated list. "
759d00756ccSwyllys 			    "See the man page for details.\n"));
760d00756ccSwyllys 			rv = PK_ERR_USAGE;
761d00756ccSwyllys 			goto end;
762d00756ccSwyllys 		}
763d00756ccSwyllys 	}
764d00756ccSwyllys 
76599ebb4caSwyllys 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
76699ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
76799ebb4caSwyllys 		    keytype);
76899ebb4caSwyllys 		goto end;
76999ebb4caSwyllys 	}
77099ebb4caSwyllys 
77199ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
77299ebb4caSwyllys 		if (tokenname == NULL || !strlen(tokenname)) {
77399ebb4caSwyllys 			if (kstype == KMF_KEYSTORE_NSS) {
77499ebb4caSwyllys 				tokenname = "internal";
77599ebb4caSwyllys 			} else  {
77699ebb4caSwyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
77799ebb4caSwyllys 			}
77899ebb4caSwyllys 		}
77999ebb4caSwyllys 
78099ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
78199ebb4caSwyllys 	}
78299ebb4caSwyllys 
783577f4726Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
784577f4726Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
785577f4726Swyllys 		return (PK_ERR_USAGE);
786577f4726Swyllys 	}
787577f4726Swyllys 
788577f4726Swyllys 
78999ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
79099ebb4caSwyllys 		if (dir == NULL)
79199ebb4caSwyllys 			dir = PK_DEFAULT_DIRECTORY;
79299ebb4caSwyllys 
79399ebb4caSwyllys 		rv = gencsr_nss(kmfhandle,
79499ebb4caSwyllys 		    tokenname, subname, altname, alttype, altcrit,
79599ebb4caSwyllys 		    certlabel, dir, prefix,
79699ebb4caSwyllys 		    keyAlg, keylen, kubits, kucrit,
797d00756ccSwyllys 		    fmt, outcsr, &tokencred, ekulist);
79899ebb4caSwyllys 
79999ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
80099ebb4caSwyllys 		rv = gencsr_pkcs11(kmfhandle,
80199ebb4caSwyllys 		    tokenname, subname, altname, alttype, altcrit,
80299ebb4caSwyllys 		    certlabel, keyAlg, keylen,
803d00756ccSwyllys 		    kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
80499ebb4caSwyllys 
80599ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
80699ebb4caSwyllys 		rv = gencsr_file(kmfhandle,
80799ebb4caSwyllys 		    keyAlg, keylen, fmt, subname, altname,
80899ebb4caSwyllys 		    alttype, altcrit, kubits, kucrit,
809448b8615Swyllys 		    outcsr, outkey, ekulist);
81099ebb4caSwyllys 	}
81199ebb4caSwyllys 
81299ebb4caSwyllys end:
813592106a2SWyllys Ingersoll 	if (rv != KMF_OK) {
81499ebb4caSwyllys 		display_error(kmfhandle, rv,
81599ebb4caSwyllys 		    gettext("Error creating CSR or keypair"));
81699ebb4caSwyllys 
817592106a2SWyllys Ingersoll 		if (rv == KMF_ERR_RDN_PARSER) {
818592106a2SWyllys Ingersoll 			cryptoerror(LOG_STDERR, gettext("subject or "
819592106a2SWyllys Ingersoll 			    "issuer name must be in proper DN format.\n"));
820592106a2SWyllys Ingersoll 		}
821592106a2SWyllys Ingersoll 	}
822592106a2SWyllys Ingersoll 
823d00756ccSwyllys 	if (ekulist != NULL)
824d00756ccSwyllys 		free_eku_list(ekulist);
825d00756ccSwyllys 
82699ebb4caSwyllys 	if (subname)
82799ebb4caSwyllys 		free(subname);
82899ebb4caSwyllys 
82999ebb4caSwyllys 	if (tokencred.cred != NULL)
83099ebb4caSwyllys 		free(tokencred.cred);
83199ebb4caSwyllys 
83230a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
83399ebb4caSwyllys 	if (rv != KMF_OK)
83499ebb4caSwyllys 		return (PK_ERR_USAGE);
83599ebb4caSwyllys 
83699ebb4caSwyllys 	return (0);
83799ebb4caSwyllys }
838