xref: /titanic_41/usr/src/cmd/cmd-crypto/pktool/genkeypair.c (revision 1aa8defbaa9c395fdce1fa3a2ae1892b684dfa4f)
1*e65e5c2dSWyllys Ingersoll /*
2*e65e5c2dSWyllys Ingersoll  * CDDL HEADER START
3*e65e5c2dSWyllys Ingersoll  *
4*e65e5c2dSWyllys Ingersoll  * The contents of this file are subject to the terms of the
5*e65e5c2dSWyllys Ingersoll  * Common Development and Distribution License (the "License").
6*e65e5c2dSWyllys Ingersoll  * You may not use this file except in compliance with the License.
7*e65e5c2dSWyllys Ingersoll  *
8*e65e5c2dSWyllys Ingersoll  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*e65e5c2dSWyllys Ingersoll  * or http://www.opensolaris.org/os/licensing.
10*e65e5c2dSWyllys Ingersoll  * See the License for the specific language governing permissions
11*e65e5c2dSWyllys Ingersoll  * and limitations under the License.
12*e65e5c2dSWyllys Ingersoll  *
13*e65e5c2dSWyllys Ingersoll  * When distributing Covered Code, include this CDDL HEADER in each
14*e65e5c2dSWyllys Ingersoll  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*e65e5c2dSWyllys Ingersoll  * If applicable, add the following below this CDDL HEADER, with the
16*e65e5c2dSWyllys Ingersoll  * fields enclosed by brackets "[]" replaced with your own identifying
17*e65e5c2dSWyllys Ingersoll  * information: Portions Copyright [yyyy] [name of copyright owner]
18*e65e5c2dSWyllys Ingersoll  *
19*e65e5c2dSWyllys Ingersoll  * CDDL HEADER END
20*e65e5c2dSWyllys Ingersoll  */
21*e65e5c2dSWyllys Ingersoll /*
22*e65e5c2dSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*e65e5c2dSWyllys Ingersoll  * Use is subject to license terms.
24*e65e5c2dSWyllys Ingersoll  */
25*e65e5c2dSWyllys Ingersoll 
26*e65e5c2dSWyllys Ingersoll #include <stdio.h>
27*e65e5c2dSWyllys Ingersoll #include <string.h>
28*e65e5c2dSWyllys Ingersoll #include <ctype.h>
29*e65e5c2dSWyllys Ingersoll #include <malloc.h>
30*e65e5c2dSWyllys Ingersoll #include <libgen.h>
31*e65e5c2dSWyllys Ingersoll #include <errno.h>
32*e65e5c2dSWyllys Ingersoll #include <cryptoutil.h>
33*e65e5c2dSWyllys Ingersoll #include <security/cryptoki.h>
34*e65e5c2dSWyllys Ingersoll #include "common.h"
35*e65e5c2dSWyllys Ingersoll 
36*e65e5c2dSWyllys Ingersoll #include <kmfapi.h>
37*e65e5c2dSWyllys Ingersoll 
38*e65e5c2dSWyllys Ingersoll #define	SET_VALUE(f, s) \
39*e65e5c2dSWyllys Ingersoll 	kmfrv = f; \
40*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK) { \
41*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, \
42*e65e5c2dSWyllys Ingersoll 			gettext("Failed to set %s: 0x%02x\n"), \
43*e65e5c2dSWyllys Ingersoll 			s, kmfrv); \
44*e65e5c2dSWyllys Ingersoll 		goto cleanup; \
45*e65e5c2dSWyllys Ingersoll 	}
46*e65e5c2dSWyllys Ingersoll 
47*e65e5c2dSWyllys Ingersoll KMF_RETURN
genkeypair_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * keylabel,KMF_KEY_ALG keyAlg,int keylen,KMF_CREDENTIAL * tokencred,KMF_OID * curveoid,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)48*e65e5c2dSWyllys Ingersoll genkeypair_pkcs11(KMF_HANDLE_T kmfhandle,
49*e65e5c2dSWyllys Ingersoll 	char *token, char *keylabel, KMF_KEY_ALG keyAlg,
50*e65e5c2dSWyllys Ingersoll 	int keylen, KMF_CREDENTIAL *tokencred, KMF_OID *curveoid,
51*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
52*e65e5c2dSWyllys Ingersoll {
53*e65e5c2dSWyllys Ingersoll 	KMF_RETURN kmfrv = KMF_OK;
54*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE pubk, prik;
55*e65e5c2dSWyllys Ingersoll 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
56*e65e5c2dSWyllys Ingersoll 	KMF_ATTRIBUTE attrlist[16];
57*e65e5c2dSWyllys Ingersoll 	int numattr = 0;
58*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keytype;
59*e65e5c2dSWyllys Ingersoll 	uint32_t keylength;
60*e65e5c2dSWyllys Ingersoll 
61*e65e5c2dSWyllys Ingersoll 	keylength = keylen; /* bits */
62*e65e5c2dSWyllys Ingersoll 	keytype = keyAlg;
63*e65e5c2dSWyllys Ingersoll 
64*e65e5c2dSWyllys Ingersoll 	/* Select a PKCS11 token */
65*e65e5c2dSWyllys Ingersoll 	kmfrv = select_token(kmfhandle, token, FALSE);
66*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
67*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
68*e65e5c2dSWyllys Ingersoll 
69*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
70*e65e5c2dSWyllys Ingersoll 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
71*e65e5c2dSWyllys Ingersoll 	    sizeof (kstype));
72*e65e5c2dSWyllys Ingersoll 	numattr++;
73*e65e5c2dSWyllys Ingersoll 
74*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
75*e65e5c2dSWyllys Ingersoll 	    KMF_KEYALG_ATTR, &keytype,
76*e65e5c2dSWyllys Ingersoll 	    sizeof (keytype));
77*e65e5c2dSWyllys Ingersoll 	numattr++;
78*e65e5c2dSWyllys Ingersoll 
79*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
80*e65e5c2dSWyllys Ingersoll 	    KMF_KEYLENGTH_ATTR, &keylength,
81*e65e5c2dSWyllys Ingersoll 	    sizeof (keylength));
82*e65e5c2dSWyllys Ingersoll 	numattr++;
83*e65e5c2dSWyllys Ingersoll 
84*e65e5c2dSWyllys Ingersoll 	if (keylabel != NULL) {
85*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
86*e65e5c2dSWyllys Ingersoll 		    KMF_KEYLABEL_ATTR, keylabel,
87*e65e5c2dSWyllys Ingersoll 		    strlen(keylabel));
88*e65e5c2dSWyllys Ingersoll 		numattr++;
89*e65e5c2dSWyllys Ingersoll 	}
90*e65e5c2dSWyllys Ingersoll 
91*e65e5c2dSWyllys Ingersoll 	if (tokencred != NULL && tokencred->cred != NULL) {
92*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
93*e65e5c2dSWyllys Ingersoll 		    KMF_CREDENTIAL_ATTR, tokencred,
94*e65e5c2dSWyllys Ingersoll 		    sizeof (KMF_CREDENTIAL));
95*e65e5c2dSWyllys Ingersoll 		numattr++;
96*e65e5c2dSWyllys Ingersoll 	}
97*e65e5c2dSWyllys Ingersoll 
98*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
99*e65e5c2dSWyllys Ingersoll 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
100*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
101*e65e5c2dSWyllys Ingersoll 	numattr++;
102*e65e5c2dSWyllys Ingersoll 
103*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
104*e65e5c2dSWyllys Ingersoll 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
105*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
106*e65e5c2dSWyllys Ingersoll 	numattr++;
107*e65e5c2dSWyllys Ingersoll 
108*e65e5c2dSWyllys Ingersoll 	if (keytype == KMF_ECDSA && curveoid != NULL) {
109*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
110*e65e5c2dSWyllys Ingersoll 		    KMF_ECC_CURVE_OID_ATTR, curveoid,
111*e65e5c2dSWyllys Ingersoll 		    sizeof (KMF_OID));
112*e65e5c2dSWyllys Ingersoll 		numattr++;
113*e65e5c2dSWyllys Ingersoll 	}
114*e65e5c2dSWyllys Ingersoll 
115*e65e5c2dSWyllys Ingersoll 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
116*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK) {
117*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
118*e65e5c2dSWyllys Ingersoll 	}
119*e65e5c2dSWyllys Ingersoll 
120*e65e5c2dSWyllys Ingersoll cleanup:
121*e65e5c2dSWyllys Ingersoll 	if (kmfrv == KMF_OK) {
122*e65e5c2dSWyllys Ingersoll 		if (outPriKey != NULL)
123*e65e5c2dSWyllys Ingersoll 			*outPriKey = prik;
124*e65e5c2dSWyllys Ingersoll 		if (outPubKey != NULL)
125*e65e5c2dSWyllys Ingersoll 			*outPubKey = pubk;
126*e65e5c2dSWyllys Ingersoll 	}
127*e65e5c2dSWyllys Ingersoll 
128*e65e5c2dSWyllys Ingersoll 	return (kmfrv);
129*e65e5c2dSWyllys Ingersoll }
130*e65e5c2dSWyllys Ingersoll 
131*e65e5c2dSWyllys Ingersoll KMF_RETURN
genkeypair_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,int keylen,KMF_ENCODE_FORMAT fmt,char * outkey,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)132*e65e5c2dSWyllys Ingersoll genkeypair_file(KMF_HANDLE_T kmfhandle,
133*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keyAlg, int keylen, KMF_ENCODE_FORMAT fmt,
134*e65e5c2dSWyllys Ingersoll 	char *outkey,
135*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
136*e65e5c2dSWyllys Ingersoll {
137*e65e5c2dSWyllys Ingersoll 	KMF_RETURN kmfrv;
138*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE pubk, prik;
139*e65e5c2dSWyllys Ingersoll 	char *fullkeypath = NULL;
140*e65e5c2dSWyllys Ingersoll 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
141*e65e5c2dSWyllys Ingersoll 	KMF_ATTRIBUTE attrlist[10];
142*e65e5c2dSWyllys Ingersoll 	int numattr = 0;
143*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keytype;
144*e65e5c2dSWyllys Ingersoll 	uint32_t keylength;
145*e65e5c2dSWyllys Ingersoll 	KMF_ENCODE_FORMAT format;
146*e65e5c2dSWyllys Ingersoll 
147*e65e5c2dSWyllys Ingersoll 	if (EMPTYSTRING(outkey)) {
148*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR,
149*e65e5c2dSWyllys Ingersoll 		    gettext("No output file was specified for "
150*e65e5c2dSWyllys Ingersoll 		    "the key\n"));
151*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
152*e65e5c2dSWyllys Ingersoll 	}
153*e65e5c2dSWyllys Ingersoll 
154*e65e5c2dSWyllys Ingersoll 	fullkeypath = strdup(outkey);
155*e65e5c2dSWyllys Ingersoll 	if (verify_file(fullkeypath)) {
156*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR,
157*e65e5c2dSWyllys Ingersoll 		    gettext("Cannot write the indicated output "
158*e65e5c2dSWyllys Ingersoll 		    "key file (%s).\n"), fullkeypath);
159*e65e5c2dSWyllys Ingersoll 		free(fullkeypath);
160*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
161*e65e5c2dSWyllys Ingersoll 	}
162*e65e5c2dSWyllys Ingersoll 
163*e65e5c2dSWyllys Ingersoll 	keylength = keylen; /* bits */
164*e65e5c2dSWyllys Ingersoll 	keytype = keyAlg;
165*e65e5c2dSWyllys Ingersoll 	format = fmt;
166*e65e5c2dSWyllys Ingersoll 
167*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
168*e65e5c2dSWyllys Ingersoll 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
169*e65e5c2dSWyllys Ingersoll 	    sizeof (kstype));
170*e65e5c2dSWyllys Ingersoll 	numattr++;
171*e65e5c2dSWyllys Ingersoll 
172*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
173*e65e5c2dSWyllys Ingersoll 	    KMF_KEYALG_ATTR, &keytype,
174*e65e5c2dSWyllys Ingersoll 	    sizeof (keytype));
175*e65e5c2dSWyllys Ingersoll 	numattr++;
176*e65e5c2dSWyllys Ingersoll 
177*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
178*e65e5c2dSWyllys Ingersoll 	    KMF_KEYLENGTH_ATTR, &keylength,
179*e65e5c2dSWyllys Ingersoll 	    sizeof (keylength));
180*e65e5c2dSWyllys Ingersoll 	numattr++;
181*e65e5c2dSWyllys Ingersoll 
182*e65e5c2dSWyllys Ingersoll 	if (fullkeypath != NULL) {
183*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
184*e65e5c2dSWyllys Ingersoll 		    KMF_KEY_FILENAME_ATTR, fullkeypath,
185*e65e5c2dSWyllys Ingersoll 		    strlen(fullkeypath));
186*e65e5c2dSWyllys Ingersoll 		numattr++;
187*e65e5c2dSWyllys Ingersoll 	}
188*e65e5c2dSWyllys Ingersoll 
189*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
190*e65e5c2dSWyllys Ingersoll 	    KMF_ENCODE_FORMAT_ATTR, &format,
191*e65e5c2dSWyllys Ingersoll 	    sizeof (format));
192*e65e5c2dSWyllys Ingersoll 	numattr++;
193*e65e5c2dSWyllys Ingersoll 
194*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
195*e65e5c2dSWyllys Ingersoll 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
196*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
197*e65e5c2dSWyllys Ingersoll 	numattr++;
198*e65e5c2dSWyllys Ingersoll 
199*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
200*e65e5c2dSWyllys Ingersoll 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
201*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
202*e65e5c2dSWyllys Ingersoll 	numattr++;
203*e65e5c2dSWyllys Ingersoll 
204*e65e5c2dSWyllys Ingersoll 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
205*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK) {
206*e65e5c2dSWyllys Ingersoll 		goto cleanup;
207*e65e5c2dSWyllys Ingersoll 	}
208*e65e5c2dSWyllys Ingersoll 
209*e65e5c2dSWyllys Ingersoll cleanup:
210*e65e5c2dSWyllys Ingersoll 	if (fullkeypath != NULL)
211*e65e5c2dSWyllys Ingersoll 		free(fullkeypath);
212*e65e5c2dSWyllys Ingersoll 
213*e65e5c2dSWyllys Ingersoll 	if (kmfrv == KMF_OK) {
214*e65e5c2dSWyllys Ingersoll 		if (outPriKey != NULL)
215*e65e5c2dSWyllys Ingersoll 			*outPriKey = prik;
216*e65e5c2dSWyllys Ingersoll 		if (outPubKey != NULL)
217*e65e5c2dSWyllys Ingersoll 			*outPubKey = pubk;
218*e65e5c2dSWyllys Ingersoll 	}
219*e65e5c2dSWyllys Ingersoll 
220*e65e5c2dSWyllys Ingersoll 	return (kmfrv);
221*e65e5c2dSWyllys Ingersoll }
222*e65e5c2dSWyllys Ingersoll 
223*e65e5c2dSWyllys Ingersoll KMF_RETURN
genkeypair_nss(KMF_HANDLE_T kmfhandle,char * token,char * nickname,char * dir,char * prefix,KMF_KEY_ALG keyAlg,int keylen,KMF_CREDENTIAL * tokencred,KMF_OID * curveoid,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)224*e65e5c2dSWyllys Ingersoll genkeypair_nss(KMF_HANDLE_T kmfhandle,
225*e65e5c2dSWyllys Ingersoll 	char *token,
226*e65e5c2dSWyllys Ingersoll 	char *nickname, char *dir, char *prefix,
227*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keyAlg,
228*e65e5c2dSWyllys Ingersoll 	int keylen, KMF_CREDENTIAL *tokencred,
229*e65e5c2dSWyllys Ingersoll 	KMF_OID *curveoid,
230*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
231*e65e5c2dSWyllys Ingersoll {
232*e65e5c2dSWyllys Ingersoll 	KMF_RETURN kmfrv;
233*e65e5c2dSWyllys Ingersoll 	KMF_KEY_HANDLE pubk, prik;
234*e65e5c2dSWyllys Ingersoll 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
235*e65e5c2dSWyllys Ingersoll 	KMF_ATTRIBUTE attrlist[16];
236*e65e5c2dSWyllys Ingersoll 	int numattr = 0;
237*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keytype;
238*e65e5c2dSWyllys Ingersoll 	uint32_t keylength;
239*e65e5c2dSWyllys Ingersoll 
240*e65e5c2dSWyllys Ingersoll 	if (token == NULL)
241*e65e5c2dSWyllys Ingersoll 		token = DEFAULT_NSS_TOKEN;
242*e65e5c2dSWyllys Ingersoll 
243*e65e5c2dSWyllys Ingersoll 	kmfrv = configure_nss(kmfhandle, dir, prefix);
244*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK)
245*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
246*e65e5c2dSWyllys Ingersoll 
247*e65e5c2dSWyllys Ingersoll 	keylength = keylen; /* bits */
248*e65e5c2dSWyllys Ingersoll 	keytype = keyAlg;
249*e65e5c2dSWyllys Ingersoll 
250*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
251*e65e5c2dSWyllys Ingersoll 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
252*e65e5c2dSWyllys Ingersoll 	    sizeof (kstype));
253*e65e5c2dSWyllys Ingersoll 	numattr++;
254*e65e5c2dSWyllys Ingersoll 
255*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
256*e65e5c2dSWyllys Ingersoll 	    KMF_KEYALG_ATTR, &keytype,
257*e65e5c2dSWyllys Ingersoll 	    sizeof (keytype));
258*e65e5c2dSWyllys Ingersoll 	numattr++;
259*e65e5c2dSWyllys Ingersoll 
260*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
261*e65e5c2dSWyllys Ingersoll 	    KMF_KEYLENGTH_ATTR, &keylength,
262*e65e5c2dSWyllys Ingersoll 	    sizeof (keylength));
263*e65e5c2dSWyllys Ingersoll 	numattr++;
264*e65e5c2dSWyllys Ingersoll 
265*e65e5c2dSWyllys Ingersoll 	if (nickname != NULL) {
266*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
267*e65e5c2dSWyllys Ingersoll 		    KMF_KEYLABEL_ATTR, nickname,
268*e65e5c2dSWyllys Ingersoll 		    strlen(nickname));
269*e65e5c2dSWyllys Ingersoll 		numattr++;
270*e65e5c2dSWyllys Ingersoll 	}
271*e65e5c2dSWyllys Ingersoll 
272*e65e5c2dSWyllys Ingersoll 	if (tokencred != NULL && tokencred->cred != NULL) {
273*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
274*e65e5c2dSWyllys Ingersoll 		    KMF_CREDENTIAL_ATTR, tokencred,
275*e65e5c2dSWyllys Ingersoll 		    sizeof (KMF_CREDENTIAL));
276*e65e5c2dSWyllys Ingersoll 		numattr++;
277*e65e5c2dSWyllys Ingersoll 	}
278*e65e5c2dSWyllys Ingersoll 
279*e65e5c2dSWyllys Ingersoll 	if (token != NULL) {
280*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
281*e65e5c2dSWyllys Ingersoll 		    KMF_TOKEN_LABEL_ATTR, token,
282*e65e5c2dSWyllys Ingersoll 		    strlen(token));
283*e65e5c2dSWyllys Ingersoll 		numattr++;
284*e65e5c2dSWyllys Ingersoll 	}
285*e65e5c2dSWyllys Ingersoll 
286*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
287*e65e5c2dSWyllys Ingersoll 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
288*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
289*e65e5c2dSWyllys Ingersoll 	numattr++;
290*e65e5c2dSWyllys Ingersoll 
291*e65e5c2dSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr,
292*e65e5c2dSWyllys Ingersoll 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
293*e65e5c2dSWyllys Ingersoll 	    sizeof (KMF_KEY_HANDLE));
294*e65e5c2dSWyllys Ingersoll 	numattr++;
295*e65e5c2dSWyllys Ingersoll 
296*e65e5c2dSWyllys Ingersoll 	if (keytype == KMF_ECDSA && curveoid != NULL) {
297*e65e5c2dSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr,
298*e65e5c2dSWyllys Ingersoll 		    KMF_ECC_CURVE_OID_ATTR, curveoid,
299*e65e5c2dSWyllys Ingersoll 		    sizeof (KMF_OID));
300*e65e5c2dSWyllys Ingersoll 		numattr++;
301*e65e5c2dSWyllys Ingersoll 	}
302*e65e5c2dSWyllys Ingersoll 
303*e65e5c2dSWyllys Ingersoll 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
304*e65e5c2dSWyllys Ingersoll 	if (kmfrv != KMF_OK) {
305*e65e5c2dSWyllys Ingersoll 		return (kmfrv);
306*e65e5c2dSWyllys Ingersoll 	}
307*e65e5c2dSWyllys Ingersoll cleanup:
308*e65e5c2dSWyllys Ingersoll 	if (kmfrv == KMF_OK) {
309*e65e5c2dSWyllys Ingersoll 		if (outPriKey != NULL)
310*e65e5c2dSWyllys Ingersoll 			*outPriKey = prik;
311*e65e5c2dSWyllys Ingersoll 		if (outPubKey != NULL)
312*e65e5c2dSWyllys Ingersoll 			*outPubKey = pubk;
313*e65e5c2dSWyllys Ingersoll 	}
314*e65e5c2dSWyllys Ingersoll 	return (kmfrv);
315*e65e5c2dSWyllys Ingersoll }
316*e65e5c2dSWyllys Ingersoll 
317*e65e5c2dSWyllys Ingersoll int
pk_genkeypair(int argc,char * argv[])318*e65e5c2dSWyllys Ingersoll pk_genkeypair(int argc, char *argv[])
319*e65e5c2dSWyllys Ingersoll {
320*e65e5c2dSWyllys Ingersoll 	int rv;
321*e65e5c2dSWyllys Ingersoll 	int opt;
322*e65e5c2dSWyllys Ingersoll 	extern int	optind_av;
323*e65e5c2dSWyllys Ingersoll 	extern char	*optarg_av;
324*e65e5c2dSWyllys Ingersoll 	KMF_KEYSTORE_TYPE kstype = 0;
325*e65e5c2dSWyllys Ingersoll 	char *tokenname = NULL;
326*e65e5c2dSWyllys Ingersoll 	char *dir = NULL;
327*e65e5c2dSWyllys Ingersoll 	char *prefix = NULL;
328*e65e5c2dSWyllys Ingersoll 	char *keytype = PK_DEFAULT_KEYTYPE;
329*e65e5c2dSWyllys Ingersoll 	int keylen = PK_DEFAULT_KEYLENGTH;
330*e65e5c2dSWyllys Ingersoll 	char *label = NULL;
331*e65e5c2dSWyllys Ingersoll 	char *outkey = NULL;
332*e65e5c2dSWyllys Ingersoll 	char *format = NULL;
333*e65e5c2dSWyllys Ingersoll 	KMF_HANDLE_T kmfhandle = NULL;
334*e65e5c2dSWyllys Ingersoll 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
335*e65e5c2dSWyllys Ingersoll 	KMF_KEY_ALG keyAlg = KMF_RSA;
336*e65e5c2dSWyllys Ingersoll 	KMF_ALGORITHM_INDEX sigAlg;
337*e65e5c2dSWyllys Ingersoll 	KMF_CREDENTIAL tokencred = { NULL, 0 };
338*e65e5c2dSWyllys Ingersoll 	KMF_OID *curveoid = NULL; /* ECC */
339*e65e5c2dSWyllys Ingersoll 	int y_flag = 0;
340*e65e5c2dSWyllys Ingersoll 
341*e65e5c2dSWyllys Ingersoll 	while ((opt = getopt_av(argc, argv,
342*e65e5c2dSWyllys Ingersoll 	    "k:(keystore)s:(subject)n:(nickname)"
343*e65e5c2dSWyllys Ingersoll 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
344*e65e5c2dSWyllys Ingersoll 	    "l:(label)K:(outkey)F:(format)C:(curve)"
345*e65e5c2dSWyllys Ingersoll 	    "E(listcurves)")) != EOF) {
346*e65e5c2dSWyllys Ingersoll 
347*e65e5c2dSWyllys Ingersoll 		if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
348*e65e5c2dSWyllys Ingersoll 			return (PK_ERR_USAGE);
349*e65e5c2dSWyllys Ingersoll 
350*e65e5c2dSWyllys Ingersoll 		switch (opt) {
351*e65e5c2dSWyllys Ingersoll 			case 'k':
352*e65e5c2dSWyllys Ingersoll 				kstype = KS2Int(optarg_av);
353*e65e5c2dSWyllys Ingersoll 				if (kstype == 0)
354*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
355*e65e5c2dSWyllys Ingersoll 				break;
356*e65e5c2dSWyllys Ingersoll 			case 'l':
357*e65e5c2dSWyllys Ingersoll 			case 'n':
358*e65e5c2dSWyllys Ingersoll 				if (label)
359*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
360*e65e5c2dSWyllys Ingersoll 				label = optarg_av;
361*e65e5c2dSWyllys Ingersoll 				break;
362*e65e5c2dSWyllys Ingersoll 			case 'T':
363*e65e5c2dSWyllys Ingersoll 				if (tokenname)
364*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
365*e65e5c2dSWyllys Ingersoll 				tokenname = optarg_av;
366*e65e5c2dSWyllys Ingersoll 				break;
367*e65e5c2dSWyllys Ingersoll 			case 'd':
368*e65e5c2dSWyllys Ingersoll 				if (dir)
369*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
370*e65e5c2dSWyllys Ingersoll 				dir = optarg_av;
371*e65e5c2dSWyllys Ingersoll 				break;
372*e65e5c2dSWyllys Ingersoll 			case 'p':
373*e65e5c2dSWyllys Ingersoll 				if (prefix)
374*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
375*e65e5c2dSWyllys Ingersoll 				prefix = optarg_av;
376*e65e5c2dSWyllys Ingersoll 				break;
377*e65e5c2dSWyllys Ingersoll 			case 't':
378*e65e5c2dSWyllys Ingersoll 				keytype = optarg_av;
379*e65e5c2dSWyllys Ingersoll 				break;
380*e65e5c2dSWyllys Ingersoll 			case 'y':
381*e65e5c2dSWyllys Ingersoll 				if (sscanf(optarg_av, "%d",
382*e65e5c2dSWyllys Ingersoll 				    &keylen) != 1) {
383*e65e5c2dSWyllys Ingersoll 					cryptoerror(LOG_STDERR,
384*e65e5c2dSWyllys Ingersoll 					    gettext("key length must be"
385*e65e5c2dSWyllys Ingersoll 					    "a numeric value (%s)\n"),
386*e65e5c2dSWyllys Ingersoll 					    optarg_av);
387*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
388*e65e5c2dSWyllys Ingersoll 				}
389*e65e5c2dSWyllys Ingersoll 				y_flag++;
390*e65e5c2dSWyllys Ingersoll 				break;
391*e65e5c2dSWyllys Ingersoll 			case 'K':
392*e65e5c2dSWyllys Ingersoll 				if (outkey)
393*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
394*e65e5c2dSWyllys Ingersoll 				outkey = optarg_av;
395*e65e5c2dSWyllys Ingersoll 				break;
396*e65e5c2dSWyllys Ingersoll 			case 'F':
397*e65e5c2dSWyllys Ingersoll 				if (format)
398*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
399*e65e5c2dSWyllys Ingersoll 				format = optarg_av;
400*e65e5c2dSWyllys Ingersoll 				break;
401*e65e5c2dSWyllys Ingersoll 			case 'C':
402*e65e5c2dSWyllys Ingersoll 				curveoid = ecc_name_to_oid(optarg_av);
403*e65e5c2dSWyllys Ingersoll 				if (curveoid == NULL) {
404*e65e5c2dSWyllys Ingersoll 					cryptoerror(LOG_STDERR,
405*e65e5c2dSWyllys Ingersoll 					    gettext(
406*e65e5c2dSWyllys Ingersoll 					    "Unrecognized ECC curve.\n"));
407*e65e5c2dSWyllys Ingersoll 					return (PK_ERR_USAGE);
408*e65e5c2dSWyllys Ingersoll 				}
409*e65e5c2dSWyllys Ingersoll 				break;
410*e65e5c2dSWyllys Ingersoll 			case 'E':
411*e65e5c2dSWyllys Ingersoll 				show_ecc_curves();
412*e65e5c2dSWyllys Ingersoll 				return (0);
413*e65e5c2dSWyllys Ingersoll 			default:
414*e65e5c2dSWyllys Ingersoll 				return (PK_ERR_USAGE);
415*e65e5c2dSWyllys Ingersoll 		}
416*e65e5c2dSWyllys Ingersoll 	}
417*e65e5c2dSWyllys Ingersoll 
418*e65e5c2dSWyllys Ingersoll 	/* No additional args allowed. */
419*e65e5c2dSWyllys Ingersoll 	argc -= optind_av;
420*e65e5c2dSWyllys Ingersoll 	argv += optind_av;
421*e65e5c2dSWyllys Ingersoll 	if (argc) {
422*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
423*e65e5c2dSWyllys Ingersoll 	}
424*e65e5c2dSWyllys Ingersoll 
425*e65e5c2dSWyllys Ingersoll 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
426*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
427*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
428*e65e5c2dSWyllys Ingersoll 	}
429*e65e5c2dSWyllys Ingersoll 
430*e65e5c2dSWyllys Ingersoll 	/* Assume keystore = PKCS#11 if not specified. */
431*e65e5c2dSWyllys Ingersoll 	if (kstype == 0)
432*e65e5c2dSWyllys Ingersoll 		kstype = KMF_KEYSTORE_PK11TOKEN;
433*e65e5c2dSWyllys Ingersoll 
434*e65e5c2dSWyllys Ingersoll 	DIR_OPTION_CHECK(kstype, dir);
435*e65e5c2dSWyllys Ingersoll 
436*e65e5c2dSWyllys Ingersoll 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
437*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR,
438*e65e5c2dSWyllys Ingersoll 		    gettext("Error parsing format string (%s).\n"),
439*e65e5c2dSWyllys Ingersoll 		    format);
440*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
441*e65e5c2dSWyllys Ingersoll 	}
442*e65e5c2dSWyllys Ingersoll 
443*e65e5c2dSWyllys Ingersoll 	if (Str2KeyType(keytype, NULL, &keyAlg, &sigAlg) != 0) {
444*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
445*e65e5c2dSWyllys Ingersoll 		    keytype);
446*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
447*e65e5c2dSWyllys Ingersoll 	}
448*e65e5c2dSWyllys Ingersoll 	if (curveoid != NULL && keyAlg != KMF_ECDSA) {
449*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("EC curves are only "
450*e65e5c2dSWyllys Ingersoll 		    "valid for EC keytypes.\n"));
451*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
452*e65e5c2dSWyllys Ingersoll 	}
453*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_ECDSA && curveoid == NULL) {
454*e65e5c2dSWyllys Ingersoll 		cryptoerror(LOG_STDERR, gettext("A curve must be "
455*e65e5c2dSWyllys Ingersoll 		    "specifed when using EC keys.\n"));
456*e65e5c2dSWyllys Ingersoll 		return (PK_ERR_USAGE);
457*e65e5c2dSWyllys Ingersoll 	}
458*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
459*e65e5c2dSWyllys Ingersoll 		(void) fprintf(stderr, gettext("ECC certificates are"
460*e65e5c2dSWyllys Ingersoll 		    "only supported with the pkcs11 and nss keystores\n"));
461*e65e5c2dSWyllys Ingersoll 		rv = PK_ERR_USAGE;
462*e65e5c2dSWyllys Ingersoll 		goto end;
463*e65e5c2dSWyllys Ingersoll 	}
464*e65e5c2dSWyllys Ingersoll 	/* Adjust default keylength for NSS and DSA */
465*e65e5c2dSWyllys Ingersoll 	if (keyAlg == KMF_DSA && kstype == KMF_KEYSTORE_NSS) {
466*e65e5c2dSWyllys Ingersoll 		/* NSS only allows for 512-1024 bit DSA keys */
467*e65e5c2dSWyllys Ingersoll 		if (!y_flag)
468*e65e5c2dSWyllys Ingersoll 			/* If nothing was given, default to 1024 */
469*e65e5c2dSWyllys Ingersoll 			keylen = 1024;
470*e65e5c2dSWyllys Ingersoll 		else if (keylen > 1024 || keylen < 512) {
471*e65e5c2dSWyllys Ingersoll 			(void) fprintf(stderr, gettext("NSS keystore only "
472*e65e5c2dSWyllys Ingersoll 			    "supports DSA keylengths of 512 - 1024 bits\n"));
473*e65e5c2dSWyllys Ingersoll 			rv = PK_ERR_USAGE;
474*e65e5c2dSWyllys Ingersoll 			goto end;
475*e65e5c2dSWyllys Ingersoll 		}
476*e65e5c2dSWyllys Ingersoll 	}
477*e65e5c2dSWyllys Ingersoll 
478*e65e5c2dSWyllys Ingersoll 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
479*e65e5c2dSWyllys Ingersoll 		if (label == NULL) {
480*e65e5c2dSWyllys Ingersoll 			(void) fprintf(stderr,
481*e65e5c2dSWyllys Ingersoll 			    gettext("No key label specified\n"));
482*e65e5c2dSWyllys Ingersoll 			rv = PK_ERR_USAGE;
483*e65e5c2dSWyllys Ingersoll 			goto end;
484*e65e5c2dSWyllys Ingersoll 		}
485*e65e5c2dSWyllys Ingersoll 		if (tokenname == NULL || !strlen(tokenname)) {
486*e65e5c2dSWyllys Ingersoll 			if (kstype == KMF_KEYSTORE_NSS) {
487*e65e5c2dSWyllys Ingersoll 				tokenname = "internal";
488*e65e5c2dSWyllys Ingersoll 			} else  {
489*e65e5c2dSWyllys Ingersoll 				tokenname = PK_DEFAULT_PK11TOKEN;
490*e65e5c2dSWyllys Ingersoll 			}
491*e65e5c2dSWyllys Ingersoll 		}
492*e65e5c2dSWyllys Ingersoll 
493*e65e5c2dSWyllys Ingersoll 		(void) get_token_password(kstype, tokenname, &tokencred);
494*e65e5c2dSWyllys Ingersoll 	}
495*e65e5c2dSWyllys Ingersoll 
496*e65e5c2dSWyllys Ingersoll 	if (kstype == KMF_KEYSTORE_NSS) {
497*e65e5c2dSWyllys Ingersoll 		if (dir == NULL)
498*e65e5c2dSWyllys Ingersoll 			dir = PK_DEFAULT_DIRECTORY;
499*e65e5c2dSWyllys Ingersoll 
500*e65e5c2dSWyllys Ingersoll 		rv = genkeypair_nss(kmfhandle,
501*e65e5c2dSWyllys Ingersoll 		    tokenname, label, dir, prefix, keyAlg, keylen,
502*e65e5c2dSWyllys Ingersoll 		    &tokencred, curveoid, NULL, NULL);
503*e65e5c2dSWyllys Ingersoll 
504*e65e5c2dSWyllys Ingersoll 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
505*e65e5c2dSWyllys Ingersoll 		rv = genkeypair_pkcs11(kmfhandle,
506*e65e5c2dSWyllys Ingersoll 		    tokenname, label, keyAlg, keylen,
507*e65e5c2dSWyllys Ingersoll 		    &tokencred, curveoid, NULL, NULL);
508*e65e5c2dSWyllys Ingersoll 
509*e65e5c2dSWyllys Ingersoll 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
510*e65e5c2dSWyllys Ingersoll 		rv = genkeypair_file(kmfhandle, keyAlg, keylen,
511*e65e5c2dSWyllys Ingersoll 		    fmt, outkey, NULL, NULL);
512*e65e5c2dSWyllys Ingersoll 	}
513*e65e5c2dSWyllys Ingersoll 
514*e65e5c2dSWyllys Ingersoll 	if (rv != KMF_OK)
515*e65e5c2dSWyllys Ingersoll 		display_error(kmfhandle, rv,
516*e65e5c2dSWyllys Ingersoll 		    gettext("Error creating and keypair"));
517*e65e5c2dSWyllys Ingersoll end:
518*e65e5c2dSWyllys Ingersoll 	if (tokencred.cred != NULL)
519*e65e5c2dSWyllys Ingersoll 		free(tokencred.cred);
520*e65e5c2dSWyllys Ingersoll 
521*e65e5c2dSWyllys Ingersoll 	(void) kmf_finalize(kmfhandle);
522*e65e5c2dSWyllys Ingersoll 	return (rv);
523*e65e5c2dSWyllys Ingersoll }
524