summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto/pktool/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/common.c')
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/common.c1471
1 files changed, 576 insertions, 895 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.c b/usr/src/cmd/cmd-crypto/pktool/common.c
index 030f8c158a..660afe2d57 100644
--- a/usr/src/cmd/cmd-crypto/pktool/common.c
+++ b/usr/src/cmd/cmd-crypto/pktool/common.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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,19 +37,19 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <tzfile.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
-#include "common.h"
-#include "biginteger.h"
+#include <kmfapi.h>
-/* True and false for attribute templates. */
-CK_BBOOL pk_true = B_TRUE;
-CK_BBOOL pk_false = B_FALSE;
+#include "common.h"
/* Local status variables. */
static boolean_t initialized = B_FALSE;
static boolean_t session_opened = B_FALSE;
-static boolean_t session_writable = B_FALSE;
static boolean_t logged_in = B_FALSE;
/* Supporting structures and global variables for getopt_av(). */
@@ -67,6 +66,9 @@ static int _save_numopts = 0;
int optind_av = 1;
char *optarg_av = NULL;
+static void close_sess(CK_SESSION_HANDLE);
+static void logout_token(CK_SESSION_HANDLE);
+
/*
* Perform PKCS#11 setup here. Currently only C_Initialize is required,
* along with setting/resetting state variables.
@@ -76,19 +78,15 @@ init_pk11(void)
{
CK_RV rv = CKR_OK;
- cryptodebug("inside init_pk11");
-
/* If C_Initialize() already called, nothing to do here. */
if (initialized == B_TRUE)
return (CKR_OK);
/* Reset state variables because C_Initialize() not yet done. */
session_opened = B_FALSE;
- session_writable = B_FALSE;
logged_in = B_FALSE;
/* Initialize PKCS#11 library. */
- cryptodebug("calling C_Initialize()");
if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
return (rv);
@@ -105,7 +103,6 @@ init_pk11(void)
void
final_pk11(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside final_pk11");
/* If the library wasn't initialized, nothing to do here. */
if (!initialized)
@@ -114,127 +111,41 @@ final_pk11(CK_SESSION_HANDLE sess)
/* Make sure the sesion is closed first. */
close_sess(sess);
- cryptodebug("calling C_Finalize()");
(void) C_Finalize(NULL);
initialized = B_FALSE;
}
/*
- * Create a PKCS#11 session on the given slot, and set state information.
- * If session is already open, check that the read-only/read-write state
- * requested matches that of the session. If it doesn't, make it so.
- */
-CK_RV
-open_sess(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside open_sess");
-
- /* If the session is already open, check the session flags. */
- if (session_opened) {
- /*
- * If requesting R/W session and it is currently R/O,
- * need to close the session and reopen it R/W. The
- * other cases are considered acceptable:
- * sess_flags current state
- * ---------- -------------
- * ~CKF_RW_SESSION !session_writable
- * ~CKF_RW_SESSION session_writable
- * CKF_RW_SESSION session_writable
- */
- if ((sess_flags & CKF_RW_SESSION) && !session_writable)
- close_sess(*sess);
- else
- return (CKR_OK);
- }
-
- /* Make sure the PKCS#11 is already initialized. */
- if (!initialized)
- if ((rv = init_pk11()) != CKR_OK)
- return (rv);
-
- /* Create a session for subsequent operations. */
- cryptodebug("calling C_OpenSession()");
- if ((rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION|sess_flags,
- NULL, NULL, sess)) != CKR_OK)
- return (rv);
- session_opened = B_TRUE;
- session_writable = (sess_flags & CKF_RW_SESSION) ? B_TRUE : B_FALSE;
- return (CKR_OK);
-}
-
-/*
* Close PKCS#11 session and reset state variables. Any logins are
* logged out.
*/
-void
+static void
close_sess(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside close_sess");
if (sess == NULL) {
- cryptodebug("session handle is null");
return;
}
/* If session is already closed, nothing to do here. */
- session_writable = B_FALSE;
if (!session_opened)
return;
/* Make sure user is logged out of token. */
logout_token(sess);
- cryptodebug("calling C_CloseSession()");
(void) C_CloseSession(sess);
session_opened = B_FALSE;
}
/*
- * Log user into token in given slot. If this first login ever for this
- * token, the initial PIN is "changeme", C_Login() will succeed, but all
- * PKCS#11 calls following the C_Login() will fail with CKR_PIN_EXPIRED.
- */
-CK_RV
-login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pinlen,
- CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside login_token");
-
- /* If already logged in, nothing to do here. */
- if (logged_in)
- return (CKR_OK);
-
- /* Make sure we have a session first, assume R/O is enough. */
- if (!session_opened)
- if ((rv = open_sess(slot_id, CKF_SERIAL_SESSION, sess)) !=
- CKR_OK)
- return (rv);
-
- /* Log the user into the token. */
- cryptodebug("calling C_Login()");
- if ((rv = C_Login(*sess, CKU_USER, pin, pinlen)) != CKR_OK) {
- cryptodebug("C_Login returns %s", pkcs11_strerror(rv));
- return (rv);
- }
-
- logged_in = B_TRUE;
- return (CKR_OK);
-}
-
-/*
* Log user out of token and reset status variable.
*/
-void
+static void
logout_token(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside logout_token");
if (sess == NULL) {
- cryptodebug("session handle is null");
return;
}
@@ -242,49 +153,11 @@ logout_token(CK_SESSION_HANDLE sess)
if (!logged_in)
return;
- cryptodebug("calling C_Logout()");
(void) C_Logout(sess);
logged_in = B_FALSE;
}
/*
- * Shortcut function to get from an uninitialized state to user logged in.
- * If the library is already initialized, the session is already opened,
- * or the user is already logged in, those steps are skipped and the next
- * step is checked.
- */
-CK_RV
-quick_start(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_UTF8CHAR_PTR pin,
- CK_ULONG pinlen, CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside quick_start");
-
- /* Call open_sess() explicitly if R/W session is needed. */
- if (sess_flags & CKF_RW_SESSION)
- if ((rv = open_sess(slot_id, sess_flags, sess)) != CKR_OK)
- return (rv);
-
- if ((rv = login_token(slot_id, pin, pinlen, sess)) != CKR_OK)
- return (rv);
-
- return (CKR_OK);
-}
-
-/*
- * Shortcut function to go from any state to uninitialized PKCS#11 library.
- */
-void
-quick_finish(CK_SESSION_HANDLE sess)
-{
- cryptodebug("inside quick_finish");
-
- /* All the needed calls are done implicitly. */
- final_pk11(sess);
-}
-
-/*
* Gets PIN from user. Caller needs to free the returned PIN when done.
* If two prompts are given, the PIN is confirmed with second prompt.
* Note that getphassphrase() may return data in static memory area.
@@ -294,15 +167,20 @@ get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
{
char *save_phrase, *phrase1, *phrase2;
- cryptodebug("inside get_pin");
+
+#ifdef DEBUG
+ if (getenv("TOKENPIN") != NULL) {
+ *pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN"));
+ *pinlen = strlen((char *)(*pin));
+ return (CKR_OK);
+ }
+#endif /* DEBUG */
/* Prompt user for a PIN. */
if (prompt1 == NULL) {
- cryptodebug("no passphrase prompt given");
return (CKR_ARGUMENTS_BAD);
}
if ((phrase1 = getpassphrase(prompt1)) == NULL) {
- cryptodebug("getpassphrase() failed");
return (CKR_FUNCTION_FAILED);
}
@@ -313,12 +191,10 @@ get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
/* If second prompt given, PIN confirmation is requested. */
if (prompt2 != NULL) {
if ((phrase2 = getpassphrase(prompt2)) == NULL) {
- cryptodebug("getpassphrase() confirmation failed");
free(save_phrase);
return (CKR_FUNCTION_FAILED);
}
if (strcmp(save_phrase, phrase2) != 0) {
- cryptodebug("passphrases do not match");
free(save_phrase);
return (CKR_PIN_INCORRECT);
}
@@ -343,7 +219,13 @@ yesno(char *prompt, char *invalid, boolean_t dflt)
char *yes = gettext("yes");
char *no = gettext("no");
- cryptodebug("inside yesno");
+
+#ifdef DEBUG
+ /* If debugging or testing, return TRUE and avoid prompting */
+ if (getenv("TOKENPIN") != NULL) {
+ return (B_TRUE);
+ }
+#endif /* DEBUG */
if (prompt == NULL)
prompt = gettext("Enter (y)es or (n)o? ");
@@ -388,8 +270,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
int rv = CKR_OK;
- cryptodebug("inside get_token_slots");
-
if (!initialized)
if ((rv = init_pk11()) != CKR_OK)
return (rv);
@@ -402,12 +282,10 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
* Also select only those slots that have tokens in them,
* because this tool has no need to know about empty slots.
*/
- cryptodebug("calling C_GetSlotList() for slot count");
if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
return (rv);
if (tmp_count == 0) {
- cryptodebug("no slots with tokens found");
*slot_list = NULL_PTR;
*slot_count = 0;
return (CKR_OK);
@@ -420,7 +298,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
/* Then get the slot list itself. */
for (;;) {
- cryptodebug("calling C_GetSlotList()");
if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
*slot_list = tmp_list;
*slot_count = tmp_count;
@@ -433,7 +310,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
}
/* If the number of slots grew, try again. */
- cryptodebug("number of tokens present increased");
if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
free(tmp_list);
@@ -447,878 +323,683 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
}
/*
- * memcmp_pad_max() is a specialized version of memcmp() which
- * compares two pieces of data up to a maximum length. If the
- * the two data match up the maximum length, they are considered
- * matching. Trailing blanks do not cause the match to fail if
- * one of the data is shorted.
- *
- * Examples of matches:
- * "one" |
- * "one " |
- * ^maximum length
- *
- * "Number One | X" (X is beyond maximum length)
- * "Number One " |
- * ^maximum length
- *
- * Examples of mismatches:
- * " one"
- * "one"
- *
- * "Number One X|"
- * "Number One |"
- * ^maximum length
+ * Breaks out the getopt-style option string into a structure that can be
+ * traversed later for calls to getopt_av(). Option string is NOT altered,
+ * but the struct fields point to locations within option string.
*/
static int
-memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
+populate_opts(char *optstring)
{
- uint_t len, extra_len;
+ int i;
+ av_opts *temp;
char *marker;
- /* No point in comparing anything beyond max_sz */
- if (d1_len > max_sz)
- d1_len = max_sz;
- if (d2_len > max_sz)
- d2_len = max_sz;
-
- /* Find shorter of the two data. */
- if (d1_len <= d2_len) {
- len = d1_len;
- extra_len = d2_len;
- marker = d2;
- } else { /* d1_len > d2_len */
- len = d2_len;
- extra_len = d1_len;
- marker = d1;
- }
+ if (optstring == NULL || *optstring == '\0')
+ return (0);
+
+ /*
+ * This tries to imitate getopt(3c) Each option must conform to:
+ * <short name char> [ ':' ] [ '(' <long name string> ')' ]
+ * If long name is missing, the short name is used for long name.
+ */
+ for (i = 0; *optstring != '\0'; i++) {
+ if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
+ realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ return (0);
+ } else {
+ opts_av = (av_opts *)temp;
+ }
- /* Have a match in the shortest length of data? */
- if (memcmp(d1, d2, len) != 0)
- /* CONSTCOND */
- return (!0);
+ (void) memset(&opts_av[i], 0, sizeof (av_opts));
+ marker = optstring; /* may need optstring later */
- /* If the rest of longer data is nulls or blanks, call it a match. */
- while (len < extra_len)
- if (!isspace(marker[len++]))
- /* CONSTCOND */
- return (!0);
- return (0);
+ opts_av[i].shortnm = *marker++; /* set short name */
+
+ if (*marker == ':') { /* check for opt arg */
+ marker++;
+ opts_av[i].has_arg = B_TRUE;
+ }
+
+ if (*marker == '(') { /* check and set long name */
+ marker++;
+ opts_av[i].longnm = marker;
+ opts_av[i].longnm_len = strcspn(marker, ")");
+ optstring = marker + opts_av[i].longnm_len + 1;
+ } else {
+ /* use short name option character */
+ opts_av[i].longnm = optstring;
+ opts_av[i].longnm_len = 1;
+ optstring = marker;
+ }
+ }
+
+ return (i);
}
/*
- * Locate a token slot whose token matches the label, manufacturer ID, and
- * serial number given. Token label must be specified, manufacturer ID and
- * serial number are optional. When the token is located, the PIN state
- * is also returned to determine if it still has the default PIN.
+ * getopt_av() is very similar to getopt(3c) in that the takes an option
+ * string, compares command line arguments for matches, and returns a single
+ * letter option when a match is found. However, getopt_av() differs from
+ * getopt(3c) by requiring that only longname options and values be found
+ * on the command line and all leading dashes are omitted. In other words,
+ * it tries to enforce only longname "option=value" arguments on the command
+ * line. Boolean options are not allowed either.
*/
-CK_RV
-find_token_slot(char *token_name, char *manuf_id, char *serial_no,
- CK_SLOT_ID *slot_id, CK_FLAGS *pin_state)
+int
+getopt_av(int argc, char * const *argv, const char *optstring)
{
- CK_SLOT_ID_PTR slot_list;
- CK_TOKEN_INFO token_info;
- CK_ULONG slot_count = 0;
- int rv = CKR_OK;
- int i;
- uint_t len, max_sz;
- boolean_t tok_match = B_FALSE,
- man_match = B_FALSE,
- ser_match = B_FALSE;
+ int i;
+ int len;
+ char *cur_option;
- cryptodebug("inside find_token_slot");
+ if (optind_av >= argc)
+ return (EOF);
- if (token_name == NULL)
- return (CKR_ARGUMENTS_BAD);
+ /* First time or when optstring changes from previous one */
+ if (_save_optstr != optstring) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ _save_optstr = optstring;
+ _save_numopts = populate_opts((char *)optstring);
+ }
- /* Get a list of all slots with tokens present. */
- if ((rv = get_token_slots(&slot_list, &slot_count)) != CKR_OK)
- return (rv);
+ for (i = 0; i < _save_numopts; i++) {
+ cur_option = argv[optind_av];
- /* If there are no such slots, the desired token won't be found. */
- if (slot_count == 0)
- return (CKR_TOKEN_NOT_PRESENT);
-
- /* Search the slot list for the token. */
- for (i = 0; i < slot_count; i++) {
- cryptodebug("calling C_GetTokenInfo()");
- if ((rv = C_GetTokenInfo(slot_list[i], &token_info)) !=
- CKR_OK) {
- cryptodebug("token in slot %d returns %s", i,
- pkcs11_strerror(rv));
- continue;
+ if (strcmp(cur_option, "--") == 0) {
+ optind_av++;
+ break;
}
- /* See if the token label matches. */
- len = strlen(token_name);
- max_sz = sizeof (token_info.label);
- if (memcmp_pad_max(&(token_info.label), max_sz, token_name, len,
- max_sz) == 0)
- tok_match = B_TRUE;
-
- /*
- * If manufacturer id was given, see if it actually matches.
- * If no manufacturer id was given, assume match is true.
- */
- if (manuf_id) {
- len = strlen(manuf_id);
- max_sz = sizeof ((char *)(token_info.manufacturerID));
- if (memcmp_pad_max(&(token_info.manufacturerID), max_sz,
- manuf_id, len, max_sz) == 0)
- man_match = B_TRUE;
- } else
- man_match = B_TRUE;
-
- /*
- * If serial number was given, see if it actually matches.
- * If no serial number was given, assume match is true.
- */
- if (serial_no) {
- len = strlen(serial_no);
- max_sz = sizeof ((char *)(token_info.serialNumber));
- if (memcmp_pad_max(&(token_info.serialNumber), max_sz,
- serial_no, len, max_sz) == 0)
- ser_match = B_TRUE;
- } else
- ser_match = B_TRUE;
-
- cryptodebug("slot %d:", i);
- cryptodebug("\tlabel = \"%.32s\"%s", token_info.label,
- tok_match ? " match" : "");
- cryptodebug("\tmanuf = \"%.32s\"%s", token_info.manufacturerID,
- man_match ? " match" : "");
- cryptodebug("\tserno = \"%.16s\"%s", token_info.serialNumber,
- ser_match ? " match" : "");
- cryptodebug("\tmodel = \"%.16s\"", token_info.model);
-
- cryptodebug("\tCKF_USER_PIN_INITIALIZED = %s",
- (token_info.flags & CKF_USER_PIN_INITIALIZED) ?
- "true" : "false");
- cryptodebug("\tCKF_USER_PIN_TO_BE_CHANGED = %s",
- (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED) ?
- "true" : "false");
-
- if (tok_match && man_match && ser_match)
- break; /* found it! */
- }
+ if (cur_option[0] == '-' && strlen(cur_option) == 2) {
+ len = 1;
+ cur_option++; /* remove "-" */
+ } else {
+ len = strcspn(cur_option, "=");
+ }
- /* Scanned the whole list without finding the token. */
- if (i == slot_count) {
- cryptodebug("token not found");
- free(slot_list);
- return (CKR_TOKEN_NOT_PRESENT);
+ if (len == opts_av[i].longnm_len && strncmp(cur_option,
+ opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
+ /* matched */
+ if (!opts_av[i].has_arg) {
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ /* needs optarg */
+ if (cur_option[len] == '=') {
+ optarg_av = &(cur_option[len+1]);
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ optarg_av = NULL;
+ optind_av++;
+ return ((int)'?');
+ }
}
- /* Return slot id where token was found and its PIN state. */
- cryptodebug("token found at slot %d", i);
- *slot_id = slot_list[i];
- *pin_state = (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED);
- free(slot_list);
- return (CKR_OK);
+ return (EOF);
}
-/*
- * Returns pointer to either null-terminator or next unescaped colon. The
- * string to be extracted starts at the beginning and goes until one character
- * before this pointer. If NULL is returned, the string itself is NULL.
- */
-static char *
-find_unescaped_colon(char *str)
+KMF_KEYSTORE_TYPE
+KS2Int(char *keystore_str)
{
- char *end;
+ if (keystore_str == NULL)
+ return (0);
+ if (!strcasecmp(keystore_str, "pkcs11"))
+ return (KMF_KEYSTORE_PK11TOKEN);
+ else if (!strcasecmp(keystore_str, "nss"))
+ return (KMF_KEYSTORE_NSS);
+ else if (!strcasecmp(keystore_str, "file"))
+ return (KMF_KEYSTORE_OPENSSL);
+ else
+ return (0);
+}
- if (str == NULL)
- return (NULL);
- while ((end = strchr(str, ':')) != NULL) {
- if (end != str && *(end-1) != '\\')
- return (end);
- str = end + 1; /* could point to null-terminator */
+int
+Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
+{
+ if (algm == NULL) {
+ *sigAlg = KMF_ALGID_MD5WithRSA;
+ *ktype = KMF_RSA;
+ } else if (strcasecmp(algm, "DSA") == 0) {
+ *sigAlg = KMF_ALGID_SHA1WithDSA;
+ *ktype = KMF_DSA;
+ } else if (strcasecmp(algm, "RSA") == 0) {
+ *sigAlg = KMF_ALGID_MD5WithRSA;
+ *ktype = KMF_RSA;
+ } else {
+ return (-1);
}
- if (end == NULL)
- end = strchr(str, '\0');
- return (end);
+ return (0);
}
-/*
- * Compresses away any characters escaped with backslash from given string.
- * The string is altered in-place. Example, "ab\:\\e" becomes "ab:\e".
- */
-static void
-unescape_str(char *str)
+int
+Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
{
- boolean_t escaped = B_FALSE;
- char *mark;
-
- if (str == NULL)
- return;
+ if (algm == NULL)
+ *ktype = KMF_AES;
+ else if (strcasecmp(algm, "aes") == 0)
+ *ktype = KMF_AES;
+ else if (strcasecmp(algm, "arcfour") == 0)
+ *ktype = KMF_RC4;
+ else if (strcasecmp(algm, "des") == 0)
+ *ktype = KMF_DES;
+ else if (strcasecmp(algm, "3des") == 0)
+ *ktype = KMF_DES3;
+ else
+ return (-1);
- for (mark = str; *str != '\0'; str++) {
- if (*str != '\\' || escaped == B_TRUE) {
- *mark++ = *str;
- escaped = B_FALSE;
- } else {
- escaped = B_TRUE;
- }
- }
- *mark = '\0';
+ return (0);
}
-/*
- * Given a colon-separated token specifier, this functions splits it into
- * its label, manufacturer ID (if any), and serial number (if any). Literal
- * colons within the label/manuf/serial can be escaped with a backslash.
- * Fields can left blank and trailing colons can be omitted, however leading
- * colons are required as placeholders. For example, these are equivalent:
- * (a) "lbl", "lbl:", "lbl::" (b) "lbl:man", "lbl:man:"
- * but these are not:
- * (c) "man", ":man" (d) "ser", "::ser"
- * Furthermore, the token label is required always.
- *
- * The buffer containing the token specifier is altered by replacing the
- * colons to null-terminators, and pointers returned are pointers into this
- * string. No new memory is allocated.
- */
int
-parse_token_spec(char *token_spec, char **token_name, char **manuf_id,
- char **serial_no)
+Str2Lifetime(char *ltimestr, uint32_t *ltime)
{
- char *mark;
+ int num;
+ char timetok[6];
- if (token_spec == NULL || *token_spec == '\0') {
- cryptodebug("token specifier is empty");
- return (-1);
+ if (ltimestr == NULL || !strlen(ltimestr)) {
+ /* default to 1 year lifetime */
+ *ltime = SECSPERDAY * DAYSPERNYEAR;
+ return (0);
}
- *token_name = NULL;
- *manuf_id = NULL;
- *serial_no = NULL;
-
- /* Token label (required) */
- mark = find_unescaped_colon(token_spec);
- *token_name = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* mark points to next field, if any */
- unescape_str(*token_name);
+ (void) memset(timetok, 0, sizeof (timetok));
+ if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
+ return (-1);
- if (*(*token_name) == '\0') { /* token label is required */
- cryptodebug("no token label found");
+ if (!strcasecmp(timetok, "day") ||
+ !strcasecmp(timetok, "days")) {
+ *ltime = num * SECSPERDAY;
+ } else if (!strcasecmp(timetok, "hour") ||
+ !strcasecmp(timetok, "hours")) {
+ *ltime = num * SECSPERHOUR;
+ } else if (!strcasecmp(timetok, "year") ||
+ !strcasecmp(timetok, "years")) {
+ *ltime = num * SECSPERDAY * DAYSPERNYEAR;
+ } else {
+ *ltime = 0;
return (-1);
}
- if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */
- return (0);
- token_spec = mark;
-
- /* Manufacturer identifier (optional) */
- mark = find_unescaped_colon(token_spec);
- *manuf_id = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* mark points to next field, if any */
- unescape_str(*manuf_id);
+ return (0);
+}
- if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */
- return (0);
- token_spec = mark;
+int
+OT2Int(char *objclass)
+{
+ char *c = NULL;
+ int retval = 0;
- /* Serial number (optional) */
- mark = find_unescaped_colon(token_spec);
- *serial_no = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* null-terminate, just in case */
- unescape_str(*serial_no);
+ if (objclass == NULL)
+ return (-1);
- return (0);
+ c = strchr(objclass, ':');
+ if (c != NULL) {
+ if (!strcasecmp(c, ":private"))
+ retval = PK_PRIVATE_OBJ;
+ else if (!strcasecmp(c, ":public"))
+ retval = PK_PUBLIC_OBJ;
+ else if (!strcasecmp(c, ":both"))
+ retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
+ else /* unrecognized option */
+ return (-1);
+
+ *c = '\0';
+ }
+
+ if (!strcasecmp(objclass, "public")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ |
+ PK_PUBKEY_OBJ);
+ } else if (!strcasecmp(objclass, "private")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
+ } else if (!strcasecmp(objclass, "both")) {
+ if (retval)
+ return (-1);
+ return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
+ } else if (!strcasecmp(objclass, "cert")) {
+ return (retval | PK_CERT_OBJ);
+ } else if (!strcasecmp(objclass, "key")) {
+ if (retval == 0) /* return all keys */
+ return (retval | PK_KEY_OBJ);
+ else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
+ /* return all keys */
+ return (retval | PK_KEY_OBJ);
+ else if (retval & PK_PUBLIC_OBJ)
+ /* Only return public keys */
+ return (retval | PK_PUBKEY_OBJ);
+ else if (retval & PK_PRIVATE_OBJ)
+ /* Only return private keys */
+ return (retval | PK_PRIKEY_OBJ);
+ } else if (!strcasecmp(objclass, "crl")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_CRL_OBJ);
+ }
+
+ if (retval == 0) /* No matches found */
+ retval = -1;
+ return (retval);
}
-/*
- * Constructs a fully qualified token name from its label, manufacturer ID
- * (if any), and its serial number (if any). Note that the given buf must
- * be big enough. Do NOT i18n/l10n.
- *
- * FULL_NAME_LEN is defined in common.h to be 91 because a fully qualified
- * token name adds up this way:
- * =32(label) + 32(manuf) + 16(serial) + 4("", ) + 4("", ) + 3("" and nul)
- */
-void
-full_token_name(char *token_name, char *manuf_id, char *serial_no, char *buf)
+KMF_ENCODE_FORMAT
+Str2Format(char *formstr)
{
- char *marker = buf;
- int n_written = 0;
- int space_left = FULL_NAME_LEN;
+ if (formstr == NULL || !strcasecmp(formstr, "der"))
+ return (KMF_FORMAT_ASN1);
+ if (!strcasecmp(formstr, "pem"))
+ return (KMF_FORMAT_PEM);
+ if (!strcasecmp(formstr, "pkcs12"))
+ return (KMF_FORMAT_PKCS12);
+
+ return (KMF_FORMAT_UNDEF);
+}
- if (!token_name)
- return;
- n_written = sprintf(buf, "\"%.32s\"", token_name);
- marker += n_written;
- space_left -= n_written;
+KMF_RETURN
+select_token(void *kmfhandle, char *token,
+ int readonly)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_CONFIG_PARAMS config;
- n_written = sprintf(marker, ", \"%.32s\"", manuf_id ? manuf_id : "");
- marker += n_written;
- space_left -= n_written;
+ if (token == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
- n_written = sprintf(marker, ", \"%.16s\"", serial_no ? serial_no : "");
- marker += n_written;
- space_left -= n_written;
+ (void) memset(&config, 0, sizeof (config));
+ config.kstype = KMF_KEYSTORE_PK11TOKEN;
+ config.pkcs11config.label = token;
+ config.pkcs11config.readonly = readonly;
- /* space_left should always be >= 1 */
+ rv = KMF_ConfigureKeystore(kmfhandle, &config);
+ if (rv == KMF_ERR_TOKEN_SELECTED)
+ rv = KMF_OK;
+ return (rv);
}
-/*
- * Find how many token objects with the given label.
- */
-CK_RV
-find_obj_count(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label,
- CK_ULONG *count)
+
+KMF_RETURN
+configure_nss(void *kmfhandle, char *dir, char *prefix)
{
- CK_RV rv = CKR_OK;
- CK_ATTRIBUTE attrs[4] = {
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { 0, NULL, 0 },
- { 0, NULL, 0 },
- { 0, NULL, 0 }
- };
- CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */
- CK_OBJECT_CLASS obj_class;
- CK_OBJECT_HANDLE tmp_obj;
- CK_ULONG obj_count = 0;
-
- cryptodebug("inside find_obj_count");
-
- if (!session_opened || sess == NULL) {
- cryptodebug("session handle is null");
- return (CKR_SESSION_HANDLE_INVALID);
- }
+ KMF_RETURN rv = KMF_OK;
+ KMF_CONFIG_PARAMS config;
- if (label) {
- cryptodebug("object label was specified");
- attrs[cur_attr].type = CKA_LABEL;
- attrs[cur_attr].pValue = label;
- attrs[cur_attr].ulValueLen = strlen((char *)label);
- cur_attr++;
- }
+ (void) memset(&config, 0, sizeof (config));
+ config.kstype = KMF_KEYSTORE_NSS;
+ config.nssconfig.configdir = dir;
+ config.nssconfig.certPrefix = prefix;
+ config.nssconfig.keyPrefix = prefix;
+ config.nssconfig.secModName = NULL;
- if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) {
- cryptodebug("only searching for private objects");
- attrs[cur_attr].type = CKA_PRIVATE;
- attrs[cur_attr].pValue = &pk_true;
- attrs[cur_attr].ulValueLen = sizeof (pk_true);
- cur_attr++;
- }
+ rv = KMF_ConfigureKeystore(kmfhandle, &config);
+ if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
+ rv = KMF_OK;
- /*
- * If "certs and all keys" is not specified, but at least either
- * "certs" or some "keys" is specified, then go into this block.
- * If all certs and keys were specified, there's no point in
- * putting that fact in the attribute template -- leave that open,
- * and all certs and keys will be matched automatically.
- * In other words, only if at least one of 0x10,0x20,0x40,0x80
- * bits is off, go into this code block.
- *
- * NOTE: For now, only one of cert or key types is allowed.
- * This needs to change in the future.
- */
- if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) &&
- ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) {
- if (obj_type & PK_CERT_OBJ) {
- cryptodebug("only searching for certificates");
- obj_class = CKO_CERTIFICATE;
- } else if (obj_type & PK_PRIKEY_OBJ) {
- cryptodebug("only searching for private keys");
- obj_class = CKO_PRIVATE_KEY;
- } else if (obj_type & PK_PUBKEY_OBJ) {
- cryptodebug("only searching for public keys");
- obj_class = CKO_PUBLIC_KEY;
- } else if (obj_type & PK_SECKEY_OBJ) {
- cryptodebug("only searching for secret keys");
- obj_class = CKO_SECRET_KEY;
- }
+ return (rv);
+}
- attrs[cur_attr].type = CKA_CLASS;
- attrs[cur_attr].pValue = &obj_class;
- attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS);
- cur_attr++;
- }
+
+KMF_RETURN
+get_pk12_password(KMF_CREDENTIAL *cred)
+{
+ KMF_RETURN rv = KMF_OK;
+ char prompt[1024];
/*
- * This can't happen now. When finding objects is enhanced in the
- * future. this could lead to buffer overruns.
+ * Get the password to use for the PK12 encryption.
*/
- if (cur_attr > num_attrs)
- cryptodebug("internal error: attr template overrun");
+ (void) strlcpy(prompt,
+ gettext("Enter password to use for "
+ "accessing the PKCS12 file: "),
+ sizeof (prompt));
- cryptodebug("calling C_FindObjectsInit");
- if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK)
- return (rv);
-
- /* Look for the object, checking if there are more than one. */
- cryptodebug("calling C_FindObjects");
- for (*count = 0; /* empty */; (*count)++) {
- if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) !=
- CKR_OK)
- break;
-
- /* No more found. */
- if (obj_count == 0)
- break;
+ if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
+ (ulong_t *)&cred->credlen) != CKR_OK) {
+ cred->cred = NULL;
+ cred->credlen = 0;
}
- cryptodebug("%d matching objects found", *count);
-
- cryptodebug("calling C_FindObjectsFinal");
- (void) C_FindObjectsFinal(sess);
return (rv);
}
-/*
- * Find the token object with the given label.
- */
-CK_RV
-find_objs(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label,
- CK_OBJECT_HANDLE_PTR *obj, CK_ULONG *count)
-{
- CK_RV rv = CKR_OK;
- CK_ATTRIBUTE attrs[4] = {
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { 0, NULL, 0 },
- { 0, NULL, 0 },
- { 0, NULL, 0 }
- };
- CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */
- CK_OBJECT_CLASS obj_class;
- CK_OBJECT_HANDLE tmp_obj;
- CK_ULONG obj_count = 0;
- int i;
-
- cryptodebug("inside find_obj");
-
- if ((rv = find_obj_count(sess, obj_type, label, count)) != CKR_OK)
- return (rv);
- if (*count == 0)
- return (CKR_OK);
+#define COUNTRY_PROMPT "Country Name (2 letter code) [US]:"
+#define STATE_PROMPT "State or Province Name (full name) [Some-State]:"
+#define LOCALITY_PROMPT "Locality Name (eg, city) []:"
+#define ORG_PROMPT "Organization Name (eg, company) []:"
+#define UNIT_PROMPT "Organizational Unit Name (eg, section) []:"
+#define NAME_PROMPT "Common Name (eg, YOUR name) []:"
+#define EMAIL_PROMPT "Email Address []:"
- if ((*obj = (CK_OBJECT_HANDLE_PTR) malloc((*count) *
- sizeof (CK_OBJECT_HANDLE))) == NULL) {
- cryptodebug("no memory for found object");
- return (CKR_HOST_MEMORY);
- }
+#define COUNTRY_DEFAULT "US"
+#define STATE_DEFAULT "Some-State"
+#define INVALID_INPUT "Invalid input; please re-enter ..."
- if (label) {
- cryptodebug("object label was specified");
- attrs[cur_attr].type = CKA_LABEL;
- attrs[cur_attr].pValue = label;
- attrs[cur_attr].ulValueLen = strlen((char *)label);
- cur_attr++;
- }
+#define SUBNAMESIZ 1024
+#define RDN_MIN 1
+#define RDN_MAX 64
+#define COUNTRYNAME_MIN 2
+#define COUNTRYNAME_MAX 2
- if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) {
- cryptodebug("only searching for private objects");
- attrs[cur_attr].type = CKA_PRIVATE;
- attrs[cur_attr].pValue = &pk_true;
- attrs[cur_attr].ulValueLen = sizeof (pk_true);
- cur_attr++;
- }
+static char *
+get_input_string(char *prompt, char *default_str, int min_len, int max_len)
+{
+ char buf[1024];
+ char *response = NULL;
+ char *ret = NULL;
+ int len;
- /*
- * If "certs and all keys" is not specified, but at least either
- * "certs" or some "keys" is specified, then go into this block.
- * If all certs and keys were specified, there's no point in
- * putting that fact in the attribute template -- leave that open,
- * and all certs and keys will be matched automatically.
- * In other words, only if at least one of 0x10,0x20,0x40,0x80
- * bits is off, go into this code block.
- *
- * NOTE: For now, only one of cert or key types is allowed.
- * This needs to change in the future.
- */
- if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) &&
- ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) {
- if (obj_type & PK_CERT_OBJ) {
- cryptodebug("only searching for certificates");
- obj_class = CKO_CERTIFICATE;
- } else if (obj_type & PK_PRIKEY_OBJ) {
- cryptodebug("only searching for private keys");
- obj_class = CKO_PRIVATE_KEY;
- } else if (obj_type & PK_PUBKEY_OBJ) {
- cryptodebug("only searching for public keys");
- obj_class = CKO_PUBLIC_KEY;
- } else if (obj_type & PK_SECKEY_OBJ) {
- cryptodebug("only searching for secret keys");
- obj_class = CKO_SECRET_KEY;
+ for (;;) {
+ (void) printf("\t%s", prompt);
+ (void) fflush(stdout);
+
+ response = fgets(buf, sizeof (buf), stdin);
+ if (response == NULL) {
+ if (default_str != NULL) {
+ ret = strdup(default_str);
+ }
+ break;
+ }
+
+ /* Skip any leading white space. */
+ while (isspace(*response))
+ response++;
+ if (*response == '\0') {
+ if (default_str != NULL) {
+ ret = strdup(default_str);
+ }
+ break;
+ }
+
+ len = strlen(response);
+ response[len-1] = '\0'; /* get rid of "LF" */
+ len--;
+ if (len >= min_len && len <= max_len) {
+ ret = strdup(response);
+ break;
}
- attrs[cur_attr].type = CKA_CLASS;
- attrs[cur_attr].pValue = &obj_class;
- attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS);
- cur_attr++;
+ (void) printf("%s\n", INVALID_INPUT);
+
}
- /*
- * This can't happen now. When finding objects is enhanced in the
- * future. this could lead to buffer overruns.
- */
- if (cur_attr > num_attrs)
- cryptodebug("internal error: attr template overrun");
+ return (ret);
+}
- cryptodebug("calling C_FindObjectsInit");
- if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) {
- free(*obj);
- return (rv);
+int
+get_subname(char **result)
+{
+ char *country = NULL;
+ char *state = NULL;
+ char *locality = NULL;
+ char *org = NULL;
+ char *unit = NULL;
+ char *name = NULL;
+ char *email = NULL;
+ char *subname = NULL;
+
+ (void) printf("Entering following fields for subject (a DN) ...\n");
+ country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
+ COUNTRYNAME_MIN, COUNTRYNAME_MAX);
+ if (country == NULL)
+ return (-1);
+
+ state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
+ RDN_MIN, RDN_MAX);
+ if (state == NULL) {
+ goto out;
}
- /*
- * Find all the matching objects. The loop goes 1 more beyond
- * the number of objects found to determine if any new objects
- * were created since the time the object count was done.
- */
- cryptodebug("calling C_FindObjects");
- for (i = 0; i < (*count) + 1; i++) {
- if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) !=
- CKR_OK)
- break;
+ locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
- /* No more found. */
- if (obj_count == 0)
- break;
+ /* Now create a subject name from the input strings */
+ if ((subname = malloc(SUBNAMESIZ)) == NULL)
+ goto out;
+
+ (void) memset(subname, 0, SUBNAMESIZ);
+ (void) strlcpy(subname, "C=", SUBNAMESIZ);
+ (void) strlcat(subname, country, SUBNAMESIZ);
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "ST=", SUBNAMESIZ);
+ (void) strlcat(subname, state, SUBNAMESIZ);
- /*
- * Save the object in the list being created, as long as
- * we don't overrun the size of the list.
- */
- if (i < *count)
- (*obj)[i] = tmp_obj;
- else
- cryptodebug("number of objects changed since last count");
+ if (locality) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "L=", SUBNAMESIZ);
+ (void) strlcat(subname, locality, SUBNAMESIZ);
}
- if (rv != CKR_OK) {
- free(*obj);
- } else {
- /*
- * There are three cases to handle: (1) fewer objects were
- * found than originally counted => change *count to the
- * smaller number; (2) the number of objects found matches
- * the number originally counted => do nothing; (3) more
- * objects found than originally counted => list passed
- * in is too small to contain the extra object(s), flag
- * that in the debug output but don't change number of
- * objects returned. The caller can double-check by
- * calling find_obj_count() after this function to make
- * sure the numbers match, if desired.
- */
- /* Case 1: Fewer objects. */
- if (i < *count) {
- cryptodebug("%d objects found, expected %d", i, *count);
- *count = i;
- /* Case 3: More objects. */
- } else if (i > *count) {
- cryptodebug("at least %d objects found, expected %d",
- i, *count);
- }
- /*
- * Case 2: Same number of objects.
- *
- * else if (i == *count)
- * ;
- */
+ if (org) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "O=", SUBNAMESIZ);
+ (void) strlcat(subname, org, SUBNAMESIZ);
}
- cryptodebug("calling C_FindObjectsFinal");
- (void) C_FindObjectsFinal(sess);
- return (rv);
-}
+ if (unit) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "OU=", SUBNAMESIZ);
+ (void) strlcat(subname, unit, SUBNAMESIZ);
+ }
-char *
-class_str(CK_OBJECT_CLASS class)
-{
- switch (class) {
- case CKO_DATA: return (gettext("data"));
- case CKO_CERTIFICATE: return (gettext("certificate"));
- case CKO_PUBLIC_KEY: return (gettext("public key"));
- case CKO_PRIVATE_KEY: return (gettext("private key"));
- case CKO_SECRET_KEY: return (gettext("secret key"));
- case CKO_DOMAIN_PARAMETERS: return (gettext("domain parameter"));
- default: return (gettext("unknown object"));
+ if (name) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "CN=", SUBNAMESIZ);
+ (void) strlcat(subname, name, SUBNAMESIZ);
}
-}
-char *
-keytype_str(CK_KEY_TYPE keytype)
-{
- switch (keytype) {
- case CKK_RSA: return (gettext("RSA"));
- case CKK_DSA: return (gettext("DSA"));
- case CKK_DH: return (gettext("Diffie-Hellman"));
- case CKK_X9_42_DH: return (gettext("X9.42 Diffie-Hellman"));
- case CKK_GENERIC_SECRET: return (gettext("generic"));
- case CKK_RC2: return (gettext("RC2"));
- case CKK_RC4: return (gettext("RC4"));
- case CKK_DES: return (gettext("DES"));
- case CKK_DES2: return (gettext("Double-DES"));
- case CKK_DES3: return (gettext("Triple-DES"));
- case CKK_RC5: return (gettext("RC5"));
- case CKK_AES: return (gettext("AES"));
- default: return (gettext("typeless"));
+ if (email) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "E=", SUBNAMESIZ);
+ (void) strlcat(subname, email, SUBNAMESIZ);
}
-}
-char *
-attr_str(CK_ATTRIBUTE_TYPE attrtype)
-{
- switch (attrtype) {
- case CKA_PRIVATE: return (gettext("private"));
- case CKA_LOCAL: return (gettext("local"));
- case CKA_SENSITIVE: return (gettext("sensitive"));
- case CKA_EXTRACTABLE: return (gettext("extractable"));
- case CKA_ENCRYPT: return (gettext("encrypt"));
- case CKA_DECRYPT: return (gettext("decrypt"));
- case CKA_WRAP: return (gettext("wrap"));
- case CKA_UNWRAP: return (gettext("unwrap"));
- case CKA_SIGN: return (gettext("sign"));
- case CKA_SIGN_RECOVER: return (gettext("sign-recover"));
- case CKA_VERIFY: return (gettext("verify"));
- case CKA_VERIFY_RECOVER: return (gettext("verify-recover"));
- case CKA_DERIVE: return (gettext("derive"));
- case CKA_ALWAYS_SENSITIVE: return (gettext("always sensitive"));
- case CKA_NEVER_EXTRACTABLE: return (gettext("never extractable"));
- default: return (gettext("unknown capability"));
+out:
+ if (country)
+ free(country);
+ if (state)
+ free(state);
+ if (locality)
+ free(locality);
+ if (org)
+ free(org);
+ if (unit)
+ free(unit);
+ if (name)
+ free(name);
+ if (email)
+ free(email);
+
+ if (subname == NULL)
+ return (-1);
+ else {
+ *result = subname;
+ return (0);
}
}
/*
- * Convert a byte string into a string of octets formatted like this:
- * oo oo oo oo oo ... oo
- * where each "oo" is an octet is space separated and in the form:
- * [0-f][0-f] if the octet is a non-printable character
- * <space><char> if the octet is a printable character
- *
- * Note: octets_sz must be 3 * str_sz + 1, or at least as long as "blank"
+ * Parse a string of KeyUsage values and convert
+ * them to the correct KU Bits.
+ * The field may be marked "critical" by prepending
+ * "critical:" to the list.
+ * EX: critical:digitialSignature,keyEncipherment
*/
-void
-octetify(CK_BYTE *str, CK_ULONG str_sz, char *octets, int octets_sz,
- boolean_t stop_on_nul, boolean_t do_ascii, int limit, char *indent,
- char *blank)
+KMF_RETURN
+verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
{
- char *marker;
- int nc;
- int newline;
- int indent_len;
- boolean_t first = B_TRUE;
-
- cryptodebug("inside octetify");
-
- cryptodebug(stop_on_nul ? "stopping on first nul found" :
- "continuing to full length of buffer");
- cryptodebug(do_ascii ? "using ascii chars where printable" :
- "using only hex octets");
- cryptodebug("every %d characters indent with \"%s\"\n ", limit, indent);
- cryptodebug("return \"%s\" if buffer is null or empty", blank);
-
- /* If string is empty, write as much of the blank string and leave. */
- if (str_sz == 0) {
- (void) snprintf(octets, octets_sz, "%s", blank);
- return;
+ KMF_RETURN ret = KMF_OK;
+ uint16_t kuval;
+ char *k;
+
+ *kubits = 0;
+ if (kustr == NULL || !strlen(kustr))
+ return (KMF_ERR_BAD_PARAMETER);
+
+ /* Check to see if this is critical */
+ if (!strncasecmp(kustr, "critical:", strlen("critical:"))) {
+ *critical = TRUE;
+ kustr += strlen("critical:");
+ } else {
+ *critical = FALSE;
}
- /* If only limit or indent is set, pick default for the other. */
- if (limit > 0 && indent == NULL)
- indent = "\n";
- if (indent != NULL && limit == 0)
- limit = 60;
- indent_len = strlen(indent);
-
- for (marker = octets, newline = 0, first = B_TRUE;
- (stop_on_nul && *str != '\0') ||
- (!stop_on_nul && str_sz > 0 && octets_sz > 0);
- str++, str_sz--, marker += nc, octets_sz -= nc) {
- if (!first) {
- if (limit > 0 && ((marker - octets) / limit) >
- newline) {
- nc = snprintf(marker, indent_len, "%s", indent);
- newline++;
- continue;
- }
- nc = sprintf(marker,
- ((do_ascii && isprint(*str) && !isspace(*str)) ?
- "%s%c" : "%s%02x"), (do_ascii ? " " : ":"), *str);
- } else {
- nc = sprintf(marker,
- ((do_ascii && isprint(*str) && !isspace(*str)) ?
- "%c" : "%02x"), *str);
- first = B_FALSE;
+ k = strtok(kustr, ",");
+ while (k != NULL) {
+ kuval = KMF_StringToKeyUsage(k);
+ if (kuval == 0) {
+ *kubits = 0;
+ return (KMF_ERR_BAD_PARAMETER);
}
+ *kubits |= kuval;
+ k = strtok(NULL, ",");
}
- *marker = '\0';
-}
-/*
- * Copies a biginteger_t to a template attribute.
- * Should be a macro instead of a function.
- */
-void
-copy_bigint_to_attr(biginteger_t big, CK_ATTRIBUTE_PTR attr)
-{
- attr->pValue = big.big_value;
- attr->ulValueLen = big.big_value_len;
+ return (ret);
}
/*
- * Copies a string and its length to a template attribute.
- * Should be a macro instead of a function.
+ * Verify the alternate subject label is real or invalid.
+ *
+ * The field may be marked "critical" by prepending
+ * "critical:" to the list.
+ * EX: "critical:IP=1.2.3.4"
*/
-void
-copy_string_to_attr(CK_BYTE *buf, CK_ULONG buflen, CK_ATTRIBUTE_PTR attr)
+KMF_RETURN
+verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
{
- attr->pValue = buf;
- attr->ulValueLen = buflen;
-}
+ char *p;
+ KMF_RETURN rv = KMF_OK;
-/*
- * Copies a template attribute to a biginteger_t.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_bigint(CK_ATTRIBUTE_PTR attr, biginteger_t *big)
-{
- big->big_value = attr->pValue;
- big->big_value_len = attr->ulValueLen;
-}
+ /* Check to see if this is critical */
+ if (!strncasecmp(arg, "critical:", strlen("critical:"))) {
+ *critical = TRUE;
+ arg += strlen("critical:");
+ } else {
+ *critical = FALSE;
+ }
-/*
- * Copies a template attribute to a string and its length.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_string(CK_ATTRIBUTE_PTR attr, CK_BYTE **buf, CK_ULONG *buflen)
-{
- *buf = attr->pValue;
- *buflen = attr->ulValueLen;
-}
+ /* Make sure there is an "=" sign */
+ p = strchr(arg, '=');
+ if (p == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
-/*
- * Copies a template attribute to a date and its length.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_date(CK_ATTRIBUTE_PTR attr, CK_DATE **buf, CK_ULONG *buflen)
-{
- *buf = (CK_DATE *)attr->pValue;
- *buflen = attr->ulValueLen;
+ p[0] = '\0';
+
+ if (strcmp(arg, "IP") == 0)
+ *type = GENNAME_IPADDRESS;
+ else if (strcmp(arg, "DNS") == 0)
+ *type = GENNAME_DNSNAME;
+ else if (strcmp(arg, "EMAIL") == 0)
+ *type = GENNAME_RFC822NAME;
+ else if (strcmp(arg, "URI") == 0)
+ *type = GENNAME_URI;
+ else if (strcmp(arg, "DN") == 0)
+ *type = GENNAME_DIRECTORYNAME;
+ else if (strcmp(arg, "RID") == 0)
+ *type = GENNAME_REGISTEREDID;
+ else
+ rv = KMF_ERR_BAD_PARAMETER;
+
+ p[0] = '=';
+
+ return (rv);
}
-/*
- * Breaks out the getopt-style option string into a structure that can be
- * traversed later for calls to getopt_av(). Option string is NOT altered,
- * but the struct fields point to locations within option string.
- */
-static int
-populate_opts(char *optstring)
+int
+get_token_password(KMF_KEYSTORE_TYPE kstype,
+ char *token_spec, KMF_CREDENTIAL *cred)
{
- int i;
- av_opts *temp;
- char *marker;
-
- if (optstring == NULL || *optstring == '\0')
- return (0);
+ char prompt[1024];
+ char *p = NULL;
+ if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ p = strchr(token_spec, ':');
+ if (p != NULL)
+ *p = 0;
+ }
/*
- * This tries to imitate getopt(3c) Each option must conform to:
- * <short name char> [ ':' ] [ '(' <long name string> ')' ]
- * If long name is missing, the short name is used for long name.
+ * Login to the token first.
*/
- for (i = 0; *optstring != '\0'; i++) {
- if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
- realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
- free(opts_av);
- opts_av = NULL;
- return (0);
- } else
- opts_av = (av_opts *)temp;
-
- marker = optstring; /* may need optstring later */
-
- opts_av[i].shortnm = *marker++; /* set short name */
-
- if (*marker == ':') { /* check for opt arg */
- marker++;
- opts_av[i].has_arg = B_TRUE;
- }
+ (void) snprintf(prompt, sizeof (prompt),
+ gettext(DEFAULT_TOKEN_PROMPT),
+ token_spec);
- if (*marker == '(') { /* check and set long name */
- marker++;
- opts_av[i].longnm = marker;
- opts_av[i].longnm_len = strcspn(marker, ")");
- optstring = marker + opts_av[i].longnm_len + 1;
- } else {
- /* use short name option character */
- opts_av[i].longnm = optstring;
- opts_av[i].longnm_len = 1;
- optstring = marker;
- }
+ if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
+ (ulong_t *)&cred->credlen) != CKR_OK) {
+ cred->cred = NULL;
+ cred->credlen = 0;
}
- return (i);
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
+ *p = ':';
+ return (KMF_OK);
}
-/*
- * getopt_av() is very similar to getopt(3c) in that the takes an option
- * string, compares command line arguments for matches, and returns a single
- * letter option when a match is found. However, getopt_av() differs from
- * getopt(3c) by requiring that only longname options and values be found
- * on the command line and all leading dashes are omitted. In other words,
- * it tries to enforce only longname "option=value" arguments on the command
- * line. Boolean options are not allowed either.
- */
-int
-getopt_av(int argc, char * const *argv, const char *optstring)
+KMF_RETURN
+verify_file(char *filename)
{
- int i;
- int len;
+ KMF_RETURN ret = KMF_OK;
+ int fd;
- if (optind_av >= argc)
- return (EOF);
+ /*
+ * Attempt to open with the EXCL flag so that if
+ * it already exists, the open will fail. It will
+ * also fail if the file cannot be created due to
+ * permissions on the parent directory, or if the
+ * parent directory itself does not exist.
+ */
+ fd = open(filename, O_CREAT | O_EXCL, 0600);
+ if (fd == -1)
+ return (KMF_ERR_OPEN_FILE);
- /* First time or when optstring changes from previous one */
- if (_save_optstr != optstring) {
- if (opts_av != NULL)
- free(opts_av);
- opts_av = NULL;
- _save_optstr = optstring;
- _save_numopts = populate_opts((char *)optstring);
- }
+ /* If we were able to create it, delete it. */
+ (void) close(fd);
+ (void) unlink(filename);
- for (i = 0; i < _save_numopts; i++) {
- if (strcmp(argv[optind_av], "--") == 0) {
- optind_av++;
- break;
- }
+ return (ret);
+}
- len = strcspn(argv[optind_av], "=");
+void
+display_error(void *handle, KMF_RETURN errcode, char *prefix)
+{
+ KMF_RETURN rv1, rv2;
+ char *plugin_errmsg = NULL;
+ char *kmf_errmsg = NULL;
- if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
- opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
- /* matched */
- if (!opts_av[i].has_arg) {
- optind_av++;
- return (opts_av[i].shortnm);
- }
+ rv1 = KMF_GetPluginErrorString(handle, &plugin_errmsg);
+ rv2 = KMF_GetKMFErrorString(errcode, &kmf_errmsg);
- /* needs optarg */
- if (argv[optind_av][len] == '=') {
- optarg_av = &(argv[optind_av][len+1]);
- optind_av++;
- return (opts_av[i].shortnm);
- }
+ cryptoerror(LOG_STDERR, "%s:", prefix);
+ if (rv1 == KMF_OK && plugin_errmsg) {
+ cryptoerror(LOG_STDERR,
+ gettext("keystore error: %s"),
+ plugin_errmsg);
+ KMF_FreeString(plugin_errmsg);
+ }
- optarg_av = NULL;
- optind_av++;
- return ((int)'?');
- }
+ if (rv2 == KMF_OK && kmf_errmsg) {
+ cryptoerror(LOG_STDERR,
+ gettext("libkmf error: %s"),
+ kmf_errmsg);
+ KMF_FreeString(kmf_errmsg);
}
- return (EOF);
+ if (rv1 != KMF_OK && rv2 != KMF_OK)
+ cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
+
}