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