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