xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 3089:8ddeb2ace8aa)
1*3089Swyllys /*
2*3089Swyllys  * CDDL HEADER START
3*3089Swyllys  *
4*3089Swyllys  * The contents of this file are subject to the terms of the
5*3089Swyllys  * Common Development and Distribution License (the "License").
6*3089Swyllys  * You may not use this file except in compliance with the License.
7*3089Swyllys  *
8*3089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3089Swyllys  * or http://www.opensolaris.org/os/licensing.
10*3089Swyllys  * See the License for the specific language governing permissions
11*3089Swyllys  * and limitations under the License.
12*3089Swyllys  *
13*3089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
14*3089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
16*3089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
17*3089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3089Swyllys  *
19*3089Swyllys  * CDDL HEADER END
20*3089Swyllys  */
21*3089Swyllys /*
22*3089Swyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*3089Swyllys  * Use is subject to license terms.
24*3089Swyllys  */
25*3089Swyllys 
26*3089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3089Swyllys 
28*3089Swyllys #include <stdio.h>
29*3089Swyllys #include <string.h>
30*3089Swyllys #include <ctype.h>
31*3089Swyllys #include <malloc.h>
32*3089Swyllys #include <libgen.h>
33*3089Swyllys #include <errno.h>
34*3089Swyllys #include <cryptoutil.h>
35*3089Swyllys #include <security/cryptoki.h>
36*3089Swyllys #include "common.h"
37*3089Swyllys 
38*3089Swyllys #include <kmfapi.h>
39*3089Swyllys 
40*3089Swyllys #define	SET_VALUE(f, s) \
41*3089Swyllys 	kmfrv = f; \
42*3089Swyllys 	if (kmfrv != KMF_OK) { \
43*3089Swyllys 		cryptoerror(LOG_STDERR, \
44*3089Swyllys 			gettext("Failed to set %s: 0x%02x\n"), \
45*3089Swyllys 			s, kmfrv); \
46*3089Swyllys 		goto cleanup; \
47*3089Swyllys 	}
48*3089Swyllys 
49*3089Swyllys static int
50*3089Swyllys gencert_pkcs11(KMF_HANDLE_T kmfhandle,
51*3089Swyllys 	char *token, char *subject, char *altname,
52*3089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
53*3089Swyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
54*3089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
55*3089Swyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
56*3089Swyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred)
57*3089Swyllys {
58*3089Swyllys 	KMF_RETURN kmfrv = KMF_OK;
59*3089Swyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
60*3089Swyllys 	KMF_STORECERT_PARAMS sc_params;
61*3089Swyllys 	KMF_KEY_HANDLE pubk, prik;
62*3089Swyllys 	KMF_X509_CERTIFICATE signedCert;
63*3089Swyllys 	KMF_X509_NAME	certSubject;
64*3089Swyllys 	KMF_X509_NAME	certIssuer;
65*3089Swyllys 	KMF_DATA x509DER;
66*3089Swyllys 
67*3089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
68*3089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
69*3089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
70*3089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
71*3089Swyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
72*3089Swyllys 
73*3089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
74*3089Swyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
75*3089Swyllys 		cryptoerror(LOG_STDERR,
76*3089Swyllys 			gettext("Subject name cannot be parsed.\n"));
77*3089Swyllys 		return (PK_ERR_USAGE);
78*3089Swyllys 	}
79*3089Swyllys 
80*3089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
81*3089Swyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
82*3089Swyllys 		cryptoerror(LOG_STDERR,
83*3089Swyllys 			gettext("Subject name cannot be parsed.\n"));
84*3089Swyllys 		return (PK_ERR_USAGE);
85*3089Swyllys 	}
86*3089Swyllys 
87*3089Swyllys 	kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
88*3089Swyllys 	kp_params.keylabel = certlabel;
89*3089Swyllys 	kp_params.keylength = keylen; /* bits */
90*3089Swyllys 	kp_params.keytype = keyAlg;
91*3089Swyllys 	kp_params.cred.cred = tokencred->cred;
92*3089Swyllys 	kp_params.cred.credlen = tokencred->credlen;
93*3089Swyllys 
94*3089Swyllys 	/* Select a PKCS11 token */
95*3089Swyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
96*3089Swyllys 
97*3089Swyllys 	if (kmfrv != KMF_OK) {
98*3089Swyllys 		return (kmfrv);
99*3089Swyllys 	}
100*3089Swyllys 
101*3089Swyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
102*3089Swyllys 	if (kmfrv != KMF_OK) {
103*3089Swyllys 		return (kmfrv);
104*3089Swyllys 	}
105*3089Swyllys 
106*3089Swyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
107*3089Swyllys 			"keypair");
108*3089Swyllys 
109*3089Swyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
110*3089Swyllys 
111*3089Swyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
112*3089Swyllys 			"serial number");
113*3089Swyllys 
114*3089Swyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
115*3089Swyllys 		"validity time");
116*3089Swyllys 
117*3089Swyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
118*3089Swyllys 		"signature algorithm");
119*3089Swyllys 
120*3089Swyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
121*3089Swyllys 		"subject name");
122*3089Swyllys 
123*3089Swyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
124*3089Swyllys 		"issuer name");
125*3089Swyllys 
126*3089Swyllys 	if (altname != NULL)
127*3089Swyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
128*3089Swyllys 			alttype, altname), "subjectAltName");
129*3089Swyllys 
130*3089Swyllys 	if (kubits != 0)
131*3089Swyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
132*3089Swyllys 			"KeyUsage");
133*3089Swyllys 
134*3089Swyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
135*3089Swyllys 		&signedCert, &x509DER)) != KMF_OK) {
136*3089Swyllys 		goto cleanup;
137*3089Swyllys 	}
138*3089Swyllys 
139*3089Swyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
140*3089Swyllys 	sc_params.kstype = KMF_KEYSTORE_PK11TOKEN;
141*3089Swyllys 	sc_params.certLabel = certlabel;
142*3089Swyllys 
143*3089Swyllys 	/*
144*3089Swyllys 	 * Store the cert in the DB.
145*3089Swyllys 	 */
146*3089Swyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
147*3089Swyllys 
148*3089Swyllys cleanup:
149*3089Swyllys 	KMF_FreeData(&x509DER);
150*3089Swyllys 	KMF_FreeDN(&certSubject);
151*3089Swyllys 	KMF_FreeDN(&certIssuer);
152*3089Swyllys 	return (kmfrv);
153*3089Swyllys }
154*3089Swyllys 
155*3089Swyllys static int
156*3089Swyllys gencert_file(KMF_HANDLE_T kmfhandle,
157*3089Swyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
158*3089Swyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
159*3089Swyllys 	uint32_t ltime, char *subject, char *altname,
160*3089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
161*3089Swyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
162*3089Swyllys 	char *dir, char *outcert, char *outkey)
163*3089Swyllys {
164*3089Swyllys 	KMF_RETURN kmfrv;
165*3089Swyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
166*3089Swyllys 	KMF_STORECERT_PARAMS sc_params;
167*3089Swyllys 	KMF_KEY_HANDLE pubk, prik;
168*3089Swyllys 	KMF_X509_CERTIFICATE signedCert;
169*3089Swyllys 	KMF_X509_NAME	certSubject;
170*3089Swyllys 	KMF_X509_NAME	certIssuer;
171*3089Swyllys 	KMF_DATA x509DER;
172*3089Swyllys 	char *fullcertpath = NULL;
173*3089Swyllys 	char *fullkeypath = NULL;
174*3089Swyllys 
175*3089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
176*3089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
177*3089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
178*3089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
179*3089Swyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
180*3089Swyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
181*3089Swyllys 
182*3089Swyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
183*3089Swyllys 		cryptoerror(LOG_STDERR,
184*3089Swyllys 			gettext("No output file was specified for "
185*3089Swyllys 				"the cert or key\n"));
186*3089Swyllys 		return (PK_ERR_USAGE);
187*3089Swyllys 	}
188*3089Swyllys 	if (dir != NULL) {
189*3089Swyllys 		fullcertpath = get_fullpath(dir, outcert);
190*3089Swyllys 		if (fullcertpath == NULL) {
191*3089Swyllys 			cryptoerror(LOG_STDERR,
192*3089Swyllys 				gettext("Cannot create file %s in "
193*3089Swyllys 					"directory %s\n"), dir, outcert);
194*3089Swyllys 			return (PK_ERR_USAGE);
195*3089Swyllys 		}
196*3089Swyllys 	} else {
197*3089Swyllys 		fullcertpath = strdup(outcert);
198*3089Swyllys 	}
199*3089Swyllys 	if (verify_file(fullcertpath)) {
200*3089Swyllys 		cryptoerror(LOG_STDERR,
201*3089Swyllys 			gettext("Cannot write the indicated output "
202*3089Swyllys 				"certificate file (%s).\n"),
203*3089Swyllys 				fullcertpath);
204*3089Swyllys 		free(fullcertpath);
205*3089Swyllys 		return (PK_ERR_USAGE);
206*3089Swyllys 	}
207*3089Swyllys 	if (dir != NULL) {
208*3089Swyllys 		fullkeypath = get_fullpath(dir, outkey);
209*3089Swyllys 		if (fullkeypath == NULL) {
210*3089Swyllys 			cryptoerror(LOG_STDERR,
211*3089Swyllys 				gettext("Cannot create file %s in "
212*3089Swyllys 					"directory %s\n"), dir, outkey);
213*3089Swyllys 			free(fullcertpath);
214*3089Swyllys 			return (PK_ERR_USAGE);
215*3089Swyllys 		}
216*3089Swyllys 	} else {
217*3089Swyllys 		fullkeypath = strdup(outkey);
218*3089Swyllys 	}
219*3089Swyllys 	if (verify_file(fullkeypath)) {
220*3089Swyllys 		cryptoerror(LOG_STDERR,
221*3089Swyllys 			gettext("Cannot write the indicated output "
222*3089Swyllys 				"key file (%s).\n"),
223*3089Swyllys 				fullkeypath);
224*3089Swyllys 		free(fullkeypath);
225*3089Swyllys 		free(fullcertpath);
226*3089Swyllys 		return (PK_ERR_USAGE);
227*3089Swyllys 	}
228*3089Swyllys 
229*3089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
230*3089Swyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
231*3089Swyllys 		cryptoerror(LOG_STDERR,
232*3089Swyllys 			gettext("Subject name cannot be parsed (%s)\n"),
233*3089Swyllys 			subject);
234*3089Swyllys 		return (PK_ERR_USAGE);
235*3089Swyllys 	}
236*3089Swyllys 
237*3089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
238*3089Swyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
239*3089Swyllys 		cryptoerror(LOG_STDERR,
240*3089Swyllys 			gettext("Subject name cannot be parsed (%s)\n"),
241*3089Swyllys 			subject);
242*3089Swyllys 		KMF_FreeDN(&certSubject);
243*3089Swyllys 		return (PK_ERR_USAGE);
244*3089Swyllys 	}
245*3089Swyllys 
246*3089Swyllys 	kp_params.kstype = KMF_KEYSTORE_OPENSSL;
247*3089Swyllys 	kp_params.keylength = keylen; /* bits */
248*3089Swyllys 	kp_params.keytype = keyAlg;
249*3089Swyllys 
250*3089Swyllys 	kp_params.sslparms.keyfile = fullkeypath;
251*3089Swyllys 	kp_params.sslparms.format = fmt;
252*3089Swyllys 
253*3089Swyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
254*3089Swyllys 	if (kmfrv != KMF_OK) {
255*3089Swyllys 		goto cleanup;
256*3089Swyllys 	}
257*3089Swyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
258*3089Swyllys 		"keypair");
259*3089Swyllys 
260*3089Swyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
261*3089Swyllys 
262*3089Swyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
263*3089Swyllys 		"serial number");
264*3089Swyllys 
265*3089Swyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
266*3089Swyllys 		"validity time");
267*3089Swyllys 
268*3089Swyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
269*3089Swyllys 		"signature algorithm");
270*3089Swyllys 
271*3089Swyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
272*3089Swyllys 		"subject name");
273*3089Swyllys 
274*3089Swyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
275*3089Swyllys 		"issuer name");
276*3089Swyllys 
277*3089Swyllys 	if (altname != NULL)
278*3089Swyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
279*3089Swyllys 			alttype, altname), "subjectAltName");
280*3089Swyllys 
281*3089Swyllys 	if (kubits != 0)
282*3089Swyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
283*3089Swyllys 			"KeyUsage");
284*3089Swyllys 
285*3089Swyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
286*3089Swyllys 		&signedCert, &x509DER)) != KMF_OK) {
287*3089Swyllys 		goto cleanup;
288*3089Swyllys 	}
289*3089Swyllys 
290*3089Swyllys 	sc_params.kstype = KMF_KEYSTORE_OPENSSL;
291*3089Swyllys 	sc_params.sslparms.certfile = fullcertpath;
292*3089Swyllys 	sc_params.sslparms.keyfile = fullkeypath;
293*3089Swyllys 	sc_params.sslparms.format = fmt;
294*3089Swyllys 	/*
295*3089Swyllys 	 * Store the cert in the DB.
296*3089Swyllys 	 */
297*3089Swyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
298*3089Swyllys 
299*3089Swyllys cleanup:
300*3089Swyllys 	if (fullkeypath != NULL)
301*3089Swyllys 		free(fullkeypath);
302*3089Swyllys 	if (fullcertpath != NULL)
303*3089Swyllys 		free(fullcertpath);
304*3089Swyllys 
305*3089Swyllys 	KMF_FreeData(&x509DER);
306*3089Swyllys 	KMF_FreeDN(&certSubject);
307*3089Swyllys 	KMF_FreeDN(&certIssuer);
308*3089Swyllys 	return (kmfrv);
309*3089Swyllys }
310*3089Swyllys 
311*3089Swyllys static KMF_RETURN
312*3089Swyllys gencert_nss(KMF_HANDLE_T kmfhandle,
313*3089Swyllys 	char *token, char *subject, char *altname,
314*3089Swyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
315*3089Swyllys 	char *nickname, char *dir, char *prefix,
316*3089Swyllys 	KMF_KEY_ALG keyAlg,
317*3089Swyllys 	KMF_ALGORITHM_INDEX sigAlg,
318*3089Swyllys 	int keylen, char *trust,
319*3089Swyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
320*3089Swyllys 	int kucrit, KMF_CREDENTIAL *tokencred)
321*3089Swyllys {
322*3089Swyllys 	KMF_RETURN kmfrv;
323*3089Swyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
324*3089Swyllys 	KMF_STORECERT_PARAMS sc_params;
325*3089Swyllys 	KMF_KEY_HANDLE pubk, prik;
326*3089Swyllys 	KMF_X509_CERTIFICATE signedCert;
327*3089Swyllys 	KMF_X509_NAME	certSubject;
328*3089Swyllys 	KMF_X509_NAME	certIssuer;
329*3089Swyllys 	KMF_DATA x509DER;
330*3089Swyllys 
331*3089Swyllys 	if (token == NULL)
332*3089Swyllys 		token = DEFAULT_NSS_TOKEN;
333*3089Swyllys 
334*3089Swyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
335*3089Swyllys 	if (kmfrv != KMF_OK)
336*3089Swyllys 		return (kmfrv);
337*3089Swyllys 
338*3089Swyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
339*3089Swyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
340*3089Swyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
341*3089Swyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
342*3089Swyllys 
343*3089Swyllys 	/* If the subject name cannot be parsed, flag it now and exit */
344*3089Swyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
345*3089Swyllys 		cryptoerror(LOG_STDERR,
346*3089Swyllys 			gettext("Subject name cannot be parsed.\n"));
347*3089Swyllys 		return (PK_ERR_USAGE);
348*3089Swyllys 	}
349*3089Swyllys 
350*3089Swyllys 	/* For a self-signed cert, the issuser and subject are the same */
351*3089Swyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
352*3089Swyllys 		cryptoerror(LOG_STDERR,
353*3089Swyllys 			gettext("Subject name cannot be parsed.\n"));
354*3089Swyllys 		return (PK_ERR_USAGE);
355*3089Swyllys 	}
356*3089Swyllys 
357*3089Swyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
358*3089Swyllys 
359*3089Swyllys 	kp_params.kstype = KMF_KEYSTORE_NSS;
360*3089Swyllys 	kp_params.keylabel = nickname;
361*3089Swyllys 	kp_params.keylength = keylen; /* bits */
362*3089Swyllys 	kp_params.keytype = keyAlg;
363*3089Swyllys 	kp_params.cred.cred = tokencred->cred;
364*3089Swyllys 	kp_params.cred.credlen = tokencred->credlen;
365*3089Swyllys 	kp_params.nssparms.slotlabel = token;
366*3089Swyllys 
367*3089Swyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
368*3089Swyllys 	if (kmfrv != KMF_OK) {
369*3089Swyllys 		return (kmfrv);
370*3089Swyllys 	}
371*3089Swyllys 
372*3089Swyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
373*3089Swyllys 			"keypair");
374*3089Swyllys 
375*3089Swyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
376*3089Swyllys 
377*3089Swyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
378*3089Swyllys 			"serial number");
379*3089Swyllys 
380*3089Swyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
381*3089Swyllys 		"validity time");
382*3089Swyllys 
383*3089Swyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
384*3089Swyllys 		"signature algorithm");
385*3089Swyllys 
386*3089Swyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
387*3089Swyllys 		"subject name");
388*3089Swyllys 
389*3089Swyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
390*3089Swyllys 		"issuer name");
391*3089Swyllys 
392*3089Swyllys 	if (altname != NULL)
393*3089Swyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
394*3089Swyllys 			alttype, altname), "subjectAltName");
395*3089Swyllys 
396*3089Swyllys 	if (kubits)
397*3089Swyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
398*3089Swyllys 			"subjectAltName");
399*3089Swyllys 
400*3089Swyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
401*3089Swyllys 		&signedCert, &x509DER)) != KMF_OK) {
402*3089Swyllys 		goto cleanup;
403*3089Swyllys 	}
404*3089Swyllys 
405*3089Swyllys 	sc_params.kstype = KMF_KEYSTORE_NSS;
406*3089Swyllys 	sc_params.certLabel = nickname;
407*3089Swyllys 	sc_params.nssparms.trustflag = trust;
408*3089Swyllys 	sc_params.nssparms.slotlabel = token;
409*3089Swyllys 
410*3089Swyllys 	/*
411*3089Swyllys 	 * Store the cert in the DB.
412*3089Swyllys 	 */
413*3089Swyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
414*3089Swyllys 
415*3089Swyllys cleanup:
416*3089Swyllys 	KMF_FreeData(&x509DER);
417*3089Swyllys 	KMF_FreeDN(&certSubject);
418*3089Swyllys 	KMF_FreeDN(&certIssuer);
419*3089Swyllys 	return (kmfrv);
420*3089Swyllys }
421*3089Swyllys 
422*3089Swyllys int
423*3089Swyllys pk_gencert(int argc, char *argv[])
424*3089Swyllys {
425*3089Swyllys 	int rv;
426*3089Swyllys 	int opt;
427*3089Swyllys 	extern int	optind_av;
428*3089Swyllys 	extern char	*optarg_av;
429*3089Swyllys 	KMF_KEYSTORE_TYPE kstype = 0;
430*3089Swyllys 	char *subject = NULL;
431*3089Swyllys 	char *tokenname = NULL;
432*3089Swyllys 	char *dir = NULL;
433*3089Swyllys 	char *prefix = NULL;
434*3089Swyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
435*3089Swyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
436*3089Swyllys 	char *trust = NULL;
437*3089Swyllys 	char *lifetime = NULL;
438*3089Swyllys 	char *certlabel = NULL;
439*3089Swyllys 	char *outcert = NULL;
440*3089Swyllys 	char *outkey = NULL;
441*3089Swyllys 	char *format = NULL;
442*3089Swyllys 	char *serstr = NULL;
443*3089Swyllys 	char *altname = NULL;
444*3089Swyllys 	char *keyusagestr = NULL;
445*3089Swyllys 	KMF_GENERALNAMECHOICES alttype = 0;
446*3089Swyllys 	KMF_BIGINT serial = { NULL, 0 };
447*3089Swyllys 	uint32_t ltime;
448*3089Swyllys 	KMF_HANDLE_T kmfhandle = NULL;
449*3089Swyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
450*3089Swyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
451*3089Swyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
452*3089Swyllys 	boolean_t interactive = B_FALSE;
453*3089Swyllys 	char *subname = NULL;
454*3089Swyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
455*3089Swyllys 	uint16_t kubits = 0;
456*3089Swyllys 	int altcrit = 0, kucrit = 0;
457*3089Swyllys 
458*3089Swyllys 	while ((opt = getopt_av(argc, argv,
459*3089Swyllys 		"ik:(keystore)s:(subject)n:(nickname)A:(altname)"
460*3089Swyllys 		"T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
461*3089Swyllys 		"r:(trust)L:(lifetime)l:(label)c:(outcert)"
462*3089Swyllys 		"K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
463*3089Swyllys 
464*3089Swyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
465*3089Swyllys 			return (PK_ERR_USAGE);
466*3089Swyllys 
467*3089Swyllys 		switch (opt) {
468*3089Swyllys 			case 'A':
469*3089Swyllys 				altname = optarg_av;
470*3089Swyllys 				break;
471*3089Swyllys 			case 'i':
472*3089Swyllys 				if (interactive || subject)
473*3089Swyllys 					return (PK_ERR_USAGE);
474*3089Swyllys 				else
475*3089Swyllys 					interactive = B_TRUE;
476*3089Swyllys 				break;
477*3089Swyllys 			case 'k':
478*3089Swyllys 				kstype = KS2Int(optarg_av);
479*3089Swyllys 				if (kstype == 0)
480*3089Swyllys 					return (PK_ERR_USAGE);
481*3089Swyllys 				break;
482*3089Swyllys 			case 's':
483*3089Swyllys 				if (interactive || subject)
484*3089Swyllys 					return (PK_ERR_USAGE);
485*3089Swyllys 				else
486*3089Swyllys 					subject = optarg_av;
487*3089Swyllys 				break;
488*3089Swyllys 			case 'l':
489*3089Swyllys 			case 'n':
490*3089Swyllys 				if (certlabel)
491*3089Swyllys 					return (PK_ERR_USAGE);
492*3089Swyllys 				certlabel = optarg_av;
493*3089Swyllys 				break;
494*3089Swyllys 			case 'T':
495*3089Swyllys 				if (tokenname)
496*3089Swyllys 					return (PK_ERR_USAGE);
497*3089Swyllys 				tokenname = optarg_av;
498*3089Swyllys 				break;
499*3089Swyllys 			case 'd':
500*3089Swyllys 				if (dir)
501*3089Swyllys 					return (PK_ERR_USAGE);
502*3089Swyllys 				dir = optarg_av;
503*3089Swyllys 				break;
504*3089Swyllys 			case 'p':
505*3089Swyllys 				if (prefix)
506*3089Swyllys 					return (PK_ERR_USAGE);
507*3089Swyllys 				prefix = optarg_av;
508*3089Swyllys 				break;
509*3089Swyllys 			case 't':
510*3089Swyllys 				keytype = optarg_av;
511*3089Swyllys 				break;
512*3089Swyllys 			case 'u':
513*3089Swyllys 				keyusagestr = optarg_av;
514*3089Swyllys 				break;
515*3089Swyllys 			case 'y':
516*3089Swyllys 				if (sscanf(optarg_av, "%d",
517*3089Swyllys 					&keylen) != 1) {
518*3089Swyllys 					cryptoerror(LOG_STDERR,
519*3089Swyllys 						gettext("key length must be"
520*3089Swyllys 						"a numeric value (%s)\n"),
521*3089Swyllys 						optarg_av);
522*3089Swyllys 					return (PK_ERR_USAGE);
523*3089Swyllys 				}
524*3089Swyllys 				break;
525*3089Swyllys 			case 'r':
526*3089Swyllys 				if (trust)
527*3089Swyllys 					return (PK_ERR_USAGE);
528*3089Swyllys 				trust = optarg_av;
529*3089Swyllys 				break;
530*3089Swyllys 			case 'L':
531*3089Swyllys 				if (lifetime)
532*3089Swyllys 					return (PK_ERR_USAGE);
533*3089Swyllys 				lifetime = optarg_av;
534*3089Swyllys 				break;
535*3089Swyllys 			case 'c':
536*3089Swyllys 				if (outcert)
537*3089Swyllys 					return (PK_ERR_USAGE);
538*3089Swyllys 				outcert = optarg_av;
539*3089Swyllys 				break;
540*3089Swyllys 			case 'K':
541*3089Swyllys 				if (outkey)
542*3089Swyllys 					return (PK_ERR_USAGE);
543*3089Swyllys 				outkey = optarg_av;
544*3089Swyllys 				break;
545*3089Swyllys 			case 'S':
546*3089Swyllys 				serstr = optarg_av;
547*3089Swyllys 				break;
548*3089Swyllys 			case 'F':
549*3089Swyllys 				if (format)
550*3089Swyllys 					return (PK_ERR_USAGE);
551*3089Swyllys 				format = optarg_av;
552*3089Swyllys 				break;
553*3089Swyllys 			default:
554*3089Swyllys 				return (PK_ERR_USAGE);
555*3089Swyllys 		}
556*3089Swyllys 	}
557*3089Swyllys 
558*3089Swyllys 	/* No additional args allowed. */
559*3089Swyllys 	argc -= optind_av;
560*3089Swyllys 	argv += optind_av;
561*3089Swyllys 	if (argc) {
562*3089Swyllys 		return (PK_ERR_USAGE);
563*3089Swyllys 	}
564*3089Swyllys 
565*3089Swyllys 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
566*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
567*3089Swyllys 		return (PK_ERR_USAGE);
568*3089Swyllys 	}
569*3089Swyllys 
570*3089Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
571*3089Swyllys 	if (kstype == 0)
572*3089Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
573*3089Swyllys 
574*3089Swyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
575*3089Swyllys 	    EMPTYSTRING(certlabel)) {
576*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("A label must be specified "
577*3089Swyllys 		    "to create a self-signed certificate.\n"));
578*3089Swyllys 		return (PK_ERR_USAGE);
579*3089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
580*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
581*3089Swyllys 		    "be specified to create a self-signed certificate.\n"));
582*3089Swyllys 		return (PK_ERR_USAGE);
583*3089Swyllys 	}
584*3089Swyllys 
585*3089Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
586*3089Swyllys 		cryptoerror(LOG_STDERR,
587*3089Swyllys 		    gettext("Error parsing format string (%s).\n"),
588*3089Swyllys 		    format);
589*3089Swyllys 		return (PK_ERR_USAGE);
590*3089Swyllys 	}
591*3089Swyllys 
592*3089Swyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
593*3089Swyllys 		cryptoerror(LOG_STDERR,
594*3089Swyllys 			gettext("Error parsing lifetime string\n"));
595*3089Swyllys 		return (PK_ERR_USAGE);
596*3089Swyllys 	}
597*3089Swyllys 
598*3089Swyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
599*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
600*3089Swyllys 			keytype);
601*3089Swyllys 		return (PK_ERR_USAGE);
602*3089Swyllys 	}
603*3089Swyllys 
604*3089Swyllys 
605*3089Swyllys 	/*
606*3089Swyllys 	 * Check the subject name.
607*3089Swyllys 	 * If interactive is true, get it now interactively.
608*3089Swyllys 	 */
609*3089Swyllys 	if (interactive) {
610*3089Swyllys 		if (get_subname(&subname) != KMF_OK) {
611*3089Swyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
612*3089Swyllys 			    "subject name interactively.\n"));
613*3089Swyllys 			return (PK_ERR_USAGE);
614*3089Swyllys 		}
615*3089Swyllys 	} else {
616*3089Swyllys 		if (EMPTYSTRING(subject)) {
617*3089Swyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
618*3089Swyllys 			    "-i must be specified to create a self-signed "
619*3089Swyllys 			    "certificate.\n"));
620*3089Swyllys 			return (PK_ERR_USAGE);
621*3089Swyllys 		} else {
622*3089Swyllys 			subname = strdup(subject);
623*3089Swyllys 			if (subname == NULL) {
624*3089Swyllys 				cryptoerror(LOG_STDERR,
625*3089Swyllys 				    gettext("Out of memory.\n"));
626*3089Swyllys 				return (PK_ERR_SYSTEM);
627*3089Swyllys 			}
628*3089Swyllys 		}
629*3089Swyllys 	}
630*3089Swyllys 
631*3089Swyllys 	if (serstr == NULL) {
632*3089Swyllys 		(void) fprintf(stderr, gettext("A serial number "
633*3089Swyllys 			"must be specified as a hex number when creating"
634*3089Swyllys 			" a self-signed certificate "
635*3089Swyllys 			"(ex: serno=0x0102030405feedface)\n"));
636*3089Swyllys 		rv = PK_ERR_USAGE;
637*3089Swyllys 		goto end;
638*3089Swyllys 	} else {
639*3089Swyllys 		uchar_t *bytes = NULL;
640*3089Swyllys 		size_t bytelen;
641*3089Swyllys 
642*3089Swyllys 		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
643*3089Swyllys 		if (rv != KMF_OK || bytes == NULL) {
644*3089Swyllys 			(void) fprintf(stderr, gettext("serial number "
645*3089Swyllys 				"must be specified as a hex number "
646*3089Swyllys 				"(ex: 0x0102030405ffeeddee)\n"));
647*3089Swyllys 			rv = PK_ERR_USAGE;
648*3089Swyllys 			goto end;
649*3089Swyllys 		}
650*3089Swyllys 		serial.val = bytes;
651*3089Swyllys 		serial.len = bytelen;
652*3089Swyllys 	}
653*3089Swyllys 
654*3089Swyllys 	if (altname != NULL) {
655*3089Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
656*3089Swyllys 		if (rv != KMF_OK) {
657*3089Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
658*3089Swyllys 				"must be specified as a name=value pair. "
659*3089Swyllys 				"See the man page for details.\n"));
660*3089Swyllys 			rv = PK_ERR_USAGE;
661*3089Swyllys 			goto end;
662*3089Swyllys 		} else {
663*3089Swyllys 			/* advance the altname past the '=' sign */
664*3089Swyllys 			char *p = strchr(altname, '=');
665*3089Swyllys 			if (p != NULL)
666*3089Swyllys 				altname = p + 1;
667*3089Swyllys 		}
668*3089Swyllys 	}
669*3089Swyllys 
670*3089Swyllys 	if (keyusagestr != NULL) {
671*3089Swyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
672*3089Swyllys 		if (rv != KMF_OK) {
673*3089Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
674*3089Swyllys 				"must be specified as a comma-separated list. "
675*3089Swyllys 				"See the man page for details.\n"));
676*3089Swyllys 			rv = PK_ERR_USAGE;
677*3089Swyllys 			goto end;
678*3089Swyllys 		}
679*3089Swyllys 	}
680*3089Swyllys 
681*3089Swyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
682*3089Swyllys 		if (tokenname == NULL || !strlen(tokenname)) {
683*3089Swyllys 			if (kstype == KMF_KEYSTORE_NSS) {
684*3089Swyllys 				tokenname = "internal";
685*3089Swyllys 			} else  {
686*3089Swyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
687*3089Swyllys 			}
688*3089Swyllys 		}
689*3089Swyllys 
690*3089Swyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
691*3089Swyllys 	}
692*3089Swyllys 
693*3089Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
694*3089Swyllys 		if (dir == NULL)
695*3089Swyllys 			dir = PK_DEFAULT_DIRECTORY;
696*3089Swyllys 
697*3089Swyllys 		rv = gencert_nss(kmfhandle,
698*3089Swyllys 			tokenname, subname, altname, alttype, altcrit,
699*3089Swyllys 			certlabel, dir, prefix, keyAlg, sigAlg, keylen,
700*3089Swyllys 			trust, ltime, &serial, kubits, kucrit, &tokencred);
701*3089Swyllys 
702*3089Swyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
703*3089Swyllys 		rv = gencert_pkcs11(kmfhandle,
704*3089Swyllys 			tokenname, subname, altname, alttype, altcrit,
705*3089Swyllys 			certlabel, keyAlg, sigAlg, keylen, ltime,
706*3089Swyllys 			&serial, kubits, kucrit, &tokencred);
707*3089Swyllys 
708*3089Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
709*3089Swyllys 		rv = gencert_file(kmfhandle,
710*3089Swyllys 			keyAlg, sigAlg, keylen, fmt,
711*3089Swyllys 			ltime, subname, altname, alttype, altcrit,
712*3089Swyllys 			&serial, kubits, kucrit, dir, outcert, outkey);
713*3089Swyllys 	}
714*3089Swyllys 
715*3089Swyllys 	if (rv != KMF_OK)
716*3089Swyllys 		display_error(kmfhandle, rv,
717*3089Swyllys 			gettext("Error creating certificate and keypair"));
718*3089Swyllys end:
719*3089Swyllys 	if (subname)
720*3089Swyllys 		free(subname);
721*3089Swyllys 	if (tokencred.cred != NULL)
722*3089Swyllys 		free(tokencred.cred);
723*3089Swyllys 
724*3089Swyllys 	if (serial.val != NULL)
725*3089Swyllys 		free(serial.val);
726*3089Swyllys 
727*3089Swyllys 	(void) KMF_Finalize(kmfhandle);
728*3089Swyllys 	return (rv);
729*3089Swyllys }
730