dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-crypto / pktool / genkey.c
blob6f9bb06b2783cb750a036a33a6bb0cb7d7856fdd
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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>
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)
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;
50 if (keylabel == NULL) {
51 cryptoerror(LOG_STDERR,
52 gettext("A key label must be specified \n"));
53 return (KMF_ERR_BAD_PARAMETER);
56 kmfrv = configure_nss(kmfhandle, dir, prefix);
57 if (kmfrv != KMF_OK)
58 return (kmfrv);
60 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
62 keytype = keyAlg;
63 keylength = keylen;
65 kmf_set_attr_at_index(attlist, i,
66 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
67 i++;
69 kmf_set_attr_at_index(attlist, i,
70 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
71 i++;
73 kmf_set_attr_at_index(attlist, i,
74 KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
75 i++;
77 kmf_set_attr_at_index(attlist, i,
78 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
79 i++;
81 if (keylabel != NULL) {
82 kmf_set_attr_at_index(attlist, i,
83 KMF_KEYLABEL_ATTR, keylabel,
84 strlen(keylabel));
85 i++;
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++;
95 if (token != NULL) {
96 kmf_set_attr_at_index(attlist, i,
97 KMF_TOKEN_LABEL_ATTR, token,
98 strlen(token));
99 i++;
102 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
104 return (kmfrv);
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)
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;
126 if (keylabel == NULL) {
127 cryptoerror(LOG_STDERR,
128 gettext("A key label must be specified \n"));
129 return (KMF_ERR_BAD_PARAMETER);
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);
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);
158 /* Select a PKCS11 token first */
159 kmfrv = select_token(kmfhandle, token, FALSE);
160 if (kmfrv != KMF_OK) {
161 return (kmfrv);
164 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
166 keytype = keyAlg;
167 keylength = keylen; /* bits */
169 kmf_set_attr_at_index(attlist, i,
170 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
171 i++;
173 kmf_set_attr_at_index(attlist, i,
174 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
175 i++;
177 kmf_set_attr_at_index(attlist, i,
178 KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
179 i++;
181 kmf_set_attr_at_index(attlist, i,
182 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
183 i++;
185 if (keylabel != NULL) {
186 kmf_set_attr_at_index(attlist, i,
187 KMF_KEYLABEL_ATTR, keylabel,
188 strlen(keylabel));
189 i++;
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++;
199 kmf_set_attr_at_index(attlist, i,
200 KMF_SENSITIVE_BOOL_ATTR, &sensitive,
201 sizeof (sensitive));
202 i++;
204 kmf_set_attr_at_index(attlist, i,
205 KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
206 sizeof (not_extractable));
207 i++;
209 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
210 if (kmfrv != KMF_OK) {
211 goto out;
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;
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;
231 hexstrlen = 2 * rkey->keydata.len + 1;
232 hexstr = malloc(hexstrlen);
233 if (hexstr == NULL) {
234 kmfrv = KMF_ERR_MEMORY;
235 goto out;
238 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
239 hexstrlen);
240 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
244 out:
245 kmf_free_raw_sym_key(rkey);
247 free(hexstr);
249 return (kmfrv);
253 static KMF_RETURN
254 genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
255 char *outkey, boolean_t print_hex)
257 KMF_RETURN kmfrv = KMF_OK;
258 KMF_KEY_HANDLE key;
259 KMF_RAW_SYM_KEY *rkey = NULL;
260 char *hexstr = NULL;
261 int hexstrlen;
262 KMF_ATTRIBUTE attlist[20];
263 int i = 0;
264 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
265 KMF_KEY_ALG keytype;
266 uint32_t keylength;
267 char *dirpath;
269 if (EMPTYSTRING(outkey)) {
270 cryptoerror(LOG_STDERR,
271 gettext("No output key file was specified for the key\n"));
272 return (KMF_ERR_BAD_PARAMETER);
275 if (verify_file(outkey)) {
276 cryptoerror(LOG_STDERR,
277 gettext("Cannot write the indicated output "
278 "key file (%s).\n"), outkey);
279 return (KMF_ERR_BAD_PARAMETER);
282 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
284 keytype = keyAlg;
285 keylength = keylen;
287 dirpath = dir;
289 kmf_set_attr_at_index(attlist, i,
290 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
291 i++;
293 kmf_set_attr_at_index(attlist, i,
294 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
295 i++;
297 kmf_set_attr_at_index(attlist, i,
298 KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
299 i++;
301 kmf_set_attr_at_index(attlist, i,
302 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
303 i++;
305 if (dirpath != NULL) {
306 kmf_set_attr_at_index(attlist, i,
307 KMF_DIRPATH_ATTR, dirpath,
308 strlen(dirpath));
309 i++;
312 if (outkey != NULL) {
313 kmf_set_attr_at_index(attlist, i,
314 KMF_KEY_FILENAME_ATTR, outkey,
315 strlen(outkey));
316 i++;
319 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
320 if (kmfrv != KMF_OK) {
321 goto out;
324 if (print_hex) {
325 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
326 if (rkey == NULL) {
327 kmfrv = KMF_ERR_MEMORY;
328 goto out;
330 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
331 kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
332 if (kmfrv != KMF_OK) {
333 goto out;
336 hexstrlen = 2 * rkey->keydata.len + 1;
337 hexstr = malloc(hexstrlen);
338 if (hexstr == NULL) {
339 kmfrv = KMF_ERR_MEMORY;
340 goto out;
342 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
343 hexstrlen);
344 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
347 out:
348 kmf_free_raw_sym_key(rkey);
350 free(hexstr);
352 return (kmfrv);
356 pk_genkey(int argc, char *argv[])
358 int rv;
359 int opt;
360 extern int optind_av;
361 extern char *optarg_av;
362 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
363 char *tokenname = NULL;
364 char *dir = NULL;
365 char *prefix = NULL;
366 char *keytype = "generic";
367 char *keylenstr = NULL;
368 int keylen = 0;
369 char *keylabel = NULL;
370 char *outkey = NULL;
371 char *senstr = NULL;
372 char *extstr = NULL;
373 char *printstr = NULL;
374 KMF_HANDLE_T kmfhandle = NULL;
375 KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
376 boolean_t print_hex = B_FALSE;
377 KMF_CREDENTIAL tokencred = { NULL, 0 };
379 while ((opt = getopt_av(argc, argv,
380 "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
381 "t:(keytype)y:(keylen)K:(outkey)P:(print)"
382 "s:(sensitive)e:(extractable)")) != EOF) {
383 if (EMPTYSTRING(optarg_av))
384 return (PK_ERR_USAGE);
385 switch (opt) {
386 case 'k':
387 kstype = KS2Int(optarg_av);
388 if (kstype == 0)
389 return (PK_ERR_USAGE);
390 break;
391 case 'l':
392 if (keylabel)
393 return (PK_ERR_USAGE);
394 keylabel = optarg_av;
395 break;
396 case 'T':
397 if (tokenname)
398 return (PK_ERR_USAGE);
399 tokenname = optarg_av;
400 break;
401 case 'd':
402 if (dir)
403 return (PK_ERR_USAGE);
404 dir = optarg_av;
405 break;
406 case 'p':
407 if (prefix)
408 return (PK_ERR_USAGE);
409 prefix = optarg_av;
410 break;
411 case 't':
412 keytype = optarg_av;
413 break;
414 case 'y':
415 if (keylenstr)
416 return (PK_ERR_USAGE);
417 keylenstr = optarg_av;
418 break;
419 case 'K':
420 if (outkey)
421 return (PK_ERR_USAGE);
422 outkey = optarg_av;
423 break;
424 case 'P':
425 if (printstr)
426 return (PK_ERR_USAGE);
427 printstr = optarg_av;
428 break;
429 case 's':
430 if (senstr)
431 return (PK_ERR_USAGE);
432 senstr = optarg_av;
433 break;
434 case 'e':
435 if (extstr)
436 return (PK_ERR_USAGE);
437 extstr = optarg_av;
438 break;
439 default:
440 return (PK_ERR_USAGE);
444 /* No additional args allowed. */
445 argc -= optind_av;
446 argv += optind_av;
447 if (argc) {
448 return (PK_ERR_USAGE);
451 /* Check keytype. If not specified, default to AES */
452 if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
453 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
454 keytype);
455 return (PK_ERR_USAGE);
459 * Check and set the key length.
460 * - For DES and 3DES, the key size are fixed. Ingore the keylen
461 * option, even if it is specified.
462 * - For AES and ARCFOUR, if keylen is not specified, default to
463 * 128 bits.
465 if (keyAlg == KMF_DES)
466 keylen = 64; /* fixed size; ignore input */
467 else if (keyAlg == KMF_DES3)
468 keylen = 192; /* fixed size; ignore input */
469 else /* AES, ARCFOUR, or GENERIC SECRET */ {
470 if (keylenstr == NULL) {
471 cryptoerror(LOG_STDERR,
472 gettext("Key length must be specified for "
473 "AES, ARCFOUR or GENERIC symmetric keys.\n"));
474 return (PK_ERR_USAGE);
476 if (sscanf(keylenstr, "%d", &keylen) != 1) {
477 cryptoerror(LOG_STDERR,
478 gettext("Unrecognized key length (%s).\n"),
479 keytype);
480 return (PK_ERR_USAGE);
482 if (keylen == 0 || (keylen % 8) != 0) {
483 cryptoerror(LOG_STDERR,
484 gettext("Key length bitlength must be a "
485 "multiple of 8.\n"));
486 return (PK_ERR_USAGE);
490 /* check the print option */
491 if (printstr != NULL) {
492 if (kstype == KMF_KEYSTORE_NSS) {
493 cryptoerror(LOG_STDERR,
494 gettext("The print option does not apply "
495 "to the NSS keystore.\n"));
496 return (PK_ERR_USAGE);
499 if (tolower(printstr[0]) == 'y')
500 print_hex = B_TRUE;
501 else if (tolower(printstr[0]) == 'n')
502 print_hex = B_FALSE;
503 else {
504 cryptoerror(LOG_STDERR,
505 gettext("Incorrect print option value.\n"));
506 return (PK_ERR_USAGE);
510 /* check the sensitive and extractable options */
511 if ((senstr != NULL || extstr != NULL) &&
512 (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
513 cryptoerror(LOG_STDERR,
514 gettext("The sensitive or extractable option applies "
515 "to the PKCS11 keystore only.\n"));
516 return (PK_ERR_USAGE);
519 if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
520 tokenname = PK_DEFAULT_PK11TOKEN;
521 } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
522 tokenname = DEFAULT_NSS_TOKEN;
524 DIR_OPTION_CHECK(kstype, dir);
526 if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
527 (void) get_token_password(kstype, tokenname, &tokencred);
529 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
530 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
531 goto end;
534 if (kstype == KMF_KEYSTORE_NSS) {
535 rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
536 keylabel, keyAlg, keylen, &tokencred);
537 } else if (kstype == KMF_KEYSTORE_OPENSSL) {
538 rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
539 print_hex);
540 } else {
541 rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
542 keylen, senstr, extstr, print_hex, &tokencred);
545 end:
546 if (rv != KMF_OK)
547 display_error(kmfhandle, rv,
548 gettext("Error generating key"));
550 free(tokencred.cred);
552 (void) kmf_finalize(kmfhandle);
553 if (rv != KMF_OK)
554 return (PK_ERR_USAGE);
556 return (0);