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