summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto/pktool/genkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/genkey.c')
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/genkey.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/genkey.c b/usr/src/cmd/cmd-crypto/pktool/genkey.c
new file mode 100644
index 0000000000..f94093029e
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/genkey.c
@@ -0,0 +1,450 @@
+/*
+ * 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 2006 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_CREATESYMKEY_PARAMS csk_params;
+ KMF_KEY_HANDLE key;
+
+ 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));
+ csk_params.kstype = KMF_KEYSTORE_NSS;
+ csk_params.nssparms.slotlabel = token;
+ csk_params.keytype = keyAlg;
+ csk_params.keylength = keylen;
+ csk_params.keylabel = keylabel;
+ csk_params.cred.cred = tokencred->cred;
+ csk_params.cred.credlen = tokencred->credlen;
+ kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
+
+ 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_CREATESYMKEY_PARAMS params;
+ 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;
+
+ 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));
+ params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ params.keytype = keyAlg;
+ params.keylength = keylen; /* bits */
+ params.keylabel = keylabel;
+ params.pkcs11parms.sensitive = sensitive;
+ params.pkcs11parms.not_extractable = not_extractable;
+ params.cred.cred = tokencred->cred;
+ params.cred.credlen = tokencred->credlen;
+ kmfrv = KMF_CreateSymKey(kmfhandle, &params, &key);
+ 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_GetSymKeyValue(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_FreeRawSymKey(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_CREATESYMKEY_PARAMS csk_params;
+ KMF_KEY_HANDLE key;
+ KMF_RAW_SYM_KEY *rkey = NULL;
+ char *hexstr = NULL;
+ int hexstrlen;
+
+ 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));
+ csk_params.kstype = KMF_KEYSTORE_OPENSSL;
+ csk_params.keytype = keyAlg;
+ csk_params.keylength = keylen;
+ csk_params.cred.cred = NULL;
+ csk_params.cred.credlen = 0;
+ csk_params.sslparms.dirpath = (dir == NULL) ? "." : dir;
+ csk_params.sslparms.keyfile = outkey;
+
+ kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
+ 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_GetSymKeyValue(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_FreeRawSymKey(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 = "AES";
+ 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_AES;
+ 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 or ARCFOUR */ {
+ if (keylenstr == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Key length must be specified "
+ "for AES and ARCFOUR 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);
+}