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