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