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 2007 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 
40 static KMF_RETURN
41 genkey_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->credlen > 0) {
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 
109 static KMF_RETURN
110 genkey_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->credlen > 0) {
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 
246 out:
247 	kmf_free_raw_sym_key(rkey);
248 
249 	if (hexstr != NULL)
250 		free(hexstr);
251 
252 	return (kmfrv);
253 }
254 
255 
256 static KMF_RETURN
257 genkey_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 == NULL) ? "." : dir;
291 
292 
293 	kmf_set_attr_at_index(attlist, i,
294 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
295 	i++;
296 
297 	kmf_set_attr_at_index(attlist, i,
298 	    KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
299 	i++;
300 
301 	kmf_set_attr_at_index(attlist, i,
302 	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
303 	i++;
304 
305 	kmf_set_attr_at_index(attlist, i,
306 	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
307 	i++;
308 
309 	if (dirpath != NULL) {
310 		kmf_set_attr_at_index(attlist, i,
311 		    KMF_DIRPATH_ATTR, dirpath,
312 		    strlen(dirpath));
313 		i++;
314 	}
315 
316 	if (outkey != NULL) {
317 		kmf_set_attr_at_index(attlist, i,
318 		    KMF_KEY_FILENAME_ATTR, outkey,
319 		    strlen(outkey));
320 		i++;
321 	}
322 
323 	kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
324 	if (kmfrv != KMF_OK) {
325 		goto out;
326 	}
327 
328 	if (print_hex) {
329 		rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
330 		if (rkey == NULL) {
331 			kmfrv = KMF_ERR_MEMORY;
332 			goto out;
333 		}
334 		(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
335 		kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
336 		if (kmfrv != KMF_OK) {
337 			goto out;
338 		}
339 
340 		hexstrlen = 2 * rkey->keydata.len + 1;
341 		hexstr = malloc(hexstrlen);
342 		if (hexstr == NULL) {
343 			kmfrv = KMF_ERR_MEMORY;
344 			goto out;
345 		}
346 		tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
347 		    hexstrlen);
348 		(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
349 	}
350 
351 out:
352 	kmf_free_raw_sym_key(rkey);
353 
354 	if (hexstr != NULL)
355 		free(hexstr);
356 
357 	return (kmfrv);
358 }
359 
360 int
361 pk_genkey(int argc, char *argv[])
362 {
363 	int rv;
364 	int opt;
365 	extern int	optind_av;
366 	extern char	*optarg_av;
367 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
368 	char *tokenname = NULL;
369 	char *dir = NULL;
370 	char *prefix = NULL;
371 	char *keytype = "generic";
372 	char *keylenstr = NULL;
373 	int keylen = 0;
374 	char *keylabel = NULL;
375 	char *outkey = NULL;
376 	char *senstr = NULL;
377 	char *extstr = NULL;
378 	char *printstr = NULL;
379 	KMF_HANDLE_T kmfhandle = NULL;
380 	KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
381 	boolean_t print_hex = B_FALSE;
382 	KMF_CREDENTIAL tokencred = {NULL, 0};
383 
384 	while ((opt = getopt_av(argc, argv,
385 	    "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
386 	    "t:(keytype)y:(keylen)K:(outkey)P:(print)"
387 	    "s:(sensitive)e:(extractable)")) != EOF) {
388 		if (EMPTYSTRING(optarg_av))
389 			return (PK_ERR_USAGE);
390 		switch (opt) {
391 			case 'k':
392 				kstype = KS2Int(optarg_av);
393 				if (kstype == 0)
394 					return (PK_ERR_USAGE);
395 				break;
396 			case 'l':
397 				if (keylabel)
398 					return (PK_ERR_USAGE);
399 				keylabel = optarg_av;
400 				break;
401 			case 'T':
402 				if (tokenname)
403 					return (PK_ERR_USAGE);
404 				tokenname = optarg_av;
405 				break;
406 			case 'd':
407 				if (dir)
408 					return (PK_ERR_USAGE);
409 				dir = optarg_av;
410 				break;
411 			case 'p':
412 				if (prefix)
413 					return (PK_ERR_USAGE);
414 				prefix = optarg_av;
415 				break;
416 			case 't':
417 				keytype = optarg_av;
418 				break;
419 			case 'y':
420 				if (keylenstr)
421 					return (PK_ERR_USAGE);
422 				keylenstr = optarg_av;
423 				break;
424 			case 'K':
425 				if (outkey)
426 					return (PK_ERR_USAGE);
427 				outkey = optarg_av;
428 				break;
429 			case 'P':
430 				if (printstr)
431 					return (PK_ERR_USAGE);
432 				printstr = optarg_av;
433 				break;
434 			case 's':
435 				if (senstr)
436 					return (PK_ERR_USAGE);
437 				senstr = optarg_av;
438 				break;
439 			case 'e':
440 				if (extstr)
441 					return (PK_ERR_USAGE);
442 				extstr = optarg_av;
443 				break;
444 			default:
445 				return (PK_ERR_USAGE);
446 		}
447 	}
448 
449 	/* No additional args allowed. */
450 	argc -= optind_av;
451 	argv += optind_av;
452 	if (argc) {
453 		return (PK_ERR_USAGE);
454 	}
455 
456 	/* Check keytype. If not specified, default to AES */
457 	if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
458 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
459 		    keytype);
460 		return (PK_ERR_USAGE);
461 	}
462 
463 	/*
464 	 * Check and set the key length.
465 	 * - For DES and 3DES, the key size are fixed. Ingore the keylen
466 	 *   option, even if it is specified.
467 	 * - For AES and ARCFOUR, if keylen is not specified, default to
468 	 *   128 bits.
469 	 */
470 	if (keyAlg == KMF_DES)
471 		keylen = 64;  /* fixed size; ignore input */
472 	else if (keyAlg == KMF_DES3)
473 		keylen = 192; /* fixed size; ignore input */
474 	else /* AES, ARCFOUR, or GENERIC SECRET */ {
475 		if (keylenstr == NULL) {
476 			cryptoerror(LOG_STDERR,
477 			    gettext("Key length must be specified for "
478 			    "AES, ARCFOUR or GENERIC symmetric keys.\n"));
479 			return (PK_ERR_USAGE);
480 		}
481 		if (sscanf(keylenstr, "%d", &keylen) != 1) {
482 			cryptoerror(LOG_STDERR,
483 			    gettext("Unrecognized key length (%s).\n"),
484 			    keytype);
485 			return (PK_ERR_USAGE);
486 		}
487 		if (keylen == 0 || (keylen % 8) != 0) {
488 			cryptoerror(LOG_STDERR,
489 			    gettext("Key length bitlength must be a "
490 			    "multiple of 8.\n"));
491 			return (PK_ERR_USAGE);
492 		}
493 	}
494 
495 	/* check the print option */
496 	if (printstr != NULL) {
497 		if (kstype == KMF_KEYSTORE_NSS) {
498 			cryptoerror(LOG_STDERR,
499 			    gettext("The print option does not apply "
500 			    "to the NSS keystore.\n"));
501 			return (PK_ERR_USAGE);
502 		}
503 
504 		if (tolower(printstr[0]) == 'y')
505 			print_hex = B_TRUE;
506 		else if (tolower(printstr[0]) == 'n')
507 			print_hex = B_FALSE;
508 		else {
509 			cryptoerror(LOG_STDERR,
510 			    gettext("Incorrect print option value.\n"));
511 			return (PK_ERR_USAGE);
512 		}
513 	}
514 
515 	/* check the sensitive and extractable options */
516 	if ((senstr != NULL || extstr != NULL) &&
517 	    (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
518 		cryptoerror(LOG_STDERR,
519 		    gettext("The sensitive or extractable option applies "
520 		    "to the PKCS11 keystore only.\n"));
521 		return (PK_ERR_USAGE);
522 	}
523 
524 	if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
525 		tokenname = PK_DEFAULT_PK11TOKEN;
526 	} else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
527 		tokenname = DEFAULT_NSS_TOKEN;
528 	}
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 
549 end:
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