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 2006 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_CREATESYMKEY_PARAMS csk_params; 46 KMF_KEY_HANDLE key; 47 48 if (keylabel == NULL) { 49 cryptoerror(LOG_STDERR, 50 gettext("A key label must be specified \n")); 51 return (KMF_ERR_BAD_PARAMETER); 52 } 53 54 kmfrv = configure_nss(kmfhandle, dir, prefix); 55 if (kmfrv != KMF_OK) 56 return (kmfrv); 57 58 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 59 csk_params.kstype = KMF_KEYSTORE_NSS; 60 csk_params.nssparms.slotlabel = token; 61 csk_params.keytype = keyAlg; 62 csk_params.keylength = keylen; 63 csk_params.keylabel = keylabel; 64 csk_params.cred.cred = tokencred->cred; 65 csk_params.cred.credlen = tokencred->credlen; 66 kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key); 67 68 return (kmfrv); 69 } 70 71 static KMF_RETURN 72 genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token, 73 char *keylabel, KMF_KEY_ALG keyAlg, int keylen, 74 char *senstr, char *extstr, boolean_t print_hex, 75 KMF_CREDENTIAL *tokencred) 76 { 77 KMF_RETURN kmfrv = KMF_OK; 78 KMF_CREATESYMKEY_PARAMS params; 79 KMF_KEY_HANDLE key; 80 KMF_RAW_SYM_KEY *rkey = NULL; 81 boolean_t sensitive = B_FALSE; 82 boolean_t not_extractable = B_FALSE; 83 char *hexstr = NULL; 84 int hexstrlen; 85 86 if (keylabel == NULL) { 87 cryptoerror(LOG_STDERR, 88 gettext("A key label must be specified \n")); 89 return (KMF_ERR_BAD_PARAMETER); 90 } 91 92 /* Check the sensitive option value if specified. */ 93 if (senstr != NULL) { 94 if (tolower(senstr[0]) == 'y') 95 sensitive = B_TRUE; 96 else if (tolower(senstr[0]) == 'n') 97 sensitive = B_FALSE; 98 else { 99 cryptoerror(LOG_STDERR, 100 gettext("Incorrect sensitive option value.\n")); 101 return (KMF_ERR_BAD_PARAMETER); 102 } 103 } 104 105 /* Check the extractable option value if specified. */ 106 if (extstr != NULL) { 107 if (tolower(extstr[0]) == 'y') 108 not_extractable = B_FALSE; 109 else if (tolower(extstr[0]) == 'n') 110 not_extractable = B_TRUE; 111 else { 112 cryptoerror(LOG_STDERR, 113 gettext("Incorrect extractable option value.\n")); 114 return (KMF_ERR_BAD_PARAMETER); 115 } 116 } 117 118 /* Select a PKCS11 token first */ 119 kmfrv = select_token(kmfhandle, token, FALSE); 120 if (kmfrv != KMF_OK) { 121 return (kmfrv); 122 } 123 124 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 125 params.kstype = KMF_KEYSTORE_PK11TOKEN; 126 params.keytype = keyAlg; 127 params.keylength = keylen; /* bits */ 128 params.keylabel = keylabel; 129 params.pkcs11parms.sensitive = sensitive; 130 params.pkcs11parms.not_extractable = not_extractable; 131 params.cred.cred = tokencred->cred; 132 params.cred.credlen = tokencred->credlen; 133 kmfrv = KMF_CreateSymKey(kmfhandle, ¶ms, &key); 134 if (kmfrv != KMF_OK) { 135 goto out; 136 } 137 138 if (print_hex) { 139 if (sensitive == B_TRUE || not_extractable == B_TRUE) { 140 cryptoerror(LOG_STDERR, 141 gettext("Warning: can not reveal the key value " 142 "for a sensitive or non-extractable key.\n")); 143 goto out; 144 } else { 145 rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 146 if (rkey == NULL) { 147 kmfrv = KMF_ERR_MEMORY; 148 goto out; 149 } 150 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 151 kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey); 152 if (kmfrv != KMF_OK) { 153 goto out; 154 } 155 hexstrlen = 2 * rkey->keydata.len + 1; 156 hexstr = malloc(hexstrlen); 157 if (hexstr == NULL) { 158 kmfrv = KMF_ERR_MEMORY; 159 goto out; 160 } 161 162 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr, 163 hexstrlen); 164 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr); 165 } 166 } 167 168 out: 169 KMF_FreeRawSymKey(rkey); 170 171 if (hexstr != NULL) 172 free(hexstr); 173 174 return (kmfrv); 175 } 176 177 178 static KMF_RETURN 179 genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir, 180 char *outkey, boolean_t print_hex) 181 { 182 KMF_RETURN kmfrv = KMF_OK; 183 KMF_CREATESYMKEY_PARAMS csk_params; 184 KMF_KEY_HANDLE key; 185 KMF_RAW_SYM_KEY *rkey = NULL; 186 char *hexstr = NULL; 187 int hexstrlen; 188 189 if (EMPTYSTRING(outkey)) { 190 cryptoerror(LOG_STDERR, 191 gettext("No output key file was specified for the key\n")); 192 return (KMF_ERR_BAD_PARAMETER); 193 } 194 195 if (verify_file(outkey)) { 196 cryptoerror(LOG_STDERR, 197 gettext("Cannot write the indicated output " 198 "key file (%s).\n"), outkey); 199 return (KMF_ERR_BAD_PARAMETER); 200 } 201 202 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 203 csk_params.kstype = KMF_KEYSTORE_OPENSSL; 204 csk_params.keytype = keyAlg; 205 csk_params.keylength = keylen; 206 csk_params.cred.cred = NULL; 207 csk_params.cred.credlen = 0; 208 csk_params.sslparms.dirpath = (dir == NULL) ? "." : dir; 209 csk_params.sslparms.keyfile = outkey; 210 211 kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key); 212 if (kmfrv != KMF_OK) { 213 goto out; 214 } 215 216 if (print_hex) { 217 rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 218 if (rkey == NULL) { 219 kmfrv = KMF_ERR_MEMORY; 220 goto out; 221 } 222 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 223 kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey); 224 if (kmfrv != KMF_OK) { 225 goto out; 226 } 227 228 hexstrlen = 2 * rkey->keydata.len + 1; 229 hexstr = malloc(hexstrlen); 230 if (hexstr == NULL) { 231 kmfrv = KMF_ERR_MEMORY; 232 goto out; 233 } 234 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr, 235 hexstrlen); 236 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr); 237 } 238 239 out: 240 KMF_FreeRawSymKey(rkey); 241 242 if (hexstr != NULL) 243 free(hexstr); 244 245 return (kmfrv); 246 } 247 248 int 249 pk_genkey(int argc, char *argv[]) 250 { 251 int rv; 252 int opt; 253 extern int optind_av; 254 extern char *optarg_av; 255 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 256 char *tokenname = NULL; 257 char *dir = NULL; 258 char *prefix = NULL; 259 char *keytype = "AES"; 260 char *keylenstr = NULL; 261 int keylen = 0; 262 char *keylabel = NULL; 263 char *outkey = NULL; 264 char *senstr = NULL; 265 char *extstr = NULL; 266 char *printstr = NULL; 267 KMF_HANDLE_T kmfhandle = NULL; 268 KMF_KEY_ALG keyAlg = KMF_AES; 269 boolean_t print_hex = B_FALSE; 270 KMF_CREDENTIAL tokencred = {NULL, 0}; 271 272 while ((opt = getopt_av(argc, argv, 273 "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)" 274 "t:(keytype)y:(keylen)K:(outkey)P:(print)" 275 "s:(sensitive)e:(extractable)")) != EOF) { 276 if (EMPTYSTRING(optarg_av)) 277 return (PK_ERR_USAGE); 278 switch (opt) { 279 case 'k': 280 kstype = KS2Int(optarg_av); 281 if (kstype == 0) 282 return (PK_ERR_USAGE); 283 break; 284 case 'l': 285 if (keylabel) 286 return (PK_ERR_USAGE); 287 keylabel = optarg_av; 288 break; 289 case 'T': 290 if (tokenname) 291 return (PK_ERR_USAGE); 292 tokenname = optarg_av; 293 break; 294 case 'd': 295 if (dir) 296 return (PK_ERR_USAGE); 297 dir = optarg_av; 298 break; 299 case 'p': 300 if (prefix) 301 return (PK_ERR_USAGE); 302 prefix = optarg_av; 303 break; 304 case 't': 305 keytype = optarg_av; 306 break; 307 case 'y': 308 if (keylenstr) 309 return (PK_ERR_USAGE); 310 keylenstr = optarg_av; 311 break; 312 case 'K': 313 if (outkey) 314 return (PK_ERR_USAGE); 315 outkey = optarg_av; 316 break; 317 case 'P': 318 if (printstr) 319 return (PK_ERR_USAGE); 320 printstr = optarg_av; 321 break; 322 case 's': 323 if (senstr) 324 return (PK_ERR_USAGE); 325 senstr = optarg_av; 326 break; 327 case 'e': 328 if (extstr) 329 return (PK_ERR_USAGE); 330 extstr = optarg_av; 331 break; 332 default: 333 return (PK_ERR_USAGE); 334 } 335 } 336 337 /* No additional args allowed. */ 338 argc -= optind_av; 339 argv += optind_av; 340 if (argc) { 341 return (PK_ERR_USAGE); 342 } 343 344 /* Check keytype. If not specified, default to AES */ 345 if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) { 346 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"), 347 keytype); 348 return (PK_ERR_USAGE); 349 } 350 351 /* 352 * Check and set the key length. 353 * - For DES and 3DES, the key size are fixed. Ingore the keylen 354 * option, even if it is specified. 355 * - For AES and ARCFOUR, if keylen is not specified, default to 356 * 128 bits. 357 */ 358 if (keyAlg == KMF_DES) 359 keylen = 64; /* fixed size; ignore input */ 360 else if (keyAlg == KMF_DES3) 361 keylen = 192; /* fixed size; ignore input */ 362 else /* AES or ARCFOUR */ { 363 if (keylenstr == NULL) { 364 cryptoerror(LOG_STDERR, 365 gettext("Key length must be specified " 366 "for AES and ARCFOUR symmetric keys.\n")); 367 return (PK_ERR_USAGE); 368 } 369 if (sscanf(keylenstr, "%d", &keylen) != 1) { 370 cryptoerror(LOG_STDERR, 371 gettext("Unrecognized key length (%s).\n"), 372 keytype); 373 return (PK_ERR_USAGE); 374 } 375 if (keylen == 0 || (keylen % 8) != 0) { 376 cryptoerror(LOG_STDERR, 377 gettext("Key length bitlength must be a " 378 "multiple of 8.\n")); 379 return (PK_ERR_USAGE); 380 } 381 } 382 383 /* check the print option */ 384 if (printstr != NULL) { 385 if (kstype == KMF_KEYSTORE_NSS) { 386 cryptoerror(LOG_STDERR, 387 gettext("The print option does not apply " 388 "to the NSS keystore.\n")); 389 return (PK_ERR_USAGE); 390 } 391 392 if (tolower(printstr[0]) == 'y') 393 print_hex = B_TRUE; 394 else if (tolower(printstr[0]) == 'n') 395 print_hex = B_FALSE; 396 else { 397 cryptoerror(LOG_STDERR, 398 gettext("Incorrect print option value.\n")); 399 return (PK_ERR_USAGE); 400 } 401 } 402 403 /* check the sensitive and extractable options */ 404 if ((senstr != NULL || extstr != NULL) && 405 (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) { 406 cryptoerror(LOG_STDERR, 407 gettext("The sensitive or extractable option applies " 408 "to the PKCS11 keystore only.\n")); 409 return (PK_ERR_USAGE); 410 } 411 412 if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) { 413 tokenname = PK_DEFAULT_PK11TOKEN; 414 } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) { 415 tokenname = DEFAULT_NSS_TOKEN; 416 } 417 418 if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS) 419 (void) get_token_password(kstype, tokenname, &tokencred); 420 421 if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 422 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 423 goto end; 424 } 425 426 if (kstype == KMF_KEYSTORE_NSS) { 427 rv = genkey_nss(kmfhandle, tokenname, dir, prefix, 428 keylabel, keyAlg, keylen, &tokencred); 429 } else if (kstype == KMF_KEYSTORE_OPENSSL) { 430 rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey, 431 print_hex); 432 } else { 433 rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg, 434 keylen, senstr, extstr, print_hex, &tokencred); 435 } 436 437 end: 438 if (rv != KMF_OK) 439 display_error(kmfhandle, rv, 440 gettext("Error generating key")); 441 442 if (tokencred.cred != NULL) 443 free(tokencred.cred); 444 445 (void) KMF_Finalize(kmfhandle); 446 if (rv != KMF_OK) 447 return (PK_ERR_USAGE); 448 449 return (0); 450 } 451