xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 11973:480f5412d630)
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*11973Swyllys.ingersoll@sun.com  * Copyright 2010 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,
55*11973Swyllys.ingersoll@sun.com 	EKU_LIST *ekulist, KMF_OID *curveoid)
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 	if (kmfrv != KMF_OK) {
943089Swyllys 		return (kmfrv);
953089Swyllys 	}
963089Swyllys 
97*11973Swyllys.ingersoll@sun.com 	/*
98*11973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
99*11973Swyllys.ingersoll@sun.com 	 */
100*11973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
101*11973Swyllys.ingersoll@sun.com 	    keytype, keylength, tokencred, curveoid, &prik, &pubk);
102*11973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
1033089Swyllys 		return (kmfrv);
1043089Swyllys 
1055051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
1065051Swyllys 	    "keypair");
1073089Swyllys 
1085051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
1093089Swyllys 
1105051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
1115051Swyllys 	    "serial number");
1123089Swyllys 
1135051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
1145051Swyllys 	    "validity time");
1153089Swyllys 
1165051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
1175051Swyllys 	    "signature algorithm");
1183089Swyllys 
1195051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
1205051Swyllys 	    "subject name");
1213089Swyllys 
1225051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
1235051Swyllys 	    "issuer name");
1243089Swyllys 
1253089Swyllys 	if (altname != NULL)
1265051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
1275051Swyllys 		    alttype, altname), "subjectAltName");
1283089Swyllys 
1293089Swyllys 	if (kubits != 0)
1305051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
1315051Swyllys 		    "KeyUsage");
1325051Swyllys 
1336051Swyllys 	if (ekulist != NULL) {
1346051Swyllys 		int i;
1356051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1366051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
1376051Swyllys 			    &ekulist->ekulist[i], ekulist->critlist[i]),
1386051Swyllys 			    "Extended Key Usage");
1396051Swyllys 		}
1406051Swyllys 	}
1416051Swyllys 
1425051Swyllys 	/*
1435051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
1445051Swyllys 	 */
1455051Swyllys 	numattr = 0;
1465051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1475051Swyllys 	    &kstype, sizeof (kstype));
1485051Swyllys 	numattr++;
1493089Swyllys 
1505051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
1515051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
1525051Swyllys 	numattr++;
1535051Swyllys 
1545051Swyllys 	/* cert data that is to be signed */
1555051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
1565051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
1575051Swyllys 	numattr++;
1585051Swyllys 
1595051Swyllys 	/* output buffer for the signed cert */
1605051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
1615051Swyllys 	    &x509DER, sizeof (KMF_DATA));
1625051Swyllys 	numattr++;
1635051Swyllys 
1645051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
1655051Swyllys 	    KMF_OK) {
1663089Swyllys 		goto cleanup;
1673089Swyllys 	}
1683089Swyllys 
1693089Swyllys 	/*
1703089Swyllys 	 * Store the cert in the DB.
1713089Swyllys 	 */
1725051Swyllys 	numattr = 0;
1735051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1745051Swyllys 	    &kstype, sizeof (kstype));
1755051Swyllys 	numattr++;
1765051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
1775051Swyllys 	    &x509DER, sizeof (KMF_DATA));
1785051Swyllys 	numattr++;
1795051Swyllys 
1805051Swyllys 	if (certlabel != NULL) {
1815051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
1825051Swyllys 		    certlabel, strlen(certlabel));
1835051Swyllys 		numattr++;
1845051Swyllys 	}
1855051Swyllys 
1865051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
1875051Swyllys 
1883089Swyllys cleanup:
1895051Swyllys 	kmf_free_data(&x509DER);
1905051Swyllys 	kmf_free_dn(&certSubject);
1915051Swyllys 	kmf_free_dn(&certIssuer);
1929145SHuie-Ying.Lee@Sun.COM 
1939145SHuie-Ying.Lee@Sun.COM 	/*
1949145SHuie-Ying.Lee@Sun.COM 	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
1959145SHuie-Ying.Lee@Sun.COM 	 * the key pair from the token.
1969145SHuie-Ying.Lee@Sun.COM 	 */
1979145SHuie-Ying.Lee@Sun.COM 	if (kmfrv != KMF_OK) {
1989145SHuie-Ying.Lee@Sun.COM 		/* delete the public key */
1999145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
2009145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2019145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2029145SHuie-Ying.Lee@Sun.COM 		numattr++;
2039145SHuie-Ying.Lee@Sun.COM 
2049145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2059145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
2069145SHuie-Ying.Lee@Sun.COM 		numattr++;
2079145SHuie-Ying.Lee@Sun.COM 
2089145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
2099145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
2109145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
2119145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
2129145SHuie-Ying.Lee@Sun.COM 			numattr++;
2139145SHuie-Ying.Lee@Sun.COM 		}
2149145SHuie-Ying.Lee@Sun.COM 
2159145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
2169145SHuie-Ying.Lee@Sun.COM 		    attrlist);
2179145SHuie-Ying.Lee@Sun.COM 
2189145SHuie-Ying.Lee@Sun.COM 		/* delete the private key */
2199145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
2209145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2219145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2229145SHuie-Ying.Lee@Sun.COM 		numattr++;
2239145SHuie-Ying.Lee@Sun.COM 
2249145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2259145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
2269145SHuie-Ying.Lee@Sun.COM 		numattr++;
2279145SHuie-Ying.Lee@Sun.COM 
2289145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
2299145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
2309145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
2319145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
2329145SHuie-Ying.Lee@Sun.COM 			numattr++;
2339145SHuie-Ying.Lee@Sun.COM 		}
2349145SHuie-Ying.Lee@Sun.COM 
2359145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
2369145SHuie-Ying.Lee@Sun.COM 		    attrlist);
2379145SHuie-Ying.Lee@Sun.COM 	}
2389145SHuie-Ying.Lee@Sun.COM 
2393089Swyllys 	return (kmfrv);
2403089Swyllys }
2413089Swyllys 
2423089Swyllys static int
2433089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
2443089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
2453089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
2463089Swyllys 	uint32_t ltime, char *subject, char *altname,
2473089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2483089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
2496669Swyllys 	char *outcert, char *outkey,
2506051Swyllys 	EKU_LIST *ekulist)
2513089Swyllys {
2523089Swyllys 	KMF_RETURN kmfrv;
2533089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2543089Swyllys 	KMF_X509_CERTIFICATE signedCert;
2553089Swyllys 	KMF_X509_NAME	certSubject;
2563089Swyllys 	KMF_X509_NAME	certIssuer;
2573089Swyllys 	KMF_DATA x509DER;
2583089Swyllys 	char *fullcertpath = NULL;
2593089Swyllys 	char *fullkeypath = NULL;
2605051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2615051Swyllys 	KMF_ATTRIBUTE attrlist[10];
2625051Swyllys 	int numattr = 0;
2633089Swyllys 
2643089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
2653089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
2663089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
2673089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
2683089Swyllys 
2693089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
2703089Swyllys 		cryptoerror(LOG_STDERR,
2715051Swyllys 		    gettext("No output file was specified for "
2725051Swyllys 		    "the cert or key\n"));
2733089Swyllys 		return (PK_ERR_USAGE);
2743089Swyllys 	}
2756669Swyllys 	fullcertpath = strdup(outcert);
2763089Swyllys 	if (verify_file(fullcertpath)) {
2773089Swyllys 		cryptoerror(LOG_STDERR,
2785051Swyllys 		    gettext("Cannot write the indicated output "
2795051Swyllys 		    "certificate file (%s).\n"), fullcertpath);
2803089Swyllys 		free(fullcertpath);
2813089Swyllys 		return (PK_ERR_USAGE);
2823089Swyllys 	}
2836669Swyllys 
2843089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
2855051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
2863089Swyllys 		cryptoerror(LOG_STDERR,
2875051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
2883089Swyllys 		return (PK_ERR_USAGE);
2893089Swyllys 	}
2903089Swyllys 
2913089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
2925051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
2933089Swyllys 		cryptoerror(LOG_STDERR,
2945051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
2955051Swyllys 		kmf_free_dn(&certSubject);
2963089Swyllys 		return (PK_ERR_USAGE);
2973089Swyllys 	}
2983089Swyllys 
299*11973Swyllys.ingersoll@sun.com 	/*
300*11973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
301*11973Swyllys.ingersoll@sun.com 	 */
302*11973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
303*11973Swyllys.ingersoll@sun.com 	    fmt, outkey, &prik, &pubk);
304*11973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
305*11973Swyllys.ingersoll@sun.com 		return (kmfrv);
3065051Swyllys 
3075051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
3085051Swyllys 	    "keypair");
3093089Swyllys 
3105051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
3113089Swyllys 
3125051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
3135051Swyllys 	    "serial number");
3143089Swyllys 
3155051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
3165051Swyllys 	    "validity time");
3173089Swyllys 
3185051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
3195051Swyllys 	    "signature algorithm");
3203089Swyllys 
3215051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
3225051Swyllys 	    "subject name");
3233089Swyllys 
3245051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
3255051Swyllys 	    "issuer name");
3263089Swyllys 
3273089Swyllys 	if (altname != NULL)
3285051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
3295051Swyllys 		    alttype, altname), "subjectAltName");
3303089Swyllys 
3313089Swyllys 	if (kubits != 0)
3325051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
3335051Swyllys 		    "KeyUsage");
3346051Swyllys 
3356051Swyllys 	if (ekulist != NULL) {
3366051Swyllys 		int i;
3376051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
3386051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
3396051Swyllys 			    &ekulist->ekulist[i],
3406051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
3416051Swyllys 		}
3426051Swyllys 	}
3435051Swyllys 	/*
3445051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
3455051Swyllys 	 */
3465051Swyllys 	numattr = 0;
3475051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3485051Swyllys 	    &kstype, sizeof (kstype));
3495051Swyllys 	numattr++;
3503089Swyllys 
3515051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
3525051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
3535051Swyllys 	numattr++;
3545051Swyllys 
3555051Swyllys 	/* cert data that is to be signed */
3565051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
3575051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
3585051Swyllys 	numattr++;
3595051Swyllys 
3605051Swyllys 	/* output buffer for the signed cert */
3615051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
3625051Swyllys 	    &x509DER, sizeof (KMF_DATA));
3635051Swyllys 	numattr++;
3645051Swyllys 
3655051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
3665051Swyllys 	    KMF_OK) {
3673089Swyllys 		goto cleanup;
3683089Swyllys 	}
3693089Swyllys 
3703089Swyllys 	/*
3713089Swyllys 	 * Store the cert in the DB.
3723089Swyllys 	 */
3735051Swyllys 	numattr = 0;
3745051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3755051Swyllys 	    &kstype, sizeof (kstype));
3765051Swyllys 	numattr++;
3775051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
3785051Swyllys 	    &x509DER, sizeof (KMF_DATA));
3795051Swyllys 	numattr++;
3805051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
3815051Swyllys 	    fullcertpath, strlen(fullcertpath));
3825051Swyllys 	numattr++;
3835051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
3845051Swyllys 	    &fmt, sizeof (fmt));
3855051Swyllys 	numattr++;
3865051Swyllys 
3875051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
3883089Swyllys 
3893089Swyllys cleanup:
3903089Swyllys 	if (fullkeypath != NULL)
3913089Swyllys 		free(fullkeypath);
3923089Swyllys 	if (fullcertpath != NULL)
3933089Swyllys 		free(fullcertpath);
3943089Swyllys 
3955051Swyllys 	kmf_free_data(&x509DER);
3965051Swyllys 	kmf_free_dn(&certSubject);
3975051Swyllys 	kmf_free_dn(&certIssuer);
3983089Swyllys 	return (kmfrv);
3993089Swyllys }
4003089Swyllys 
4013089Swyllys static KMF_RETURN
4023089Swyllys gencert_nss(KMF_HANDLE_T kmfhandle,
4033089Swyllys 	char *token, char *subject, char *altname,
4043089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
4053089Swyllys 	char *nickname, char *dir, char *prefix,
4063089Swyllys 	KMF_KEY_ALG keyAlg,
4073089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
4083089Swyllys 	int keylen, char *trust,
4093089Swyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
4106051Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred,
411*11973Swyllys.ingersoll@sun.com 	EKU_LIST *ekulist, KMF_OID *curveoid)
4123089Swyllys {
4133089Swyllys 	KMF_RETURN kmfrv;
4143089Swyllys 	KMF_KEY_HANDLE pubk, prik;
4153089Swyllys 	KMF_X509_CERTIFICATE signedCert;
4163089Swyllys 	KMF_X509_NAME	certSubject;
4173089Swyllys 	KMF_X509_NAME	certIssuer;
4183089Swyllys 	KMF_DATA x509DER;
4195051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
4205051Swyllys 	KMF_ATTRIBUTE attrlist[16];
4215051Swyllys 	int numattr = 0;
4223089Swyllys 
4233089Swyllys 	if (token == NULL)
4243089Swyllys 		token = DEFAULT_NSS_TOKEN;
4253089Swyllys 
4263089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
4273089Swyllys 	if (kmfrv != KMF_OK)
4283089Swyllys 		return (kmfrv);
4293089Swyllys 
4303089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
4313089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
4323089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
4333089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
4343089Swyllys 
4353089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
4365051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
4373089Swyllys 		cryptoerror(LOG_STDERR,
4385051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4393089Swyllys 		return (PK_ERR_USAGE);
4403089Swyllys 	}
4413089Swyllys 
4423089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
4435051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
4443089Swyllys 		cryptoerror(LOG_STDERR,
4455051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4463089Swyllys 		return (PK_ERR_USAGE);
4473089Swyllys 	}
4483089Swyllys 
449*11973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
450*11973Swyllys.ingersoll@sun.com 	    prefix, keyAlg, keylen, tokencred, curveoid,
451*11973Swyllys.ingersoll@sun.com 	    &prik, &pubk);
452*11973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
4533089Swyllys 		return (kmfrv);
4543089Swyllys 
4555051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
4565051Swyllys 	    "keypair");
4573089Swyllys 
4585051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
4593089Swyllys 
4605051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
4615051Swyllys 	    "serial number");
4623089Swyllys 
4635051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
4645051Swyllys 	    "validity time");
4653089Swyllys 
4665051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
4675051Swyllys 	    "signature algorithm");
4683089Swyllys 
4695051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
4705051Swyllys 	    "subject name");
4713089Swyllys 
4725051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
4735051Swyllys 	    "issuer name");
4743089Swyllys 
4753089Swyllys 	if (altname != NULL)
4765051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
4775051Swyllys 		    alttype, altname), "subjectAltName");
4783089Swyllys 
4793089Swyllys 	if (kubits)
4805051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
4815051Swyllys 		    "subjectAltName");
4825051Swyllys 
4836051Swyllys 	if (ekulist != NULL) {
4846051Swyllys 		int i;
4856051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
4866051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
4876051Swyllys 			    &ekulist->ekulist[i],
4886051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
4896051Swyllys 		}
4906051Swyllys 	}
4915051Swyllys 	/*
4925051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
4935051Swyllys 	 */
4945051Swyllys 	numattr = 0;
4955051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4965051Swyllys 	    &kstype, sizeof (kstype));
4975051Swyllys 	numattr++;
4983089Swyllys 
4995051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
5005051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
5015051Swyllys 	numattr++;
5025051Swyllys 
5035051Swyllys 	/* cert data that is to be signed */
5045051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
5055051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
5065051Swyllys 	numattr++;
5075051Swyllys 
5085051Swyllys 	/* output buffer for the signed cert */
5095051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
5105051Swyllys 	    &x509DER, sizeof (KMF_DATA));
5115051Swyllys 	numattr++;
5125051Swyllys 
5135051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
5145051Swyllys 	    KMF_OK) {
5153089Swyllys 		goto cleanup;
5163089Swyllys 	}
5173089Swyllys 
5183089Swyllys 	/*
5193089Swyllys 	 * Store the cert in the DB.
5203089Swyllys 	 */
5215051Swyllys 	numattr = 0;
5225051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
5235051Swyllys 	    &kstype, sizeof (kstype));
5245051Swyllys 	numattr++;
5255051Swyllys 
5265051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
5275051Swyllys 	    &x509DER, sizeof (KMF_DATA));
5285051Swyllys 	numattr++;
5295051Swyllys 
5305051Swyllys 	if (nickname != NULL) {
5315051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
5325051Swyllys 		    nickname, strlen(nickname));
5335051Swyllys 		numattr++;
5345051Swyllys 	}
5355051Swyllys 
5365051Swyllys 	if (trust != NULL) {
5375051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
5385051Swyllys 		    trust, strlen(trust));
5395051Swyllys 		numattr++;
5405051Swyllys 	}
5415051Swyllys 
5425051Swyllys 	if (token != NULL) {
5435051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
5445051Swyllys 		    token, strlen(token));
5455051Swyllys 		numattr++;
5465051Swyllys 	}
5475051Swyllys 
5485051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
5493089Swyllys 
5503089Swyllys cleanup:
5515051Swyllys 	kmf_free_data(&x509DER);
5525051Swyllys 	kmf_free_dn(&certSubject);
5535051Swyllys 	kmf_free_dn(&certIssuer);
5543089Swyllys 	return (kmfrv);
5553089Swyllys }
5563089Swyllys 
5573089Swyllys int
5583089Swyllys pk_gencert(int argc, char *argv[])
5593089Swyllys {
5603089Swyllys 	int rv;
5613089Swyllys 	int opt;
5623089Swyllys 	extern int	optind_av;
5633089Swyllys 	extern char	*optarg_av;
5643089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
5653089Swyllys 	char *subject = NULL;
5663089Swyllys 	char *tokenname = NULL;
5673089Swyllys 	char *dir = NULL;
5683089Swyllys 	char *prefix = NULL;
5693089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
5703089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
5713089Swyllys 	char *trust = NULL;
5723089Swyllys 	char *lifetime = NULL;
5733089Swyllys 	char *certlabel = NULL;
5743089Swyllys 	char *outcert = NULL;
5753089Swyllys 	char *outkey = NULL;
5763089Swyllys 	char *format = NULL;
5773089Swyllys 	char *serstr = NULL;
5783089Swyllys 	char *altname = NULL;
5793089Swyllys 	char *keyusagestr = NULL;
5806051Swyllys 	char *ekustr = NULL;
581*11973Swyllys.ingersoll@sun.com 	char *hashname = NULL;
5823089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
5833089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
5843089Swyllys 	uint32_t ltime;
5853089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
5863089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
5873089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
58810744Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
5893089Swyllys 	boolean_t interactive = B_FALSE;
5903089Swyllys 	char *subname = NULL;
5913089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
5923089Swyllys 	uint16_t kubits = 0;
5933089Swyllys 	int altcrit = 0, kucrit = 0;
5946051Swyllys 	EKU_LIST *ekulist = NULL;
595*11973Swyllys.ingersoll@sun.com 	KMF_OID *curveoid = NULL; /* ECC */
596*11973Swyllys.ingersoll@sun.com 	KMF_OID *hashoid = NULL;
597*11973Swyllys.ingersoll@sun.com 	int y_flag = 0;
5983089Swyllys 
5993089Swyllys 	while ((opt = getopt_av(argc, argv,
6005051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
6015051Swyllys 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
6026051Swyllys 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
603*11973Swyllys.ingersoll@sun.com 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)C:(curve)"
604*11973Swyllys.ingersoll@sun.com 	    "E(listcurves)h:(hash)")) != EOF) {
6053089Swyllys 
606*11973Swyllys.ingersoll@sun.com 		if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
6073089Swyllys 			return (PK_ERR_USAGE);
6083089Swyllys 
6093089Swyllys 		switch (opt) {
6103089Swyllys 			case 'A':
6113089Swyllys 				altname = optarg_av;
6123089Swyllys 				break;
6133089Swyllys 			case 'i':
6143089Swyllys 				if (interactive || subject)
6153089Swyllys 					return (PK_ERR_USAGE);
6163089Swyllys 				else
6173089Swyllys 					interactive = B_TRUE;
6183089Swyllys 				break;
6193089Swyllys 			case 'k':
6203089Swyllys 				kstype = KS2Int(optarg_av);
6213089Swyllys 				if (kstype == 0)
6223089Swyllys 					return (PK_ERR_USAGE);
6233089Swyllys 				break;
6243089Swyllys 			case 's':
6253089Swyllys 				if (interactive || subject)
6263089Swyllys 					return (PK_ERR_USAGE);
6273089Swyllys 				else
6283089Swyllys 					subject = optarg_av;
6293089Swyllys 				break;
6303089Swyllys 			case 'l':
6313089Swyllys 			case 'n':
6323089Swyllys 				if (certlabel)
6333089Swyllys 					return (PK_ERR_USAGE);
6343089Swyllys 				certlabel = optarg_av;
6353089Swyllys 				break;
6363089Swyllys 			case 'T':
6373089Swyllys 				if (tokenname)
6383089Swyllys 					return (PK_ERR_USAGE);
6393089Swyllys 				tokenname = optarg_av;
6403089Swyllys 				break;
6413089Swyllys 			case 'd':
6423089Swyllys 				if (dir)
6433089Swyllys 					return (PK_ERR_USAGE);
6443089Swyllys 				dir = optarg_av;
6453089Swyllys 				break;
6463089Swyllys 			case 'p':
6473089Swyllys 				if (prefix)
6483089Swyllys 					return (PK_ERR_USAGE);
6493089Swyllys 				prefix = optarg_av;
6503089Swyllys 				break;
6513089Swyllys 			case 't':
6523089Swyllys 				keytype = optarg_av;
6533089Swyllys 				break;
6543089Swyllys 			case 'u':
6553089Swyllys 				keyusagestr = optarg_av;
6563089Swyllys 				break;
6573089Swyllys 			case 'y':
6583089Swyllys 				if (sscanf(optarg_av, "%d",
6595051Swyllys 				    &keylen) != 1) {
6603089Swyllys 					cryptoerror(LOG_STDERR,
6615051Swyllys 					    gettext("key length must be"
6625051Swyllys 					    "a numeric value (%s)\n"),
6635051Swyllys 					    optarg_av);
6643089Swyllys 					return (PK_ERR_USAGE);
6653089Swyllys 				}
666*11973Swyllys.ingersoll@sun.com 				y_flag++;
6673089Swyllys 				break;
6683089Swyllys 			case 'r':
6693089Swyllys 				if (trust)
6703089Swyllys 					return (PK_ERR_USAGE);
6713089Swyllys 				trust = optarg_av;
6723089Swyllys 				break;
6733089Swyllys 			case 'L':
6743089Swyllys 				if (lifetime)
6753089Swyllys 					return (PK_ERR_USAGE);
6763089Swyllys 				lifetime = optarg_av;
6773089Swyllys 				break;
6783089Swyllys 			case 'c':
6793089Swyllys 				if (outcert)
6803089Swyllys 					return (PK_ERR_USAGE);
6813089Swyllys 				outcert = optarg_av;
6823089Swyllys 				break;
6833089Swyllys 			case 'K':
6843089Swyllys 				if (outkey)
6853089Swyllys 					return (PK_ERR_USAGE);
6863089Swyllys 				outkey = optarg_av;
6873089Swyllys 				break;
6883089Swyllys 			case 'S':
6893089Swyllys 				serstr = optarg_av;
6903089Swyllys 				break;
6913089Swyllys 			case 'F':
6923089Swyllys 				if (format)
6933089Swyllys 					return (PK_ERR_USAGE);
6943089Swyllys 				format = optarg_av;
6953089Swyllys 				break;
6966051Swyllys 			case 'e':
6976051Swyllys 				ekustr = optarg_av;
6986051Swyllys 				break;
699*11973Swyllys.ingersoll@sun.com 			case 'C':
700*11973Swyllys.ingersoll@sun.com 				curveoid = ecc_name_to_oid(optarg_av);
701*11973Swyllys.ingersoll@sun.com 				if (curveoid == NULL) {
702*11973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
703*11973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized ECC "
704*11973Swyllys.ingersoll@sun.com 					    "curve.\n"));
705*11973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
706*11973Swyllys.ingersoll@sun.com 				}
707*11973Swyllys.ingersoll@sun.com 				break;
708*11973Swyllys.ingersoll@sun.com 			case 'E':
709*11973Swyllys.ingersoll@sun.com 				/*
710*11973Swyllys.ingersoll@sun.com 				 * This argument is only to be used
711*11973Swyllys.ingersoll@sun.com 				 * by itself, no other options should
712*11973Swyllys.ingersoll@sun.com 				 * be present.
713*11973Swyllys.ingersoll@sun.com 				 */
714*11973Swyllys.ingersoll@sun.com 				if (argc != 2) {
715*11973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
716*11973Swyllys.ingersoll@sun.com 					    gettext("listcurves has no other "
717*11973Swyllys.ingersoll@sun.com 					    "options.\n"));
718*11973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
719*11973Swyllys.ingersoll@sun.com 				}
720*11973Swyllys.ingersoll@sun.com 				show_ecc_curves();
721*11973Swyllys.ingersoll@sun.com 				return (0);
722*11973Swyllys.ingersoll@sun.com 			case 'h':
723*11973Swyllys.ingersoll@sun.com 				hashname = optarg_av;
724*11973Swyllys.ingersoll@sun.com 				hashoid = ecc_name_to_oid(optarg_av);
725*11973Swyllys.ingersoll@sun.com 				if (hashoid == NULL) {
726*11973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
727*11973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized hash.\n"));
728*11973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
729*11973Swyllys.ingersoll@sun.com 				}
730*11973Swyllys.ingersoll@sun.com 				break;
7313089Swyllys 			default:
7323089Swyllys 				return (PK_ERR_USAGE);
7333089Swyllys 		}
7343089Swyllys 	}
7353089Swyllys 
7363089Swyllys 	/* No additional args allowed. */
7373089Swyllys 	argc -= optind_av;
7383089Swyllys 	argv += optind_av;
7393089Swyllys 	if (argc) {
7403089Swyllys 		return (PK_ERR_USAGE);
7413089Swyllys 	}
7423089Swyllys 
7435051Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7443089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
7453089Swyllys 		return (PK_ERR_USAGE);
7463089Swyllys 	}
7473089Swyllys 
7483089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
7493089Swyllys 	if (kstype == 0)
7503089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
7513089Swyllys 
7525221Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
7535221Swyllys 		if (interactive && EMPTYSTRING(certlabel)) {
7545221Swyllys 			(void) get_certlabel(&certlabel);
7555221Swyllys 		}
7565221Swyllys 		/* It better not be empty now */
7575221Swyllys 		if (EMPTYSTRING(certlabel)) {
7585221Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
7595221Swyllys 			    "specified to create a self-signed certificate."
7605221Swyllys 			    "\n"));
7615221Swyllys 			return (PK_ERR_USAGE);
7625221Swyllys 		}
7633089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
7643089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
7653089Swyllys 		    "be specified to create a self-signed certificate.\n"));
7663089Swyllys 		return (PK_ERR_USAGE);
7673089Swyllys 	}
7683089Swyllys 
7696884Swyllys 	DIR_OPTION_CHECK(kstype, dir);
7706884Swyllys 
7713089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
7723089Swyllys 		cryptoerror(LOG_STDERR,
7733089Swyllys 		    gettext("Error parsing format string (%s).\n"),
7743089Swyllys 		    format);
7753089Swyllys 		return (PK_ERR_USAGE);
7763089Swyllys 	}
7773089Swyllys 
7783089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
7793089Swyllys 		cryptoerror(LOG_STDERR,
7805051Swyllys 		    gettext("Error parsing lifetime string\n"));
7813089Swyllys 		return (PK_ERR_USAGE);
7823089Swyllys 	}
7833089Swyllys 
784*11973Swyllys.ingersoll@sun.com 	if (Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg) != 0) {
785*11973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR,
786*11973Swyllys.ingersoll@sun.com 		    gettext("Unsupported key/hash combination (%s/%s).\n"),
787*11973Swyllys.ingersoll@sun.com 		    keytype, (hashname ? hashname : "none"));
7883089Swyllys 		return (PK_ERR_USAGE);
7893089Swyllys 	}
790*11973Swyllys.ingersoll@sun.com 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
791*11973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
792*11973Swyllys.ingersoll@sun.com 		    "valid for EC keytypes.\n"));
793*11973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
794*11973Swyllys.ingersoll@sun.com 	}
795*11973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
796*11973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("A curve must be "
797*11973Swyllys.ingersoll@sun.com 		    "specifed when using EC keys.\n"));
798*11973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
799*11973Swyllys.ingersoll@sun.com 	}
800*11973Swyllys.ingersoll@sun.com 	/* Adjust default keylength for NSS and DSA */
801*11973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
802*11973Swyllys.ingersoll@sun.com 		keylen = 1024;
8033089Swyllys 
8043089Swyllys 	/*
8053089Swyllys 	 * Check the subject name.
8063089Swyllys 	 * If interactive is true, get it now interactively.
8073089Swyllys 	 */
8083089Swyllys 	if (interactive) {
8095221Swyllys 		subname = NULL;
8105221Swyllys 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
8113089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
8123089Swyllys 			    "subject name interactively.\n"));
8133089Swyllys 			return (PK_ERR_USAGE);
8143089Swyllys 		}
8155221Swyllys 		if (serstr == NULL) {
8165221Swyllys 			(void) get_serial(&serstr);
8175221Swyllys 		}
8183089Swyllys 	} else {
8193089Swyllys 		if (EMPTYSTRING(subject)) {
8203089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
8213089Swyllys 			    "-i must be specified to create a self-signed "
8223089Swyllys 			    "certificate.\n"));
8233089Swyllys 			return (PK_ERR_USAGE);
8243089Swyllys 		} else {
8253089Swyllys 			subname = strdup(subject);
8263089Swyllys 			if (subname == NULL) {
8273089Swyllys 				cryptoerror(LOG_STDERR,
8283089Swyllys 				    gettext("Out of memory.\n"));
8293089Swyllys 				return (PK_ERR_SYSTEM);
8303089Swyllys 			}
8313089Swyllys 		}
8323089Swyllys 	}
8333089Swyllys 
8343089Swyllys 	if (serstr == NULL) {
8353089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
8365051Swyllys 		    "must be specified as a hex number when creating"
8375051Swyllys 		    " a self-signed certificate "
8385051Swyllys 		    "(ex: serial=0x0102030405feedface)\n"));
8393089Swyllys 		rv = PK_ERR_USAGE;
8403089Swyllys 		goto end;
8413089Swyllys 	} else {
8423089Swyllys 		uchar_t *bytes = NULL;
8433089Swyllys 		size_t bytelen;
8443089Swyllys 
8455051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
8463089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
8473089Swyllys 			(void) fprintf(stderr, gettext("serial number "
8485051Swyllys 			    "must be specified as a hex number "
8495051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
8503089Swyllys 			rv = PK_ERR_USAGE;
8513089Swyllys 			goto end;
8523089Swyllys 		}
8533089Swyllys 		serial.val = bytes;
8543089Swyllys 		serial.len = bytelen;
8553089Swyllys 	}
8563089Swyllys 
8573089Swyllys 	if (altname != NULL) {
8583089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
8593089Swyllys 		if (rv != KMF_OK) {
8603089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
8615051Swyllys 			    "must be specified as a name=value pair. "
8625051Swyllys 			    "See the man page for details.\n"));
8633089Swyllys 			rv = PK_ERR_USAGE;
8643089Swyllys 			goto end;
8653089Swyllys 		} else {
8663089Swyllys 			/* advance the altname past the '=' sign */
8673089Swyllys 			char *p = strchr(altname, '=');
8683089Swyllys 			if (p != NULL)
8693089Swyllys 				altname = p + 1;
8703089Swyllys 		}
8713089Swyllys 	}
8723089Swyllys 
8733089Swyllys 	if (keyusagestr != NULL) {
8743089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
8753089Swyllys 		if (rv != KMF_OK) {
8763089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
8775051Swyllys 			    "must be specified as a comma-separated list. "
8785051Swyllys 			    "See the man page for details.\n"));
8793089Swyllys 			rv = PK_ERR_USAGE;
8803089Swyllys 			goto end;
8813089Swyllys 		}
8823089Swyllys 	}
8836051Swyllys 	if (ekustr != NULL) {
8846051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
8856051Swyllys 		if (rv != KMF_OK) {
8866051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
8876051Swyllys 			    "be specified as a comma-separated list. "
8886051Swyllys 			    "See the man page for details.\n"));
8896051Swyllys 			rv = PK_ERR_USAGE;
8906051Swyllys 			goto end;
8916051Swyllys 		}
8926051Swyllys 	}
893*11973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
894*11973Swyllys.ingersoll@sun.com 		(void) fprintf(stderr, gettext("ECC certificates are"
895*11973Swyllys.ingersoll@sun.com 		    "only supported with the pkcs11 and nss keystores\n"));
896*11973Swyllys.ingersoll@sun.com 		rv = PK_ERR_USAGE;
897*11973Swyllys.ingersoll@sun.com 		goto end;
898*11973Swyllys.ingersoll@sun.com 	}
8993089Swyllys 
9003089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
9013089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
9023089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
9033089Swyllys 				tokenname = "internal";
9043089Swyllys 			} else  {
9053089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
9063089Swyllys 			}
9073089Swyllys 		}
9083089Swyllys 
9093089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
9103089Swyllys 	}
9113089Swyllys 
9123089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
9133089Swyllys 		if (dir == NULL)
9143089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
9153089Swyllys 
9163089Swyllys 		rv = gencert_nss(kmfhandle,
9175051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9185051Swyllys 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
9196051Swyllys 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
920*11973Swyllys.ingersoll@sun.com 		    ekulist, curveoid);
9213089Swyllys 
9223089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
9233089Swyllys 		rv = gencert_pkcs11(kmfhandle,
9245051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9255051Swyllys 		    certlabel, keyAlg, sigAlg, keylen, ltime,
926*11973Swyllys.ingersoll@sun.com 		    &serial, kubits, kucrit, &tokencred, ekulist,
927*11973Swyllys.ingersoll@sun.com 		    curveoid);
9283089Swyllys 
9293089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
9303089Swyllys 		rv = gencert_file(kmfhandle,
9315051Swyllys 		    keyAlg, sigAlg, keylen, fmt,
9325051Swyllys 		    ltime, subname, altname, alttype, altcrit,
9336669Swyllys 		    &serial, kubits, kucrit, outcert, outkey,
9346051Swyllys 		    ekulist);
9353089Swyllys 	}
9363089Swyllys 
9373089Swyllys 	if (rv != KMF_OK)
9383089Swyllys 		display_error(kmfhandle, rv,
9395051Swyllys 		    gettext("Error creating certificate and keypair"));
9403089Swyllys end:
9416051Swyllys 	if (ekulist != NULL)
9426051Swyllys 		free_eku_list(ekulist);
9433089Swyllys 	if (subname)
9443089Swyllys 		free(subname);
9453089Swyllys 	if (tokencred.cred != NULL)
9463089Swyllys 		free(tokencred.cred);
9473089Swyllys 
9483089Swyllys 	if (serial.val != NULL)
9493089Swyllys 		free(serial.val);
9503089Swyllys 
9515051Swyllys 	(void) kmf_finalize(kmfhandle);
9523089Swyllys 	return (rv);
9533089Swyllys }
954