xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
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  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
22  */
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <malloc.h>
28 #include <libgen.h>
29 #include <errno.h>
30 #include <cryptoutil.h>
31 #include <security/cryptoki.h>
32 #include "common.h"
33 
34 #include <kmfapi.h>
35 
36 #define	SET_VALUE(f, s) \
37 	kmfrv = f; \
38 	if (kmfrv != KMF_OK) { \
39 		cryptoerror(LOG_STDERR, \
40 			gettext("Failed to set %s: 0x%02x\n"), \
41 			s, kmfrv); \
42 		goto cleanup; \
43 	}
44 
45 static int
46 gencert_pkcs11(KMF_HANDLE_T kmfhandle,
47 	char *token, char *subject, char *altname,
48 	KMF_GENERALNAMECHOICES alttype, int altcrit,
49 	char *certlabel, KMF_KEY_ALG keyAlg,
50 	KMF_ALGORITHM_INDEX sigAlg,
51 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
52 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
53 	EKU_LIST *ekulist, KMF_OID *curveoid)
54 {
55 	KMF_RETURN kmfrv = KMF_OK;
56 	KMF_KEY_HANDLE pubk, prik;
57 	KMF_X509_CERTIFICATE signedCert;
58 	KMF_X509_NAME	certSubject;
59 	KMF_X509_NAME	certIssuer;
60 	KMF_DATA x509DER;
61 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
62 	KMF_ATTRIBUTE attrlist[16];
63 	int numattr = 0;
64 	KMF_KEY_ALG keytype;
65 	uint32_t keylength;
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 
72 	/* If the subject name cannot be parsed, flag it now and exit */
73 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
74 		cryptoerror(LOG_STDERR,
75 		    gettext("Subject name cannot be parsed.\n"));
76 		return (PK_ERR_USAGE);
77 	}
78 
79 	/* For a self-signed cert, the issuser and subject are the same */
80 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
81 		cryptoerror(LOG_STDERR,
82 		    gettext("Subject name cannot be parsed.\n"));
83 		return (PK_ERR_USAGE);
84 	}
85 
86 	keylength = keylen; /* bits */
87 	keytype = keyAlg;
88 
89 	/* Select a PKCS11 token */
90 	kmfrv = select_token(kmfhandle, token, FALSE);
91 	if (kmfrv != KMF_OK) {
92 		return (kmfrv);
93 	}
94 
95 	/*
96 	 * Share the "genkeypair" routine for creating the keypair.
97 	 */
98 	kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
99 	    keytype, keylength, tokencred, curveoid, &prik, &pubk);
100 	if (kmfrv != KMF_OK)
101 		return (kmfrv);
102 
103 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
104 	    "keypair");
105 
106 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
107 
108 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
109 	    "serial number");
110 
111 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
112 	    "validity time");
113 
114 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
115 	    "signature algorithm");
116 
117 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
118 	    "subject name");
119 
120 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
121 	    "issuer name");
122 
123 	if (altname != NULL)
124 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
125 		    alttype, altname), "subjectAltName");
126 
127 	if (kubits != 0)
128 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
129 		    "KeyUsage");
130 
131 	if (ekulist != NULL) {
132 		int i;
133 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
134 			SET_VALUE(kmf_add_cert_eku(&signedCert,
135 			    &ekulist->ekulist[i], ekulist->critlist[i]),
136 			    "Extended Key Usage");
137 		}
138 	}
139 
140 	/*
141 	 * Construct attributes for the kmf_sign_cert operation.
142 	 */
143 	numattr = 0;
144 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
145 	    &kstype, sizeof (kstype));
146 	numattr++;
147 
148 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
149 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
150 	numattr++;
151 
152 	/* cert data that is to be signed */
153 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
154 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
155 	numattr++;
156 
157 	/* output buffer for the signed cert */
158 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
159 	    &x509DER, sizeof (KMF_DATA));
160 	numattr++;
161 
162 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
163 	    &sigAlg, sizeof (sigAlg));
164 	numattr++;
165 
166 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
167 	    KMF_OK) {
168 		goto cleanup;
169 	}
170 
171 	/*
172 	 * Store the cert in the DB.
173 	 */
174 	numattr = 0;
175 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
176 	    &kstype, sizeof (kstype));
177 	numattr++;
178 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
179 	    &x509DER, sizeof (KMF_DATA));
180 	numattr++;
181 
182 	if (certlabel != NULL) {
183 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
184 		    certlabel, strlen(certlabel));
185 		numattr++;
186 	}
187 
188 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
189 
190 cleanup:
191 	kmf_free_data(&x509DER);
192 	kmf_free_dn(&certSubject);
193 	kmf_free_dn(&certIssuer);
194 
195 	/*
196 	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
197 	 * the key pair from the token.
198 	 */
199 	if (kmfrv != KMF_OK) {
200 		/* delete the public key */
201 		numattr = 0;
202 		kmf_set_attr_at_index(attrlist, numattr,
203 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
204 		numattr++;
205 
206 		kmf_set_attr_at_index(attrlist, numattr,
207 		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
208 		numattr++;
209 
210 		if (tokencred != NULL && tokencred->cred != NULL) {
211 			kmf_set_attr_at_index(attrlist, numattr,
212 			    KMF_CREDENTIAL_ATTR, tokencred,
213 			    sizeof (KMF_CREDENTIAL));
214 			numattr++;
215 		}
216 
217 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
218 		    attrlist);
219 
220 		/* delete the private key */
221 		numattr = 0;
222 		kmf_set_attr_at_index(attrlist, numattr,
223 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
224 		numattr++;
225 
226 		kmf_set_attr_at_index(attrlist, numattr,
227 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
228 		numattr++;
229 
230 		if (tokencred != NULL && tokencred->cred != NULL) {
231 			kmf_set_attr_at_index(attrlist, numattr,
232 			    KMF_CREDENTIAL_ATTR, tokencred,
233 			    sizeof (KMF_CREDENTIAL));
234 			numattr++;
235 		}
236 
237 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
238 		    attrlist);
239 	}
240 
241 	return (kmfrv);
242 }
243 
244 static int
245 gencert_file(KMF_HANDLE_T kmfhandle,
246 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
247 	int keylen, KMF_ENCODE_FORMAT fmt,
248 	uint32_t ltime, char *subject, char *altname,
249 	KMF_GENERALNAMECHOICES alttype, int altcrit,
250 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
251 	char *outcert, char *outkey,
252 	EKU_LIST *ekulist)
253 {
254 	KMF_RETURN kmfrv;
255 	KMF_KEY_HANDLE pubk, prik;
256 	KMF_X509_CERTIFICATE signedCert;
257 	KMF_X509_NAME	certSubject;
258 	KMF_X509_NAME	certIssuer;
259 	KMF_DATA x509DER;
260 	char *fullcertpath = NULL;
261 	char *fullkeypath = NULL;
262 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
263 	KMF_ATTRIBUTE attrlist[10];
264 	int numattr = 0;
265 
266 	(void) memset(&signedCert, 0, sizeof (signedCert));
267 	(void) memset(&certSubject, 0, sizeof (certSubject));
268 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
269 	(void) memset(&x509DER, 0, sizeof (x509DER));
270 
271 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
272 		cryptoerror(LOG_STDERR,
273 		    gettext("No output file was specified for "
274 		    "the cert or key\n"));
275 		return (PK_ERR_USAGE);
276 	}
277 	fullcertpath = strdup(outcert);
278 	if (verify_file(fullcertpath)) {
279 		cryptoerror(LOG_STDERR,
280 		    gettext("Cannot write the indicated output "
281 		    "certificate file (%s).\n"), fullcertpath);
282 		free(fullcertpath);
283 		return (PK_ERR_USAGE);
284 	}
285 
286 	/* If the subject name cannot be parsed, flag it now and exit */
287 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
288 		cryptoerror(LOG_STDERR,
289 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
290 		return (PK_ERR_USAGE);
291 	}
292 
293 	/* For a self-signed cert, the issuser and subject are the same */
294 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
295 		cryptoerror(LOG_STDERR,
296 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
297 		kmf_free_dn(&certSubject);
298 		return (PK_ERR_USAGE);
299 	}
300 
301 	/*
302 	 * Share the "genkeypair" routine for creating the keypair.
303 	 */
304 	kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
305 	    fmt, outkey, &prik, &pubk);
306 	if (kmfrv != KMF_OK)
307 		return (kmfrv);
308 
309 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
310 	    "keypair");
311 
312 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
313 
314 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
315 	    "serial number");
316 
317 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
318 	    "validity time");
319 
320 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
321 	    "signature algorithm");
322 
323 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
324 	    "subject name");
325 
326 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
327 	    "issuer name");
328 
329 	if (altname != NULL)
330 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
331 		    alttype, altname), "subjectAltName");
332 
333 	if (kubits != 0)
334 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
335 		    "KeyUsage");
336 
337 	if (ekulist != NULL) {
338 		int i;
339 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
340 			SET_VALUE(kmf_add_cert_eku(&signedCert,
341 			    &ekulist->ekulist[i],
342 			    ekulist->critlist[i]), "Extended Key Usage");
343 		}
344 	}
345 	/*
346 	 * Construct attributes for the kmf_sign_cert operation.
347 	 */
348 	numattr = 0;
349 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
350 	    &kstype, sizeof (kstype));
351 	numattr++;
352 
353 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
354 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
355 	numattr++;
356 
357 	/* cert data that is to be signed */
358 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
359 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
360 	numattr++;
361 
362 	/* output buffer for the signed cert */
363 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
364 	    &x509DER, sizeof (KMF_DATA));
365 	numattr++;
366 
367 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
368 	    &sigAlg, sizeof (sigAlg));
369 	numattr++;
370 
371 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
372 	    KMF_OK) {
373 		goto cleanup;
374 	}
375 
376 	/*
377 	 * Store the cert in the DB.
378 	 */
379 	numattr = 0;
380 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
381 	    &kstype, sizeof (kstype));
382 	numattr++;
383 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
384 	    &x509DER, sizeof (KMF_DATA));
385 	numattr++;
386 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
387 	    fullcertpath, strlen(fullcertpath));
388 	numattr++;
389 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
390 	    &fmt, sizeof (fmt));
391 	numattr++;
392 
393 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
394 
395 cleanup:
396 	if (fullkeypath != NULL)
397 		free(fullkeypath);
398 	if (fullcertpath != NULL)
399 		free(fullcertpath);
400 
401 	kmf_free_data(&x509DER);
402 	kmf_free_dn(&certSubject);
403 	kmf_free_dn(&certIssuer);
404 	return (kmfrv);
405 }
406 
407 static KMF_RETURN
408 gencert_nss(KMF_HANDLE_T kmfhandle,
409 	char *token, char *subject, char *altname,
410 	KMF_GENERALNAMECHOICES alttype, int altcrit,
411 	char *nickname, char *dir, char *prefix,
412 	KMF_KEY_ALG keyAlg,
413 	KMF_ALGORITHM_INDEX sigAlg,
414 	int keylen, char *trust,
415 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
416 	int kucrit, KMF_CREDENTIAL *tokencred,
417 	EKU_LIST *ekulist, KMF_OID *curveoid)
418 {
419 	KMF_RETURN kmfrv;
420 	KMF_KEY_HANDLE pubk, prik;
421 	KMF_X509_CERTIFICATE signedCert;
422 	KMF_X509_NAME	certSubject;
423 	KMF_X509_NAME	certIssuer;
424 	KMF_DATA x509DER;
425 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
426 	KMF_ATTRIBUTE attrlist[16];
427 	int numattr = 0;
428 
429 	if (token == NULL)
430 		token = DEFAULT_NSS_TOKEN;
431 
432 	kmfrv = configure_nss(kmfhandle, dir, prefix);
433 	if (kmfrv != KMF_OK)
434 		return (kmfrv);
435 
436 	(void) memset(&signedCert, 0, sizeof (signedCert));
437 	(void) memset(&certSubject, 0, sizeof (certSubject));
438 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
439 	(void) memset(&x509DER, 0, sizeof (x509DER));
440 
441 	/* If the subject name cannot be parsed, flag it now and exit */
442 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
443 		cryptoerror(LOG_STDERR,
444 		    gettext("Subject name cannot be parsed.\n"));
445 		return (PK_ERR_USAGE);
446 	}
447 
448 	/* For a self-signed cert, the issuser and subject are the same */
449 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
450 		cryptoerror(LOG_STDERR,
451 		    gettext("Subject name cannot be parsed.\n"));
452 		return (PK_ERR_USAGE);
453 	}
454 
455 	kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
456 	    prefix, keyAlg, keylen, tokencred, curveoid,
457 	    &prik, &pubk);
458 	if (kmfrv != KMF_OK)
459 		return (kmfrv);
460 
461 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
462 	    "keypair");
463 
464 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
465 
466 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
467 	    "serial number");
468 
469 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
470 	    "validity time");
471 
472 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
473 	    "signature algorithm");
474 
475 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
476 	    "subject name");
477 
478 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
479 	    "issuer name");
480 
481 	if (altname != NULL)
482 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
483 		    alttype, altname), "subjectAltName");
484 
485 	if (kubits)
486 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
487 		    "subjectAltName");
488 
489 	if (ekulist != NULL) {
490 		int i;
491 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
492 			SET_VALUE(kmf_add_cert_eku(&signedCert,
493 			    &ekulist->ekulist[i],
494 			    ekulist->critlist[i]), "Extended Key Usage");
495 		}
496 	}
497 	/*
498 	 * Construct attributes for the kmf_sign_cert operation.
499 	 */
500 	numattr = 0;
501 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
502 	    &kstype, sizeof (kstype));
503 	numattr++;
504 
505 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
506 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
507 	numattr++;
508 
509 	/* cert data that is to be signed */
510 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
511 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
512 	numattr++;
513 
514 	/* output buffer for the signed cert */
515 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
516 	    &x509DER, sizeof (KMF_DATA));
517 	numattr++;
518 
519 	kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR,
520 	    &sigAlg, sizeof (sigAlg));
521 	numattr++;
522 
523 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
524 	    KMF_OK) {
525 		goto cleanup;
526 	}
527 
528 	/*
529 	 * Store the cert in the DB.
530 	 */
531 	numattr = 0;
532 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
533 	    &kstype, sizeof (kstype));
534 	numattr++;
535 
536 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
537 	    &x509DER, sizeof (KMF_DATA));
538 	numattr++;
539 
540 	if (nickname != NULL) {
541 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
542 		    nickname, strlen(nickname));
543 		numattr++;
544 	}
545 
546 	if (trust != NULL) {
547 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
548 		    trust, strlen(trust));
549 		numattr++;
550 	}
551 
552 	if (token != NULL) {
553 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
554 		    token, strlen(token));
555 		numattr++;
556 	}
557 
558 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
559 
560 cleanup:
561 	kmf_free_data(&x509DER);
562 	kmf_free_dn(&certSubject);
563 	kmf_free_dn(&certIssuer);
564 	return (kmfrv);
565 }
566 
567 int
568 pk_gencert(int argc, char *argv[])
569 {
570 	int rv;
571 	int opt;
572 	extern int	optind_av;
573 	extern char	*optarg_av;
574 	KMF_KEYSTORE_TYPE kstype = 0;
575 	char *subject = NULL;
576 	char *tokenname = NULL;
577 	char *dir = NULL;
578 	char *prefix = NULL;
579 	char *keytype = PK_DEFAULT_KEYTYPE;
580 	int keylen = PK_DEFAULT_KEYLENGTH;
581 	char *trust = NULL;
582 	char *lifetime = NULL;
583 	char *certlabel = NULL;
584 	char *outcert = NULL;
585 	char *outkey = NULL;
586 	char *format = NULL;
587 	char *serstr = NULL;
588 	char *altname = NULL;
589 	char *keyusagestr = NULL;
590 	char *ekustr = NULL;
591 	char *hashname = NULL;
592 	KMF_GENERALNAMECHOICES alttype = 0;
593 	KMF_BIGINT serial = { NULL, 0 };
594 	uint32_t ltime;
595 	KMF_HANDLE_T kmfhandle = NULL;
596 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
597 	KMF_KEY_ALG keyAlg = KMF_RSA;
598 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
599 	boolean_t interactive = B_FALSE;
600 	char *subname = NULL;
601 	KMF_CREDENTIAL tokencred = { NULL, 0 };
602 	uint16_t kubits = 0;
603 	int altcrit = 0, kucrit = 0;
604 	EKU_LIST *ekulist = NULL;
605 	KMF_OID *curveoid = NULL; /* ECC */
606 	KMF_OID *hashoid = NULL;
607 	int y_flag = 0;
608 
609 	while ((opt = getopt_av(argc, argv,
610 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
611 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
612 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
613 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)C:(curve)"
614 	    "E(listcurves)h:(hash)")) != EOF) {
615 
616 		if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
617 			return (PK_ERR_USAGE);
618 
619 		switch (opt) {
620 			case 'A':
621 				altname = optarg_av;
622 				break;
623 			case 'i':
624 				if (interactive || subject)
625 					return (PK_ERR_USAGE);
626 				else
627 					interactive = B_TRUE;
628 				break;
629 			case 'k':
630 				kstype = KS2Int(optarg_av);
631 				if (kstype == 0)
632 					return (PK_ERR_USAGE);
633 				break;
634 			case 's':
635 				if (interactive || subject)
636 					return (PK_ERR_USAGE);
637 				else
638 					subject = optarg_av;
639 				break;
640 			case 'l':
641 			case 'n':
642 				if (certlabel)
643 					return (PK_ERR_USAGE);
644 				certlabel = optarg_av;
645 				break;
646 			case 'T':
647 				if (tokenname)
648 					return (PK_ERR_USAGE);
649 				tokenname = optarg_av;
650 				break;
651 			case 'd':
652 				if (dir)
653 					return (PK_ERR_USAGE);
654 				dir = optarg_av;
655 				break;
656 			case 'p':
657 				if (prefix)
658 					return (PK_ERR_USAGE);
659 				prefix = optarg_av;
660 				break;
661 			case 't':
662 				keytype = optarg_av;
663 				break;
664 			case 'u':
665 				keyusagestr = optarg_av;
666 				break;
667 			case 'y':
668 				if (sscanf(optarg_av, "%d",
669 				    &keylen) != 1) {
670 					cryptoerror(LOG_STDERR,
671 					    gettext("key length must be"
672 					    "a numeric value (%s)\n"),
673 					    optarg_av);
674 					return (PK_ERR_USAGE);
675 				}
676 				y_flag++;
677 				break;
678 			case 'r':
679 				if (trust)
680 					return (PK_ERR_USAGE);
681 				trust = optarg_av;
682 				break;
683 			case 'L':
684 				if (lifetime)
685 					return (PK_ERR_USAGE);
686 				lifetime = optarg_av;
687 				break;
688 			case 'c':
689 				if (outcert)
690 					return (PK_ERR_USAGE);
691 				outcert = optarg_av;
692 				break;
693 			case 'K':
694 				if (outkey)
695 					return (PK_ERR_USAGE);
696 				outkey = optarg_av;
697 				break;
698 			case 'S':
699 				serstr = optarg_av;
700 				break;
701 			case 'F':
702 				if (format)
703 					return (PK_ERR_USAGE);
704 				format = optarg_av;
705 				break;
706 			case 'e':
707 				ekustr = optarg_av;
708 				break;
709 			case 'C':
710 				curveoid = ecc_name_to_oid(optarg_av);
711 				if (curveoid == NULL) {
712 					cryptoerror(LOG_STDERR,
713 					    gettext("Unrecognized ECC "
714 					    "curve.\n"));
715 					return (PK_ERR_USAGE);
716 				}
717 				break;
718 			case 'E':
719 				/*
720 				 * This argument is only to be used
721 				 * by itself, no other options should
722 				 * be present.
723 				 */
724 				if (argc != 2) {
725 					cryptoerror(LOG_STDERR,
726 					    gettext("listcurves has no other "
727 					    "options.\n"));
728 					return (PK_ERR_USAGE);
729 				}
730 				show_ecc_curves();
731 				return (0);
732 			case 'h':
733 				hashname = optarg_av;
734 				hashoid = ecc_name_to_oid(optarg_av);
735 				if (hashoid == NULL) {
736 					cryptoerror(LOG_STDERR,
737 					    gettext("Unrecognized hash.\n"));
738 					return (PK_ERR_USAGE);
739 				}
740 				break;
741 			default:
742 				return (PK_ERR_USAGE);
743 		}
744 	}
745 
746 	/* No additional args allowed. */
747 	argc -= optind_av;
748 	argv += optind_av;
749 	if (argc) {
750 		return (PK_ERR_USAGE);
751 	}
752 
753 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
754 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
755 		return (PK_ERR_USAGE);
756 	}
757 
758 	/* Assume keystore = PKCS#11 if not specified. */
759 	if (kstype == 0)
760 		kstype = KMF_KEYSTORE_PK11TOKEN;
761 
762 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
763 		if (interactive && EMPTYSTRING(certlabel)) {
764 			(void) get_certlabel(&certlabel);
765 		}
766 		/* It better not be empty now */
767 		if (EMPTYSTRING(certlabel)) {
768 			cryptoerror(LOG_STDERR, gettext("A label must be "
769 			    "specified to create a self-signed certificate."
770 			    "\n"));
771 			return (PK_ERR_USAGE);
772 		}
773 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
774 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
775 		    "be specified to create a self-signed certificate.\n"));
776 		return (PK_ERR_USAGE);
777 	}
778 
779 	DIR_OPTION_CHECK(kstype, dir);
780 
781 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
782 		cryptoerror(LOG_STDERR,
783 		    gettext("Error parsing format string (%s).\n"),
784 		    format);
785 		return (PK_ERR_USAGE);
786 	}
787 
788 	if (Str2Lifetime(lifetime, &ltime) != 0) {
789 		cryptoerror(LOG_STDERR,
790 		    gettext("Error parsing lifetime string\n"));
791 		return (PK_ERR_USAGE);
792 	}
793 
794 	if (Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg) != 0) {
795 		cryptoerror(LOG_STDERR,
796 		    gettext("Unsupported key/hash combination (%s/%s).\n"),
797 		    keytype, (hashname ? hashname : "none"));
798 		return (PK_ERR_USAGE);
799 	}
800 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
801 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
802 		    "valid for EC keytypes.\n"));
803 		return (PK_ERR_USAGE);
804 	}
805 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
806 		cryptoerror(LOG_STDERR, gettext("A curve must be "
807 		    "specifed when using EC keys.\n"));
808 		return (PK_ERR_USAGE);
809 	}
810 	/* Adjust default keylength for NSS and DSA */
811 	if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
812 		keylen = 1024;
813 
814 	/*
815 	 * Check the subject name.
816 	 * If interactive is true, get it now interactively.
817 	 */
818 	if (interactive) {
819 		subname = NULL;
820 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
821 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
822 			    "subject name interactively.\n"));
823 			return (PK_ERR_USAGE);
824 		}
825 		if (serstr == NULL) {
826 			(void) get_serial(&serstr);
827 		}
828 	} else {
829 		if (EMPTYSTRING(subject)) {
830 			cryptoerror(LOG_STDERR, gettext("A subject name or "
831 			    "-i must be specified to create a self-signed "
832 			    "certificate.\n"));
833 			return (PK_ERR_USAGE);
834 		} else {
835 			subname = strdup(subject);
836 			if (subname == NULL) {
837 				cryptoerror(LOG_STDERR,
838 				    gettext("Out of memory.\n"));
839 				return (PK_ERR_SYSTEM);
840 			}
841 		}
842 	}
843 
844 	if (serstr == NULL) {
845 		(void) fprintf(stderr, gettext("A serial number "
846 		    "must be specified as a hex number when creating"
847 		    " a self-signed certificate "
848 		    "(ex: serial=0x0102030405feedface)\n"));
849 		rv = PK_ERR_USAGE;
850 		goto end;
851 	} else {
852 		uchar_t *bytes = NULL;
853 		size_t bytelen;
854 
855 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
856 		if (rv != KMF_OK || bytes == NULL) {
857 			(void) fprintf(stderr, gettext("serial number "
858 			    "must be specified as a hex number "
859 			    "(ex: 0x0102030405ffeeddee)\n"));
860 			rv = PK_ERR_USAGE;
861 			goto end;
862 		}
863 		serial.val = bytes;
864 		serial.len = bytelen;
865 	}
866 
867 	if (altname != NULL) {
868 		rv = verify_altname(altname, &alttype, &altcrit);
869 		if (rv != KMF_OK) {
870 			(void) fprintf(stderr, gettext("Subject AltName "
871 			    "must be specified as a name=value pair. "
872 			    "See the man page for details.\n"));
873 			rv = PK_ERR_USAGE;
874 			goto end;
875 		} else {
876 			/* advance the altname past the '=' sign */
877 			char *p = strchr(altname, '=');
878 			if (p != NULL)
879 				altname = p + 1;
880 		}
881 	}
882 
883 	if (keyusagestr != NULL) {
884 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
885 		if (rv != KMF_OK) {
886 			(void) fprintf(stderr, gettext("KeyUsage "
887 			    "must be specified as a comma-separated list. "
888 			    "See the man page for details.\n"));
889 			rv = PK_ERR_USAGE;
890 			goto end;
891 		}
892 	}
893 	if (ekustr != NULL) {
894 		rv = verify_ekunames(ekustr, &ekulist);
895 		if (rv != KMF_OK) {
896 			(void) fprintf(stderr, gettext("EKUs must "
897 			    "be specified as a comma-separated list. "
898 			    "See the man page for details.\n"));
899 			rv = PK_ERR_USAGE;
900 			goto end;
901 		}
902 	}
903 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
904 		(void) fprintf(stderr, gettext("ECC certificates are"
905 		    "only supported with the pkcs11 and nss keystores\n"));
906 		rv = PK_ERR_USAGE;
907 		goto end;
908 	}
909 
910 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
911 		if (tokenname == NULL || !strlen(tokenname)) {
912 			if (kstype == KMF_KEYSTORE_NSS) {
913 				tokenname = "internal";
914 			} else  {
915 				tokenname = PK_DEFAULT_PK11TOKEN;
916 			}
917 		}
918 
919 		(void) get_token_password(kstype, tokenname, &tokencred);
920 	}
921 
922 	if (kstype == KMF_KEYSTORE_NSS) {
923 		if (dir == NULL)
924 			dir = PK_DEFAULT_DIRECTORY;
925 
926 		rv = gencert_nss(kmfhandle,
927 		    tokenname, subname, altname, alttype, altcrit,
928 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
929 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
930 		    ekulist, curveoid);
931 
932 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
933 		rv = gencert_pkcs11(kmfhandle,
934 		    tokenname, subname, altname, alttype, altcrit,
935 		    certlabel, keyAlg, sigAlg, keylen, ltime,
936 		    &serial, kubits, kucrit, &tokencred, ekulist,
937 		    curveoid);
938 
939 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
940 		rv = gencert_file(kmfhandle,
941 		    keyAlg, sigAlg, keylen, fmt,
942 		    ltime, subname, altname, alttype, altcrit,
943 		    &serial, kubits, kucrit, outcert, outkey,
944 		    ekulist);
945 	}
946 
947 	if (rv != KMF_OK)
948 		display_error(kmfhandle, rv,
949 		    gettext("Error creating certificate and keypair"));
950 end:
951 	if (ekulist != NULL)
952 		free_eku_list(ekulist);
953 	if (subname)
954 		free(subname);
955 	if (tokencred.cred != NULL)
956 		free(tokencred.cred);
957 
958 	if (serial.val != NULL)
959 		free(serial.val);
960 
961 	(void) kmf_finalize(kmfhandle);
962 	return (rv);
963 }
964