xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 6669:bc95c5ad177e)
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 /*
226051Swyllys  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233089Swyllys  * Use is subject to license terms.
243089Swyllys  */
253089Swyllys 
263089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
273089Swyllys 
283089Swyllys #include <stdio.h>
293089Swyllys #include <string.h>
303089Swyllys #include <ctype.h>
313089Swyllys #include <malloc.h>
323089Swyllys #include <libgen.h>
333089Swyllys #include <errno.h>
343089Swyllys #include <cryptoutil.h>
353089Swyllys #include <security/cryptoki.h>
363089Swyllys #include "common.h"
373089Swyllys 
383089Swyllys #include <kmfapi.h>
393089Swyllys 
403089Swyllys #define	SET_VALUE(f, s) \
413089Swyllys 	kmfrv = f; \
423089Swyllys 	if (kmfrv != KMF_OK) { \
433089Swyllys 		cryptoerror(LOG_STDERR, \
443089Swyllys 			gettext("Failed to set %s: 0x%02x\n"), \
453089Swyllys 			s, kmfrv); \
463089Swyllys 		goto cleanup; \
473089Swyllys 	}
483089Swyllys 
493089Swyllys static int
503089Swyllys gencert_pkcs11(KMF_HANDLE_T kmfhandle,
513089Swyllys 	char *token, char *subject, char *altname,
523089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
533089Swyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
543089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
553089Swyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
566051Swyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
576051Swyllys 	EKU_LIST *ekulist)
583089Swyllys {
593089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
603089Swyllys 	KMF_KEY_HANDLE pubk, prik;
613089Swyllys 	KMF_X509_CERTIFICATE signedCert;
623089Swyllys 	KMF_X509_NAME	certSubject;
633089Swyllys 	KMF_X509_NAME	certIssuer;
643089Swyllys 	KMF_DATA x509DER;
655051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
665051Swyllys 	KMF_ATTRIBUTE attrlist[16];
675051Swyllys 	int numattr = 0;
685051Swyllys 	KMF_KEY_ALG keytype;
695051Swyllys 	uint32_t keylength;
703089Swyllys 
713089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
723089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
733089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
743089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
753089Swyllys 
763089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
775051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
783089Swyllys 		cryptoerror(LOG_STDERR,
795051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
803089Swyllys 		return (PK_ERR_USAGE);
813089Swyllys 	}
823089Swyllys 
833089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
845051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
853089Swyllys 		cryptoerror(LOG_STDERR,
865051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
873089Swyllys 		return (PK_ERR_USAGE);
883089Swyllys 	}
893089Swyllys 
905051Swyllys 	keylength = keylen; /* bits */
915051Swyllys 	keytype = keyAlg;
923089Swyllys 
933089Swyllys 	/* Select a PKCS11 token */
943089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
953089Swyllys 
963089Swyllys 	if (kmfrv != KMF_OK) {
973089Swyllys 		return (kmfrv);
983089Swyllys 	}
993089Swyllys 
1005051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1015051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
1025051Swyllys 	    sizeof (kstype));
1035051Swyllys 	numattr++;
1045051Swyllys 
1055051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1065051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
1075051Swyllys 	    sizeof (keytype));
1085051Swyllys 	numattr++;
1095051Swyllys 
1105051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1115051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
1125051Swyllys 	    sizeof (keylength));
1135051Swyllys 	numattr++;
1145051Swyllys 
1155051Swyllys 	if (certlabel != NULL) {
1165051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
1175051Swyllys 		    KMF_KEYLABEL_ATTR, certlabel,
1185051Swyllys 		    strlen(certlabel));
1195051Swyllys 		numattr++;
1205051Swyllys 	}
1215051Swyllys 
1226354Swyllys 	if (tokencred != NULL && tokencred->cred != NULL) {
1235051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
1245051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
1255051Swyllys 		    sizeof (KMF_CREDENTIAL));
1265051Swyllys 		numattr++;
1275051Swyllys 	}
1285051Swyllys 
1295051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1305051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
1315051Swyllys 	    sizeof (KMF_KEY_HANDLE));
1325051Swyllys 	numattr++;
1335051Swyllys 
1345051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
1355051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
1365051Swyllys 	    sizeof (KMF_KEY_HANDLE));
1375051Swyllys 	numattr++;
1385051Swyllys 
1395051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
1403089Swyllys 	if (kmfrv != KMF_OK) {
1413089Swyllys 		return (kmfrv);
1423089Swyllys 	}
1433089Swyllys 
1445051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
1455051Swyllys 	    "keypair");
1463089Swyllys 
1475051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
1483089Swyllys 
1495051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
1505051Swyllys 	    "serial number");
1513089Swyllys 
1525051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
1535051Swyllys 	    "validity time");
1543089Swyllys 
1555051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
1565051Swyllys 	    "signature algorithm");
1573089Swyllys 
1585051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
1595051Swyllys 	    "subject name");
1603089Swyllys 
1615051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
1625051Swyllys 	    "issuer name");
1633089Swyllys 
1643089Swyllys 	if (altname != NULL)
1655051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
1665051Swyllys 		    alttype, altname), "subjectAltName");
1673089Swyllys 
1683089Swyllys 	if (kubits != 0)
1695051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
1705051Swyllys 		    "KeyUsage");
1715051Swyllys 
1726051Swyllys 	if (ekulist != NULL) {
1736051Swyllys 		int i;
1746051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1756051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
1766051Swyllys 			    &ekulist->ekulist[i], ekulist->critlist[i]),
1776051Swyllys 			    "Extended Key Usage");
1786051Swyllys 		}
1796051Swyllys 	}
1806051Swyllys 
1815051Swyllys 	/*
1825051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
1835051Swyllys 	 */
1845051Swyllys 	numattr = 0;
1855051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1865051Swyllys 	    &kstype, sizeof (kstype));
1875051Swyllys 	numattr++;
1883089Swyllys 
1895051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
1905051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
1915051Swyllys 	numattr++;
1925051Swyllys 
1935051Swyllys 	/* cert data that is to be signed */
1945051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
1955051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
1965051Swyllys 	numattr++;
1975051Swyllys 
1985051Swyllys 	/* output buffer for the signed cert */
1995051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
2005051Swyllys 	    &x509DER, sizeof (KMF_DATA));
2015051Swyllys 	numattr++;
2025051Swyllys 
2035051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
2045051Swyllys 	    KMF_OK) {
2053089Swyllys 		goto cleanup;
2063089Swyllys 	}
2073089Swyllys 
2083089Swyllys 	/*
2093089Swyllys 	 * Store the cert in the DB.
2103089Swyllys 	 */
2115051Swyllys 	numattr = 0;
2125051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
2135051Swyllys 	    &kstype, sizeof (kstype));
2145051Swyllys 	numattr++;
2155051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
2165051Swyllys 	    &x509DER, sizeof (KMF_DATA));
2175051Swyllys 	numattr++;
2185051Swyllys 
2195051Swyllys 	if (certlabel != NULL) {
2205051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
2215051Swyllys 		    certlabel, strlen(certlabel));
2225051Swyllys 		numattr++;
2235051Swyllys 	}
2245051Swyllys 
2255051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
2265051Swyllys 
2273089Swyllys 
2283089Swyllys cleanup:
2295051Swyllys 	kmf_free_data(&x509DER);
2305051Swyllys 	kmf_free_dn(&certSubject);
2315051Swyllys 	kmf_free_dn(&certIssuer);
2323089Swyllys 	return (kmfrv);
2333089Swyllys }
2343089Swyllys 
2353089Swyllys static int
2363089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
2373089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
2383089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
2393089Swyllys 	uint32_t ltime, char *subject, char *altname,
2403089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2413089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
242*6669Swyllys 	char *outcert, char *outkey,
2436051Swyllys 	EKU_LIST *ekulist)
2443089Swyllys {
2453089Swyllys 	KMF_RETURN kmfrv;
2463089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2473089Swyllys 	KMF_X509_CERTIFICATE signedCert;
2483089Swyllys 	KMF_X509_NAME	certSubject;
2493089Swyllys 	KMF_X509_NAME	certIssuer;
2503089Swyllys 	KMF_DATA x509DER;
2513089Swyllys 	char *fullcertpath = NULL;
2523089Swyllys 	char *fullkeypath = NULL;
2535051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2545051Swyllys 	KMF_ATTRIBUTE attrlist[10];
2555051Swyllys 	int numattr = 0;
2565051Swyllys 	KMF_KEY_ALG keytype;
2575051Swyllys 	uint32_t keylength;
2585051Swyllys 	KMF_ENCODE_FORMAT format;
2593089Swyllys 
2603089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
2613089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
2623089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
2633089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
2643089Swyllys 
2653089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
2663089Swyllys 		cryptoerror(LOG_STDERR,
2675051Swyllys 		    gettext("No output file was specified for "
2685051Swyllys 		    "the cert or key\n"));
2693089Swyllys 		return (PK_ERR_USAGE);
2703089Swyllys 	}
271*6669Swyllys 	fullcertpath = strdup(outcert);
2723089Swyllys 	if (verify_file(fullcertpath)) {
2733089Swyllys 		cryptoerror(LOG_STDERR,
2745051Swyllys 		    gettext("Cannot write the indicated output "
2755051Swyllys 		    "certificate file (%s).\n"), fullcertpath);
2763089Swyllys 		free(fullcertpath);
2773089Swyllys 		return (PK_ERR_USAGE);
2783089Swyllys 	}
279*6669Swyllys 
280*6669Swyllys 	fullkeypath = strdup(outkey);
2813089Swyllys 	if (verify_file(fullkeypath)) {
2823089Swyllys 		cryptoerror(LOG_STDERR,
2835051Swyllys 		    gettext("Cannot write the indicated output "
2845051Swyllys 		    "key file (%s).\n"), fullkeypath);
2853089Swyllys 		free(fullkeypath);
2863089Swyllys 		free(fullcertpath);
2873089Swyllys 		return (PK_ERR_USAGE);
2883089Swyllys 	}
2893089Swyllys 
2903089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
2915051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
2923089Swyllys 		cryptoerror(LOG_STDERR,
2935051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
2943089Swyllys 		return (PK_ERR_USAGE);
2953089Swyllys 	}
2963089Swyllys 
2973089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
2985051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
2993089Swyllys 		cryptoerror(LOG_STDERR,
3005051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
3015051Swyllys 		kmf_free_dn(&certSubject);
3023089Swyllys 		return (PK_ERR_USAGE);
3033089Swyllys 	}
3043089Swyllys 
3055051Swyllys 	keylength = keylen; /* bits */
3065051Swyllys 	keytype = keyAlg;
3075051Swyllys 	format = fmt;
3085051Swyllys 
3095051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3105051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
3115051Swyllys 	    sizeof (kstype));
3125051Swyllys 	numattr++;
3135051Swyllys 
3145051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3155051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
3165051Swyllys 	    sizeof (keytype));
3175051Swyllys 	numattr++;
3185051Swyllys 
3195051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3205051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
3215051Swyllys 	    sizeof (keylength));
3225051Swyllys 	numattr++;
3233089Swyllys 
3245051Swyllys 	if (fullkeypath != NULL) {
3255051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
3265051Swyllys 		    KMF_KEY_FILENAME_ATTR, fullkeypath,
3275051Swyllys 		    strlen(fullkeypath));
3285051Swyllys 		numattr++;
3295051Swyllys 	}
3305051Swyllys 
3315051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3325051Swyllys 	    KMF_ENCODE_FORMAT_ATTR, &format,
3335051Swyllys 	    sizeof (format));
3345051Swyllys 	numattr++;
3353089Swyllys 
3365051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3375051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
3385051Swyllys 	    sizeof (KMF_KEY_HANDLE));
3395051Swyllys 	numattr++;
3405051Swyllys 
3415051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
3425051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
3435051Swyllys 	    sizeof (KMF_KEY_HANDLE));
3445051Swyllys 	numattr++;
3455051Swyllys 
3465051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
3473089Swyllys 	if (kmfrv != KMF_OK) {
3483089Swyllys 		goto cleanup;
3493089Swyllys 	}
3505051Swyllys 
3515051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
3525051Swyllys 	    "keypair");
3533089Swyllys 
3545051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
3553089Swyllys 
3565051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
3575051Swyllys 	    "serial number");
3583089Swyllys 
3595051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
3605051Swyllys 	    "validity time");
3613089Swyllys 
3625051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
3635051Swyllys 	    "signature algorithm");
3643089Swyllys 
3655051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
3665051Swyllys 	    "subject name");
3673089Swyllys 
3685051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
3695051Swyllys 	    "issuer name");
3703089Swyllys 
3713089Swyllys 	if (altname != NULL)
3725051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
3735051Swyllys 		    alttype, altname), "subjectAltName");
3743089Swyllys 
3753089Swyllys 	if (kubits != 0)
3765051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
3775051Swyllys 		    "KeyUsage");
3786051Swyllys 
3796051Swyllys 	if (ekulist != NULL) {
3806051Swyllys 		int i;
3816051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
3826051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
3836051Swyllys 			    &ekulist->ekulist[i],
3846051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
3856051Swyllys 		}
3866051Swyllys 	}
3875051Swyllys 	/*
3885051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
3895051Swyllys 	 */
3905051Swyllys 	numattr = 0;
3915051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3925051Swyllys 	    &kstype, sizeof (kstype));
3935051Swyllys 	numattr++;
3943089Swyllys 
3955051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
3965051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
3975051Swyllys 	numattr++;
3985051Swyllys 
3995051Swyllys 	/* cert data that is to be signed */
4005051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
4015051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
4025051Swyllys 	numattr++;
4035051Swyllys 
4045051Swyllys 	/* output buffer for the signed cert */
4055051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
4065051Swyllys 	    &x509DER, sizeof (KMF_DATA));
4075051Swyllys 	numattr++;
4085051Swyllys 
4095051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
4105051Swyllys 	    KMF_OK) {
4113089Swyllys 		goto cleanup;
4123089Swyllys 	}
4133089Swyllys 
4143089Swyllys 	/*
4153089Swyllys 	 * Store the cert in the DB.
4163089Swyllys 	 */
4175051Swyllys 	numattr = 0;
4185051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4195051Swyllys 	    &kstype, sizeof (kstype));
4205051Swyllys 	numattr++;
4215051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
4225051Swyllys 	    &x509DER, sizeof (KMF_DATA));
4235051Swyllys 	numattr++;
4245051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
4255051Swyllys 	    fullcertpath, strlen(fullcertpath));
4265051Swyllys 	numattr++;
4275051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
4285051Swyllys 	    &fmt, sizeof (fmt));
4295051Swyllys 	numattr++;
4305051Swyllys 
4315051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
4323089Swyllys 
4333089Swyllys cleanup:
4343089Swyllys 	if (fullkeypath != NULL)
4353089Swyllys 		free(fullkeypath);
4363089Swyllys 	if (fullcertpath != NULL)
4373089Swyllys 		free(fullcertpath);
4383089Swyllys 
4395051Swyllys 	kmf_free_data(&x509DER);
4405051Swyllys 	kmf_free_dn(&certSubject);
4415051Swyllys 	kmf_free_dn(&certIssuer);
4423089Swyllys 	return (kmfrv);
4433089Swyllys }
4443089Swyllys 
4453089Swyllys static KMF_RETURN
4463089Swyllys gencert_nss(KMF_HANDLE_T kmfhandle,
4473089Swyllys 	char *token, char *subject, char *altname,
4483089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
4493089Swyllys 	char *nickname, char *dir, char *prefix,
4503089Swyllys 	KMF_KEY_ALG keyAlg,
4513089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
4523089Swyllys 	int keylen, char *trust,
4533089Swyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
4546051Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred,
4556051Swyllys 	EKU_LIST *ekulist)
4563089Swyllys {
4573089Swyllys 	KMF_RETURN kmfrv;
4583089Swyllys 	KMF_KEY_HANDLE pubk, prik;
4593089Swyllys 	KMF_X509_CERTIFICATE signedCert;
4603089Swyllys 	KMF_X509_NAME	certSubject;
4613089Swyllys 	KMF_X509_NAME	certIssuer;
4623089Swyllys 	KMF_DATA x509DER;
4635051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
4645051Swyllys 	KMF_ATTRIBUTE attrlist[16];
4655051Swyllys 	int numattr = 0;
4665051Swyllys 	KMF_KEY_ALG keytype;
4675051Swyllys 	uint32_t keylength;
4683089Swyllys 
4693089Swyllys 	if (token == NULL)
4703089Swyllys 		token = DEFAULT_NSS_TOKEN;
4713089Swyllys 
4723089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
4733089Swyllys 	if (kmfrv != KMF_OK)
4743089Swyllys 		return (kmfrv);
4753089Swyllys 
4763089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
4773089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
4783089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
4793089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
4803089Swyllys 
4813089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
4825051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
4833089Swyllys 		cryptoerror(LOG_STDERR,
4845051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4853089Swyllys 		return (PK_ERR_USAGE);
4863089Swyllys 	}
4873089Swyllys 
4883089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
4895051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
4903089Swyllys 		cryptoerror(LOG_STDERR,
4915051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4923089Swyllys 		return (PK_ERR_USAGE);
4933089Swyllys 	}
4943089Swyllys 
4955051Swyllys 	keylength = keylen; /* bits */
4965051Swyllys 	keytype = keyAlg;
4975051Swyllys 
4985051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
4995051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
5005051Swyllys 	    sizeof (kstype));
5015051Swyllys 	numattr++;
5025051Swyllys 
5035051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5045051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
5055051Swyllys 	    sizeof (keytype));
5065051Swyllys 	numattr++;
5075051Swyllys 
5085051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5095051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
5105051Swyllys 	    sizeof (keylength));
5115051Swyllys 	numattr++;
5125051Swyllys 
5135051Swyllys 	if (nickname != NULL) {
5145051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5155051Swyllys 		    KMF_KEYLABEL_ATTR, nickname,
5165051Swyllys 		    strlen(nickname));
5175051Swyllys 		numattr++;
5185051Swyllys 	}
5193089Swyllys 
5206354Swyllys 	if (tokencred != NULL && tokencred->cred != NULL) {
5215051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5225051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
5235051Swyllys 		    sizeof (KMF_CREDENTIAL));
5245051Swyllys 		numattr++;
5255051Swyllys 	}
5263089Swyllys 
5275051Swyllys 	if (token != NULL) {
5285051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
5295051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
5305051Swyllys 		    strlen(token));
5315051Swyllys 		numattr++;
5325051Swyllys 	}
5335051Swyllys 
5345051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5355051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
5365051Swyllys 	    sizeof (KMF_KEY_HANDLE));
5375051Swyllys 	numattr++;
5385051Swyllys 
5395051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
5405051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
5415051Swyllys 	    sizeof (KMF_KEY_HANDLE));
5425051Swyllys 	numattr++;
5435051Swyllys 
5445051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
5453089Swyllys 	if (kmfrv != KMF_OK) {
5463089Swyllys 		return (kmfrv);
5473089Swyllys 	}
5483089Swyllys 
5495051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
5505051Swyllys 	    "keypair");
5513089Swyllys 
5525051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
5533089Swyllys 
5545051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
5555051Swyllys 	    "serial number");
5563089Swyllys 
5575051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
5585051Swyllys 	    "validity time");
5593089Swyllys 
5605051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
5615051Swyllys 	    "signature algorithm");
5623089Swyllys 
5635051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
5645051Swyllys 	    "subject name");
5653089Swyllys 
5665051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
5675051Swyllys 	    "issuer name");
5683089Swyllys 
5693089Swyllys 	if (altname != NULL)
5705051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
5715051Swyllys 		    alttype, altname), "subjectAltName");
5723089Swyllys 
5733089Swyllys 	if (kubits)
5745051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
5755051Swyllys 		    "subjectAltName");
5765051Swyllys 
5776051Swyllys 	if (ekulist != NULL) {
5786051Swyllys 		int i;
5796051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
5806051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
5816051Swyllys 			    &ekulist->ekulist[i],
5826051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
5836051Swyllys 		}
5846051Swyllys 	}
5855051Swyllys 	/*
5865051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
5875051Swyllys 	 */
5885051Swyllys 	numattr = 0;
5895051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
5905051Swyllys 	    &kstype, sizeof (kstype));
5915051Swyllys 	numattr++;
5923089Swyllys 
5935051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
5945051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
5955051Swyllys 	numattr++;
5965051Swyllys 
5975051Swyllys 	/* cert data that is to be signed */
5985051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
5995051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
6005051Swyllys 	numattr++;
6015051Swyllys 
6025051Swyllys 	/* output buffer for the signed cert */
6035051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
6045051Swyllys 	    &x509DER, sizeof (KMF_DATA));
6055051Swyllys 	numattr++;
6065051Swyllys 
6075051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
6085051Swyllys 	    KMF_OK) {
6093089Swyllys 		goto cleanup;
6103089Swyllys 	}
6113089Swyllys 
6123089Swyllys 	/*
6133089Swyllys 	 * Store the cert in the DB.
6143089Swyllys 	 */
6155051Swyllys 	numattr = 0;
6165051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6175051Swyllys 	    &kstype, sizeof (kstype));
6185051Swyllys 	numattr++;
6195051Swyllys 
6205051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
6215051Swyllys 	    &x509DER, sizeof (KMF_DATA));
6225051Swyllys 	numattr++;
6235051Swyllys 
6245051Swyllys 	if (nickname != NULL) {
6255051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
6265051Swyllys 		    nickname, strlen(nickname));
6275051Swyllys 		numattr++;
6285051Swyllys 	}
6295051Swyllys 
6305051Swyllys 	if (trust != NULL) {
6315051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
6325051Swyllys 		    trust, strlen(trust));
6335051Swyllys 		numattr++;
6345051Swyllys 	}
6355051Swyllys 
6365051Swyllys 	if (token != NULL) {
6375051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
6385051Swyllys 		    token, strlen(token));
6395051Swyllys 		numattr++;
6405051Swyllys 	}
6415051Swyllys 
6425051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
6433089Swyllys 
6443089Swyllys cleanup:
6455051Swyllys 	kmf_free_data(&x509DER);
6465051Swyllys 	kmf_free_dn(&certSubject);
6475051Swyllys 	kmf_free_dn(&certIssuer);
6483089Swyllys 	return (kmfrv);
6493089Swyllys }
6503089Swyllys 
6513089Swyllys int
6523089Swyllys pk_gencert(int argc, char *argv[])
6533089Swyllys {
6543089Swyllys 	int rv;
6553089Swyllys 	int opt;
6563089Swyllys 	extern int	optind_av;
6573089Swyllys 	extern char	*optarg_av;
6583089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
6593089Swyllys 	char *subject = NULL;
6603089Swyllys 	char *tokenname = NULL;
6613089Swyllys 	char *dir = NULL;
6623089Swyllys 	char *prefix = NULL;
6633089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
6643089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
6653089Swyllys 	char *trust = NULL;
6663089Swyllys 	char *lifetime = NULL;
6673089Swyllys 	char *certlabel = NULL;
6683089Swyllys 	char *outcert = NULL;
6693089Swyllys 	char *outkey = NULL;
6703089Swyllys 	char *format = NULL;
6713089Swyllys 	char *serstr = NULL;
6723089Swyllys 	char *altname = NULL;
6733089Swyllys 	char *keyusagestr = NULL;
6746051Swyllys 	char *ekustr = NULL;
6753089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
6763089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
6773089Swyllys 	uint32_t ltime;
6783089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
6793089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
6803089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
6813089Swyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
6823089Swyllys 	boolean_t interactive = B_FALSE;
6833089Swyllys 	char *subname = NULL;
6843089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
6853089Swyllys 	uint16_t kubits = 0;
6863089Swyllys 	int altcrit = 0, kucrit = 0;
6876051Swyllys 	EKU_LIST *ekulist = NULL;
6883089Swyllys 
6893089Swyllys 	while ((opt = getopt_av(argc, argv,
6905051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
6915051Swyllys 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
6926051Swyllys 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
6935051Swyllys 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
6943089Swyllys 
6953089Swyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
6963089Swyllys 			return (PK_ERR_USAGE);
6973089Swyllys 
6983089Swyllys 		switch (opt) {
6993089Swyllys 			case 'A':
7003089Swyllys 				altname = optarg_av;
7013089Swyllys 				break;
7023089Swyllys 			case 'i':
7033089Swyllys 				if (interactive || subject)
7043089Swyllys 					return (PK_ERR_USAGE);
7053089Swyllys 				else
7063089Swyllys 					interactive = B_TRUE;
7073089Swyllys 				break;
7083089Swyllys 			case 'k':
7093089Swyllys 				kstype = KS2Int(optarg_av);
7103089Swyllys 				if (kstype == 0)
7113089Swyllys 					return (PK_ERR_USAGE);
7123089Swyllys 				break;
7133089Swyllys 			case 's':
7143089Swyllys 				if (interactive || subject)
7153089Swyllys 					return (PK_ERR_USAGE);
7163089Swyllys 				else
7173089Swyllys 					subject = optarg_av;
7183089Swyllys 				break;
7193089Swyllys 			case 'l':
7203089Swyllys 			case 'n':
7213089Swyllys 				if (certlabel)
7223089Swyllys 					return (PK_ERR_USAGE);
7233089Swyllys 				certlabel = optarg_av;
7243089Swyllys 				break;
7253089Swyllys 			case 'T':
7263089Swyllys 				if (tokenname)
7273089Swyllys 					return (PK_ERR_USAGE);
7283089Swyllys 				tokenname = optarg_av;
7293089Swyllys 				break;
7303089Swyllys 			case 'd':
7313089Swyllys 				if (dir)
7323089Swyllys 					return (PK_ERR_USAGE);
7333089Swyllys 				dir = optarg_av;
7343089Swyllys 				break;
7353089Swyllys 			case 'p':
7363089Swyllys 				if (prefix)
7373089Swyllys 					return (PK_ERR_USAGE);
7383089Swyllys 				prefix = optarg_av;
7393089Swyllys 				break;
7403089Swyllys 			case 't':
7413089Swyllys 				keytype = optarg_av;
7423089Swyllys 				break;
7433089Swyllys 			case 'u':
7443089Swyllys 				keyusagestr = optarg_av;
7453089Swyllys 				break;
7463089Swyllys 			case 'y':
7473089Swyllys 				if (sscanf(optarg_av, "%d",
7485051Swyllys 				    &keylen) != 1) {
7493089Swyllys 					cryptoerror(LOG_STDERR,
7505051Swyllys 					    gettext("key length must be"
7515051Swyllys 					    "a numeric value (%s)\n"),
7525051Swyllys 					    optarg_av);
7533089Swyllys 					return (PK_ERR_USAGE);
7543089Swyllys 				}
7553089Swyllys 				break;
7563089Swyllys 			case 'r':
7573089Swyllys 				if (trust)
7583089Swyllys 					return (PK_ERR_USAGE);
7593089Swyllys 				trust = optarg_av;
7603089Swyllys 				break;
7613089Swyllys 			case 'L':
7623089Swyllys 				if (lifetime)
7633089Swyllys 					return (PK_ERR_USAGE);
7643089Swyllys 				lifetime = optarg_av;
7653089Swyllys 				break;
7663089Swyllys 			case 'c':
7673089Swyllys 				if (outcert)
7683089Swyllys 					return (PK_ERR_USAGE);
7693089Swyllys 				outcert = optarg_av;
7703089Swyllys 				break;
7713089Swyllys 			case 'K':
7723089Swyllys 				if (outkey)
7733089Swyllys 					return (PK_ERR_USAGE);
7743089Swyllys 				outkey = optarg_av;
7753089Swyllys 				break;
7763089Swyllys 			case 'S':
7773089Swyllys 				serstr = optarg_av;
7783089Swyllys 				break;
7793089Swyllys 			case 'F':
7803089Swyllys 				if (format)
7813089Swyllys 					return (PK_ERR_USAGE);
7823089Swyllys 				format = optarg_av;
7833089Swyllys 				break;
7846051Swyllys 			case 'e':
7856051Swyllys 				ekustr = optarg_av;
7866051Swyllys 				break;
7873089Swyllys 			default:
7883089Swyllys 				return (PK_ERR_USAGE);
7893089Swyllys 		}
7903089Swyllys 	}
7913089Swyllys 
7923089Swyllys 	/* No additional args allowed. */
7933089Swyllys 	argc -= optind_av;
7943089Swyllys 	argv += optind_av;
7953089Swyllys 	if (argc) {
7963089Swyllys 		return (PK_ERR_USAGE);
7973089Swyllys 	}
7983089Swyllys 
7995051Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
8003089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
8013089Swyllys 		return (PK_ERR_USAGE);
8023089Swyllys 	}
8033089Swyllys 
8043089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
8053089Swyllys 	if (kstype == 0)
8063089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
8073089Swyllys 
8085221Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
8095221Swyllys 		if (interactive && EMPTYSTRING(certlabel)) {
8105221Swyllys 			(void) get_certlabel(&certlabel);
8115221Swyllys 		}
8125221Swyllys 		/* It better not be empty now */
8135221Swyllys 		if (EMPTYSTRING(certlabel)) {
8145221Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
8155221Swyllys 			    "specified to create a self-signed certificate."
8165221Swyllys 			    "\n"));
8175221Swyllys 			return (PK_ERR_USAGE);
8185221Swyllys 		}
8193089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
8203089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
8213089Swyllys 		    "be specified to create a self-signed certificate.\n"));
8223089Swyllys 		return (PK_ERR_USAGE);
8233089Swyllys 	}
8243089Swyllys 
8253089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
8263089Swyllys 		cryptoerror(LOG_STDERR,
8273089Swyllys 		    gettext("Error parsing format string (%s).\n"),
8283089Swyllys 		    format);
8293089Swyllys 		return (PK_ERR_USAGE);
8303089Swyllys 	}
8313089Swyllys 
8323089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
8333089Swyllys 		cryptoerror(LOG_STDERR,
8345051Swyllys 		    gettext("Error parsing lifetime string\n"));
8353089Swyllys 		return (PK_ERR_USAGE);
8363089Swyllys 	}
8373089Swyllys 
8383089Swyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
8393089Swyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
8405051Swyllys 		    keytype);
8413089Swyllys 		return (PK_ERR_USAGE);
8423089Swyllys 	}
8433089Swyllys 
8443089Swyllys 	/*
8453089Swyllys 	 * Check the subject name.
8463089Swyllys 	 * If interactive is true, get it now interactively.
8473089Swyllys 	 */
8483089Swyllys 	if (interactive) {
8495221Swyllys 		subname = NULL;
8505221Swyllys 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
8513089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
8523089Swyllys 			    "subject name interactively.\n"));
8533089Swyllys 			return (PK_ERR_USAGE);
8543089Swyllys 		}
8555221Swyllys 		if (serstr == NULL) {
8565221Swyllys 			(void) get_serial(&serstr);
8575221Swyllys 		}
8583089Swyllys 	} else {
8593089Swyllys 		if (EMPTYSTRING(subject)) {
8603089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
8613089Swyllys 			    "-i must be specified to create a self-signed "
8623089Swyllys 			    "certificate.\n"));
8633089Swyllys 			return (PK_ERR_USAGE);
8643089Swyllys 		} else {
8653089Swyllys 			subname = strdup(subject);
8663089Swyllys 			if (subname == NULL) {
8673089Swyllys 				cryptoerror(LOG_STDERR,
8683089Swyllys 				    gettext("Out of memory.\n"));
8693089Swyllys 				return (PK_ERR_SYSTEM);
8703089Swyllys 			}
8713089Swyllys 		}
8723089Swyllys 	}
8733089Swyllys 
8743089Swyllys 	if (serstr == NULL) {
8753089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
8765051Swyllys 		    "must be specified as a hex number when creating"
8775051Swyllys 		    " a self-signed certificate "
8785051Swyllys 		    "(ex: serial=0x0102030405feedface)\n"));
8793089Swyllys 		rv = PK_ERR_USAGE;
8803089Swyllys 		goto end;
8813089Swyllys 	} else {
8823089Swyllys 		uchar_t *bytes = NULL;
8833089Swyllys 		size_t bytelen;
8843089Swyllys 
8855051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
8863089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
8873089Swyllys 			(void) fprintf(stderr, gettext("serial number "
8885051Swyllys 			    "must be specified as a hex number "
8895051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
8903089Swyllys 			rv = PK_ERR_USAGE;
8913089Swyllys 			goto end;
8923089Swyllys 		}
8933089Swyllys 		serial.val = bytes;
8943089Swyllys 		serial.len = bytelen;
8953089Swyllys 	}
8963089Swyllys 
8973089Swyllys 	if (altname != NULL) {
8983089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
8993089Swyllys 		if (rv != KMF_OK) {
9003089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
9015051Swyllys 			    "must be specified as a name=value pair. "
9025051Swyllys 			    "See the man page for details.\n"));
9033089Swyllys 			rv = PK_ERR_USAGE;
9043089Swyllys 			goto end;
9053089Swyllys 		} else {
9063089Swyllys 			/* advance the altname past the '=' sign */
9073089Swyllys 			char *p = strchr(altname, '=');
9083089Swyllys 			if (p != NULL)
9093089Swyllys 				altname = p + 1;
9103089Swyllys 		}
9113089Swyllys 	}
9123089Swyllys 
9133089Swyllys 	if (keyusagestr != NULL) {
9143089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
9153089Swyllys 		if (rv != KMF_OK) {
9163089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
9175051Swyllys 			    "must be specified as a comma-separated list. "
9185051Swyllys 			    "See the man page for details.\n"));
9193089Swyllys 			rv = PK_ERR_USAGE;
9203089Swyllys 			goto end;
9213089Swyllys 		}
9223089Swyllys 	}
9236051Swyllys 	if (ekustr != NULL) {
9246051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
9256051Swyllys 		if (rv != KMF_OK) {
9266051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
9276051Swyllys 			    "be specified as a comma-separated list. "
9286051Swyllys 			    "See the man page for details.\n"));
9296051Swyllys 			rv = PK_ERR_USAGE;
9306051Swyllys 			goto end;
9316051Swyllys 		}
9326051Swyllys 	}
9333089Swyllys 
9343089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
9353089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
9363089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
9373089Swyllys 				tokenname = "internal";
9383089Swyllys 			} else  {
9393089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
9403089Swyllys 			}
9413089Swyllys 		}
9423089Swyllys 
9433089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
9443089Swyllys 	}
9453089Swyllys 
9463089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
9473089Swyllys 		if (dir == NULL)
9483089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
9493089Swyllys 
9503089Swyllys 		rv = gencert_nss(kmfhandle,
9515051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9525051Swyllys 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
9536051Swyllys 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
9546051Swyllys 		    ekulist);
9553089Swyllys 
9563089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
9573089Swyllys 		rv = gencert_pkcs11(kmfhandle,
9585051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9595051Swyllys 		    certlabel, keyAlg, sigAlg, keylen, ltime,
9606051Swyllys 		    &serial, kubits, kucrit, &tokencred, ekulist);
9613089Swyllys 
9623089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
9633089Swyllys 		rv = gencert_file(kmfhandle,
9645051Swyllys 		    keyAlg, sigAlg, keylen, fmt,
9655051Swyllys 		    ltime, subname, altname, alttype, altcrit,
966*6669Swyllys 		    &serial, kubits, kucrit, outcert, outkey,
9676051Swyllys 		    ekulist);
9683089Swyllys 	}
9693089Swyllys 
9703089Swyllys 	if (rv != KMF_OK)
9713089Swyllys 		display_error(kmfhandle, rv,
9725051Swyllys 		    gettext("Error creating certificate and keypair"));
9733089Swyllys end:
9746051Swyllys 	if (ekulist != NULL)
9756051Swyllys 		free_eku_list(ekulist);
9763089Swyllys 	if (subname)
9773089Swyllys 		free(subname);
9783089Swyllys 	if (tokencred.cred != NULL)
9793089Swyllys 		free(tokencred.cred);
9803089Swyllys 
9813089Swyllys 	if (serial.val != NULL)
9823089Swyllys 		free(serial.val);
9833089Swyllys 
9845051Swyllys 	(void) kmf_finalize(kmfhandle);
9853089Swyllys 	return (rv);
9863089Swyllys }
987