Home | History | Annotate | Download | only in pktool
      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