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