gencert.c revision 6051:7b29d160facb
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
49static int
50gencert_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
228cleanup:
229	kmf_free_data(&x509DER);
230	kmf_free_dn(&certSubject);
231	kmf_free_dn(&certIssuer);
232	return (kmfrv);
233}
234
235static int
236gencert_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
453cleanup:
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
465static KMF_RETURN
466gencert_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
664cleanup:
665	kmf_free_data(&x509DER);
666	kmf_free_dn(&certSubject);
667	kmf_free_dn(&certIssuer);
668	return (kmfrv);
669}
670
671int
672pk_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"));
993end:
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