summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto/digest/digest.c
diff options
context:
space:
mode:
authorhylee <none@none>2007-03-13 17:01:48 -0700
committerhylee <none@none>2007-03-13 17:01:48 -0700
commitc197cb9db36685d2808c057fdbe5700734483ab2 (patch)
treeb7b451caf5991f2f401a29afa6a932c2ab51f625 /usr/src/cmd/cmd-crypto/digest/digest.c
parentafc2fd2a5a871e36a0a9d4caf75440127f572f5f (diff)
downloadillumos-joyent-c197cb9db36685d2808c057fdbe5700734483ab2.tar.gz
PSARC 2007/094 encrypt(1) / mac(1) token key support
4868006 encrypt(1) and mac(1) needs to support token objects 6517162 pktool genkey needs to support generic secret key
Diffstat (limited to 'usr/src/cmd/cmd-crypto/digest/digest.c')
-rw-r--r--usr/src/cmd/cmd-crypto/digest/digest.c273
1 files changed, 227 insertions, 46 deletions
diff --git a/usr/src/cmd/cmd-crypto/digest/digest.c b/usr/src/cmd/cmd-crypto/digest/digest.c
index 73b805c812..4ef01b23fb 100644
--- a/usr/src/cmd/cmd-crypto/digest/digest.c
+++ b/usr/src/cmd/cmd-crypto/digest/digest.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -52,6 +51,7 @@
#include <security/cryptoki.h>
#include <limits.h>
#include <cryptoutil.h>
+#include <kmfapi.h>
#define BUFFERSIZE (4096) /* Buffer size for reading file */
@@ -78,15 +78,23 @@
#define EXIT_USAGE 2 /* usage/syntax error */
#define MAC_NAME "mac" /* name of mac command */
-#define MAC_OPTIONS "lva:k:" /* for getopt */
+#define MAC_OPTIONS "lva:k:T:K:" /* for getopt */
#define DIGEST_NAME "digest" /* name of mac command */
#define DIGEST_OPTIONS "lva:" /* for getopt */
+#define DEFAULT_TOKEN_PROMPT "Enter PIN for %s: "
+#define PK_DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL
static boolean_t vflag = B_FALSE; /* -v (verbose) flag, optional */
static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
static boolean_t lflag = B_FALSE; /* -l flag, for mac and digest */
+static boolean_t kflag = B_FALSE;
+static boolean_t Tflag = B_FALSE;
+static boolean_t Kflag = B_FALSE;
static char *keyfile = NULL; /* name of keyfile */
+static char *token_label = NULL;
+static char *key_label = NULL;
+
static CK_BYTE buf[BUFFERSIZE];
struct mech_alias {
@@ -125,6 +133,7 @@ static CK_RV do_mac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
static CK_RV do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen);
static int getkey(char *filename, CK_BYTE_PTR *pkeydata);
+static int getpasswd(char *token_spec, CK_BYTE_PTR *pdata, CK_ULONG_PTR psize);
int
main(int argc, char **argv)
@@ -184,11 +193,20 @@ main(int argc, char **argv)
algo_str = optarg;
break;
case 'k':
+ kflag = B_TRUE;
keyfile = optarg;
break;
case 'l':
lflag = B_TRUE;
break;
+ case 'T':
+ Tflag = B_TRUE;
+ token_label = optarg;
+ break;
+ case 'K':
+ Kflag = B_TRUE;
+ key_label = optarg;
+ break;
default:
errflag++;
}
@@ -196,7 +214,7 @@ main(int argc, char **argv)
filecount = argc - optind;
if (errflag || (!aflag && !lflag) || (lflag && argc > 2) ||
- filecount < 0) {
+ (kflag && Kflag) || (Tflag && !Kflag) || filecount < 0) {
usage(mac_cmd);
exit(EXIT_USAGE);
}
@@ -216,14 +234,15 @@ main(int argc, char **argv)
static void
usage(boolean_t mac_cmd)
{
+ (void) fprintf(stderr, gettext("Usage:\n"));
if (mac_cmd) {
- cryptoerror(LOG_STDERR, gettext(
- "usage: mac -l | [-v] -a <algorithm> [-k <keyfile>] "
- "[file...]"));
+ (void) fprintf(stderr, gettext(" mac -l\n"));
+ (void) fprintf(stderr, gettext(" mac [-v] -a <algorithm> "
+ "[-k <keyfile> | -K <keylabel> [-T <tokenspec>]] "
+ "[file...]\n"));
} else {
- cryptoerror(LOG_STDERR,
- gettext("usage: digest -l | [-v] -a <algorithm> "
- "[file...]"));
+ (void) fprintf(stderr, gettext(" digest -l | [-v] "
+ "-a <algorithm> [file...]\n"));
}
}
@@ -325,6 +344,80 @@ generate_pkcs5_key(CK_SESSION_HANDLE hSession,
}
+static int
+get_token_key(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keytype,
+ char *keylabel, CK_BYTE *password, int password_len,
+ CK_OBJECT_HANDLE *keyobj)
+{
+ CK_RV rv;
+ CK_ATTRIBUTE pTmpl[10];
+ CK_OBJECT_CLASS class = CKO_SECRET_KEY;
+ CK_BBOOL true = 1;
+ CK_BBOOL is_token = 1;
+ CK_ULONG key_obj_count = 1;
+ int i;
+ CK_KEY_TYPE ckKeyType = keytype;
+
+
+ rv = C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)password,
+ password_len);
+ if (rv != CKR_OK) {
+ (void) fprintf(stderr, "Cannot login to the token."
+ " error = %s\n", pkcs11_strerror(rv));
+ return (-1);
+ }
+
+ i = 0;
+ pTmpl[i].type = CKA_TOKEN;
+ pTmpl[i].pValue = &is_token;
+ pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
+ i++;
+
+ pTmpl[i].type = CKA_CLASS;
+ pTmpl[i].pValue = &class;
+ pTmpl[i].ulValueLen = sizeof (class);
+ i++;
+
+ pTmpl[i].type = CKA_LABEL;
+ pTmpl[i].pValue = keylabel;
+ pTmpl[i].ulValueLen = strlen(keylabel);
+ i++;
+
+ pTmpl[i].type = CKA_KEY_TYPE;
+ pTmpl[i].pValue = &ckKeyType;
+ pTmpl[i].ulValueLen = sizeof (ckKeyType);
+ i++;
+
+ pTmpl[i].type = CKA_PRIVATE;
+ pTmpl[i].pValue = &true;
+ pTmpl[i].ulValueLen = sizeof (true);
+ i++;
+
+ rv = C_FindObjectsInit(hSession, pTmpl, i);
+ if (rv != CKR_OK) {
+ goto out;
+ }
+
+ rv = C_FindObjects(hSession, keyobj, 1, &key_obj_count);
+ (void) C_FindObjectsFinal(hSession);
+
+out:
+ if (rv != CKR_OK) {
+ (void) fprintf(stderr,
+ "Cannot retrieve key object. error = %s\n",
+ pkcs11_strerror(rv));
+ return (-1);
+ }
+
+ if (key_obj_count == 0) {
+ (void) fprintf(stderr, "Cannot find the key object.\n");
+ return (-1);
+ }
+
+ return (0);
+}
+
+
/*
* Execute the command.
* algo_str - name of algorithm
@@ -359,6 +452,9 @@ execute_cmd(char *algo_str, int filecount, char **filelist, boolean_t mac_cmd)
CK_BYTE salt[PBKD2_SALT_SIZE];
CK_ULONG keysize;
CK_ULONG iterations = PBKD2_ITERATIONS;
+ CK_KEY_TYPE keytype;
+ KMF_RETURN kmfrv;
+ CK_SLOT_ID token_slot_id;
if (aflag) {
/*
@@ -382,17 +478,36 @@ execute_cmd(char *algo_str, int filecount, char **filelist, boolean_t mac_cmd)
/* Get key to do a MAC operation */
if (mac_cmd) {
- keylen = getkey(keyfile, &pkeydata);
- if (keylen <= 0 || pkeydata == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("invalid key."));
- return (EXIT_FAILURE);
+ if (Kflag) {
+ int status;
+
+ if (token_label == NULL ||
+ !strlen(token_label)) {
+ token_label = PK_DEFAULT_PK11TOKEN;
+ }
+
+ status = getpasswd(token_label, &pkeydata,
+ (CK_ULONG *)&keylen);
+ if (status == -1) {
+ cryptoerror(LOG_STDERR,
+ gettext("invalid passphrase."));
+ return (EXIT_FAILURE);
+ }
+
+ } else {
+ keylen = getkey(keyfile, &pkeydata);
+ if (keylen <= 0 || pkeydata == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("invalid key."));
+ return (EXIT_FAILURE);
+ }
}
}
}
/* Initialize, and get list of slots */
- if ((rv = C_Initialize(NULL)) != CKR_OK) {
+ rv = C_Initialize(NULL);
+ if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
cryptoerror(LOG_STDERR,
gettext("failed to initialize PKCS #11 framework: %s"),
pkcs11_strerror(rv));
@@ -472,34 +587,56 @@ execute_cmd(char *algo_str, int filecount, char **filelist, boolean_t mac_cmd)
goto cleanup;
}
- /* Find a slot with matching mechanism */
- for (i = 0; i < slotcount; i++) {
- slotID = pSlotList[i];
- rv = C_GetMechanismInfo(slotID, mech_type, &info);
- if (rv != CKR_OK) {
- continue; /* to the next slot */
- } else {
- if (mac_cmd) {
- /*
- * Make sure the slot supports
- * PKCS5 key generation if we
- * will be using it later.
- * We use it whenever the key
- * is entered at command line.
- */
- if ((info.flags & CKF_SIGN) &&
- (keyfile == NULL)) {
- CK_MECHANISM_INFO kg_info;
- rv = C_GetMechanismInfo(slotID,
- CKM_PKCS5_PBKD2, &kg_info);
- if (rv == CKR_OK)
- break;
- } else if (info.flags & CKF_SIGN) {
- break;
- }
+ /*
+ * Find a slot with matching mechanism
+ *
+ * If -K is specified, we find the slot id for the token first, then
+ * check if the slot supports the algorithm.
+ */
+ i = 0;
+ if (Kflag) {
+ kmfrv = KMF_PK11TokenLookup(NULL, token_label, &token_slot_id);
+ if (kmfrv != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("no matching PKCS#11 token"));
+ exitcode = EXIT_FAILURE;
+ goto cleanup;
+ }
+ rv = C_GetMechanismInfo(token_slot_id, mech_type, &info);
+ if (rv == CKR_OK && (info.flags & CKF_SIGN))
+ slotID = token_slot_id;
+ else
+ i = slotcount;
+
+ } else {
+ for (i = 0; i < slotcount; i++) {
+ slotID = pSlotList[i];
+ rv = C_GetMechanismInfo(slotID, mech_type, &info);
+ if (rv != CKR_OK) {
+ continue; /* to the next slot */
} else {
- if (info.flags & CKF_DIGEST)
- break;
+ if (mac_cmd) {
+ /*
+ * Make sure the slot supports
+ * PKCS5 key generation if we
+ * will be using it later.
+ * We use it whenever the key
+ * is entered at command line.
+ */
+ if ((info.flags & CKF_SIGN) &&
+ (keyfile == NULL)) {
+ CK_MECHANISM_INFO kg_info;
+ rv = C_GetMechanismInfo(slotID,
+ CKM_PKCS5_PBKD2, &kg_info);
+ if (rv == CKR_OK)
+ break;
+ } else if (info.flags & CKF_SIGN) {
+ break;
+ }
+ } else {
+ if (info.flags & CKF_DIGEST)
+ break;
+ }
}
}
}
@@ -570,6 +707,21 @@ execute_cmd(char *algo_str, int filecount, char **filelist, boolean_t mac_cmd)
rv = C_CreateObject(hSession, template,
nattr, &key);
+
+ } else if (Kflag) {
+
+ if (mech_type == CKM_DES_MAC) {
+ keytype = CKK_DES;
+ } else {
+ keytype = CKK_GENERIC_SECRET;
+ }
+
+ rv = get_token_key(hSession, keytype, key_label,
+ pkeydata, keylen, &key);
+ if (rv != CKR_OK) {
+ exitcode = EXIT_FAILURE;
+ goto cleanup;
+ }
} else {
CK_KEY_TYPE keytype;
if (mech_type == CKM_DES_MAC) {
@@ -716,7 +868,7 @@ cleanup:
free(pSlotList);
}
- if (key != (CK_OBJECT_HANDLE) 0) {
+ if (!Kflag && key != (CK_OBJECT_HANDLE) 0) {
(void) C_DestroyObject(hSession, key);
}
@@ -939,3 +1091,32 @@ getkey(char *filename, CK_BYTE_PTR *pkeydata)
return (keylen);
}
+
+static int
+getpasswd(char *token_spec, CK_BYTE_PTR *pdata, CK_ULONG *psize)
+{
+ char *databuf;
+ char *tmpbuf;
+ char prompt[1024];
+
+ if (token_spec == NULL)
+ return (-1);
+
+ (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT,
+ token_spec);
+ tmpbuf = getpassphrase(gettext(prompt));
+
+ if (tmpbuf == NULL) {
+ return (-1); /* error */
+ }
+
+ databuf = strdup(tmpbuf);
+ (void) memset(tmpbuf, 0, strlen(tmpbuf));
+ if (databuf == NULL)
+ return (-1);
+
+ *pdata = (CK_BYTE_PTR)databuf;
+ *psize = (CK_ULONG)strlen(databuf);
+
+ return (0);
+}