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