xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/genkey.c (revision d583b39bfb4e2571d3e41097c5c357ffe353ad45)
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 
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->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 
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->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 
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;
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 
350 out:
351 	kmf_free_raw_sym_key(rkey);
352 
353 	if (hexstr != NULL)
354 		free(hexstr);
355 
356 	return (kmfrv);
357 }
358 
359 int
360 pk_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 
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