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