xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/genkey.c (revision 30a5e8fa1253cb33980ee4514743cf683f584b4e)
199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
2099ebb4caSwyllys  */
2199ebb4caSwyllys /*
22c197cb9dShylee  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2399ebb4caSwyllys  * Use is subject to license terms.
2499ebb4caSwyllys  */
2599ebb4caSwyllys 
2699ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
2799ebb4caSwyllys 
2899ebb4caSwyllys #include <stdio.h>
2999ebb4caSwyllys #include <string.h>
3099ebb4caSwyllys #include <ctype.h>
3199ebb4caSwyllys #include <malloc.h>
3299ebb4caSwyllys #include <libgen.h>
3399ebb4caSwyllys #include <errno.h>
3499ebb4caSwyllys #include <cryptoutil.h>
3599ebb4caSwyllys #include <security/cryptoki.h>
3699ebb4caSwyllys #include "common.h"
3799ebb4caSwyllys #include <kmfapi.h>
3899ebb4caSwyllys 
3999ebb4caSwyllys 
4099ebb4caSwyllys static KMF_RETURN
4199ebb4caSwyllys genkey_nss(KMF_HANDLE_T kmfhandle, char *token, char *dir, char *prefix,
4299ebb4caSwyllys     char *keylabel, KMF_KEY_ALG keyAlg, int keylen, KMF_CREDENTIAL *tokencred)
4399ebb4caSwyllys {
4499ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
4599ebb4caSwyllys 	KMF_KEY_HANDLE key;
46*30a5e8faSwyllys 	KMF_ATTRIBUTE attlist[20];
47*30a5e8faSwyllys 	int i = 0;
48*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
49*30a5e8faSwyllys 	KMF_KEY_ALG keytype;
50*30a5e8faSwyllys 	uint32_t keylength;
5199ebb4caSwyllys 
5299ebb4caSwyllys 	if (keylabel == NULL) {
5399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
5499ebb4caSwyllys 		    gettext("A key label must be specified \n"));
5599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
5699ebb4caSwyllys 	}
5799ebb4caSwyllys 
5899ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
5999ebb4caSwyllys 	if (kmfrv != KMF_OK)
6099ebb4caSwyllys 		return (kmfrv);
6199ebb4caSwyllys 
6299ebb4caSwyllys 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
63*30a5e8faSwyllys 
64*30a5e8faSwyllys 	keytype = keyAlg;
65*30a5e8faSwyllys 	keylength = keylen;
66*30a5e8faSwyllys 
67*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
68*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
69*30a5e8faSwyllys 	i++;
70*30a5e8faSwyllys 
71*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
72*30a5e8faSwyllys 	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
73*30a5e8faSwyllys 	i++;
74*30a5e8faSwyllys 
75*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
76*30a5e8faSwyllys 	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
77*30a5e8faSwyllys 	i++;
78*30a5e8faSwyllys 
79*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
80*30a5e8faSwyllys 	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
81*30a5e8faSwyllys 	i++;
82*30a5e8faSwyllys 
83*30a5e8faSwyllys 	if (keylabel != NULL) {
84*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
85*30a5e8faSwyllys 		    KMF_KEYLABEL_ATTR, keylabel,
86*30a5e8faSwyllys 		    strlen(keylabel));
87*30a5e8faSwyllys 		i++;
88*30a5e8faSwyllys 	}
89*30a5e8faSwyllys 
90*30a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
91*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
92*30a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
93*30a5e8faSwyllys 		    sizeof (KMF_CREDENTIAL));
94*30a5e8faSwyllys 		i++;
95*30a5e8faSwyllys 	}
96*30a5e8faSwyllys 
97*30a5e8faSwyllys 	if (token != NULL) {
98*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
99*30a5e8faSwyllys 		    KMF_TOKEN_LABEL_ATTR, token,
100*30a5e8faSwyllys 		    strlen(token));
101*30a5e8faSwyllys 		i++;
102*30a5e8faSwyllys 	}
103*30a5e8faSwyllys 
104*30a5e8faSwyllys 	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
10599ebb4caSwyllys 
10699ebb4caSwyllys 	return (kmfrv);
10799ebb4caSwyllys }
10899ebb4caSwyllys 
10999ebb4caSwyllys static KMF_RETURN
11099ebb4caSwyllys genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token,
11199ebb4caSwyllys 	char *keylabel, KMF_KEY_ALG keyAlg, int keylen,
11299ebb4caSwyllys 	char *senstr, char *extstr, boolean_t print_hex,
11399ebb4caSwyllys 	KMF_CREDENTIAL *tokencred)
11499ebb4caSwyllys {
11599ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
11699ebb4caSwyllys 	KMF_KEY_HANDLE key;
11799ebb4caSwyllys 	KMF_RAW_SYM_KEY  *rkey = NULL;
11899ebb4caSwyllys 	boolean_t 	sensitive = B_FALSE;
11999ebb4caSwyllys 	boolean_t	not_extractable = B_FALSE;
12099ebb4caSwyllys 	char *hexstr = NULL;
12199ebb4caSwyllys 	int  hexstrlen;
122*30a5e8faSwyllys 	KMF_ATTRIBUTE attlist[20];
123*30a5e8faSwyllys 	int i = 0;
124*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
125*30a5e8faSwyllys 	KMF_KEY_ALG keytype;
126*30a5e8faSwyllys 	uint32_t keylength;
12799ebb4caSwyllys 
12899ebb4caSwyllys 	if (keylabel == NULL) {
12999ebb4caSwyllys 		cryptoerror(LOG_STDERR,
13099ebb4caSwyllys 		    gettext("A key label must be specified \n"));
13199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
13299ebb4caSwyllys 	}
13399ebb4caSwyllys 
13499ebb4caSwyllys 	/* Check the sensitive option value if specified. */
13599ebb4caSwyllys 	if (senstr != NULL) {
13699ebb4caSwyllys 		if (tolower(senstr[0]) == 'y')
13799ebb4caSwyllys 			sensitive = B_TRUE;
13899ebb4caSwyllys 		else if (tolower(senstr[0]) == 'n')
13999ebb4caSwyllys 			sensitive = B_FALSE;
14099ebb4caSwyllys 		else {
14199ebb4caSwyllys 			cryptoerror(LOG_STDERR,
14299ebb4caSwyllys 			    gettext("Incorrect sensitive option value.\n"));
14399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
14499ebb4caSwyllys 		}
14599ebb4caSwyllys 	}
14699ebb4caSwyllys 
14799ebb4caSwyllys 	/* Check the extractable option value if specified. */
14899ebb4caSwyllys 	if (extstr != NULL) {
14999ebb4caSwyllys 		if (tolower(extstr[0]) == 'y')
15099ebb4caSwyllys 			not_extractable = B_FALSE;
15199ebb4caSwyllys 		else if (tolower(extstr[0]) == 'n')
15299ebb4caSwyllys 			not_extractable = B_TRUE;
15399ebb4caSwyllys 		else {
15499ebb4caSwyllys 			cryptoerror(LOG_STDERR,
15599ebb4caSwyllys 			    gettext("Incorrect extractable option value.\n"));
15699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
15799ebb4caSwyllys 		}
15899ebb4caSwyllys 	}
15999ebb4caSwyllys 
16099ebb4caSwyllys 	/* Select a PKCS11 token first */
16199ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
16299ebb4caSwyllys 	if (kmfrv != KMF_OK) {
16399ebb4caSwyllys 		return (kmfrv);
16499ebb4caSwyllys 	}
16599ebb4caSwyllys 
16699ebb4caSwyllys 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
167*30a5e8faSwyllys 
168*30a5e8faSwyllys 	keytype = keyAlg;
169*30a5e8faSwyllys 	keylength = keylen; /* bits */
170*30a5e8faSwyllys 
171*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
172*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
173*30a5e8faSwyllys 	i++;
174*30a5e8faSwyllys 
175*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
176*30a5e8faSwyllys 	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
177*30a5e8faSwyllys 	i++;
178*30a5e8faSwyllys 
179*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
180*30a5e8faSwyllys 	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
181*30a5e8faSwyllys 	i++;
182*30a5e8faSwyllys 
183*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
184*30a5e8faSwyllys 	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
185*30a5e8faSwyllys 	i++;
186*30a5e8faSwyllys 
187*30a5e8faSwyllys 	if (keylabel != NULL) {
188*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
189*30a5e8faSwyllys 		    KMF_KEYLABEL_ATTR, keylabel,
190*30a5e8faSwyllys 		    strlen(keylabel));
191*30a5e8faSwyllys 		i++;
192*30a5e8faSwyllys 	}
193*30a5e8faSwyllys 
194*30a5e8faSwyllys 	if (tokencred != NULL && tokencred->credlen > 0) {
195*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
196*30a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred,
197*30a5e8faSwyllys 		    sizeof (KMF_CREDENTIAL));
198*30a5e8faSwyllys 		i++;
199*30a5e8faSwyllys 	}
200*30a5e8faSwyllys 
201*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
202*30a5e8faSwyllys 	    KMF_SENSITIVE_BOOL_ATTR, &sensitive,
203*30a5e8faSwyllys 	    sizeof (sensitive));
204*30a5e8faSwyllys 	i++;
205*30a5e8faSwyllys 
206*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
207*30a5e8faSwyllys 	    KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
208*30a5e8faSwyllys 	    sizeof (not_extractable));
209*30a5e8faSwyllys 	i++;
210*30a5e8faSwyllys 
211*30a5e8faSwyllys 	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
21299ebb4caSwyllys 	if (kmfrv != KMF_OK) {
21399ebb4caSwyllys 		goto out;
21499ebb4caSwyllys 	}
21599ebb4caSwyllys 
21699ebb4caSwyllys 	if (print_hex) {
21799ebb4caSwyllys 		if (sensitive == B_TRUE || not_extractable == B_TRUE) {
21899ebb4caSwyllys 			cryptoerror(LOG_STDERR,
21999ebb4caSwyllys 			    gettext("Warning: can not reveal the key value "
22099ebb4caSwyllys 			    "for a sensitive or non-extractable key.\n"));
22199ebb4caSwyllys 			goto out;
22299ebb4caSwyllys 		} else {
22399ebb4caSwyllys 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
22499ebb4caSwyllys 			if (rkey == NULL) {
22599ebb4caSwyllys 				kmfrv = KMF_ERR_MEMORY;
22699ebb4caSwyllys 				goto out;
22799ebb4caSwyllys 			}
22899ebb4caSwyllys 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
229*30a5e8faSwyllys 			kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
23099ebb4caSwyllys 			if (kmfrv != KMF_OK) {
23199ebb4caSwyllys 				goto out;
23299ebb4caSwyllys 			}
23399ebb4caSwyllys 			hexstrlen = 2 * rkey->keydata.len + 1;
23499ebb4caSwyllys 			hexstr = malloc(hexstrlen);
23599ebb4caSwyllys 			if (hexstr == NULL) {
23699ebb4caSwyllys 				kmfrv = KMF_ERR_MEMORY;
23799ebb4caSwyllys 				goto out;
23899ebb4caSwyllys 			}
23999ebb4caSwyllys 
24099ebb4caSwyllys 			tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
24199ebb4caSwyllys 			    hexstrlen);
24299ebb4caSwyllys 			(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
24399ebb4caSwyllys 		}
24499ebb4caSwyllys 	}
24599ebb4caSwyllys 
24699ebb4caSwyllys out:
247*30a5e8faSwyllys 	kmf_free_raw_sym_key(rkey);
24899ebb4caSwyllys 
24999ebb4caSwyllys 	if (hexstr != NULL)
25099ebb4caSwyllys 		free(hexstr);
25199ebb4caSwyllys 
25299ebb4caSwyllys 	return (kmfrv);
25399ebb4caSwyllys }
25499ebb4caSwyllys 
25599ebb4caSwyllys 
25699ebb4caSwyllys static KMF_RETURN
25799ebb4caSwyllys genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
25899ebb4caSwyllys     char *outkey, boolean_t print_hex)
25999ebb4caSwyllys {
26099ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
26199ebb4caSwyllys 	KMF_KEY_HANDLE key;
26299ebb4caSwyllys 	KMF_RAW_SYM_KEY *rkey = NULL;
26399ebb4caSwyllys 	char *hexstr = NULL;
26499ebb4caSwyllys 	int hexstrlen;
265*30a5e8faSwyllys 	KMF_ATTRIBUTE attlist[20];
266*30a5e8faSwyllys 	int i = 0;
267*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
268*30a5e8faSwyllys 	KMF_KEY_ALG keytype;
269*30a5e8faSwyllys 	uint32_t keylength;
270*30a5e8faSwyllys 	char *dirpath;
27199ebb4caSwyllys 
27299ebb4caSwyllys 	if (EMPTYSTRING(outkey)) {
27399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
27499ebb4caSwyllys 		    gettext("No output key file was specified for the key\n"));
27599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
27699ebb4caSwyllys 	}
27799ebb4caSwyllys 
27899ebb4caSwyllys 	if (verify_file(outkey)) {
27999ebb4caSwyllys 		cryptoerror(LOG_STDERR,
28099ebb4caSwyllys 		    gettext("Cannot write the indicated output "
28199ebb4caSwyllys 		    "key file (%s).\n"), outkey);
28299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
28399ebb4caSwyllys 	}
28499ebb4caSwyllys 
28599ebb4caSwyllys 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
28699ebb4caSwyllys 
287*30a5e8faSwyllys 	keytype = keyAlg;
288*30a5e8faSwyllys 	keylength = keylen;
289*30a5e8faSwyllys 
290*30a5e8faSwyllys 	dirpath = (dir == NULL) ? "." : dir;
291*30a5e8faSwyllys 
292*30a5e8faSwyllys 
293*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
294*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
295*30a5e8faSwyllys 	i++;
296*30a5e8faSwyllys 
297*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
298*30a5e8faSwyllys 	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
299*30a5e8faSwyllys 	i++;
300*30a5e8faSwyllys 
301*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
302*30a5e8faSwyllys 	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
303*30a5e8faSwyllys 	i++;
304*30a5e8faSwyllys 
305*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
306*30a5e8faSwyllys 	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
307*30a5e8faSwyllys 	i++;
308*30a5e8faSwyllys 
309*30a5e8faSwyllys 	if (dirpath != NULL) {
310*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
311*30a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dirpath,
312*30a5e8faSwyllys 		    strlen(dirpath));
313*30a5e8faSwyllys 		i++;
314*30a5e8faSwyllys 	}
315*30a5e8faSwyllys 
316*30a5e8faSwyllys 	if (outkey != NULL) {
317*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
318*30a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, outkey,
319*30a5e8faSwyllys 		    strlen(outkey));
320*30a5e8faSwyllys 		i++;
321*30a5e8faSwyllys 	}
322*30a5e8faSwyllys 
323*30a5e8faSwyllys 	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
32499ebb4caSwyllys 	if (kmfrv != KMF_OK) {
32599ebb4caSwyllys 		goto out;
32699ebb4caSwyllys 	}
32799ebb4caSwyllys 
32899ebb4caSwyllys 	if (print_hex) {
32999ebb4caSwyllys 		rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
33099ebb4caSwyllys 		if (rkey == NULL) {
33199ebb4caSwyllys 			kmfrv = KMF_ERR_MEMORY;
33299ebb4caSwyllys 			goto out;
33399ebb4caSwyllys 		}
33499ebb4caSwyllys 		(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
335*30a5e8faSwyllys 		kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
33699ebb4caSwyllys 		if (kmfrv != KMF_OK) {
33799ebb4caSwyllys 			goto out;
33899ebb4caSwyllys 		}
33999ebb4caSwyllys 
34099ebb4caSwyllys 		hexstrlen = 2 * rkey->keydata.len + 1;
34199ebb4caSwyllys 		hexstr = malloc(hexstrlen);
34299ebb4caSwyllys 		if (hexstr == NULL) {
34399ebb4caSwyllys 			kmfrv = KMF_ERR_MEMORY;
34499ebb4caSwyllys 			goto out;
34599ebb4caSwyllys 		}
34699ebb4caSwyllys 		tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
34799ebb4caSwyllys 		    hexstrlen);
34899ebb4caSwyllys 		(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
34999ebb4caSwyllys 	}
35099ebb4caSwyllys 
35199ebb4caSwyllys out:
352*30a5e8faSwyllys 	kmf_free_raw_sym_key(rkey);
35399ebb4caSwyllys 
35499ebb4caSwyllys 	if (hexstr != NULL)
35599ebb4caSwyllys 		free(hexstr);
35699ebb4caSwyllys 
35799ebb4caSwyllys 	return (kmfrv);
35899ebb4caSwyllys }
35999ebb4caSwyllys 
36099ebb4caSwyllys int
36199ebb4caSwyllys pk_genkey(int argc, char *argv[])
36299ebb4caSwyllys {
36399ebb4caSwyllys 	int rv;
36499ebb4caSwyllys 	int opt;
36599ebb4caSwyllys 	extern int	optind_av;
36699ebb4caSwyllys 	extern char	*optarg_av;
36799ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
36899ebb4caSwyllys 	char *tokenname = NULL;
36999ebb4caSwyllys 	char *dir = NULL;
37099ebb4caSwyllys 	char *prefix = NULL;
371*30a5e8faSwyllys 	char *keytype = "generic";
37299ebb4caSwyllys 	char *keylenstr = NULL;
37399ebb4caSwyllys 	int keylen = 0;
37499ebb4caSwyllys 	char *keylabel = NULL;
37599ebb4caSwyllys 	char *outkey = NULL;
37699ebb4caSwyllys 	char *senstr = NULL;
37799ebb4caSwyllys 	char *extstr = NULL;
37899ebb4caSwyllys 	char *printstr = NULL;
37999ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
380*30a5e8faSwyllys 	KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
38199ebb4caSwyllys 	boolean_t print_hex = B_FALSE;
38299ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
38399ebb4caSwyllys 
38499ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
38599ebb4caSwyllys 	    "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
38699ebb4caSwyllys 	    "t:(keytype)y:(keylen)K:(outkey)P:(print)"
38799ebb4caSwyllys 	    "s:(sensitive)e:(extractable)")) != EOF) {
38899ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
38999ebb4caSwyllys 			return (PK_ERR_USAGE);
39099ebb4caSwyllys 		switch (opt) {
39199ebb4caSwyllys 			case 'k':
39299ebb4caSwyllys 				kstype = KS2Int(optarg_av);
39399ebb4caSwyllys 				if (kstype == 0)
39499ebb4caSwyllys 					return (PK_ERR_USAGE);
39599ebb4caSwyllys 				break;
39699ebb4caSwyllys 			case 'l':
39799ebb4caSwyllys 				if (keylabel)
39899ebb4caSwyllys 					return (PK_ERR_USAGE);
39999ebb4caSwyllys 				keylabel = optarg_av;
40099ebb4caSwyllys 				break;
40199ebb4caSwyllys 			case 'T':
40299ebb4caSwyllys 				if (tokenname)
40399ebb4caSwyllys 					return (PK_ERR_USAGE);
40499ebb4caSwyllys 				tokenname = optarg_av;
40599ebb4caSwyllys 				break;
40699ebb4caSwyllys 			case 'd':
40799ebb4caSwyllys 				if (dir)
40899ebb4caSwyllys 					return (PK_ERR_USAGE);
40999ebb4caSwyllys 				dir = optarg_av;
41099ebb4caSwyllys 				break;
41199ebb4caSwyllys 			case 'p':
41299ebb4caSwyllys 				if (prefix)
41399ebb4caSwyllys 					return (PK_ERR_USAGE);
41499ebb4caSwyllys 				prefix = optarg_av;
41599ebb4caSwyllys 				break;
41699ebb4caSwyllys 			case 't':
41799ebb4caSwyllys 				keytype = optarg_av;
41899ebb4caSwyllys 				break;
41999ebb4caSwyllys 			case 'y':
42099ebb4caSwyllys 				if (keylenstr)
42199ebb4caSwyllys 					return (PK_ERR_USAGE);
42299ebb4caSwyllys 				keylenstr = optarg_av;
42399ebb4caSwyllys 				break;
42499ebb4caSwyllys 			case 'K':
42599ebb4caSwyllys 				if (outkey)
42699ebb4caSwyllys 					return (PK_ERR_USAGE);
42799ebb4caSwyllys 				outkey = optarg_av;
42899ebb4caSwyllys 				break;
42999ebb4caSwyllys 			case 'P':
43099ebb4caSwyllys 				if (printstr)
43199ebb4caSwyllys 					return (PK_ERR_USAGE);
43299ebb4caSwyllys 				printstr = optarg_av;
43399ebb4caSwyllys 				break;
43499ebb4caSwyllys 			case 's':
43599ebb4caSwyllys 				if (senstr)
43699ebb4caSwyllys 					return (PK_ERR_USAGE);
43799ebb4caSwyllys 				senstr = optarg_av;
43899ebb4caSwyllys 				break;
43999ebb4caSwyllys 			case 'e':
44099ebb4caSwyllys 				if (extstr)
44199ebb4caSwyllys 					return (PK_ERR_USAGE);
44299ebb4caSwyllys 				extstr = optarg_av;
44399ebb4caSwyllys 				break;
44499ebb4caSwyllys 			default:
44599ebb4caSwyllys 				return (PK_ERR_USAGE);
44699ebb4caSwyllys 		}
44799ebb4caSwyllys 	}
44899ebb4caSwyllys 
44999ebb4caSwyllys 	/* No additional args allowed. */
45099ebb4caSwyllys 	argc -= optind_av;
45199ebb4caSwyllys 	argv += optind_av;
45299ebb4caSwyllys 	if (argc) {
45399ebb4caSwyllys 		return (PK_ERR_USAGE);
45499ebb4caSwyllys 	}
45599ebb4caSwyllys 
45699ebb4caSwyllys 	/* Check keytype. If not specified, default to AES */
45799ebb4caSwyllys 	if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
45899ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
45999ebb4caSwyllys 		    keytype);
46099ebb4caSwyllys 		return (PK_ERR_USAGE);
46199ebb4caSwyllys 	}
46299ebb4caSwyllys 
46399ebb4caSwyllys 	/*
46499ebb4caSwyllys 	 * Check and set the key length.
46599ebb4caSwyllys 	 * - For DES and 3DES, the key size are fixed. Ingore the keylen
46699ebb4caSwyllys 	 *   option, even if it is specified.
46799ebb4caSwyllys 	 * - For AES and ARCFOUR, if keylen is not specified, default to
46899ebb4caSwyllys 	 *   128 bits.
46999ebb4caSwyllys 	 */
47099ebb4caSwyllys 	if (keyAlg == KMF_DES)
47199ebb4caSwyllys 		keylen = 64;  /* fixed size; ignore input */
47299ebb4caSwyllys 	else if (keyAlg == KMF_DES3)
47399ebb4caSwyllys 		keylen = 192; /* fixed size; ignore input */
474c197cb9dShylee 	else /* AES, ARCFOUR, or GENERIC SECRET */ {
47599ebb4caSwyllys 		if (keylenstr == NULL) {
47699ebb4caSwyllys 			cryptoerror(LOG_STDERR,
477c197cb9dShylee 			    gettext("Key length must be specified for "
478c197cb9dShylee 			    "AES, ARCFOUR or GENERIC symmetric keys.\n"));
47999ebb4caSwyllys 			return (PK_ERR_USAGE);
48099ebb4caSwyllys 		}
48199ebb4caSwyllys 		if (sscanf(keylenstr, "%d", &keylen) != 1) {
48299ebb4caSwyllys 			cryptoerror(LOG_STDERR,
48399ebb4caSwyllys 			    gettext("Unrecognized key length (%s).\n"),
48499ebb4caSwyllys 			    keytype);
48599ebb4caSwyllys 			return (PK_ERR_USAGE);
48699ebb4caSwyllys 		}
48799ebb4caSwyllys 		if (keylen == 0 || (keylen % 8) != 0) {
48899ebb4caSwyllys 			cryptoerror(LOG_STDERR,
48999ebb4caSwyllys 			    gettext("Key length bitlength must be a "
49099ebb4caSwyllys 			    "multiple of 8.\n"));
49199ebb4caSwyllys 			return (PK_ERR_USAGE);
49299ebb4caSwyllys 		}
49399ebb4caSwyllys 	}
49499ebb4caSwyllys 
49599ebb4caSwyllys 	/* check the print option */
49699ebb4caSwyllys 	if (printstr != NULL) {
49799ebb4caSwyllys 		if (kstype == KMF_KEYSTORE_NSS) {
49899ebb4caSwyllys 			cryptoerror(LOG_STDERR,
49999ebb4caSwyllys 			    gettext("The print option does not apply "
50099ebb4caSwyllys 			    "to the NSS keystore.\n"));
50199ebb4caSwyllys 			return (PK_ERR_USAGE);
50299ebb4caSwyllys 		}
50399ebb4caSwyllys 
50499ebb4caSwyllys 		if (tolower(printstr[0]) == 'y')
50599ebb4caSwyllys 			print_hex = B_TRUE;
50699ebb4caSwyllys 		else if (tolower(printstr[0]) == 'n')
50799ebb4caSwyllys 			print_hex = B_FALSE;
50899ebb4caSwyllys 		else {
50999ebb4caSwyllys 			cryptoerror(LOG_STDERR,
51099ebb4caSwyllys 			    gettext("Incorrect print option value.\n"));
51199ebb4caSwyllys 			return (PK_ERR_USAGE);
51299ebb4caSwyllys 		}
51399ebb4caSwyllys 	}
51499ebb4caSwyllys 
51599ebb4caSwyllys 	/* check the sensitive and extractable options */
51699ebb4caSwyllys 	if ((senstr != NULL || extstr != NULL) &&
51799ebb4caSwyllys 	    (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
51899ebb4caSwyllys 		cryptoerror(LOG_STDERR,
51999ebb4caSwyllys 		    gettext("The sensitive or extractable option applies "
52099ebb4caSwyllys 		    "to the PKCS11 keystore only.\n"));
52199ebb4caSwyllys 		return (PK_ERR_USAGE);
52299ebb4caSwyllys 	}
52399ebb4caSwyllys 
52499ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
52599ebb4caSwyllys 		tokenname = PK_DEFAULT_PK11TOKEN;
52699ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
52799ebb4caSwyllys 		tokenname = DEFAULT_NSS_TOKEN;
52899ebb4caSwyllys 	}
52999ebb4caSwyllys 
53099ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
53199ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
53299ebb4caSwyllys 
533*30a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
53499ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
53599ebb4caSwyllys 		goto end;
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 
53899ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
53999ebb4caSwyllys 		rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
54099ebb4caSwyllys 		    keylabel, keyAlg, keylen, &tokencred);
54199ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
54299ebb4caSwyllys 		rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
54399ebb4caSwyllys 		    print_hex);
54499ebb4caSwyllys 	} else {
54599ebb4caSwyllys 		rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
54699ebb4caSwyllys 		    keylen, senstr, extstr, print_hex, &tokencred);
54799ebb4caSwyllys 	}
54899ebb4caSwyllys 
54999ebb4caSwyllys end:
55099ebb4caSwyllys 	if (rv != KMF_OK)
55199ebb4caSwyllys 		display_error(kmfhandle, rv,
55299ebb4caSwyllys 		    gettext("Error generating key"));
55399ebb4caSwyllys 
55499ebb4caSwyllys 	if (tokencred.cred != NULL)
55599ebb4caSwyllys 		free(tokencred.cred);
55699ebb4caSwyllys 
557*30a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
55899ebb4caSwyllys 	if (rv != KMF_OK)
55999ebb4caSwyllys 		return (PK_ERR_USAGE);
56099ebb4caSwyllys 
56199ebb4caSwyllys 	return (0);
56299ebb4caSwyllys }
563