xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 5051:cbbb7c8b40a9)
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 /*
223501Swyllys  * Copyright 2007 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,
563089Swyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred)
573089Swyllys {
583089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
593089Swyllys 	KMF_KEY_HANDLE pubk, prik;
603089Swyllys 	KMF_X509_CERTIFICATE signedCert;
613089Swyllys 	KMF_X509_NAME	certSubject;
623089Swyllys 	KMF_X509_NAME	certIssuer;
633089Swyllys 	KMF_DATA x509DER;
64*5051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
65*5051Swyllys 	KMF_ATTRIBUTE attrlist[16];
66*5051Swyllys 	int numattr = 0;
67*5051Swyllys 	KMF_KEY_ALG keytype;
68*5051Swyllys 	uint32_t keylength;
693089Swyllys 
703089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
713089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
723089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
733089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
743089Swyllys 
753089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
76*5051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
773089Swyllys 		cryptoerror(LOG_STDERR,
78*5051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
793089Swyllys 		return (PK_ERR_USAGE);
803089Swyllys 	}
813089Swyllys 
823089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
83*5051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
843089Swyllys 		cryptoerror(LOG_STDERR,
85*5051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
863089Swyllys 		return (PK_ERR_USAGE);
873089Swyllys 	}
883089Swyllys 
89*5051Swyllys 	keylength = keylen; /* bits */
90*5051Swyllys 	keytype = keyAlg;
913089Swyllys 
923089Swyllys 	/* Select a PKCS11 token */
933089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
943089Swyllys 
953089Swyllys 	if (kmfrv != KMF_OK) {
963089Swyllys 		return (kmfrv);
973089Swyllys 	}
983089Swyllys 
99*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
100*5051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
101*5051Swyllys 	    sizeof (kstype));
102*5051Swyllys 	numattr++;
103*5051Swyllys 
104*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
105*5051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
106*5051Swyllys 	    sizeof (keytype));
107*5051Swyllys 	numattr++;
108*5051Swyllys 
109*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
110*5051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
111*5051Swyllys 	    sizeof (keylength));
112*5051Swyllys 	numattr++;
113*5051Swyllys 
114*5051Swyllys 	if (certlabel != NULL) {
115*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
116*5051Swyllys 		    KMF_KEYLABEL_ATTR, certlabel,
117*5051Swyllys 		    strlen(certlabel));
118*5051Swyllys 		numattr++;
119*5051Swyllys 	}
120*5051Swyllys 
121*5051Swyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
122*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
123*5051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
124*5051Swyllys 		    sizeof (KMF_CREDENTIAL));
125*5051Swyllys 		numattr++;
126*5051Swyllys 	}
127*5051Swyllys 
128*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
129*5051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
130*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
131*5051Swyllys 	numattr++;
132*5051Swyllys 
133*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
134*5051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
135*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
136*5051Swyllys 	numattr++;
137*5051Swyllys 
138*5051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
1393089Swyllys 	if (kmfrv != KMF_OK) {
1403089Swyllys 		return (kmfrv);
1413089Swyllys 	}
1423089Swyllys 
143*5051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
144*5051Swyllys 	    "keypair");
1453089Swyllys 
146*5051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
1473089Swyllys 
148*5051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
149*5051Swyllys 	    "serial number");
1503089Swyllys 
151*5051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
152*5051Swyllys 	    "validity time");
1533089Swyllys 
154*5051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
155*5051Swyllys 	    "signature algorithm");
1563089Swyllys 
157*5051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
158*5051Swyllys 	    "subject name");
1593089Swyllys 
160*5051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
161*5051Swyllys 	    "issuer name");
1623089Swyllys 
1633089Swyllys 	if (altname != NULL)
164*5051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
165*5051Swyllys 		    alttype, altname), "subjectAltName");
1663089Swyllys 
1673089Swyllys 	if (kubits != 0)
168*5051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
169*5051Swyllys 		    "KeyUsage");
170*5051Swyllys 
171*5051Swyllys 	/*
172*5051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
173*5051Swyllys 	 */
174*5051Swyllys 	numattr = 0;
175*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
176*5051Swyllys 	    &kstype, sizeof (kstype));
177*5051Swyllys 	numattr++;
1783089Swyllys 
179*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
180*5051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
181*5051Swyllys 	numattr++;
182*5051Swyllys 
183*5051Swyllys 	/* cert data that is to be signed */
184*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
185*5051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
186*5051Swyllys 	numattr++;
187*5051Swyllys 
188*5051Swyllys 	/* output buffer for the signed cert */
189*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
190*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
191*5051Swyllys 	numattr++;
192*5051Swyllys 
193*5051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
194*5051Swyllys 	    KMF_OK) {
1953089Swyllys 		goto cleanup;
1963089Swyllys 	}
1973089Swyllys 
1983089Swyllys 	/*
1993089Swyllys 	 * Store the cert in the DB.
2003089Swyllys 	 */
201*5051Swyllys 	numattr = 0;
202*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
203*5051Swyllys 	    &kstype, sizeof (kstype));
204*5051Swyllys 	numattr++;
205*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
206*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
207*5051Swyllys 	numattr++;
208*5051Swyllys 
209*5051Swyllys 	if (certlabel != NULL) {
210*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
211*5051Swyllys 		    certlabel, strlen(certlabel));
212*5051Swyllys 		numattr++;
213*5051Swyllys 	}
214*5051Swyllys 
215*5051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
216*5051Swyllys 
2173089Swyllys 
2183089Swyllys cleanup:
219*5051Swyllys 	kmf_free_data(&x509DER);
220*5051Swyllys 	kmf_free_dn(&certSubject);
221*5051Swyllys 	kmf_free_dn(&certIssuer);
2223089Swyllys 	return (kmfrv);
2233089Swyllys }
2243089Swyllys 
2253089Swyllys static int
2263089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
2273089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
2283089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
2293089Swyllys 	uint32_t ltime, char *subject, char *altname,
2303089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
2313089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
2323089Swyllys 	char *dir, char *outcert, char *outkey)
2333089Swyllys {
2343089Swyllys 	KMF_RETURN kmfrv;
2353089Swyllys 	KMF_KEY_HANDLE pubk, prik;
2363089Swyllys 	KMF_X509_CERTIFICATE signedCert;
2373089Swyllys 	KMF_X509_NAME	certSubject;
2383089Swyllys 	KMF_X509_NAME	certIssuer;
2393089Swyllys 	KMF_DATA x509DER;
2403089Swyllys 	char *fullcertpath = NULL;
2413089Swyllys 	char *fullkeypath = NULL;
242*5051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
243*5051Swyllys 	KMF_ATTRIBUTE attrlist[10];
244*5051Swyllys 	int numattr = 0;
245*5051Swyllys 	KMF_KEY_ALG keytype;
246*5051Swyllys 	uint32_t keylength;
247*5051Swyllys 	KMF_ENCODE_FORMAT format;
2483089Swyllys 
2493089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
2503089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
2513089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
2523089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
2533089Swyllys 
2543089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
2553089Swyllys 		cryptoerror(LOG_STDERR,
256*5051Swyllys 		    gettext("No output file was specified for "
257*5051Swyllys 		    "the cert or key\n"));
2583089Swyllys 		return (PK_ERR_USAGE);
2593089Swyllys 	}
2603089Swyllys 	if (dir != NULL) {
2613089Swyllys 		fullcertpath = get_fullpath(dir, outcert);
2623089Swyllys 		if (fullcertpath == NULL) {
2633089Swyllys 			cryptoerror(LOG_STDERR,
264*5051Swyllys 			    gettext("Cannot create file %s in directory %s\n"),
265*5051Swyllys 			    dir, outcert);
2663089Swyllys 			return (PK_ERR_USAGE);
2673089Swyllys 		}
2683089Swyllys 	} else {
2693089Swyllys 		fullcertpath = strdup(outcert);
2703089Swyllys 	}
2713089Swyllys 	if (verify_file(fullcertpath)) {
2723089Swyllys 		cryptoerror(LOG_STDERR,
273*5051Swyllys 		    gettext("Cannot write the indicated output "
274*5051Swyllys 		    "certificate file (%s).\n"), fullcertpath);
2753089Swyllys 		free(fullcertpath);
2763089Swyllys 		return (PK_ERR_USAGE);
2773089Swyllys 	}
2783089Swyllys 	if (dir != NULL) {
2793089Swyllys 		fullkeypath = get_fullpath(dir, outkey);
2803089Swyllys 		if (fullkeypath == NULL) {
2813089Swyllys 			cryptoerror(LOG_STDERR,
282*5051Swyllys 			    gettext("Cannot create file %s in directory %s\n"),
283*5051Swyllys 			    dir, outkey);
2843089Swyllys 			free(fullcertpath);
2853089Swyllys 			return (PK_ERR_USAGE);
2863089Swyllys 		}
2873089Swyllys 	} else {
2883089Swyllys 		fullkeypath = strdup(outkey);
2893089Swyllys 	}
2903089Swyllys 	if (verify_file(fullkeypath)) {
2913089Swyllys 		cryptoerror(LOG_STDERR,
292*5051Swyllys 		    gettext("Cannot write the indicated output "
293*5051Swyllys 		    "key file (%s).\n"), fullkeypath);
2943089Swyllys 		free(fullkeypath);
2953089Swyllys 		free(fullcertpath);
2963089Swyllys 		return (PK_ERR_USAGE);
2973089Swyllys 	}
2983089Swyllys 
2993089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
300*5051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
3013089Swyllys 		cryptoerror(LOG_STDERR,
302*5051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
3033089Swyllys 		return (PK_ERR_USAGE);
3043089Swyllys 	}
3053089Swyllys 
3063089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
307*5051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
3083089Swyllys 		cryptoerror(LOG_STDERR,
309*5051Swyllys 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
310*5051Swyllys 		kmf_free_dn(&certSubject);
3113089Swyllys 		return (PK_ERR_USAGE);
3123089Swyllys 	}
3133089Swyllys 
314*5051Swyllys 	keylength = keylen; /* bits */
315*5051Swyllys 	keytype = keyAlg;
316*5051Swyllys 	format = fmt;
317*5051Swyllys 
318*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
319*5051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
320*5051Swyllys 	    sizeof (kstype));
321*5051Swyllys 	numattr++;
322*5051Swyllys 
323*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
324*5051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
325*5051Swyllys 	    sizeof (keytype));
326*5051Swyllys 	numattr++;
327*5051Swyllys 
328*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
329*5051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
330*5051Swyllys 	    sizeof (keylength));
331*5051Swyllys 	numattr++;
3323089Swyllys 
333*5051Swyllys 	if (fullkeypath != NULL) {
334*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
335*5051Swyllys 		    KMF_KEY_FILENAME_ATTR, fullkeypath,
336*5051Swyllys 		    strlen(fullkeypath));
337*5051Swyllys 		numattr++;
338*5051Swyllys 	}
339*5051Swyllys 
340*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
341*5051Swyllys 	    KMF_ENCODE_FORMAT_ATTR, &format,
342*5051Swyllys 	    sizeof (format));
343*5051Swyllys 	numattr++;
3443089Swyllys 
345*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
346*5051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
347*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
348*5051Swyllys 	numattr++;
349*5051Swyllys 
350*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
351*5051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
352*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
353*5051Swyllys 	numattr++;
354*5051Swyllys 
355*5051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
3563089Swyllys 	if (kmfrv != KMF_OK) {
3573089Swyllys 		goto cleanup;
3583089Swyllys 	}
359*5051Swyllys 
360*5051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
361*5051Swyllys 	    "keypair");
3623089Swyllys 
363*5051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
3643089Swyllys 
365*5051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
366*5051Swyllys 	    "serial number");
3673089Swyllys 
368*5051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
369*5051Swyllys 	    "validity time");
3703089Swyllys 
371*5051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
372*5051Swyllys 	    "signature algorithm");
3733089Swyllys 
374*5051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
375*5051Swyllys 	    "subject name");
3763089Swyllys 
377*5051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
378*5051Swyllys 	    "issuer name");
3793089Swyllys 
3803089Swyllys 	if (altname != NULL)
381*5051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
382*5051Swyllys 		    alttype, altname), "subjectAltName");
3833089Swyllys 
3843089Swyllys 	if (kubits != 0)
385*5051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
386*5051Swyllys 		    "KeyUsage");
387*5051Swyllys 	/*
388*5051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
389*5051Swyllys 	 */
390*5051Swyllys 	numattr = 0;
391*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
392*5051Swyllys 	    &kstype, sizeof (kstype));
393*5051Swyllys 	numattr++;
3943089Swyllys 
395*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
396*5051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
397*5051Swyllys 	numattr++;
398*5051Swyllys 
399*5051Swyllys 	/* cert data that is to be signed */
400*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
401*5051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
402*5051Swyllys 	numattr++;
403*5051Swyllys 
404*5051Swyllys 	/* output buffer for the signed cert */
405*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
406*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
407*5051Swyllys 	numattr++;
408*5051Swyllys 
409*5051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
410*5051Swyllys 	    KMF_OK) {
4113089Swyllys 		goto cleanup;
4123089Swyllys 	}
4133089Swyllys 
4143089Swyllys 	/*
4153089Swyllys 	 * Store the cert in the DB.
4163089Swyllys 	 */
417*5051Swyllys 	numattr = 0;
418*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
419*5051Swyllys 	    &kstype, sizeof (kstype));
420*5051Swyllys 	numattr++;
421*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
422*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
423*5051Swyllys 	numattr++;
424*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
425*5051Swyllys 	    fullcertpath, strlen(fullcertpath));
426*5051Swyllys 	numattr++;
427*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
428*5051Swyllys 	    &fmt, sizeof (fmt));
429*5051Swyllys 	numattr++;
430*5051Swyllys 
431*5051Swyllys 	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 
439*5051Swyllys 	kmf_free_data(&x509DER);
440*5051Swyllys 	kmf_free_dn(&certSubject);
441*5051Swyllys 	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,
4543089Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred)
4553089Swyllys {
4563089Swyllys 	KMF_RETURN kmfrv;
4573089Swyllys 	KMF_KEY_HANDLE pubk, prik;
4583089Swyllys 	KMF_X509_CERTIFICATE signedCert;
4593089Swyllys 	KMF_X509_NAME	certSubject;
4603089Swyllys 	KMF_X509_NAME	certIssuer;
4613089Swyllys 	KMF_DATA x509DER;
462*5051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
463*5051Swyllys 	KMF_ATTRIBUTE attrlist[16];
464*5051Swyllys 	int numattr = 0;
465*5051Swyllys 	KMF_KEY_ALG keytype;
466*5051Swyllys 	uint32_t keylength;
4673089Swyllys 
4683089Swyllys 	if (token == NULL)
4693089Swyllys 		token = DEFAULT_NSS_TOKEN;
4703089Swyllys 
4713089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
4723089Swyllys 	if (kmfrv != KMF_OK)
4733089Swyllys 		return (kmfrv);
4743089Swyllys 
4753089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
4763089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
4773089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
4783089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
4793089Swyllys 
4803089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
481*5051Swyllys 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
4823089Swyllys 		cryptoerror(LOG_STDERR,
483*5051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4843089Swyllys 		return (PK_ERR_USAGE);
4853089Swyllys 	}
4863089Swyllys 
4873089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
488*5051Swyllys 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
4893089Swyllys 		cryptoerror(LOG_STDERR,
490*5051Swyllys 		    gettext("Subject name cannot be parsed.\n"));
4913089Swyllys 		return (PK_ERR_USAGE);
4923089Swyllys 	}
4933089Swyllys 
494*5051Swyllys 	keylength = keylen; /* bits */
495*5051Swyllys 	keytype = keyAlg;
496*5051Swyllys 
497*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
498*5051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
499*5051Swyllys 	    sizeof (kstype));
500*5051Swyllys 	numattr++;
501*5051Swyllys 
502*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
503*5051Swyllys 	    KMF_KEYALG_ATTR, &keytype,
504*5051Swyllys 	    sizeof (keytype));
505*5051Swyllys 	numattr++;
506*5051Swyllys 
507*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
508*5051Swyllys 	    KMF_KEYLENGTH_ATTR, &keylength,
509*5051Swyllys 	    sizeof (keylength));
510*5051Swyllys 	numattr++;
511*5051Swyllys 
512*5051Swyllys 	if (nickname != NULL) {
513*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
514*5051Swyllys 		    KMF_KEYLABEL_ATTR, nickname,
515*5051Swyllys 		    strlen(nickname));
516*5051Swyllys 		numattr++;
517*5051Swyllys 	}
5183089Swyllys 
519*5051Swyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
520*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
521*5051Swyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
522*5051Swyllys 		    sizeof (KMF_CREDENTIAL));
523*5051Swyllys 		numattr++;
524*5051Swyllys 	}
5253089Swyllys 
526*5051Swyllys 	if (token != NULL) {
527*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
528*5051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
529*5051Swyllys 		    strlen(token));
530*5051Swyllys 		numattr++;
531*5051Swyllys 	}
532*5051Swyllys 
533*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
534*5051Swyllys 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
535*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
536*5051Swyllys 	numattr++;
537*5051Swyllys 
538*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr,
539*5051Swyllys 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
540*5051Swyllys 	    sizeof (KMF_KEY_HANDLE));
541*5051Swyllys 	numattr++;
542*5051Swyllys 
543*5051Swyllys 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
5443089Swyllys 	if (kmfrv != KMF_OK) {
5453089Swyllys 		return (kmfrv);
5463089Swyllys 	}
5473089Swyllys 
548*5051Swyllys 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
549*5051Swyllys 	    "keypair");
5503089Swyllys 
551*5051Swyllys 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
5523089Swyllys 
553*5051Swyllys 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
554*5051Swyllys 	    "serial number");
5553089Swyllys 
556*5051Swyllys 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
557*5051Swyllys 	    "validity time");
5583089Swyllys 
559*5051Swyllys 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
560*5051Swyllys 	    "signature algorithm");
5613089Swyllys 
562*5051Swyllys 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
563*5051Swyllys 	    "subject name");
5643089Swyllys 
565*5051Swyllys 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
566*5051Swyllys 	    "issuer name");
5673089Swyllys 
5683089Swyllys 	if (altname != NULL)
569*5051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
570*5051Swyllys 		    alttype, altname), "subjectAltName");
5713089Swyllys 
5723089Swyllys 	if (kubits)
573*5051Swyllys 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
574*5051Swyllys 		    "subjectAltName");
575*5051Swyllys 
576*5051Swyllys 	/*
577*5051Swyllys 	 * Construct attributes for the kmf_sign_cert operation.
578*5051Swyllys 	 */
579*5051Swyllys 	numattr = 0;
580*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
581*5051Swyllys 	    &kstype, sizeof (kstype));
582*5051Swyllys 	numattr++;
5833089Swyllys 
584*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
585*5051Swyllys 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
586*5051Swyllys 	numattr++;
587*5051Swyllys 
588*5051Swyllys 	/* cert data that is to be signed */
589*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
590*5051Swyllys 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
591*5051Swyllys 	numattr++;
592*5051Swyllys 
593*5051Swyllys 	/* output buffer for the signed cert */
594*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
595*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
596*5051Swyllys 	numattr++;
597*5051Swyllys 
598*5051Swyllys 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
599*5051Swyllys 	    KMF_OK) {
6003089Swyllys 		goto cleanup;
6013089Swyllys 	}
6023089Swyllys 
6033089Swyllys 	/*
6043089Swyllys 	 * Store the cert in the DB.
6053089Swyllys 	 */
606*5051Swyllys 	numattr = 0;
607*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
608*5051Swyllys 	    &kstype, sizeof (kstype));
609*5051Swyllys 	numattr++;
610*5051Swyllys 
611*5051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
612*5051Swyllys 	    &x509DER, sizeof (KMF_DATA));
613*5051Swyllys 	numattr++;
614*5051Swyllys 
615*5051Swyllys 	if (nickname != NULL) {
616*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
617*5051Swyllys 		    nickname, strlen(nickname));
618*5051Swyllys 		numattr++;
619*5051Swyllys 	}
620*5051Swyllys 
621*5051Swyllys 	if (trust != NULL) {
622*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
623*5051Swyllys 		    trust, strlen(trust));
624*5051Swyllys 		numattr++;
625*5051Swyllys 	}
626*5051Swyllys 
627*5051Swyllys 	if (token != NULL) {
628*5051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
629*5051Swyllys 		    token, strlen(token));
630*5051Swyllys 		numattr++;
631*5051Swyllys 	}
632*5051Swyllys 
633*5051Swyllys 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
6343089Swyllys 
6353089Swyllys cleanup:
636*5051Swyllys 	kmf_free_data(&x509DER);
637*5051Swyllys 	kmf_free_dn(&certSubject);
638*5051Swyllys 	kmf_free_dn(&certIssuer);
6393089Swyllys 	return (kmfrv);
6403089Swyllys }
6413089Swyllys 
6423089Swyllys int
6433089Swyllys pk_gencert(int argc, char *argv[])
6443089Swyllys {
6453089Swyllys 	int rv;
6463089Swyllys 	int opt;
6473089Swyllys 	extern int	optind_av;
6483089Swyllys 	extern char	*optarg_av;
6493089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
6503089Swyllys 	char *subject = NULL;
6513089Swyllys 	char *tokenname = NULL;
6523089Swyllys 	char *dir = NULL;
6533089Swyllys 	char *prefix = NULL;
6543089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
6553089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
6563089Swyllys 	char *trust = NULL;
6573089Swyllys 	char *lifetime = NULL;
6583089Swyllys 	char *certlabel = NULL;
6593089Swyllys 	char *outcert = NULL;
6603089Swyllys 	char *outkey = NULL;
6613089Swyllys 	char *format = NULL;
6623089Swyllys 	char *serstr = NULL;
6633089Swyllys 	char *altname = NULL;
6643089Swyllys 	char *keyusagestr = NULL;
6653089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
6663089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
6673089Swyllys 	uint32_t ltime;
6683089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
6693089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
6703089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
6713089Swyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
6723089Swyllys 	boolean_t interactive = B_FALSE;
6733089Swyllys 	char *subname = NULL;
6743089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
6753089Swyllys 	uint16_t kubits = 0;
6763089Swyllys 	int altcrit = 0, kucrit = 0;
6773089Swyllys 
6783089Swyllys 	while ((opt = getopt_av(argc, argv,
679*5051Swyllys 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
680*5051Swyllys 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
681*5051Swyllys 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)"
682*5051Swyllys 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
6833089Swyllys 
6843089Swyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
6853089Swyllys 			return (PK_ERR_USAGE);
6863089Swyllys 
6873089Swyllys 		switch (opt) {
6883089Swyllys 			case 'A':
6893089Swyllys 				altname = optarg_av;
6903089Swyllys 				break;
6913089Swyllys 			case 'i':
6923089Swyllys 				if (interactive || subject)
6933089Swyllys 					return (PK_ERR_USAGE);
6943089Swyllys 				else
6953089Swyllys 					interactive = B_TRUE;
6963089Swyllys 				break;
6973089Swyllys 			case 'k':
6983089Swyllys 				kstype = KS2Int(optarg_av);
6993089Swyllys 				if (kstype == 0)
7003089Swyllys 					return (PK_ERR_USAGE);
7013089Swyllys 				break;
7023089Swyllys 			case 's':
7033089Swyllys 				if (interactive || subject)
7043089Swyllys 					return (PK_ERR_USAGE);
7053089Swyllys 				else
7063089Swyllys 					subject = optarg_av;
7073089Swyllys 				break;
7083089Swyllys 			case 'l':
7093089Swyllys 			case 'n':
7103089Swyllys 				if (certlabel)
7113089Swyllys 					return (PK_ERR_USAGE);
7123089Swyllys 				certlabel = optarg_av;
7133089Swyllys 				break;
7143089Swyllys 			case 'T':
7153089Swyllys 				if (tokenname)
7163089Swyllys 					return (PK_ERR_USAGE);
7173089Swyllys 				tokenname = optarg_av;
7183089Swyllys 				break;
7193089Swyllys 			case 'd':
7203089Swyllys 				if (dir)
7213089Swyllys 					return (PK_ERR_USAGE);
7223089Swyllys 				dir = optarg_av;
7233089Swyllys 				break;
7243089Swyllys 			case 'p':
7253089Swyllys 				if (prefix)
7263089Swyllys 					return (PK_ERR_USAGE);
7273089Swyllys 				prefix = optarg_av;
7283089Swyllys 				break;
7293089Swyllys 			case 't':
7303089Swyllys 				keytype = optarg_av;
7313089Swyllys 				break;
7323089Swyllys 			case 'u':
7333089Swyllys 				keyusagestr = optarg_av;
7343089Swyllys 				break;
7353089Swyllys 			case 'y':
7363089Swyllys 				if (sscanf(optarg_av, "%d",
737*5051Swyllys 				    &keylen) != 1) {
7383089Swyllys 					cryptoerror(LOG_STDERR,
739*5051Swyllys 					    gettext("key length must be"
740*5051Swyllys 					    "a numeric value (%s)\n"),
741*5051Swyllys 					    optarg_av);
7423089Swyllys 					return (PK_ERR_USAGE);
7433089Swyllys 				}
7443089Swyllys 				break;
7453089Swyllys 			case 'r':
7463089Swyllys 				if (trust)
7473089Swyllys 					return (PK_ERR_USAGE);
7483089Swyllys 				trust = optarg_av;
7493089Swyllys 				break;
7503089Swyllys 			case 'L':
7513089Swyllys 				if (lifetime)
7523089Swyllys 					return (PK_ERR_USAGE);
7533089Swyllys 				lifetime = optarg_av;
7543089Swyllys 				break;
7553089Swyllys 			case 'c':
7563089Swyllys 				if (outcert)
7573089Swyllys 					return (PK_ERR_USAGE);
7583089Swyllys 				outcert = optarg_av;
7593089Swyllys 				break;
7603089Swyllys 			case 'K':
7613089Swyllys 				if (outkey)
7623089Swyllys 					return (PK_ERR_USAGE);
7633089Swyllys 				outkey = optarg_av;
7643089Swyllys 				break;
7653089Swyllys 			case 'S':
7663089Swyllys 				serstr = optarg_av;
7673089Swyllys 				break;
7683089Swyllys 			case 'F':
7693089Swyllys 				if (format)
7703089Swyllys 					return (PK_ERR_USAGE);
7713089Swyllys 				format = optarg_av;
7723089Swyllys 				break;
7733089Swyllys 			default:
7743089Swyllys 				return (PK_ERR_USAGE);
7753089Swyllys 		}
7763089Swyllys 	}
7773089Swyllys 
7783089Swyllys 	/* No additional args allowed. */
7793089Swyllys 	argc -= optind_av;
7803089Swyllys 	argv += optind_av;
7813089Swyllys 	if (argc) {
7823089Swyllys 		return (PK_ERR_USAGE);
7833089Swyllys 	}
7843089Swyllys 
785*5051Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7863089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
7873089Swyllys 		return (PK_ERR_USAGE);
7883089Swyllys 	}
7893089Swyllys 
7903089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
7913089Swyllys 	if (kstype == 0)
7923089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
7933089Swyllys 
7943089Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
7953089Swyllys 	    EMPTYSTRING(certlabel)) {
7963089Swyllys 		cryptoerror(LOG_STDERR, gettext("A label must be specified "
7973089Swyllys 		    "to create a self-signed certificate.\n"));
7983089Swyllys 		return (PK_ERR_USAGE);
7993089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
8003089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
8013089Swyllys 		    "be specified to create a self-signed certificate.\n"));
8023089Swyllys 		return (PK_ERR_USAGE);
8033089Swyllys 	}
8043089Swyllys 
8053089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
8063089Swyllys 		cryptoerror(LOG_STDERR,
8073089Swyllys 		    gettext("Error parsing format string (%s).\n"),
8083089Swyllys 		    format);
8093089Swyllys 		return (PK_ERR_USAGE);
8103089Swyllys 	}
8113089Swyllys 
8123089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
8133089Swyllys 		cryptoerror(LOG_STDERR,
814*5051Swyllys 		    gettext("Error parsing lifetime string\n"));
8153089Swyllys 		return (PK_ERR_USAGE);
8163089Swyllys 	}
8173089Swyllys 
8183089Swyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
8193089Swyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
820*5051Swyllys 		    keytype);
8213089Swyllys 		return (PK_ERR_USAGE);
8223089Swyllys 	}
8233089Swyllys 
8243089Swyllys 
8253089Swyllys 	/*
8263089Swyllys 	 * Check the subject name.
8273089Swyllys 	 * If interactive is true, get it now interactively.
8283089Swyllys 	 */
8293089Swyllys 	if (interactive) {
8303089Swyllys 		if (get_subname(&subname) != KMF_OK) {
8313089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
8323089Swyllys 			    "subject name interactively.\n"));
8333089Swyllys 			return (PK_ERR_USAGE);
8343089Swyllys 		}
8353089Swyllys 	} else {
8363089Swyllys 		if (EMPTYSTRING(subject)) {
8373089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
8383089Swyllys 			    "-i must be specified to create a self-signed "
8393089Swyllys 			    "certificate.\n"));
8403089Swyllys 			return (PK_ERR_USAGE);
8413089Swyllys 		} else {
8423089Swyllys 			subname = strdup(subject);
8433089Swyllys 			if (subname == NULL) {
8443089Swyllys 				cryptoerror(LOG_STDERR,
8453089Swyllys 				    gettext("Out of memory.\n"));
8463089Swyllys 				return (PK_ERR_SYSTEM);
8473089Swyllys 			}
8483089Swyllys 		}
8493089Swyllys 	}
8503089Swyllys 
8513089Swyllys 	if (serstr == NULL) {
8523089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
853*5051Swyllys 		    "must be specified as a hex number when creating"
854*5051Swyllys 		    " a self-signed certificate "
855*5051Swyllys 		    "(ex: serial=0x0102030405feedface)\n"));
8563089Swyllys 		rv = PK_ERR_USAGE;
8573089Swyllys 		goto end;
8583089Swyllys 	} else {
8593089Swyllys 		uchar_t *bytes = NULL;
8603089Swyllys 		size_t bytelen;
8613089Swyllys 
862*5051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
8633089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
8643089Swyllys 			(void) fprintf(stderr, gettext("serial number "
865*5051Swyllys 			    "must be specified as a hex number "
866*5051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
8673089Swyllys 			rv = PK_ERR_USAGE;
8683089Swyllys 			goto end;
8693089Swyllys 		}
8703089Swyllys 		serial.val = bytes;
8713089Swyllys 		serial.len = bytelen;
8723089Swyllys 	}
8733089Swyllys 
8743089Swyllys 	if (altname != NULL) {
8753089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
8763089Swyllys 		if (rv != KMF_OK) {
8773089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
878*5051Swyllys 			    "must be specified as a name=value pair. "
879*5051Swyllys 			    "See the man page for details.\n"));
8803089Swyllys 			rv = PK_ERR_USAGE;
8813089Swyllys 			goto end;
8823089Swyllys 		} else {
8833089Swyllys 			/* advance the altname past the '=' sign */
8843089Swyllys 			char *p = strchr(altname, '=');
8853089Swyllys 			if (p != NULL)
8863089Swyllys 				altname = p + 1;
8873089Swyllys 		}
8883089Swyllys 	}
8893089Swyllys 
8903089Swyllys 	if (keyusagestr != NULL) {
8913089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
8923089Swyllys 		if (rv != KMF_OK) {
8933089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
894*5051Swyllys 			    "must be specified as a comma-separated list. "
895*5051Swyllys 			    "See the man page for details.\n"));
8963089Swyllys 			rv = PK_ERR_USAGE;
8973089Swyllys 			goto end;
8983089Swyllys 		}
8993089Swyllys 	}
9003089Swyllys 
9013089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
9023089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
9033089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
9043089Swyllys 				tokenname = "internal";
9053089Swyllys 			} else  {
9063089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
9073089Swyllys 			}
9083089Swyllys 		}
9093089Swyllys 
9103089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
9113089Swyllys 	}
9123089Swyllys 
9133089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
9143089Swyllys 		if (dir == NULL)
9153089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
9163089Swyllys 
9173089Swyllys 		rv = gencert_nss(kmfhandle,
918*5051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
919*5051Swyllys 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
920*5051Swyllys 		    trust, ltime, &serial, kubits, kucrit, &tokencred);
9213089Swyllys 
9223089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
9233089Swyllys 		rv = gencert_pkcs11(kmfhandle,
924*5051Swyllys 		    tokenname, subname, altname, alttype, altcrit,
925*5051Swyllys 		    certlabel, keyAlg, sigAlg, keylen, ltime,
926*5051Swyllys 		    &serial, kubits, kucrit, &tokencred);
9273089Swyllys 
9283089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
9293089Swyllys 		rv = gencert_file(kmfhandle,
930*5051Swyllys 		    keyAlg, sigAlg, keylen, fmt,
931*5051Swyllys 		    ltime, subname, altname, alttype, altcrit,
932*5051Swyllys 		    &serial, kubits, kucrit, dir, outcert, outkey);
9333089Swyllys 	}
9343089Swyllys 
9353089Swyllys 	if (rv != KMF_OK)
9363089Swyllys 		display_error(kmfhandle, rv,
937*5051Swyllys 		    gettext("Error creating certificate and keypair"));
9383089Swyllys end:
9393089Swyllys 	if (subname)
9403089Swyllys 		free(subname);
9413089Swyllys 	if (tokencred.cred != NULL)
9423089Swyllys 		free(tokencred.cred);
9433089Swyllys 
9443089Swyllys 	if (serial.val != NULL)
9453089Swyllys 		free(serial.val);
9463089Swyllys 
947*5051Swyllys 	(void) kmf_finalize(kmfhandle);
9483089Swyllys 	return (rv);
9493089Swyllys }
950