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