xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 9145:2ff2d6759c0b)
13089Swyllys /*
23089Swyllys  * CDDL HEADER START
33089Swyllys  *
43089Swyllys  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
73089Swyllys  *
83089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93089Swyllys  * or http://www.opensolaris.org/os/licensing.
103089Swyllys  * See the License for the specific language governing permissions
113089Swyllys  * and limitations under the License.
123089Swyllys  *
133089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
143089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
163089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
173089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
183089Swyllys  *
193089Swyllys  * CDDL HEADER END
203089Swyllys  */
213089Swyllys /*
22*9145SHuie-Ying.Lee@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233089Swyllys  * Use is subject to license terms.
243089Swyllys  */
253089Swyllys 
263089Swyllys #include <stdio.h>
273089Swyllys #include <string.h>
283089Swyllys #include <ctype.h>
293089Swyllys #include <malloc.h>
303089Swyllys #include <libgen.h>
313089Swyllys #include <errno.h>
323089Swyllys #include <cryptoutil.h>
333089Swyllys #include <security/cryptoki.h>
343089Swyllys #include "common.h"
353089Swyllys 
363089Swyllys #include <kmfapi.h>
373089Swyllys 
383089Swyllys #define	SET_VALUE(f, s) \
393089Swyllys 	kmfrv = f; \
403089Swyllys 	if (kmfrv != KMF_OK) { \
413089Swyllys 		cryptoerror(LOG_STDERR, \
423089Swyllys 			gettext("Failed to set %s: 0x%02x\n"), \
433089Swyllys 			s, kmfrv); \
443089Swyllys 		goto cleanup; \
453089Swyllys 	}
463089Swyllys 
473089Swyllys static int
483089Swyllys gencert_pkcs11(KMF_HANDLE_T kmfhandle,
493089Swyllys 	char *token, char *subject, char *altname,
503089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
513089Swyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
523089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
533089Swyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
546051Swyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
556051Swyllys 	EKU_LIST *ekulist)
563089Swyllys {
573089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
583089Swyllys 	KMF_KEY_HANDLE pubk, prik;
593089Swyllys 	KMF_X509_CERTIFICATE signedCert;
603089Swyllys 	KMF_X509_NAME	certSubject;
613089Swyllys 	KMF_X509_NAME	certIssuer;
623089Swyllys 	KMF_DATA x509DER;
635051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
645051Swyllys 	KMF_ATTRIBUTE attrlist[16];
655051Swyllys 	int numattr = 0;
665051Swyllys 	KMF_KEY_ALG keytype;
675051Swyllys 	uint32_t keylength;
683089Swyllys 
693089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
703089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
713089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
723089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
733089Swyllys 
743089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
755051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
763089Swyllys 		cryptoerror(LOG_STDERR,
775051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
783089Swyllys 		return (PK_ERR_USAGE);
793089Swyllys 	}
803089Swyllys 
813089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
825051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
833089Swyllys 		cryptoerror(LOG_STDERR,
845051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
853089Swyllys 		return (PK_ERR_USAGE);
863089Swyllys 	}
873089Swyllys 
885051Swyllys 	keylength = keylen; /* bits */
895051Swyllys 	keytype = keyAlg;
903089Swyllys 
913089Swyllys 	/* Select a PKCS11 token */
923089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
933089Swyllys 
943089Swyllys 	if (kmfrv != KMF_OK) {
953089Swyllys 		return (kmfrv);
963089Swyllys 	}
973089Swyllys 
985051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
995051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
1005051Swyllys 	    sizeof (kstype));
1015051Swyllys 	numattr++;
1025051Swyllys 
1035051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1045051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
1055051Swyllys 	    sizeof (keytype));
1065051Swyllys 	numattr++;
1075051Swyllys 
1085051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1095051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
1105051Swyllys 	    sizeof (keylength));
1115051Swyllys 	numattr++;
1125051Swyllys 
1135051Swyllys 	if (certlabel != NULL) {
1145051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
1155051Swyllys 		    KMF_KEYLABEL_ATTR, certlabel,
1165051Swyllys 		    strlen(certlabel));
1175051Swyllys 		numattr++;
1185051Swyllys 	}
1195051Swyllys 
1206354Swyllys 	if (tokencred != NULL && tokencred->cred != NULL) {
1215051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
1225051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
1235051Swyllys 		    sizeof (KMF_CREDENTIAL));
1245051Swyllys 		numattr++;
1255051Swyllys 	}
1265051Swyllys 
1275051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1285051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
1295051Swyllys 	    sizeof (KMF_KEY_HANDLE));
1305051Swyllys 	numattr++;
1315051Swyllys 
1325051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1335051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
1345051Swyllys 	    sizeof (KMF_KEY_HANDLE));
1355051Swyllys 	numattr++;
1365051Swyllys 
1375051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
1383089Swyllys 	if (kmfrv != KMF_OK) {
1393089Swyllys 		return (kmfrv);
1403089Swyllys 	}
1413089Swyllys 
1425051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
1435051Swyllys 	    "keypair");
1443089Swyllys 
1455051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
1463089Swyllys 
1475051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
1485051Swyllys 	    "serial number");
1493089Swyllys 
1505051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
1515051Swyllys 	    "validity time");
1523089Swyllys 
1535051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
1545051Swyllys 	    "signature algorithm");
1553089Swyllys 
1565051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
1575051Swyllys 	    "subject name");
1583089Swyllys 
1595051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
1605051Swyllys 	    "issuer name");
1613089Swyllys 
1623089Swyllys 	if (altname != NULL)
1635051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
1645051Swyllys 		    alttype, altname), "subjectAltName");
1653089Swyllys 
1663089Swyllys 	if (kubits != 0)
1675051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
1685051Swyllys 		    "KeyUsage");
1695051Swyllys 
1706051Swyllys 	if (ekulist != NULL) {
1716051Swyllys 		int i;
1726051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1736051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
1746051Swyllys 			    &ekulist->ekulist[i], ekulist->critlist[i]),
1756051Swyllys 			    "Extended Key Usage");
1766051Swyllys 		}
1776051Swyllys 	}
1786051Swyllys 
1795051Swyllys 	/*
1805051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
1815051Swyllys 	 */
1825051Swyllys 	numattr = 0;
1835051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1845051Swyllys 	    &kstype, sizeof (kstype));
1855051Swyllys 	numattr++;
1863089Swyllys 
1875051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
1885051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
1895051Swyllys 	numattr++;
1905051Swyllys 
1915051Swyllys 	/* cert data that is to be signed */
1925051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
1935051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
1945051Swyllys 	numattr++;
1955051Swyllys 
1965051Swyllys 	/* output buffer for the signed cert */
1975051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
1985051Swyllys 	    &x509DER, sizeof (KMF_DATA));
1995051Swyllys 	numattr++;
2005051Swyllys 
2015051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
2025051Swyllys 	    KMF_OK) {
2033089Swyllys 		goto cleanup;
2043089Swyllys 	}
2053089Swyllys 
2063089Swyllys 	/*
2073089Swyllys 	 * Store the cert in the DB.
2083089Swyllys 	 */
2095051Swyllys 	numattr = 0;
2105051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
2115051Swyllys 	    &kstype, sizeof (kstype));
2125051Swyllys 	numattr++;
2135051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
2145051Swyllys 	    &x509DER, sizeof (KMF_DATA));
2155051Swyllys 	numattr++;
2165051Swyllys 
2175051Swyllys 	if (certlabel != NULL) {
2185051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
2195051Swyllys 		    certlabel, strlen(certlabel));
2205051Swyllys 		numattr++;
2215051Swyllys 	}
2225051Swyllys 
2235051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
2245051Swyllys 
2253089Swyllys cleanup:
2265051Swyllys 	kmf_free_data(&x509DER);
2275051Swyllys 	kmf_free_dn(&certSubject);
2285051Swyllys 	kmf_free_dn(&certIssuer);
229*9145SHuie-Ying.Lee@Sun.COM 
230*9145SHuie-Ying.Lee@Sun.COM 	/*
231*9145SHuie-Ying.Lee@Sun.COM 	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
232*9145SHuie-Ying.Lee@Sun.COM 	 * the key pair from the token.
233*9145SHuie-Ying.Lee@Sun.COM 	 */
234*9145SHuie-Ying.Lee@Sun.COM 	if (kmfrv != KMF_OK) {
235*9145SHuie-Ying.Lee@Sun.COM 		/* delete the public key */
236*9145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
237*9145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
238*9145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
239*9145SHuie-Ying.Lee@Sun.COM 		numattr++;
240*9145SHuie-Ying.Lee@Sun.COM 
241*9145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
242*9145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
243*9145SHuie-Ying.Lee@Sun.COM 		numattr++;
244*9145SHuie-Ying.Lee@Sun.COM 
245*9145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
246*9145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
247*9145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
248*9145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
249*9145SHuie-Ying.Lee@Sun.COM 			numattr++;
250*9145SHuie-Ying.Lee@Sun.COM 		}
251*9145SHuie-Ying.Lee@Sun.COM 
252*9145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
253*9145SHuie-Ying.Lee@Sun.COM 		    attrlist);
254*9145SHuie-Ying.Lee@Sun.COM 
255*9145SHuie-Ying.Lee@Sun.COM 		/* delete the private key */
256*9145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
257*9145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
258*9145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
259*9145SHuie-Ying.Lee@Sun.COM 		numattr++;
260*9145SHuie-Ying.Lee@Sun.COM 
261*9145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
262*9145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
263*9145SHuie-Ying.Lee@Sun.COM 		numattr++;
264*9145SHuie-Ying.Lee@Sun.COM 
265*9145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
266*9145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
267*9145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
268*9145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
269*9145SHuie-Ying.Lee@Sun.COM 			numattr++;
270*9145SHuie-Ying.Lee@Sun.COM 		}
271*9145SHuie-Ying.Lee@Sun.COM 
272*9145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
273*9145SHuie-Ying.Lee@Sun.COM 		    attrlist);
274*9145SHuie-Ying.Lee@Sun.COM 	}
275*9145SHuie-Ying.Lee@Sun.COM 
2763089Swyllys 	return (kmfrv);
2773089Swyllys }
2783089Swyllys 
2793089Swyllys static int
2803089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
2813089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
2823089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
2833089Swyllys 	uint32_t ltime, char *subject, char *altname,
2843089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2853089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
2866669Swyllys 	char *outcert, char *outkey,
2876051Swyllys 	EKU_LIST *ekulist)
2883089Swyllys {
2893089Swyllys 	KMF_RETURN kmfrv;
2903089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2913089Swyllys 	KMF_X509_CERTIFICATE signedCert;
2923089Swyllys 	KMF_X509_NAME	certSubject;
2933089Swyllys 	KMF_X509_NAME	certIssuer;
2943089Swyllys 	KMF_DATA x509DER;
2953089Swyllys 	char *fullcertpath = NULL;
2963089Swyllys 	char *fullkeypath = NULL;
2975051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2985051Swyllys 	KMF_ATTRIBUTE attrlist[10];
2995051Swyllys 	int numattr = 0;
3005051Swyllys 	KMF_KEY_ALG keytype;
3015051Swyllys 	uint32_t keylength;
3025051Swyllys 	KMF_ENCODE_FORMAT format;
3033089Swyllys 
3043089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
3053089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
3063089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
3073089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
3083089Swyllys 
3093089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
3103089Swyllys 		cryptoerror(LOG_STDERR,
3115051Swyllys 		    gettext("No output file was specified for "
3125051Swyllys 		    "the cert or key\n"));
3133089Swyllys 		return (PK_ERR_USAGE);
3143089Swyllys 	}
3156669Swyllys 	fullcertpath = strdup(outcert);
3163089Swyllys 	if (verify_file(fullcertpath)) {
3173089Swyllys 		cryptoerror(LOG_STDERR,
3185051Swyllys 		    gettext("Cannot write the indicated output "
3195051Swyllys 		    "certificate file (%s).\n"), fullcertpath);
3203089Swyllys 		free(fullcertpath);
3213089Swyllys 		return (PK_ERR_USAGE);
3223089Swyllys 	}
3236669Swyllys 
3246669Swyllys 	fullkeypath = strdup(outkey);
3253089Swyllys 	if (verify_file(fullkeypath)) {
3263089Swyllys 		cryptoerror(LOG_STDERR,
3275051Swyllys 		    gettext("Cannot write the indicated output "
3285051Swyllys 		    "key file (%s).\n"), fullkeypath);
3293089Swyllys 		free(fullkeypath);
3303089Swyllys 		free(fullcertpath);
3313089Swyllys 		return (PK_ERR_USAGE);
3323089Swyllys 	}
3333089Swyllys 
3343089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
3355051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
3363089Swyllys 		cryptoerror(LOG_STDERR,
3375051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
3383089Swyllys 		return (PK_ERR_USAGE);
3393089Swyllys 	}
3403089Swyllys 
3413089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
3425051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
3433089Swyllys 		cryptoerror(LOG_STDERR,
3445051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
3455051Swyllys 		kmf_free_dn(&certSubject);
3463089Swyllys 		return (PK_ERR_USAGE);
3473089Swyllys 	}
3483089Swyllys 
3495051Swyllys 	keylength = keylen; /* bits */
3505051Swyllys 	keytype = keyAlg;
3515051Swyllys 	format = fmt;
3525051Swyllys 
3535051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3545051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
3555051Swyllys 	    sizeof (kstype));
3565051Swyllys 	numattr++;
3575051Swyllys 
3585051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3595051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
3605051Swyllys 	    sizeof (keytype));
3615051Swyllys 	numattr++;
3625051Swyllys 
3635051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3645051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
3655051Swyllys 	    sizeof (keylength));
3665051Swyllys 	numattr++;
3673089Swyllys 
3685051Swyllys 	if (fullkeypath != NULL) {
3695051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
3705051Swyllys 		    KMF_KEY_FILENAME_ATTR, fullkeypath,
3715051Swyllys 		    strlen(fullkeypath));
3725051Swyllys 		numattr++;
3735051Swyllys 	}
3745051Swyllys 
3755051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3765051Swyllys 	    KMF_ENCODE_FORMAT_ATTR, &format,
3775051Swyllys 	    sizeof (format));
3785051Swyllys 	numattr++;
3793089Swyllys 
3805051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3815051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
3825051Swyllys 	    sizeof (KMF_KEY_HANDLE));
3835051Swyllys 	numattr++;
3845051Swyllys 
3855051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3865051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
3875051Swyllys 	    sizeof (KMF_KEY_HANDLE));
3885051Swyllys 	numattr++;
3895051Swyllys 
3905051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
3913089Swyllys 	if (kmfrv != KMF_OK) {
3923089Swyllys 		goto cleanup;
3933089Swyllys 	}
3945051Swyllys 
3955051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
3965051Swyllys 	    "keypair");
3973089Swyllys 
3985051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
3993089Swyllys 
4005051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
4015051Swyllys 	    "serial number");
4023089Swyllys 
4035051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
4045051Swyllys 	    "validity time");
4053089Swyllys 
4065051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
4075051Swyllys 	    "signature algorithm");
4083089Swyllys 
4095051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
4105051Swyllys 	    "subject name");
4113089Swyllys 
4125051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
4135051Swyllys 	    "issuer name");
4143089Swyllys 
4153089Swyllys 	if (altname != NULL)
4165051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
4175051Swyllys 		    alttype, altname), "subjectAltName");
4183089Swyllys 
4193089Swyllys 	if (kubits != 0)
4205051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
4215051Swyllys 		    "KeyUsage");
4226051Swyllys 
4236051Swyllys 	if (ekulist != NULL) {
4246051Swyllys 		int i;
4256051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
4266051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
4276051Swyllys 			    &ekulist->ekulist[i],
4286051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
4296051Swyllys 		}
4306051Swyllys 	}
4315051Swyllys 	/*
4325051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
4335051Swyllys 	 */
4345051Swyllys 	numattr = 0;
4355051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4365051Swyllys 	    &kstype, sizeof (kstype));
4375051Swyllys 	numattr++;
4383089Swyllys 
4395051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
4405051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
4415051Swyllys 	numattr++;
4425051Swyllys 
4435051Swyllys 	/* cert data that is to be signed */
4445051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
4455051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
4465051Swyllys 	numattr++;
4475051Swyllys 
4485051Swyllys 	/* output buffer for the signed cert */
4495051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
4505051Swyllys 	    &x509DER, sizeof (KMF_DATA));
4515051Swyllys 	numattr++;
4525051Swyllys 
4535051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
4545051Swyllys 	    KMF_OK) {
4553089Swyllys 		goto cleanup;
4563089Swyllys 	}
4573089Swyllys 
4583089Swyllys 	/*
4593089Swyllys 	 * Store the cert in the DB.
4603089Swyllys 	 */
4615051Swyllys 	numattr = 0;
4625051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4635051Swyllys 	    &kstype, sizeof (kstype));
4645051Swyllys 	numattr++;
4655051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
4665051Swyllys 	    &x509DER, sizeof (KMF_DATA));
4675051Swyllys 	numattr++;
4685051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
4695051Swyllys 	    fullcertpath, strlen(fullcertpath));
4705051Swyllys 	numattr++;
4715051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
4725051Swyllys 	    &fmt, sizeof (fmt));
4735051Swyllys 	numattr++;
4745051Swyllys 
4755051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
4763089Swyllys 
4773089Swyllys cleanup:
4783089Swyllys 	if (fullkeypath != NULL)
4793089Swyllys 		free(fullkeypath);
4803089Swyllys 	if (fullcertpath != NULL)
4813089Swyllys 		free(fullcertpath);
4823089Swyllys 
4835051Swyllys 	kmf_free_data(&x509DER);
4845051Swyllys 	kmf_free_dn(&certSubject);
4855051Swyllys 	kmf_free_dn(&certIssuer);
4863089Swyllys 	return (kmfrv);
4873089Swyllys }
4883089Swyllys 
4893089Swyllys static KMF_RETURN
4903089Swyllys gencert_nss(KMF_HANDLE_T kmfhandle,
4913089Swyllys 	char *token, char *subject, char *altname,
4923089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
4933089Swyllys 	char *nickname, char *dir, char *prefix,
4943089Swyllys 	KMF_KEY_ALG keyAlg,
4953089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
4963089Swyllys 	int keylen, char *trust,
4973089Swyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
4986051Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred,
4996051Swyllys 	EKU_LIST *ekulist)
5003089Swyllys {
5013089Swyllys 	KMF_RETURN kmfrv;
5023089Swyllys 	KMF_KEY_HANDLE pubk, prik;
5033089Swyllys 	KMF_X509_CERTIFICATE signedCert;
5043089Swyllys 	KMF_X509_NAME	certSubject;
5053089Swyllys 	KMF_X509_NAME	certIssuer;
5063089Swyllys 	KMF_DATA x509DER;
5075051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
5085051Swyllys 	KMF_ATTRIBUTE attrlist[16];
5095051Swyllys 	int numattr = 0;
5105051Swyllys 	KMF_KEY_ALG keytype;
5115051Swyllys 	uint32_t keylength;
5123089Swyllys 
5133089Swyllys 	if (token == NULL)
5143089Swyllys 		token = DEFAULT_NSS_TOKEN;
5153089Swyllys 
5163089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
5173089Swyllys 	if (kmfrv != KMF_OK)
5183089Swyllys 		return (kmfrv);
5193089Swyllys 
5203089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
5213089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
5223089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
5233089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
5243089Swyllys 
5253089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
5265051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
5273089Swyllys 		cryptoerror(LOG_STDERR,
5285051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
5293089Swyllys 		return (PK_ERR_USAGE);
5303089Swyllys 	}
5313089Swyllys 
5323089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
5335051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
5343089Swyllys 		cryptoerror(LOG_STDERR,
5355051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
5363089Swyllys 		return (PK_ERR_USAGE);
5373089Swyllys 	}
5383089Swyllys 
5395051Swyllys 	keylength = keylen; /* bits */
5405051Swyllys 	keytype = keyAlg;
5415051Swyllys 
5425051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5435051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
5445051Swyllys 	    sizeof (kstype));
5455051Swyllys 	numattr++;
5465051Swyllys 
5475051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5485051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
5495051Swyllys 	    sizeof (keytype));
5505051Swyllys 	numattr++;
5515051Swyllys 
5525051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5535051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
5545051Swyllys 	    sizeof (keylength));
5555051Swyllys 	numattr++;
5565051Swyllys 
5575051Swyllys 	if (nickname != NULL) {
5585051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5595051Swyllys 		    KMF_KEYLABEL_ATTR, nickname,
5605051Swyllys 		    strlen(nickname));
5615051Swyllys 		numattr++;
5625051Swyllys 	}
5633089Swyllys 
5646354Swyllys 	if (tokencred != NULL && tokencred->cred != NULL) {
5655051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5665051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
5675051Swyllys 		    sizeof (KMF_CREDENTIAL));
5685051Swyllys 		numattr++;
5695051Swyllys 	}
5703089Swyllys 
5715051Swyllys 	if (token != NULL) {
5725051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5735051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
5745051Swyllys 		    strlen(token));
5755051Swyllys 		numattr++;
5765051Swyllys 	}
5775051Swyllys 
5785051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5795051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
5805051Swyllys 	    sizeof (KMF_KEY_HANDLE));
5815051Swyllys 	numattr++;
5825051Swyllys 
5835051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5845051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
5855051Swyllys 	    sizeof (KMF_KEY_HANDLE));
5865051Swyllys 	numattr++;
5875051Swyllys 
5885051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
5893089Swyllys 	if (kmfrv != KMF_OK) {
5903089Swyllys 		return (kmfrv);
5913089Swyllys 	}
5923089Swyllys 
5935051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
5945051Swyllys 	    "keypair");
5953089Swyllys 
5965051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
5973089Swyllys 
5985051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
5995051Swyllys 	    "serial number");
6003089Swyllys 
6015051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
6025051Swyllys 	    "validity time");
6033089Swyllys 
6045051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
6055051Swyllys 	    "signature algorithm");
6063089Swyllys 
6075051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
6085051Swyllys 	    "subject name");
6093089Swyllys 
6105051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
6115051Swyllys 	    "issuer name");
6123089Swyllys 
6133089Swyllys 	if (altname != NULL)
6145051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
6155051Swyllys 		    alttype, altname), "subjectAltName");
6163089Swyllys 
6173089Swyllys 	if (kubits)
6185051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
6195051Swyllys 		    "subjectAltName");
6205051Swyllys 
6216051Swyllys 	if (ekulist != NULL) {
6226051Swyllys 		int i;
6236051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
6246051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
6256051Swyllys 			    &ekulist->ekulist[i],
6266051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
6276051Swyllys 		}
6286051Swyllys 	}
6295051Swyllys 	/*
6305051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
6315051Swyllys 	 */
6325051Swyllys 	numattr = 0;
6335051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6345051Swyllys 	    &kstype, sizeof (kstype));
6355051Swyllys 	numattr++;
6363089Swyllys 
6375051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
6385051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
6395051Swyllys 	numattr++;
6405051Swyllys 
6415051Swyllys 	/* cert data that is to be signed */
6425051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
6435051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
6445051Swyllys 	numattr++;
6455051Swyllys 
6465051Swyllys 	/* output buffer for the signed cert */
6475051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
6485051Swyllys 	    &x509DER, sizeof (KMF_DATA));
6495051Swyllys 	numattr++;
6505051Swyllys 
6515051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
6525051Swyllys 	    KMF_OK) {
6533089Swyllys 		goto cleanup;
6543089Swyllys 	}
6553089Swyllys 
6563089Swyllys 	/*
6573089Swyllys 	 * Store the cert in the DB.
6583089Swyllys 	 */
6595051Swyllys 	numattr = 0;
6605051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6615051Swyllys 	    &kstype, sizeof (kstype));
6625051Swyllys 	numattr++;
6635051Swyllys 
6645051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
6655051Swyllys 	    &x509DER, sizeof (KMF_DATA));
6665051Swyllys 	numattr++;
6675051Swyllys 
6685051Swyllys 	if (nickname != NULL) {
6695051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
6705051Swyllys 		    nickname, strlen(nickname));
6715051Swyllys 		numattr++;
6725051Swyllys 	}
6735051Swyllys 
6745051Swyllys 	if (trust != NULL) {
6755051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
6765051Swyllys 		    trust, strlen(trust));
6775051Swyllys 		numattr++;
6785051Swyllys 	}
6795051Swyllys 
6805051Swyllys 	if (token != NULL) {
6815051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
6825051Swyllys 		    token, strlen(token));
6835051Swyllys 		numattr++;
6845051Swyllys 	}
6855051Swyllys 
6865051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
6873089Swyllys 
6883089Swyllys cleanup:
6895051Swyllys 	kmf_free_data(&x509DER);
6905051Swyllys 	kmf_free_dn(&certSubject);
6915051Swyllys 	kmf_free_dn(&certIssuer);
6923089Swyllys 	return (kmfrv);
6933089Swyllys }
6943089Swyllys 
6953089Swyllys int
6963089Swyllys pk_gencert(int argc, char *argv[])
6973089Swyllys {
6983089Swyllys 	int rv;
6993089Swyllys 	int opt;
7003089Swyllys 	extern int	optind_av;
7013089Swyllys 	extern char	*optarg_av;
7023089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
7033089Swyllys 	char *subject = NULL;
7043089Swyllys 	char *tokenname = NULL;
7053089Swyllys 	char *dir = NULL;
7063089Swyllys 	char *prefix = NULL;
7073089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
7083089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
7093089Swyllys 	char *trust = NULL;
7103089Swyllys 	char *lifetime = NULL;
7113089Swyllys 	char *certlabel = NULL;
7123089Swyllys 	char *outcert = NULL;
7133089Swyllys 	char *outkey = NULL;
7143089Swyllys 	char *format = NULL;
7153089Swyllys 	char *serstr = NULL;
7163089Swyllys 	char *altname = NULL;
7173089Swyllys 	char *keyusagestr = NULL;
7186051Swyllys 	char *ekustr = NULL;
7193089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
7203089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
7213089Swyllys 	uint32_t ltime;
7223089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
7233089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
7243089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
7253089Swyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
7263089Swyllys 	boolean_t interactive = B_FALSE;
7273089Swyllys 	char *subname = NULL;
7283089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
7293089Swyllys 	uint16_t kubits = 0;
7303089Swyllys 	int altcrit = 0, kucrit = 0;
7316051Swyllys 	EKU_LIST *ekulist = NULL;
7323089Swyllys 
7333089Swyllys 	while ((opt = getopt_av(argc, argv,
7345051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
7355051Swyllys 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
7366051Swyllys 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
7375051Swyllys 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
7383089Swyllys 
7393089Swyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
7403089Swyllys 			return (PK_ERR_USAGE);
7413089Swyllys 
7423089Swyllys 		switch (opt) {
7433089Swyllys 			case 'A':
7443089Swyllys 				altname = optarg_av;
7453089Swyllys 				break;
7463089Swyllys 			case 'i':
7473089Swyllys 				if (interactive || subject)
7483089Swyllys 					return (PK_ERR_USAGE);
7493089Swyllys 				else
7503089Swyllys 					interactive = B_TRUE;
7513089Swyllys 				break;
7523089Swyllys 			case 'k':
7533089Swyllys 				kstype = KS2Int(optarg_av);
7543089Swyllys 				if (kstype == 0)
7553089Swyllys 					return (PK_ERR_USAGE);
7563089Swyllys 				break;
7573089Swyllys 			case 's':
7583089Swyllys 				if (interactive || subject)
7593089Swyllys 					return (PK_ERR_USAGE);
7603089Swyllys 				else
7613089Swyllys 					subject = optarg_av;
7623089Swyllys 				break;
7633089Swyllys 			case 'l':
7643089Swyllys 			case 'n':
7653089Swyllys 				if (certlabel)
7663089Swyllys 					return (PK_ERR_USAGE);
7673089Swyllys 				certlabel = optarg_av;
7683089Swyllys 				break;
7693089Swyllys 			case 'T':
7703089Swyllys 				if (tokenname)
7713089Swyllys 					return (PK_ERR_USAGE);
7723089Swyllys 				tokenname = optarg_av;
7733089Swyllys 				break;
7743089Swyllys 			case 'd':
7753089Swyllys 				if (dir)
7763089Swyllys 					return (PK_ERR_USAGE);
7773089Swyllys 				dir = optarg_av;
7783089Swyllys 				break;
7793089Swyllys 			case 'p':
7803089Swyllys 				if (prefix)
7813089Swyllys 					return (PK_ERR_USAGE);
7823089Swyllys 				prefix = optarg_av;
7833089Swyllys 				break;
7843089Swyllys 			case 't':
7853089Swyllys 				keytype = optarg_av;
7863089Swyllys 				break;
7873089Swyllys 			case 'u':
7883089Swyllys 				keyusagestr = optarg_av;
7893089Swyllys 				break;
7903089Swyllys 			case 'y':
7913089Swyllys 				if (sscanf(optarg_av, "%d",
7925051Swyllys 				    &keylen) != 1) {
7933089Swyllys 					cryptoerror(LOG_STDERR,
7945051Swyllys 					    gettext("key length must be"
7955051Swyllys 					    "a numeric value (%s)\n"),
7965051Swyllys 					    optarg_av);
7973089Swyllys 					return (PK_ERR_USAGE);
7983089Swyllys 				}
7993089Swyllys 				break;
8003089Swyllys 			case 'r':
8013089Swyllys 				if (trust)
8023089Swyllys 					return (PK_ERR_USAGE);
8033089Swyllys 				trust = optarg_av;
8043089Swyllys 				break;
8053089Swyllys 			case 'L':
8063089Swyllys 				if (lifetime)
8073089Swyllys 					return (PK_ERR_USAGE);
8083089Swyllys 				lifetime = optarg_av;
8093089Swyllys 				break;
8103089Swyllys 			case 'c':
8113089Swyllys 				if (outcert)
8123089Swyllys 					return (PK_ERR_USAGE);
8133089Swyllys 				outcert = optarg_av;
8143089Swyllys 				break;
8153089Swyllys 			case 'K':
8163089Swyllys 				if (outkey)
8173089Swyllys 					return (PK_ERR_USAGE);
8183089Swyllys 				outkey = optarg_av;
8193089Swyllys 				break;
8203089Swyllys 			case 'S':
8213089Swyllys 				serstr = optarg_av;
8223089Swyllys 				break;
8233089Swyllys 			case 'F':
8243089Swyllys 				if (format)
8253089Swyllys 					return (PK_ERR_USAGE);
8263089Swyllys 				format = optarg_av;
8273089Swyllys 				break;
8286051Swyllys 			case 'e':
8296051Swyllys 				ekustr = optarg_av;
8306051Swyllys 				break;
8313089Swyllys 			default:
8323089Swyllys 				return (PK_ERR_USAGE);
8333089Swyllys 		}
8343089Swyllys 	}
8353089Swyllys 
8363089Swyllys 	/* No additional args allowed. */
8373089Swyllys 	argc -= optind_av;
8383089Swyllys 	argv += optind_av;
8393089Swyllys 	if (argc) {
8403089Swyllys 		return (PK_ERR_USAGE);
8413089Swyllys 	}
8423089Swyllys 
8435051Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
8443089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
8453089Swyllys 		return (PK_ERR_USAGE);
8463089Swyllys 	}
8473089Swyllys 
8483089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
8493089Swyllys 	if (kstype == 0)
8503089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
8513089Swyllys 
8525221Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
8535221Swyllys 		if (interactive && EMPTYSTRING(certlabel)) {
8545221Swyllys 			(void) get_certlabel(&certlabel);
8555221Swyllys 		}
8565221Swyllys 		/* It better not be empty now */
8575221Swyllys 		if (EMPTYSTRING(certlabel)) {
8585221Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
8595221Swyllys 			    "specified to create a self-signed certificate."
8605221Swyllys 			    "\n"));
8615221Swyllys 			return (PK_ERR_USAGE);
8625221Swyllys 		}
8633089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
8643089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
8653089Swyllys 		    "be specified to create a self-signed certificate.\n"));
8663089Swyllys 		return (PK_ERR_USAGE);
8673089Swyllys 	}
8683089Swyllys 
8696884Swyllys 	DIR_OPTION_CHECK(kstype, dir);
8706884Swyllys 
8713089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
8723089Swyllys 		cryptoerror(LOG_STDERR,
8733089Swyllys 		    gettext("Error parsing format string (%s).\n"),
8743089Swyllys 		    format);
8753089Swyllys 		return (PK_ERR_USAGE);
8763089Swyllys 	}
8773089Swyllys 
8783089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
8793089Swyllys 		cryptoerror(LOG_STDERR,
8805051Swyllys 		    gettext("Error parsing lifetime string\n"));
8813089Swyllys 		return (PK_ERR_USAGE);
8823089Swyllys 	}
8833089Swyllys 
8843089Swyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
8853089Swyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
8865051Swyllys 		    keytype);
8873089Swyllys 		return (PK_ERR_USAGE);
8883089Swyllys 	}
8893089Swyllys 
8903089Swyllys 	/*
8913089Swyllys 	 * Check the subject name.
8923089Swyllys 	 * If interactive is true, get it now interactively.
8933089Swyllys 	 */
8943089Swyllys 	if (interactive) {
8955221Swyllys 		subname = NULL;
8965221Swyllys 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
8973089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
8983089Swyllys 			    "subject name interactively.\n"));
8993089Swyllys 			return (PK_ERR_USAGE);
9003089Swyllys 		}
9015221Swyllys 		if (serstr == NULL) {
9025221Swyllys 			(void) get_serial(&serstr);
9035221Swyllys 		}
9043089Swyllys 	} else {
9053089Swyllys 		if (EMPTYSTRING(subject)) {
9063089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
9073089Swyllys 			    "-i must be specified to create a self-signed "
9083089Swyllys 			    "certificate.\n"));
9093089Swyllys 			return (PK_ERR_USAGE);
9103089Swyllys 		} else {
9113089Swyllys 			subname = strdup(subject);
9123089Swyllys 			if (subname == NULL) {
9133089Swyllys 				cryptoerror(LOG_STDERR,
9143089Swyllys 				    gettext("Out of memory.\n"));
9153089Swyllys 				return (PK_ERR_SYSTEM);
9163089Swyllys 			}
9173089Swyllys 		}
9183089Swyllys 	}
9193089Swyllys 
9203089Swyllys 	if (serstr == NULL) {
9213089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
9225051Swyllys 		    "must be specified as a hex number when creating"
9235051Swyllys 		    " a self-signed certificate "
9245051Swyllys 		    "(ex: serial=0x0102030405feedface)\n"));
9253089Swyllys 		rv = PK_ERR_USAGE;
9263089Swyllys 		goto end;
9273089Swyllys 	} else {
9283089Swyllys 		uchar_t *bytes = NULL;
9293089Swyllys 		size_t bytelen;
9303089Swyllys 
9315051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
9323089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
9333089Swyllys 			(void) fprintf(stderr, gettext("serial number "
9345051Swyllys 			    "must be specified as a hex number "
9355051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
9363089Swyllys 			rv = PK_ERR_USAGE;
9373089Swyllys 			goto end;
9383089Swyllys 		}
9393089Swyllys 		serial.val = bytes;
9403089Swyllys 		serial.len = bytelen;
9413089Swyllys 	}
9423089Swyllys 
9433089Swyllys 	if (altname != NULL) {
9443089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
9453089Swyllys 		if (rv != KMF_OK) {
9463089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
9475051Swyllys 			    "must be specified as a name=value pair. "
9485051Swyllys 			    "See the man page for details.\n"));
9493089Swyllys 			rv = PK_ERR_USAGE;
9503089Swyllys 			goto end;
9513089Swyllys 		} else {
9523089Swyllys 			/* advance the altname past the '=' sign */
9533089Swyllys 			char *p = strchr(altname, '=');
9543089Swyllys 			if (p != NULL)
9553089Swyllys 				altname = p + 1;
9563089Swyllys 		}
9573089Swyllys 	}
9583089Swyllys 
9593089Swyllys 	if (keyusagestr != NULL) {
9603089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
9613089Swyllys 		if (rv != KMF_OK) {
9623089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
9635051Swyllys 			    "must be specified as a comma-separated list. "
9645051Swyllys 			    "See the man page for details.\n"));
9653089Swyllys 			rv = PK_ERR_USAGE;
9663089Swyllys 			goto end;
9673089Swyllys 		}
9683089Swyllys 	}
9696051Swyllys 	if (ekustr != NULL) {
9706051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
9716051Swyllys 		if (rv != KMF_OK) {
9726051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
9736051Swyllys 			    "be specified as a comma-separated list. "
9746051Swyllys 			    "See the man page for details.\n"));
9756051Swyllys 			rv = PK_ERR_USAGE;
9766051Swyllys 			goto end;
9776051Swyllys 		}
9786051Swyllys 	}
9793089Swyllys 
9803089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
9813089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
9823089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
9833089Swyllys 				tokenname = "internal";
9843089Swyllys 			} else  {
9853089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
9863089Swyllys 			}
9873089Swyllys 		}
9883089Swyllys 
9893089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
9903089Swyllys 	}
9913089Swyllys 
9923089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
9933089Swyllys 		if (dir == NULL)
9943089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
9953089Swyllys 
9963089Swyllys 		rv = gencert_nss(kmfhandle,
9975051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9985051Swyllys 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
9996051Swyllys 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
10006051Swyllys 		    ekulist);
10013089Swyllys 
10023089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
10033089Swyllys 		rv = gencert_pkcs11(kmfhandle,
10045051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
10055051Swyllys 		    certlabel, keyAlg, sigAlg, keylen, ltime,
10066051Swyllys 		    &serial, kubits, kucrit, &tokencred, ekulist);
10073089Swyllys 
10083089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
10093089Swyllys 		rv = gencert_file(kmfhandle,
10105051Swyllys 		    keyAlg, sigAlg, keylen, fmt,
10115051Swyllys 		    ltime, subname, altname, alttype, altcrit,
10126669Swyllys 		    &serial, kubits, kucrit, outcert, outkey,
10136051Swyllys 		    ekulist);
10143089Swyllys 	}
10153089Swyllys 
10163089Swyllys 	if (rv != KMF_OK)
10173089Swyllys 		display_error(kmfhandle, rv,
10185051Swyllys 		    gettext("Error creating certificate and keypair"));
10193089Swyllys end:
10206051Swyllys 	if (ekulist != NULL)
10216051Swyllys 		free_eku_list(ekulist);
10223089Swyllys 	if (subname)
10233089Swyllys 		free(subname);
10243089Swyllys 	if (tokencred.cred != NULL)
10253089Swyllys 		free(tokencred.cred);
10263089Swyllys 
10273089Swyllys 	if (serial.val != NULL)
10283089Swyllys 		free(serial.val);
10293089Swyllys 
10305051Swyllys 	(void) kmf_finalize(kmfhandle);
10313089Swyllys 	return (rv);
10323089Swyllys }
1033