1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <stdio.h>
29#include <string.h>
30#include <ctype.h>
31#include <malloc.h>
32#include <libgen.h>
33#include <errno.h>
34#include <cryptoutil.h>
35#include <security/cryptoki.h>
36#include "common.h"
37#include <kmfapi.h>
38
39
40static KMF_RETURN
41genkey_nss(KMF_HANDLE_T kmfhandle, char *token, char *dir, char *prefix,
42    char *keylabel, KMF_KEY_ALG keyAlg, int keylen, KMF_CREDENTIAL *tokencred)
43{
44	KMF_RETURN kmfrv = KMF_OK;
45	KMF_KEY_HANDLE key;
46	KMF_ATTRIBUTE attlist[20];
47	int i = 0;
48	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
49	KMF_KEY_ALG keytype;
50	uint32_t keylength;
51
52	if (keylabel == NULL) {
53		cryptoerror(LOG_STDERR,
54		    gettext("A key label must be specified \n"));
55		return (KMF_ERR_BAD_PARAMETER);
56	}
57
58	kmfrv = configure_nss(kmfhandle, dir, prefix);
59	if (kmfrv != KMF_OK)
60		return (kmfrv);
61
62	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
63
64	keytype = keyAlg;
65	keylength = keylen;
66
67	kmf_set_attr_at_index(attlist, i,
68	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
69	i++;
70
71	kmf_set_attr_at_index(attlist, i,
72	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
73	i++;
74
75	kmf_set_attr_at_index(attlist, i,
76	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
77	i++;
78
79	kmf_set_attr_at_index(attlist, i,
80	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
81	i++;
82
83	if (keylabel != NULL) {
84		kmf_set_attr_at_index(attlist, i,
85		    KMF_KEYLABEL_ATTR, keylabel,
86		    strlen(keylabel));
87		i++;
88	}
89
90	if (tokencred != NULL && tokencred->cred != NULL) {
91		kmf_set_attr_at_index(attlist, i,
92		    KMF_CREDENTIAL_ATTR, tokencred,
93		    sizeof (KMF_CREDENTIAL));
94		i++;
95	}
96
97	if (token != NULL) {
98		kmf_set_attr_at_index(attlist, i,
99		    KMF_TOKEN_LABEL_ATTR, token,
100		    strlen(token));
101		i++;
102	}
103
104	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
105
106	return (kmfrv);
107}
108
109static KMF_RETURN
110genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token,
111	char *keylabel, KMF_KEY_ALG keyAlg, int keylen,
112	char *senstr, char *extstr, boolean_t print_hex,
113	KMF_CREDENTIAL *tokencred)
114{
115	KMF_RETURN kmfrv = KMF_OK;
116	KMF_KEY_HANDLE key;
117	KMF_RAW_SYM_KEY  *rkey = NULL;
118	boolean_t 	sensitive = B_FALSE;
119	boolean_t	not_extractable = B_FALSE;
120	char *hexstr = NULL;
121	int  hexstrlen;
122	KMF_ATTRIBUTE attlist[20];
123	int i = 0;
124	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
125	KMF_KEY_ALG keytype;
126	uint32_t keylength;
127
128	if (keylabel == NULL) {
129		cryptoerror(LOG_STDERR,
130		    gettext("A key label must be specified \n"));
131		return (KMF_ERR_BAD_PARAMETER);
132	}
133
134	/* Check the sensitive option value if specified. */
135	if (senstr != NULL) {
136		if (tolower(senstr[0]) == 'y')
137			sensitive = B_TRUE;
138		else if (tolower(senstr[0]) == 'n')
139			sensitive = B_FALSE;
140		else {
141			cryptoerror(LOG_STDERR,
142			    gettext("Incorrect sensitive option value.\n"));
143			return (KMF_ERR_BAD_PARAMETER);
144		}
145	}
146
147	/* Check the extractable option value if specified. */
148	if (extstr != NULL) {
149		if (tolower(extstr[0]) == 'y')
150			not_extractable = B_FALSE;
151		else if (tolower(extstr[0]) == 'n')
152			not_extractable = B_TRUE;
153		else {
154			cryptoerror(LOG_STDERR,
155			    gettext("Incorrect extractable option value.\n"));
156			return (KMF_ERR_BAD_PARAMETER);
157		}
158	}
159
160	/* Select a PKCS11 token first */
161	kmfrv = select_token(kmfhandle, token, FALSE);
162	if (kmfrv != KMF_OK) {
163		return (kmfrv);
164	}
165
166	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
167
168	keytype = keyAlg;
169	keylength = keylen; /* bits */
170
171	kmf_set_attr_at_index(attlist, i,
172	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
173	i++;
174
175	kmf_set_attr_at_index(attlist, i,
176	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
177	i++;
178
179	kmf_set_attr_at_index(attlist, i,
180	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
181	i++;
182
183	kmf_set_attr_at_index(attlist, i,
184	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
185	i++;
186
187	if (keylabel != NULL) {
188		kmf_set_attr_at_index(attlist, i,
189		    KMF_KEYLABEL_ATTR, keylabel,
190		    strlen(keylabel));
191		i++;
192	}
193
194	if (tokencred != NULL && tokencred->cred != NULL) {
195		kmf_set_attr_at_index(attlist, i,
196		    KMF_CREDENTIAL_ATTR, tokencred,
197		    sizeof (KMF_CREDENTIAL));
198		i++;
199	}
200
201	kmf_set_attr_at_index(attlist, i,
202	    KMF_SENSITIVE_BOOL_ATTR, &sensitive,
203	    sizeof (sensitive));
204	i++;
205
206	kmf_set_attr_at_index(attlist, i,
207	    KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
208	    sizeof (not_extractable));
209	i++;
210
211	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
212	if (kmfrv != KMF_OK) {
213		goto out;
214	}
215
216	if (print_hex) {
217		if (sensitive == B_TRUE || not_extractable == B_TRUE) {
218			cryptoerror(LOG_STDERR,
219			    gettext("Warning: can not reveal the key value "
220			    "for a sensitive or non-extractable key.\n"));
221			goto out;
222		} else {
223			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
224			if (rkey == NULL) {
225				kmfrv = KMF_ERR_MEMORY;
226				goto out;
227			}
228			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
229			kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
230			if (kmfrv != KMF_OK) {
231				goto out;
232			}
233			hexstrlen = 2 * rkey->keydata.len + 1;
234			hexstr = malloc(hexstrlen);
235			if (hexstr == NULL) {
236				kmfrv = KMF_ERR_MEMORY;
237				goto out;
238			}
239
240			tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
241			    hexstrlen);
242			(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
243		}
244	}
245
246out:
247	kmf_free_raw_sym_key(rkey);
248
249	if (hexstr != NULL)
250		free(hexstr);
251
252	return (kmfrv);
253}
254
255
256static KMF_RETURN
257genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
258    char *outkey, boolean_t print_hex)
259{
260	KMF_RETURN kmfrv = KMF_OK;
261	KMF_KEY_HANDLE key;
262	KMF_RAW_SYM_KEY *rkey = NULL;
263	char *hexstr = NULL;
264	int hexstrlen;
265	KMF_ATTRIBUTE attlist[20];
266	int i = 0;
267	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
268	KMF_KEY_ALG keytype;
269	uint32_t keylength;
270	char *dirpath;
271
272	if (EMPTYSTRING(outkey)) {
273		cryptoerror(LOG_STDERR,
274		    gettext("No output key file was specified for the key\n"));
275		return (KMF_ERR_BAD_PARAMETER);
276	}
277
278	if (verify_file(outkey)) {
279		cryptoerror(LOG_STDERR,
280		    gettext("Cannot write the indicated output "
281		    "key file (%s).\n"), outkey);
282		return (KMF_ERR_BAD_PARAMETER);
283	}
284
285	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
286
287	keytype = keyAlg;
288	keylength = keylen;
289
290	dirpath = dir;
291
292	kmf_set_attr_at_index(attlist, i,
293	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
294	i++;
295
296	kmf_set_attr_at_index(attlist, i,
297	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
298	i++;
299
300	kmf_set_attr_at_index(attlist, i,
301	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
302	i++;
303
304	kmf_set_attr_at_index(attlist, i,
305	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
306	i++;
307
308	if (dirpath != NULL) {
309		kmf_set_attr_at_index(attlist, i,
310		    KMF_DIRPATH_ATTR, dirpath,
311		    strlen(dirpath));
312		i++;
313	}
314
315	if (outkey != NULL) {
316		kmf_set_attr_at_index(attlist, i,
317		    KMF_KEY_FILENAME_ATTR, outkey,
318		    strlen(outkey));
319		i++;
320	}
321
322	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
323	if (kmfrv != KMF_OK) {
324		goto out;
325	}
326
327	if (print_hex) {
328		rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
329		if (rkey == NULL) {
330			kmfrv = KMF_ERR_MEMORY;
331			goto out;
332		}
333		(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
334		kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
335		if (kmfrv != KMF_OK) {
336			goto out;
337		}
338
339		hexstrlen = 2 * rkey->keydata.len + 1;
340		hexstr = malloc(hexstrlen);
341		if (hexstr == NULL) {
342			kmfrv = KMF_ERR_MEMORY;
343			goto out;
344		}
345		tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
346		    hexstrlen);
347		(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
348	}
349
350out:
351	kmf_free_raw_sym_key(rkey);
352
353	if (hexstr != NULL)
354		free(hexstr);
355
356	return (kmfrv);
357}
358
359int
360pk_genkey(int argc, char *argv[])
361{
362	int rv;
363	int opt;
364	extern int	optind_av;
365	extern char	*optarg_av;
366	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
367	char *tokenname = NULL;
368	char *dir = NULL;
369	char *prefix = NULL;
370	char *keytype = "generic";
371	char *keylenstr = NULL;
372	int keylen = 0;
373	char *keylabel = NULL;
374	char *outkey = NULL;
375	char *senstr = NULL;
376	char *extstr = NULL;
377	char *printstr = NULL;
378	KMF_HANDLE_T kmfhandle = NULL;
379	KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
380	boolean_t print_hex = B_FALSE;
381	KMF_CREDENTIAL tokencred = {NULL, 0};
382
383	while ((opt = getopt_av(argc, argv,
384	    "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
385	    "t:(keytype)y:(keylen)K:(outkey)P:(print)"
386	    "s:(sensitive)e:(extractable)")) != EOF) {
387		if (EMPTYSTRING(optarg_av))
388			return (PK_ERR_USAGE);
389		switch (opt) {
390			case 'k':
391				kstype = KS2Int(optarg_av);
392				if (kstype == 0)
393					return (PK_ERR_USAGE);
394				break;
395			case 'l':
396				if (keylabel)
397					return (PK_ERR_USAGE);
398				keylabel = optarg_av;
399				break;
400			case 'T':
401				if (tokenname)
402					return (PK_ERR_USAGE);
403				tokenname = optarg_av;
404				break;
405			case 'd':
406				if (dir)
407					return (PK_ERR_USAGE);
408				dir = optarg_av;
409				break;
410			case 'p':
411				if (prefix)
412					return (PK_ERR_USAGE);
413				prefix = optarg_av;
414				break;
415			case 't':
416				keytype = optarg_av;
417				break;
418			case 'y':
419				if (keylenstr)
420					return (PK_ERR_USAGE);
421				keylenstr = optarg_av;
422				break;
423			case 'K':
424				if (outkey)
425					return (PK_ERR_USAGE);
426				outkey = optarg_av;
427				break;
428			case 'P':
429				if (printstr)
430					return (PK_ERR_USAGE);
431				printstr = optarg_av;
432				break;
433			case 's':
434				if (senstr)
435					return (PK_ERR_USAGE);
436				senstr = optarg_av;
437				break;
438			case 'e':
439				if (extstr)
440					return (PK_ERR_USAGE);
441				extstr = optarg_av;
442				break;
443			default:
444				return (PK_ERR_USAGE);
445		}
446	}
447
448	/* No additional args allowed. */
449	argc -= optind_av;
450	argv += optind_av;
451	if (argc) {
452		return (PK_ERR_USAGE);
453	}
454
455	/* Check keytype. If not specified, default to AES */
456	if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
457		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
458		    keytype);
459		return (PK_ERR_USAGE);
460	}
461
462	/*
463	 * Check and set the key length.
464	 * - For DES and 3DES, the key size are fixed. Ingore the keylen
465	 *   option, even if it is specified.
466	 * - For AES and ARCFOUR, if keylen is not specified, default to
467	 *   128 bits.
468	 */
469	if (keyAlg == KMF_DES)
470		keylen = 64;  /* fixed size; ignore input */
471	else if (keyAlg == KMF_DES3)
472		keylen = 192; /* fixed size; ignore input */
473	else /* AES, ARCFOUR, or GENERIC SECRET */ {
474		if (keylenstr == NULL) {
475			cryptoerror(LOG_STDERR,
476			    gettext("Key length must be specified for "
477			    "AES, ARCFOUR or GENERIC symmetric keys.\n"));
478			return (PK_ERR_USAGE);
479		}
480		if (sscanf(keylenstr, "%d", &keylen) != 1) {
481			cryptoerror(LOG_STDERR,
482			    gettext("Unrecognized key length (%s).\n"),
483			    keytype);
484			return (PK_ERR_USAGE);
485		}
486		if (keylen == 0 || (keylen % 8) != 0) {
487			cryptoerror(LOG_STDERR,
488			    gettext("Key length bitlength must be a "
489			    "multiple of 8.\n"));
490			return (PK_ERR_USAGE);
491		}
492	}
493
494	/* check the print option */
495	if (printstr != NULL) {
496		if (kstype == KMF_KEYSTORE_NSS) {
497			cryptoerror(LOG_STDERR,
498			    gettext("The print option does not apply "
499			    "to the NSS keystore.\n"));
500			return (PK_ERR_USAGE);
501		}
502
503		if (tolower(printstr[0]) == 'y')
504			print_hex = B_TRUE;
505		else if (tolower(printstr[0]) == 'n')
506			print_hex = B_FALSE;
507		else {
508			cryptoerror(LOG_STDERR,
509			    gettext("Incorrect print option value.\n"));
510			return (PK_ERR_USAGE);
511		}
512	}
513
514	/* check the sensitive and extractable options */
515	if ((senstr != NULL || extstr != NULL) &&
516	    (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
517		cryptoerror(LOG_STDERR,
518		    gettext("The sensitive or extractable option applies "
519		    "to the PKCS11 keystore only.\n"));
520		return (PK_ERR_USAGE);
521	}
522
523	if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
524		tokenname = PK_DEFAULT_PK11TOKEN;
525	} else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
526		tokenname = DEFAULT_NSS_TOKEN;
527	}
528	DIR_OPTION_CHECK(kstype, dir);
529
530	if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
531		(void) get_token_password(kstype, tokenname, &tokencred);
532
533	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
534		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
535		goto end;
536	}
537
538	if (kstype == KMF_KEYSTORE_NSS) {
539		rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
540		    keylabel, keyAlg, keylen, &tokencred);
541	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
542		rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
543		    print_hex);
544	} else {
545		rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
546		    keylen, senstr, extstr, print_hex, &tokencred);
547	}
548
549end:
550	if (rv != KMF_OK)
551		display_error(kmfhandle, rv,
552		    gettext("Error generating key"));
553
554	if (tokencred.cred != NULL)
555		free(tokencred.cred);
556
557	(void) kmf_finalize(kmfhandle);
558	if (rv != KMF_OK)
559		return (PK_ERR_USAGE);
560
561	return (0);
562}
563