xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 12234:cd6642d6b7dd)
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
20*12234Swyllys.ingersoll@sun.com  *
21*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
223089Swyllys  */
233089Swyllys 
243089Swyllys #include <stdio.h>
253089Swyllys #include <string.h>
263089Swyllys #include <ctype.h>
273089Swyllys #include <malloc.h>
283089Swyllys #include <libgen.h>
293089Swyllys #include <errno.h>
303089Swyllys #include <cryptoutil.h>
313089Swyllys #include <security/cryptoki.h>
323089Swyllys #include "common.h"
333089Swyllys 
343089Swyllys #include <kmfapi.h>
353089Swyllys 
363089Swyllys #define	SET_VALUE(f, s) \
373089Swyllys 	kmfrv = f; \
383089Swyllys 	if (kmfrv != KMF_OK) { \
393089Swyllys 		cryptoerror(LOG_STDERR, \
403089Swyllys 			gettext("Failed to set %s: 0x%02x\n"), \
413089Swyllys 			s, kmfrv); \
423089Swyllys 		goto cleanup; \
433089Swyllys 	}
443089Swyllys 
453089Swyllys static int
gencert_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * certlabel,KMF_KEY_ALG keyAlg,KMF_ALGORITHM_INDEX sigAlg,int keylen,uint32_t ltime,KMF_BIGINT * serial,uint16_t kubits,int kucrit,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_OID * curveoid)463089Swyllys gencert_pkcs11(KMF_HANDLE_T kmfhandle,
473089Swyllys 	char *token, char *subject, char *altname,
483089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
493089Swyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
503089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
513089Swyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
526051Swyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
5311973Swyllys.ingersoll@sun.com 	EKU_LIST *ekulist, KMF_OID *curveoid)
543089Swyllys {
553089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
563089Swyllys 	KMF_KEY_HANDLE pubk, prik;
573089Swyllys 	KMF_X509_CERTIFICATE signedCert;
583089Swyllys 	KMF_X509_NAME	certSubject;
593089Swyllys 	KMF_X509_NAME	certIssuer;
603089Swyllys 	KMF_DATA x509DER;
615051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
625051Swyllys 	KMF_ATTRIBUTE attrlist[16];
635051Swyllys 	int numattr = 0;
645051Swyllys 	KMF_KEY_ALG keytype;
655051Swyllys 	uint32_t keylength;
663089Swyllys 
673089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
683089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
693089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
703089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
713089Swyllys 
723089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
735051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
743089Swyllys 		cryptoerror(LOG_STDERR,
755051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
763089Swyllys 		return (PK_ERR_USAGE);
773089Swyllys 	}
783089Swyllys 
793089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
805051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
813089Swyllys 		cryptoerror(LOG_STDERR,
825051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
833089Swyllys 		return (PK_ERR_USAGE);
843089Swyllys 	}
853089Swyllys 
865051Swyllys 	keylength = keylen; /* bits */
875051Swyllys 	keytype = keyAlg;
883089Swyllys 
893089Swyllys 	/* Select a PKCS11 token */
903089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
913089Swyllys 	if (kmfrv != KMF_OK) {
923089Swyllys 		return (kmfrv);
933089Swyllys 	}
943089Swyllys 
9511973Swyllys.ingersoll@sun.com 	/*
9611973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
9711973Swyllys.ingersoll@sun.com 	 */
9811973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
9911973Swyllys.ingersoll@sun.com 	    keytype, keylength, tokencred, curveoid, &prik, &pubk);
10011973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
1013089Swyllys 		return (kmfrv);
1023089Swyllys 
1035051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
1045051Swyllys 	    "keypair");
1053089Swyllys 
1065051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
1073089Swyllys 
1085051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
1095051Swyllys 	    "serial number");
1103089Swyllys 
1115051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
1125051Swyllys 	    "validity time");
1133089Swyllys 
1145051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
1155051Swyllys 	    "signature algorithm");
1163089Swyllys 
1175051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
1185051Swyllys 	    "subject name");
1193089Swyllys 
1205051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
1215051Swyllys 	    "issuer name");
1223089Swyllys 
1233089Swyllys 	if (altname != NULL)
1245051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
1255051Swyllys 		    alttype, altname), "subjectAltName");
1263089Swyllys 
1273089Swyllys 	if (kubits != 0)
1285051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
1295051Swyllys 		    "KeyUsage");
1305051Swyllys 
1316051Swyllys 	if (ekulist != NULL) {
1326051Swyllys 		int i;
1336051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1346051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
1356051Swyllys 			    &ekulist->ekulist[i], ekulist->critlist[i]),
1366051Swyllys 			    "Extended Key Usage");
1376051Swyllys 		}
1386051Swyllys 	}
1396051Swyllys 
1405051Swyllys 	/*
1415051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
1425051Swyllys 	 */
1435051Swyllys 	numattr = 0;
1445051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1455051Swyllys 	    &kstype, sizeof (kstype));
1465051Swyllys 	numattr++;
1473089Swyllys 
1485051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
1495051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
1505051Swyllys 	numattr++;
1515051Swyllys 
1525051Swyllys 	/* cert data that is to be signed */
1535051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
1545051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
1555051Swyllys 	numattr++;
1565051Swyllys 
1575051Swyllys 	/* output buffer for the signed cert */
1585051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
1595051Swyllys 	    &x509DER, sizeof (KMF_DATA));
1605051Swyllys 	numattr++;
1615051Swyllys 
162*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
163*12234Swyllys.ingersoll@sun.com 	    &sigAlg, sizeof (sigAlg));
164*12234Swyllys.ingersoll@sun.com 	numattr++;
165*12234Swyllys.ingersoll@sun.com 
1665051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
1675051Swyllys 	    KMF_OK) {
1683089Swyllys 		goto cleanup;
1693089Swyllys 	}
1703089Swyllys 
1713089Swyllys 	/*
1723089Swyllys 	 * Store the cert in the DB.
1733089Swyllys 	 */
1745051Swyllys 	numattr = 0;
1755051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1765051Swyllys 	    &kstype, sizeof (kstype));
1775051Swyllys 	numattr++;
1785051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
1795051Swyllys 	    &x509DER, sizeof (KMF_DATA));
1805051Swyllys 	numattr++;
1815051Swyllys 
1825051Swyllys 	if (certlabel != NULL) {
1835051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
1845051Swyllys 		    certlabel, strlen(certlabel));
1855051Swyllys 		numattr++;
1865051Swyllys 	}
1875051Swyllys 
1885051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
1895051Swyllys 
1903089Swyllys cleanup:
1915051Swyllys 	kmf_free_data(&x509DER);
1925051Swyllys 	kmf_free_dn(&certSubject);
1935051Swyllys 	kmf_free_dn(&certIssuer);
1949145SHuie-Ying.Lee@Sun.COM 
1959145SHuie-Ying.Lee@Sun.COM 	/*
1969145SHuie-Ying.Lee@Sun.COM 	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
1979145SHuie-Ying.Lee@Sun.COM 	 * the key pair from the token.
1989145SHuie-Ying.Lee@Sun.COM 	 */
1999145SHuie-Ying.Lee@Sun.COM 	if (kmfrv != KMF_OK) {
2009145SHuie-Ying.Lee@Sun.COM 		/* delete the public key */
2019145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
2029145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2039145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2049145SHuie-Ying.Lee@Sun.COM 		numattr++;
2059145SHuie-Ying.Lee@Sun.COM 
2069145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2079145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
2089145SHuie-Ying.Lee@Sun.COM 		numattr++;
2099145SHuie-Ying.Lee@Sun.COM 
2109145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
2119145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
2129145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
2139145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
2149145SHuie-Ying.Lee@Sun.COM 			numattr++;
2159145SHuie-Ying.Lee@Sun.COM 		}
2169145SHuie-Ying.Lee@Sun.COM 
2179145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
2189145SHuie-Ying.Lee@Sun.COM 		    attrlist);
2199145SHuie-Ying.Lee@Sun.COM 
2209145SHuie-Ying.Lee@Sun.COM 		/* delete the private key */
2219145SHuie-Ying.Lee@Sun.COM 		numattr = 0;
2229145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2239145SHuie-Ying.Lee@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2249145SHuie-Ying.Lee@Sun.COM 		numattr++;
2259145SHuie-Ying.Lee@Sun.COM 
2269145SHuie-Ying.Lee@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr,
2279145SHuie-Ying.Lee@Sun.COM 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
2289145SHuie-Ying.Lee@Sun.COM 		numattr++;
2299145SHuie-Ying.Lee@Sun.COM 
2309145SHuie-Ying.Lee@Sun.COM 		if (tokencred != NULL && tokencred->cred != NULL) {
2319145SHuie-Ying.Lee@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr,
2329145SHuie-Ying.Lee@Sun.COM 			    KMF_CREDENTIAL_ATTR, tokencred,
2339145SHuie-Ying.Lee@Sun.COM 			    sizeof (KMF_CREDENTIAL));
2349145SHuie-Ying.Lee@Sun.COM 			numattr++;
2359145SHuie-Ying.Lee@Sun.COM 		}
2369145SHuie-Ying.Lee@Sun.COM 
2379145SHuie-Ying.Lee@Sun.COM 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
2389145SHuie-Ying.Lee@Sun.COM 		    attrlist);
2399145SHuie-Ying.Lee@Sun.COM 	}
2409145SHuie-Ying.Lee@Sun.COM 
2413089Swyllys 	return (kmfrv);
2423089Swyllys }
2433089Swyllys 
2443089Swyllys static int
gencert_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,KMF_ALGORITHM_INDEX sigAlg,int keylen,KMF_ENCODE_FORMAT fmt,uint32_t ltime,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,KMF_BIGINT * serial,uint16_t kubits,int kucrit,char * outcert,char * outkey,EKU_LIST * ekulist)2453089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
2463089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
2473089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
2483089Swyllys 	uint32_t ltime, char *subject, char *altname,
2493089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2503089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
2516669Swyllys 	char *outcert, char *outkey,
2526051Swyllys 	EKU_LIST *ekulist)
2533089Swyllys {
2543089Swyllys 	KMF_RETURN kmfrv;
2553089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2563089Swyllys 	KMF_X509_CERTIFICATE signedCert;
2573089Swyllys 	KMF_X509_NAME	certSubject;
2583089Swyllys 	KMF_X509_NAME	certIssuer;
2593089Swyllys 	KMF_DATA x509DER;
2603089Swyllys 	char *fullcertpath = NULL;
2613089Swyllys 	char *fullkeypath = NULL;
2625051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2635051Swyllys 	KMF_ATTRIBUTE attrlist[10];
2645051Swyllys 	int numattr = 0;
2653089Swyllys 
2663089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
2673089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
2683089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
2693089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
2703089Swyllys 
2713089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
2723089Swyllys 		cryptoerror(LOG_STDERR,
2735051Swyllys 		    gettext("No output file was specified for "
2745051Swyllys 		    "the cert or key\n"));
2753089Swyllys 		return (PK_ERR_USAGE);
2763089Swyllys 	}
2776669Swyllys 	fullcertpath = strdup(outcert);
2783089Swyllys 	if (verify_file(fullcertpath)) {
2793089Swyllys 		cryptoerror(LOG_STDERR,
2805051Swyllys 		    gettext("Cannot write the indicated output "
2815051Swyllys 		    "certificate file (%s).\n"), fullcertpath);
2823089Swyllys 		free(fullcertpath);
2833089Swyllys 		return (PK_ERR_USAGE);
2843089Swyllys 	}
2856669Swyllys 
2863089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
2875051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
2883089Swyllys 		cryptoerror(LOG_STDERR,
2895051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
2903089Swyllys 		return (PK_ERR_USAGE);
2913089Swyllys 	}
2923089Swyllys 
2933089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
2945051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
2953089Swyllys 		cryptoerror(LOG_STDERR,
2965051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
2975051Swyllys 		kmf_free_dn(&certSubject);
2983089Swyllys 		return (PK_ERR_USAGE);
2993089Swyllys 	}
3003089Swyllys 
30111973Swyllys.ingersoll@sun.com 	/*
30211973Swyllys.ingersoll@sun.com 	 * Share the "genkeypair" routine for creating the keypair.
30311973Swyllys.ingersoll@sun.com 	 */
30411973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
30511973Swyllys.ingersoll@sun.com 	    fmt, outkey, &prik, &pubk);
30611973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
30711973Swyllys.ingersoll@sun.com 		return (kmfrv);
3085051Swyllys 
3095051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
3105051Swyllys 	    "keypair");
3113089Swyllys 
3125051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
3133089Swyllys 
3145051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
3155051Swyllys 	    "serial number");
3163089Swyllys 
3175051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
3185051Swyllys 	    "validity time");
3193089Swyllys 
3205051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
3215051Swyllys 	    "signature algorithm");
3223089Swyllys 
3235051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
3245051Swyllys 	    "subject name");
3253089Swyllys 
3265051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
3275051Swyllys 	    "issuer name");
3283089Swyllys 
3293089Swyllys 	if (altname != NULL)
3305051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
3315051Swyllys 		    alttype, altname), "subjectAltName");
3323089Swyllys 
3333089Swyllys 	if (kubits != 0)
3345051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
3355051Swyllys 		    "KeyUsage");
3366051Swyllys 
3376051Swyllys 	if (ekulist != NULL) {
3386051Swyllys 		int i;
3396051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
3406051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
3416051Swyllys 			    &ekulist->ekulist[i],
3426051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
3436051Swyllys 		}
3446051Swyllys 	}
3455051Swyllys 	/*
3465051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
3475051Swyllys 	 */
3485051Swyllys 	numattr = 0;
3495051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3505051Swyllys 	    &kstype, sizeof (kstype));
3515051Swyllys 	numattr++;
3523089Swyllys 
3535051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
3545051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
3555051Swyllys 	numattr++;
3565051Swyllys 
3575051Swyllys 	/* cert data that is to be signed */
3585051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
3595051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
3605051Swyllys 	numattr++;
3615051Swyllys 
3625051Swyllys 	/* output buffer for the signed cert */
3635051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
3645051Swyllys 	    &x509DER, sizeof (KMF_DATA));
3655051Swyllys 	numattr++;
3665051Swyllys 
367*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
368*12234Swyllys.ingersoll@sun.com 	    &sigAlg, sizeof (sigAlg));
369*12234Swyllys.ingersoll@sun.com 	numattr++;
370*12234Swyllys.ingersoll@sun.com 
3715051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
3725051Swyllys 	    KMF_OK) {
3733089Swyllys 		goto cleanup;
3743089Swyllys 	}
3753089Swyllys 
3763089Swyllys 	/*
3773089Swyllys 	 * Store the cert in the DB.
3783089Swyllys 	 */
3795051Swyllys 	numattr = 0;
3805051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3815051Swyllys 	    &kstype, sizeof (kstype));
3825051Swyllys 	numattr++;
3835051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
3845051Swyllys 	    &x509DER, sizeof (KMF_DATA));
3855051Swyllys 	numattr++;
3865051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
3875051Swyllys 	    fullcertpath, strlen(fullcertpath));
3885051Swyllys 	numattr++;
3895051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
3905051Swyllys 	    &fmt, sizeof (fmt));
3915051Swyllys 	numattr++;
3925051Swyllys 
3935051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
3943089Swyllys 
3953089Swyllys cleanup:
3963089Swyllys 	if (fullkeypath != NULL)
3973089Swyllys 		free(fullkeypath);
3983089Swyllys 	if (fullcertpath != NULL)
3993089Swyllys 		free(fullcertpath);
4003089Swyllys 
4015051Swyllys 	kmf_free_data(&x509DER);
4025051Swyllys 	kmf_free_dn(&certSubject);
4035051Swyllys 	kmf_free_dn(&certIssuer);
4043089Swyllys 	return (kmfrv);
4053089Swyllys }
4063089Swyllys 
4073089Swyllys static KMF_RETURN
gencert_nss(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * nickname,char * dir,char * prefix,KMF_KEY_ALG keyAlg,KMF_ALGORITHM_INDEX sigAlg,int keylen,char * trust,uint32_t ltime,KMF_BIGINT * serial,uint16_t kubits,int kucrit,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_OID * curveoid)4083089Swyllys gencert_nss(KMF_HANDLE_T kmfhandle,
4093089Swyllys 	char *token, char *subject, char *altname,
4103089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
4113089Swyllys 	char *nickname, char *dir, char *prefix,
4123089Swyllys 	KMF_KEY_ALG keyAlg,
4133089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
4143089Swyllys 	int keylen, char *trust,
4153089Swyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
4166051Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred,
41711973Swyllys.ingersoll@sun.com 	EKU_LIST *ekulist, KMF_OID *curveoid)
4183089Swyllys {
4193089Swyllys 	KMF_RETURN kmfrv;
4203089Swyllys 	KMF_KEY_HANDLE pubk, prik;
4213089Swyllys 	KMF_X509_CERTIFICATE signedCert;
4223089Swyllys 	KMF_X509_NAME	certSubject;
4233089Swyllys 	KMF_X509_NAME	certIssuer;
4243089Swyllys 	KMF_DATA x509DER;
4255051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
4265051Swyllys 	KMF_ATTRIBUTE attrlist[16];
4275051Swyllys 	int numattr = 0;
4283089Swyllys 
4293089Swyllys 	if (token == NULL)
4303089Swyllys 		token = DEFAULT_NSS_TOKEN;
4313089Swyllys 
4323089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
4333089Swyllys 	if (kmfrv != KMF_OK)
4343089Swyllys 		return (kmfrv);
4353089Swyllys 
4363089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
4373089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
4383089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
4393089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
4403089Swyllys 
4413089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
4425051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
4433089Swyllys 		cryptoerror(LOG_STDERR,
4445051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4453089Swyllys 		return (PK_ERR_USAGE);
4463089Swyllys 	}
4473089Swyllys 
4483089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
4495051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
4503089Swyllys 		cryptoerror(LOG_STDERR,
4515051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4523089Swyllys 		return (PK_ERR_USAGE);
4533089Swyllys 	}
4543089Swyllys 
45511973Swyllys.ingersoll@sun.com 	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
45611973Swyllys.ingersoll@sun.com 	    prefix, keyAlg, keylen, tokencred, curveoid,
45711973Swyllys.ingersoll@sun.com 	    &prik, &pubk);
45811973Swyllys.ingersoll@sun.com 	if (kmfrv != KMF_OK)
4593089Swyllys 		return (kmfrv);
4603089Swyllys 
4615051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
4625051Swyllys 	    "keypair");
4633089Swyllys 
4645051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
4653089Swyllys 
4665051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
4675051Swyllys 	    "serial number");
4683089Swyllys 
4695051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
4705051Swyllys 	    "validity time");
4713089Swyllys 
4725051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
4735051Swyllys 	    "signature algorithm");
4743089Swyllys 
4755051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
4765051Swyllys 	    "subject name");
4773089Swyllys 
4785051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
4795051Swyllys 	    "issuer name");
4803089Swyllys 
4813089Swyllys 	if (altname != NULL)
4825051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
4835051Swyllys 		    alttype, altname), "subjectAltName");
4843089Swyllys 
4853089Swyllys 	if (kubits)
4865051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
4875051Swyllys 		    "subjectAltName");
4885051Swyllys 
4896051Swyllys 	if (ekulist != NULL) {
4906051Swyllys 		int i;
4916051Swyllys 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
4926051Swyllys 			SET_VALUE(kmf_add_cert_eku(&signedCert,
4936051Swyllys 			    &ekulist->ekulist[i],
4946051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
4956051Swyllys 		}
4966051Swyllys 	}
4975051Swyllys 	/*
4985051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
4995051Swyllys 	 */
5005051Swyllys 	numattr = 0;
5015051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
5025051Swyllys 	    &kstype, sizeof (kstype));
5035051Swyllys 	numattr++;
5043089Swyllys 
5055051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
5065051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
5075051Swyllys 	numattr++;
5085051Swyllys 
5095051Swyllys 	/* cert data that is to be signed */
5105051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
5115051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
5125051Swyllys 	numattr++;
5135051Swyllys 
5145051Swyllys 	/* output buffer for the signed cert */
5155051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
5165051Swyllys 	    &x509DER, sizeof (KMF_DATA));
5175051Swyllys 	numattr++;
5185051Swyllys 
519*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
520*12234Swyllys.ingersoll@sun.com 	    &sigAlg, sizeof (sigAlg));
521*12234Swyllys.ingersoll@sun.com 	numattr++;
522*12234Swyllys.ingersoll@sun.com 
5235051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
5245051Swyllys 	    KMF_OK) {
5253089Swyllys 		goto cleanup;
5263089Swyllys 	}
5273089Swyllys 
5283089Swyllys 	/*
5293089Swyllys 	 * Store the cert in the DB.
5303089Swyllys 	 */
5315051Swyllys 	numattr = 0;
5325051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
5335051Swyllys 	    &kstype, sizeof (kstype));
5345051Swyllys 	numattr++;
5355051Swyllys 
5365051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
5375051Swyllys 	    &x509DER, sizeof (KMF_DATA));
5385051Swyllys 	numattr++;
5395051Swyllys 
5405051Swyllys 	if (nickname != NULL) {
5415051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
5425051Swyllys 		    nickname, strlen(nickname));
5435051Swyllys 		numattr++;
5445051Swyllys 	}
5455051Swyllys 
5465051Swyllys 	if (trust != NULL) {
5475051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
5485051Swyllys 		    trust, strlen(trust));
5495051Swyllys 		numattr++;
5505051Swyllys 	}
5515051Swyllys 
5525051Swyllys 	if (token != NULL) {
5535051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
5545051Swyllys 		    token, strlen(token));
5555051Swyllys 		numattr++;
5565051Swyllys 	}
5575051Swyllys 
5585051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
5593089Swyllys 
5603089Swyllys cleanup:
5615051Swyllys 	kmf_free_data(&x509DER);
5625051Swyllys 	kmf_free_dn(&certSubject);
5635051Swyllys 	kmf_free_dn(&certIssuer);
5643089Swyllys 	return (kmfrv);
5653089Swyllys }
5663089Swyllys 
5673089Swyllys int
pk_gencert(int argc,char * argv[])5683089Swyllys pk_gencert(int argc, char *argv[])
5693089Swyllys {
5703089Swyllys 	int rv;
5713089Swyllys 	int opt;
5723089Swyllys 	extern int	optind_av;
5733089Swyllys 	extern char	*optarg_av;
5743089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
5753089Swyllys 	char *subject = NULL;
5763089Swyllys 	char *tokenname = NULL;
5773089Swyllys 	char *dir = NULL;
5783089Swyllys 	char *prefix = NULL;
5793089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
5803089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
5813089Swyllys 	char *trust = NULL;
5823089Swyllys 	char *lifetime = NULL;
5833089Swyllys 	char *certlabel = NULL;
5843089Swyllys 	char *outcert = NULL;
5853089Swyllys 	char *outkey = NULL;
5863089Swyllys 	char *format = NULL;
5873089Swyllys 	char *serstr = NULL;
5883089Swyllys 	char *altname = NULL;
5893089Swyllys 	char *keyusagestr = NULL;
5906051Swyllys 	char *ekustr = NULL;
59111973Swyllys.ingersoll@sun.com 	char *hashname = NULL;
5923089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
5933089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
5943089Swyllys 	uint32_t ltime;
5953089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
5963089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
5973089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
59810744Swyllys.ingersoll@sun.com 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
5993089Swyllys 	boolean_t interactive = B_FALSE;
6003089Swyllys 	char *subname = NULL;
6013089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
6023089Swyllys 	uint16_t kubits = 0;
6033089Swyllys 	int altcrit = 0, kucrit = 0;
6046051Swyllys 	EKU_LIST *ekulist = NULL;
60511973Swyllys.ingersoll@sun.com 	KMF_OID *curveoid = NULL; /* ECC */
60611973Swyllys.ingersoll@sun.com 	KMF_OID *hashoid = NULL;
60711973Swyllys.ingersoll@sun.com 	int y_flag = 0;
6083089Swyllys 
6093089Swyllys 	while ((opt = getopt_av(argc, argv,
6105051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
6115051Swyllys 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
6126051Swyllys 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
61311973Swyllys.ingersoll@sun.com 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)C:(curve)"
61411973Swyllys.ingersoll@sun.com 	    "E(listcurves)h:(hash)")) != EOF) {
6153089Swyllys 
61611973Swyllys.ingersoll@sun.com 		if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
6173089Swyllys 			return (PK_ERR_USAGE);
6183089Swyllys 
6193089Swyllys 		switch (opt) {
6203089Swyllys 			case 'A':
6213089Swyllys 				altname = optarg_av;
6223089Swyllys 				break;
6233089Swyllys 			case 'i':
6243089Swyllys 				if (interactive || subject)
6253089Swyllys 					return (PK_ERR_USAGE);
6263089Swyllys 				else
6273089Swyllys 					interactive = B_TRUE;
6283089Swyllys 				break;
6293089Swyllys 			case 'k':
6303089Swyllys 				kstype = KS2Int(optarg_av);
6313089Swyllys 				if (kstype == 0)
6323089Swyllys 					return (PK_ERR_USAGE);
6333089Swyllys 				break;
6343089Swyllys 			case 's':
6353089Swyllys 				if (interactive || subject)
6363089Swyllys 					return (PK_ERR_USAGE);
6373089Swyllys 				else
6383089Swyllys 					subject = optarg_av;
6393089Swyllys 				break;
6403089Swyllys 			case 'l':
6413089Swyllys 			case 'n':
6423089Swyllys 				if (certlabel)
6433089Swyllys 					return (PK_ERR_USAGE);
6443089Swyllys 				certlabel = optarg_av;
6453089Swyllys 				break;
6463089Swyllys 			case 'T':
6473089Swyllys 				if (tokenname)
6483089Swyllys 					return (PK_ERR_USAGE);
6493089Swyllys 				tokenname = optarg_av;
6503089Swyllys 				break;
6513089Swyllys 			case 'd':
6523089Swyllys 				if (dir)
6533089Swyllys 					return (PK_ERR_USAGE);
6543089Swyllys 				dir = optarg_av;
6553089Swyllys 				break;
6563089Swyllys 			case 'p':
6573089Swyllys 				if (prefix)
6583089Swyllys 					return (PK_ERR_USAGE);
6593089Swyllys 				prefix = optarg_av;
6603089Swyllys 				break;
6613089Swyllys 			case 't':
6623089Swyllys 				keytype = optarg_av;
6633089Swyllys 				break;
6643089Swyllys 			case 'u':
6653089Swyllys 				keyusagestr = optarg_av;
6663089Swyllys 				break;
6673089Swyllys 			case 'y':
6683089Swyllys 				if (sscanf(optarg_av, "%d",
6695051Swyllys 				    &keylen) != 1) {
6703089Swyllys 					cryptoerror(LOG_STDERR,
6715051Swyllys 					    gettext("key length must be"
6725051Swyllys 					    "a numeric value (%s)\n"),
6735051Swyllys 					    optarg_av);
6743089Swyllys 					return (PK_ERR_USAGE);
6753089Swyllys 				}
67611973Swyllys.ingersoll@sun.com 				y_flag++;
6773089Swyllys 				break;
6783089Swyllys 			case 'r':
6793089Swyllys 				if (trust)
6803089Swyllys 					return (PK_ERR_USAGE);
6813089Swyllys 				trust = optarg_av;
6823089Swyllys 				break;
6833089Swyllys 			case 'L':
6843089Swyllys 				if (lifetime)
6853089Swyllys 					return (PK_ERR_USAGE);
6863089Swyllys 				lifetime = optarg_av;
6873089Swyllys 				break;
6883089Swyllys 			case 'c':
6893089Swyllys 				if (outcert)
6903089Swyllys 					return (PK_ERR_USAGE);
6913089Swyllys 				outcert = optarg_av;
6923089Swyllys 				break;
6933089Swyllys 			case 'K':
6943089Swyllys 				if (outkey)
6953089Swyllys 					return (PK_ERR_USAGE);
6963089Swyllys 				outkey = optarg_av;
6973089Swyllys 				break;
6983089Swyllys 			case 'S':
6993089Swyllys 				serstr = optarg_av;
7003089Swyllys 				break;
7013089Swyllys 			case 'F':
7023089Swyllys 				if (format)
7033089Swyllys 					return (PK_ERR_USAGE);
7043089Swyllys 				format = optarg_av;
7053089Swyllys 				break;
7066051Swyllys 			case 'e':
7076051Swyllys 				ekustr = optarg_av;
7086051Swyllys 				break;
70911973Swyllys.ingersoll@sun.com 			case 'C':
71011973Swyllys.ingersoll@sun.com 				curveoid = ecc_name_to_oid(optarg_av);
71111973Swyllys.ingersoll@sun.com 				if (curveoid == NULL) {
71211973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
71311973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized ECC "
71411973Swyllys.ingersoll@sun.com 					    "curve.\n"));
71511973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
71611973Swyllys.ingersoll@sun.com 				}
71711973Swyllys.ingersoll@sun.com 				break;
71811973Swyllys.ingersoll@sun.com 			case 'E':
71911973Swyllys.ingersoll@sun.com 				/*
72011973Swyllys.ingersoll@sun.com 				 * This argument is only to be used
72111973Swyllys.ingersoll@sun.com 				 * by itself, no other options should
72211973Swyllys.ingersoll@sun.com 				 * be present.
72311973Swyllys.ingersoll@sun.com 				 */
72411973Swyllys.ingersoll@sun.com 				if (argc != 2) {
72511973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
72611973Swyllys.ingersoll@sun.com 					    gettext("listcurves has no other "
72711973Swyllys.ingersoll@sun.com 					    "options.\n"));
72811973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
72911973Swyllys.ingersoll@sun.com 				}
73011973Swyllys.ingersoll@sun.com 				show_ecc_curves();
73111973Swyllys.ingersoll@sun.com 				return (0);
73211973Swyllys.ingersoll@sun.com 			case 'h':
73311973Swyllys.ingersoll@sun.com 				hashname = optarg_av;
73411973Swyllys.ingersoll@sun.com 				hashoid = ecc_name_to_oid(optarg_av);
73511973Swyllys.ingersoll@sun.com 				if (hashoid == NULL) {
73611973Swyllys.ingersoll@sun.com 					cryptoerror(LOG_STDERR,
73711973Swyllys.ingersoll@sun.com 					    gettext("Unrecognized hash.\n"));
73811973Swyllys.ingersoll@sun.com 					return (PK_ERR_USAGE);
73911973Swyllys.ingersoll@sun.com 				}
74011973Swyllys.ingersoll@sun.com 				break;
7413089Swyllys 			default:
7423089Swyllys 				return (PK_ERR_USAGE);
7433089Swyllys 		}
7443089Swyllys 	}
7453089Swyllys 
7463089Swyllys 	/* No additional args allowed. */
7473089Swyllys 	argc -= optind_av;
7483089Swyllys 	argv += optind_av;
7493089Swyllys 	if (argc) {
7503089Swyllys 		return (PK_ERR_USAGE);
7513089Swyllys 	}
7523089Swyllys 
7535051Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7543089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
7553089Swyllys 		return (PK_ERR_USAGE);
7563089Swyllys 	}
7573089Swyllys 
7583089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
7593089Swyllys 	if (kstype == 0)
7603089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
7613089Swyllys 
7625221Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
7635221Swyllys 		if (interactive && EMPTYSTRING(certlabel)) {
7645221Swyllys 			(void) get_certlabel(&certlabel);
7655221Swyllys 		}
7665221Swyllys 		/* It better not be empty now */
7675221Swyllys 		if (EMPTYSTRING(certlabel)) {
7685221Swyllys 			cryptoerror(LOG_STDERR, gettext("A label must be "
7695221Swyllys 			    "specified to create a self-signed certificate."
7705221Swyllys 			    "\n"));
7715221Swyllys 			return (PK_ERR_USAGE);
7725221Swyllys 		}
7733089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
7743089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
7753089Swyllys 		    "be specified to create a self-signed certificate.\n"));
7763089Swyllys 		return (PK_ERR_USAGE);
7773089Swyllys 	}
7783089Swyllys 
7796884Swyllys 	DIR_OPTION_CHECK(kstype, dir);
7806884Swyllys 
7813089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
7823089Swyllys 		cryptoerror(LOG_STDERR,
7833089Swyllys 		    gettext("Error parsing format string (%s).\n"),
7843089Swyllys 		    format);
7853089Swyllys 		return (PK_ERR_USAGE);
7863089Swyllys 	}
7873089Swyllys 
7883089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
7893089Swyllys 		cryptoerror(LOG_STDERR,
7905051Swyllys 		    gettext("Error parsing lifetime string\n"));
7913089Swyllys 		return (PK_ERR_USAGE);
7923089Swyllys 	}
7933089Swyllys 
79411973Swyllys.ingersoll@sun.com 	if (Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg) != 0) {
79511973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR,
79611973Swyllys.ingersoll@sun.com 		    gettext("Unsupported key/hash combination (%s/%s).\n"),
79711973Swyllys.ingersoll@sun.com 		    keytype, (hashname ? hashname : "none"));
7983089Swyllys 		return (PK_ERR_USAGE);
7993089Swyllys 	}
80011973Swyllys.ingersoll@sun.com 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
80111973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
80211973Swyllys.ingersoll@sun.com 		    "valid for EC keytypes.\n"));
80311973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
80411973Swyllys.ingersoll@sun.com 	}
80511973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
80611973Swyllys.ingersoll@sun.com 		cryptoerror(LOG_STDERR, gettext("A curve must be "
80711973Swyllys.ingersoll@sun.com 		    "specifed when using EC keys.\n"));
80811973Swyllys.ingersoll@sun.com 		return (PK_ERR_USAGE);
80911973Swyllys.ingersoll@sun.com 	}
81011973Swyllys.ingersoll@sun.com 	/* Adjust default keylength for NSS and DSA */
81111973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
81211973Swyllys.ingersoll@sun.com 		keylen = 1024;
8133089Swyllys 
8143089Swyllys 	/*
8153089Swyllys 	 * Check the subject name.
8163089Swyllys 	 * If interactive is true, get it now interactively.
8173089Swyllys 	 */
8183089Swyllys 	if (interactive) {
8195221Swyllys 		subname = NULL;
8205221Swyllys 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
8213089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
8223089Swyllys 			    "subject name interactively.\n"));
8233089Swyllys 			return (PK_ERR_USAGE);
8243089Swyllys 		}
8255221Swyllys 		if (serstr == NULL) {
8265221Swyllys 			(void) get_serial(&serstr);
8275221Swyllys 		}
8283089Swyllys 	} else {
8293089Swyllys 		if (EMPTYSTRING(subject)) {
8303089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
8313089Swyllys 			    "-i must be specified to create a self-signed "
8323089Swyllys 			    "certificate.\n"));
8333089Swyllys 			return (PK_ERR_USAGE);
8343089Swyllys 		} else {
8353089Swyllys 			subname = strdup(subject);
8363089Swyllys 			if (subname == NULL) {
8373089Swyllys 				cryptoerror(LOG_STDERR,
8383089Swyllys 				    gettext("Out of memory.\n"));
8393089Swyllys 				return (PK_ERR_SYSTEM);
8403089Swyllys 			}
8413089Swyllys 		}
8423089Swyllys 	}
8433089Swyllys 
8443089Swyllys 	if (serstr == NULL) {
8453089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
8465051Swyllys 		    "must be specified as a hex number when creating"
8475051Swyllys 		    " a self-signed certificate "
8485051Swyllys 		    "(ex: serial=0x0102030405feedface)\n"));
8493089Swyllys 		rv = PK_ERR_USAGE;
8503089Swyllys 		goto end;
8513089Swyllys 	} else {
8523089Swyllys 		uchar_t *bytes = NULL;
8533089Swyllys 		size_t bytelen;
8543089Swyllys 
8555051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
8563089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
8573089Swyllys 			(void) fprintf(stderr, gettext("serial number "
8585051Swyllys 			    "must be specified as a hex number "
8595051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
8603089Swyllys 			rv = PK_ERR_USAGE;
8613089Swyllys 			goto end;
8623089Swyllys 		}
8633089Swyllys 		serial.val = bytes;
8643089Swyllys 		serial.len = bytelen;
8653089Swyllys 	}
8663089Swyllys 
8673089Swyllys 	if (altname != NULL) {
8683089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
8693089Swyllys 		if (rv != KMF_OK) {
8703089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
8715051Swyllys 			    "must be specified as a name=value pair. "
8725051Swyllys 			    "See the man page for details.\n"));
8733089Swyllys 			rv = PK_ERR_USAGE;
8743089Swyllys 			goto end;
8753089Swyllys 		} else {
8763089Swyllys 			/* advance the altname past the '=' sign */
8773089Swyllys 			char *p = strchr(altname, '=');
8783089Swyllys 			if (p != NULL)
8793089Swyllys 				altname = p + 1;
8803089Swyllys 		}
8813089Swyllys 	}
8823089Swyllys 
8833089Swyllys 	if (keyusagestr != NULL) {
8843089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
8853089Swyllys 		if (rv != KMF_OK) {
8863089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
8875051Swyllys 			    "must be specified as a comma-separated list. "
8885051Swyllys 			    "See the man page for details.\n"));
8893089Swyllys 			rv = PK_ERR_USAGE;
8903089Swyllys 			goto end;
8913089Swyllys 		}
8923089Swyllys 	}
8936051Swyllys 	if (ekustr != NULL) {
8946051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
8956051Swyllys 		if (rv != KMF_OK) {
8966051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
8976051Swyllys 			    "be specified as a comma-separated list. "
8986051Swyllys 			    "See the man page for details.\n"));
8996051Swyllys 			rv = PK_ERR_USAGE;
9006051Swyllys 			goto end;
9016051Swyllys 		}
9026051Swyllys 	}
90311973Swyllys.ingersoll@sun.com 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
90411973Swyllys.ingersoll@sun.com 		(void) fprintf(stderr, gettext("ECC certificates are"
90511973Swyllys.ingersoll@sun.com 		    "only supported with the pkcs11 and nss keystores\n"));
90611973Swyllys.ingersoll@sun.com 		rv = PK_ERR_USAGE;
90711973Swyllys.ingersoll@sun.com 		goto end;
90811973Swyllys.ingersoll@sun.com 	}
9093089Swyllys 
9103089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
9113089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
9123089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
9133089Swyllys 				tokenname = "internal";
9143089Swyllys 			} else  {
9153089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
9163089Swyllys 			}
9173089Swyllys 		}
9183089Swyllys 
9193089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
9203089Swyllys 	}
9213089Swyllys 
9223089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
9233089Swyllys 		if (dir == NULL)
9243089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
9253089Swyllys 
9263089Swyllys 		rv = gencert_nss(kmfhandle,
9275051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9285051Swyllys 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
9296051Swyllys 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
93011973Swyllys.ingersoll@sun.com 		    ekulist, curveoid);
9313089Swyllys 
9323089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
9333089Swyllys 		rv = gencert_pkcs11(kmfhandle,
9345051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
9355051Swyllys 		    certlabel, keyAlg, sigAlg, keylen, ltime,
93611973Swyllys.ingersoll@sun.com 		    &serial, kubits, kucrit, &tokencred, ekulist,
93711973Swyllys.ingersoll@sun.com 		    curveoid);
9383089Swyllys 
9393089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
9403089Swyllys 		rv = gencert_file(kmfhandle,
9415051Swyllys 		    keyAlg, sigAlg, keylen, fmt,
9425051Swyllys 		    ltime, subname, altname, alttype, altcrit,
9436669Swyllys 		    &serial, kubits, kucrit, outcert, outkey,
9446051Swyllys 		    ekulist);
9453089Swyllys 	}
9463089Swyllys 
9473089Swyllys 	if (rv != KMF_OK)
9483089Swyllys 		display_error(kmfhandle, rv,
9495051Swyllys 		    gettext("Error creating certificate and keypair"));
9503089Swyllys end:
9516051Swyllys 	if (ekulist != NULL)
9526051Swyllys 		free_eku_list(ekulist);
9533089Swyllys 	if (subname)
9543089Swyllys 		free(subname);
9553089Swyllys 	if (tokencred.cred != NULL)
9563089Swyllys 		free(tokencred.cred);
9573089Swyllys 
9583089Swyllys 	if (serial.val != NULL)
9593089Swyllys 		free(serial.val);
9603089Swyllys 
9615051Swyllys 	(void) kmf_finalize(kmfhandle);
9623089Swyllys 	return (rv);
9633089Swyllys }
964