/usr/src/cmd/cmd-crypto/pktool/genkey.c
C | 561 lines | 450 code | 73 blank | 38 comment | 147 complexity | fadf926e104678da2aea07810d485068 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, AGPL-3.0, MIT, Apache-2.0, 0BSD, GPL-2.0, LGPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014
- /*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
- /*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
- #pragma ident "%Z%%M% %I% %E% SMI"
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <malloc.h>
- #include <libgen.h>
- #include <errno.h>
- #include <cryptoutil.h>
- #include <security/cryptoki.h>
- #include "common.h"
- #include <kmfapi.h>
- 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)
- {
- KMF_RETURN kmfrv = KMF_OK;
- KMF_KEY_HANDLE key;
- KMF_ATTRIBUTE attlist[20];
- int i = 0;
- KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
- KMF_KEY_ALG keytype;
- uint32_t keylength;
- if (keylabel == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("A key label must be specified \n"));
- return (KMF_ERR_BAD_PARAMETER);
- }
- kmfrv = configure_nss(kmfhandle, dir, prefix);
- if (kmfrv != KMF_OK)
- return (kmfrv);
- (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
- keytype = keyAlg;
- keylength = keylen;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
- i++;
- if (keylabel != NULL) {
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYLABEL_ATTR, keylabel,
- strlen(keylabel));
- i++;
- }
- if (tokencred != NULL && tokencred->credlen > 0) {
- kmf_set_attr_at_index(attlist, i,
- KMF_CREDENTIAL_ATTR, tokencred,
- sizeof (KMF_CREDENTIAL));
- i++;
- }
- if (token != NULL) {
- kmf_set_attr_at_index(attlist, i,
- KMF_TOKEN_LABEL_ATTR, token,
- strlen(token));
- i++;
- }
- kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
- return (kmfrv);
- }
- 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)
- {
- KMF_RETURN kmfrv = KMF_OK;
- KMF_KEY_HANDLE key;
- KMF_RAW_SYM_KEY *rkey = NULL;
- boolean_t sensitive = B_FALSE;
- boolean_t not_extractable = B_FALSE;
- char *hexstr = NULL;
- int hexstrlen;
- KMF_ATTRIBUTE attlist[20];
- int i = 0;
- KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
- KMF_KEY_ALG keytype;
- uint32_t keylength;
- if (keylabel == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("A key label must be specified \n"));
- return (KMF_ERR_BAD_PARAMETER);
- }
- /* Check the sensitive option value if specified. */
- if (senstr != NULL) {
- if (tolower(senstr[0]) == 'y')
- sensitive = B_TRUE;
- else if (tolower(senstr[0]) == 'n')
- sensitive = B_FALSE;
- else {
- cryptoerror(LOG_STDERR,
- gettext("Incorrect sensitive option value.\n"));
- return (KMF_ERR_BAD_PARAMETER);
- }
- }
- /* Check the extractable option value if specified. */
- if (extstr != NULL) {
- if (tolower(extstr[0]) == 'y')
- not_extractable = B_FALSE;
- else if (tolower(extstr[0]) == 'n')
- not_extractable = B_TRUE;
- else {
- cryptoerror(LOG_STDERR,
- gettext("Incorrect extractable option value.\n"));
- return (KMF_ERR_BAD_PARAMETER);
- }
- }
- /* Select a PKCS11 token first */
- kmfrv = select_token(kmfhandle, token, FALSE);
- if (kmfrv != KMF_OK) {
- return (kmfrv);
- }
- (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
- keytype = keyAlg;
- keylength = keylen; /* bits */
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
- i++;
- if (keylabel != NULL) {
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYLABEL_ATTR, keylabel,
- strlen(keylabel));
- i++;
- }
- if (tokencred != NULL && tokencred->credlen > 0) {
- kmf_set_attr_at_index(attlist, i,
- KMF_CREDENTIAL_ATTR, tokencred,
- sizeof (KMF_CREDENTIAL));
- i++;
- }
- kmf_set_attr_at_index(attlist, i,
- KMF_SENSITIVE_BOOL_ATTR, &sensitive,
- sizeof (sensitive));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_NON_EXTRACTABLE_BOOL_ATTR, ¬_extractable,
- sizeof (not_extractable));
- i++;
- kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
- if (kmfrv != KMF_OK) {
- goto out;
- }
- if (print_hex) {
- if (sensitive == B_TRUE || not_extractable == B_TRUE) {
- cryptoerror(LOG_STDERR,
- gettext("Warning: can not reveal the key value "
- "for a sensitive or non-extractable key.\n"));
- goto out;
- } else {
- rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
- if (rkey == NULL) {
- kmfrv = KMF_ERR_MEMORY;
- goto out;
- }
- (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
- kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
- if (kmfrv != KMF_OK) {
- goto out;
- }
- hexstrlen = 2 * rkey->keydata.len + 1;
- hexstr = malloc(hexstrlen);
- if (hexstr == NULL) {
- kmfrv = KMF_ERR_MEMORY;
- goto out;
- }
- tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
- hexstrlen);
- (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
- }
- }
- out:
- kmf_free_raw_sym_key(rkey);
- if (hexstr != NULL)
- free(hexstr);
- return (kmfrv);
- }
- static KMF_RETURN
- genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
- char *outkey, boolean_t print_hex)
- {
- KMF_RETURN kmfrv = KMF_OK;
- KMF_KEY_HANDLE key;
- KMF_RAW_SYM_KEY *rkey = NULL;
- char *hexstr = NULL;
- int hexstrlen;
- KMF_ATTRIBUTE attlist[20];
- int i = 0;
- KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
- KMF_KEY_ALG keytype;
- uint32_t keylength;
- char *dirpath;
- if (EMPTYSTRING(outkey)) {
- cryptoerror(LOG_STDERR,
- gettext("No output key file was specified for the key\n"));
- return (KMF_ERR_BAD_PARAMETER);
- }
- if (verify_file(outkey)) {
- cryptoerror(LOG_STDERR,
- gettext("Cannot write the indicated output "
- "key file (%s).\n"), outkey);
- return (KMF_ERR_BAD_PARAMETER);
- }
- (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
- keytype = keyAlg;
- keylength = keylen;
- dirpath = dir;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
- i++;
- kmf_set_attr_at_index(attlist, i,
- KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
- i++;
- if (dirpath != NULL) {
- kmf_set_attr_at_index(attlist, i,
- KMF_DIRPATH_ATTR, dirpath,
- strlen(dirpath));
- i++;
- }
- if (outkey != NULL) {
- kmf_set_attr_at_index(attlist, i,
- KMF_KEY_FILENAME_ATTR, outkey,
- strlen(outkey));
- i++;
- }
- kmfrv = kmf_create_sym_key(kmfhandle, i, attlist);
- if (kmfrv != KMF_OK) {
- goto out;
- }
- if (print_hex) {
- rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
- if (rkey == NULL) {
- kmfrv = KMF_ERR_MEMORY;
- goto out;
- }
- (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
- kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey);
- if (kmfrv != KMF_OK) {
- goto out;
- }
- hexstrlen = 2 * rkey->keydata.len + 1;
- hexstr = malloc(hexstrlen);
- if (hexstr == NULL) {
- kmfrv = KMF_ERR_MEMORY;
- goto out;
- }
- tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
- hexstrlen);
- (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
- }
- out:
- kmf_free_raw_sym_key(rkey);
- if (hexstr != NULL)
- free(hexstr);
- return (kmfrv);
- }
- int
- pk_genkey(int argc, char *argv[])
- {
- int rv;
- int opt;
- extern int optind_av;
- extern char *optarg_av;
- KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
- char *tokenname = NULL;
- char *dir = NULL;
- char *prefix = NULL;
- char *keytype = "generic";
- char *keylenstr = NULL;
- int keylen = 0;
- char *keylabel = NULL;
- char *outkey = NULL;
- char *senstr = NULL;
- char *extstr = NULL;
- char *printstr = NULL;
- KMF_HANDLE_T kmfhandle = NULL;
- KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
- boolean_t print_hex = B_FALSE;
- KMF_CREDENTIAL tokencred = {NULL, 0};
- while ((opt = getopt_av(argc, argv,
- "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
- "t:(keytype)y:(keylen)K:(outkey)P:(print)"
- "s:(sensitive)e:(extractable)")) != EOF) {
- if (EMPTYSTRING(optarg_av))
- return (PK_ERR_USAGE);
- switch (opt) {
- case 'k':
- kstype = KS2Int(optarg_av);
- if (kstype == 0)
- return (PK_ERR_USAGE);
- break;
- case 'l':
- if (keylabel)
- return (PK_ERR_USAGE);
- keylabel = optarg_av;
- break;
- case 'T':
- if (tokenname)
- return (PK_ERR_USAGE);
- tokenname = optarg_av;
- break;
- case 'd':
- if (dir)
- return (PK_ERR_USAGE);
- dir = optarg_av;
- break;
- case 'p':
- if (prefix)
- return (PK_ERR_USAGE);
- prefix = optarg_av;
- break;
- case 't':
- keytype = optarg_av;
- break;
- case 'y':
- if (keylenstr)
- return (PK_ERR_USAGE);
- keylenstr = optarg_av;
- break;
- case 'K':
- if (outkey)
- return (PK_ERR_USAGE);
- outkey = optarg_av;
- break;
- case 'P':
- if (printstr)
- return (PK_ERR_USAGE);
- printstr = optarg_av;
- break;
- case 's':
- if (senstr)
- return (PK_ERR_USAGE);
- senstr = optarg_av;
- break;
- case 'e':
- if (extstr)
- return (PK_ERR_USAGE);
- extstr = optarg_av;
- break;
- default:
- return (PK_ERR_USAGE);
- }
- }
- /* No additional args allowed. */
- argc -= optind_av;
- argv += optind_av;
- if (argc) {
- return (PK_ERR_USAGE);
- }
- /* Check keytype. If not specified, default to AES */
- if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
- cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
- keytype);
- return (PK_ERR_USAGE);
- }
- /*
- * Check and set the key length.
- * - For DES and 3DES, the key size are fixed. Ingore the keylen
- * option, even if it is specified.
- * - For AES and ARCFOUR, if keylen is not specified, default to
- * 128 bits.
- */
- if (keyAlg == KMF_DES)
- keylen = 64; /* fixed size; ignore input */
- else if (keyAlg == KMF_DES3)
- keylen = 192; /* fixed size; ignore input */
- else /* AES, ARCFOUR, or GENERIC SECRET */ {
- if (keylenstr == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("Key length must be specified for "
- "AES, ARCFOUR or GENERIC symmetric keys.\n"));
- return (PK_ERR_USAGE);
- }
- if (sscanf(keylenstr, "%d", &keylen) != 1) {
- cryptoerror(LOG_STDERR,
- gettext("Unrecognized key length (%s).\n"),
- keytype);
- return (PK_ERR_USAGE);
- }
- if (keylen == 0 || (keylen % 8) != 0) {
- cryptoerror(LOG_STDERR,
- gettext("Key length bitlength must be a "
- "multiple of 8.\n"));
- return (PK_ERR_USAGE);
- }
- }
- /* check the print option */
- if (printstr != NULL) {
- if (kstype == KMF_KEYSTORE_NSS) {
- cryptoerror(LOG_STDERR,
- gettext("The print option does not apply "
- "to the NSS keystore.\n"));
- return (PK_ERR_USAGE);
- }
- if (tolower(printstr[0]) == 'y')
- print_hex = B_TRUE;
- else if (tolower(printstr[0]) == 'n')
- print_hex = B_FALSE;
- else {
- cryptoerror(LOG_STDERR,
- gettext("Incorrect print option value.\n"));
- return (PK_ERR_USAGE);
- }
- }
- /* check the sensitive and extractable options */
- if ((senstr != NULL || extstr != NULL) &&
- (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
- cryptoerror(LOG_STDERR,
- gettext("The sensitive or extractable option applies "
- "to the PKCS11 keystore only.\n"));
- return (PK_ERR_USAGE);
- }
- if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
- tokenname = PK_DEFAULT_PK11TOKEN;
- } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
- tokenname = DEFAULT_NSS_TOKEN;
- }
- if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
- (void) get_token_password(kstype, tokenname, &tokencred);
- if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
- cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
- goto end;
- }
- if (kstype == KMF_KEYSTORE_NSS) {
- rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
- keylabel, keyAlg, keylen, &tokencred);
- } else if (kstype == KMF_KEYSTORE_OPENSSL) {
- rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
- print_hex);
- } else {
- rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
- keylen, senstr, extstr, print_hex, &tokencred);
- }
- end:
- if (rv != KMF_OK)
- display_error(kmfhandle, rv,
- gettext("Error generating key"));
- if (tokencred.cred != NULL)
- free(tokencred.cred);
- (void) kmf_finalize(kmfhandle);
- if (rv != KMF_OK)
- return (PK_ERR_USAGE);
- return (0);
- }