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
genkey_nss(KMF_HANDLE_T kmfhandle,char * token,char * dir,char * prefix,char * keylabel,KMF_KEY_ALG keyAlg,int keylen,KMF_CREDENTIAL * tokencred)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
genkey_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * keylabel,KMF_KEY_ALG keyAlg,int keylen,char * senstr,char * extstr,boolean_t print_hex,KMF_CREDENTIAL * tokencred)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, ¬_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
genkey_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,int keylen,char * dir,char * outkey,boolean_t print_hex)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
pk_genkey(int argc,char * argv[])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