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