summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libkmf/include/kmfapi.h3
-rw-r--r--usr/src/lib/libkmf/include/kmfapiP.h23
-rw-r--r--usr/src/lib/libkmf/include/kmftypes.h16
-rw-r--r--usr/src/lib/libkmf/libkmf/common/certop.c6
-rw-r--r--usr/src/lib/libkmf/libkmf/common/generalop.c422
-rw-r--r--usr/src/lib/libkmf/libkmf/common/llib-lkmf3
-rw-r--r--usr/src/lib/libkmf/libkmf/common/mapfile-vers5
7 files changed, 454 insertions, 24 deletions
diff --git a/usr/src/lib/libkmf/include/kmfapi.h b/usr/src/lib/libkmf/include/kmfapi.h
index ad732f6ffd..85a54175ca 100644
--- a/usr/src/lib/libkmf/include/kmfapi.h
+++ b/usr/src/lib/libkmf/include/kmfapi.h
@@ -289,6 +289,9 @@ extern char *kmf_ku_to_string(uint32_t);
extern KMF_RETURN kmf_hexstr_to_bytes(unsigned char *, unsigned char **,
size_t *);
+extern KMF_RETURN kmf_get_plugin_info(KMF_HANDLE_T, char *,
+ KMF_KEYSTORE_TYPE *, char **);
+
#define KMF_CompareRDNs kmf_compare_rdns
/*
diff --git a/usr/src/lib/libkmf/include/kmfapiP.h b/usr/src/lib/libkmf/include/kmfapiP.h
index ac89acb565..948f3acfb8 100644
--- a/usr/src/lib/libkmf/include/kmfapiP.h
+++ b/usr/src/lib/libkmf/include/kmfapiP.h
@@ -330,6 +330,29 @@ typedef enum {
#define OCSPREQ_TEMPNAME "/tmp/ocsp.reqXXXXXX"
#define OCSPRESP_TEMPNAME "/tmp/ocsp.respXXXXXX"
+#define _PATH_KMF_CONF "/etc/crypto/kmf.conf"
+#define CONF_MODULEPATH "modulepath="
+#define CONF_OPTION "option="
+
+typedef struct {
+ char *keystore;
+ char *modulepath;
+ char *option;
+ KMF_KEYSTORE_TYPE kstype;
+} conf_entry_t;
+
+typedef struct conf_entrylist {
+ conf_entry_t *entry;
+ struct conf_entrylist *next;
+} conf_entrylist_t;
+
+
+extern KMF_RETURN get_entrylist(conf_entrylist_t **);
+extern void free_entrylist(conf_entrylist_t *);
+extern void free_entry(conf_entry_t *);
+extern conf_entry_t *dup_entry(conf_entry_t *);
+boolean_t is_valid_keystore_type(KMF_KEYSTORE_TYPE);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libkmf/include/kmftypes.h b/usr/src/lib/libkmf/include/kmftypes.h
index 211525f974..cb970800db 100644
--- a/usr/src/lib/libkmf/include/kmftypes.h
+++ b/usr/src/lib/libkmf/include/kmftypes.h
@@ -74,14 +74,12 @@ typedef struct
KMF_X509_PRIVATE kmf_private;
} KMF_X509_DER_CERT;
-typedef enum {
- KMF_KEYSTORE_NSS = 1,
- KMF_KEYSTORE_OPENSSL = 2,
- KMF_KEYSTORE_PK11TOKEN = 3,
- KMF_KEYSTORE_DEFAULT /* based on configuration */
-} KMF_KEYSTORE_TYPE;
+typedef int KMF_KEYSTORE_TYPE;
+#define KMF_KEYSTORE_NSS 1
+#define KMF_KEYSTORE_OPENSSL 2
+#define KMF_KEYSTORE_PK11TOKEN 3
-#define VALID_KEYSTORE_TYPE(t) ((t >= KMF_KEYSTORE_NSS) &&\
+#define VALID_DEFAULT_KEYSTORE_TYPE(t) ((t >= KMF_KEYSTORE_NSS) &&\
(t <= KMF_KEYSTORE_PK11TOKEN))
typedef enum {
@@ -291,6 +289,7 @@ typedef enum {
KMF_ERR_OCSP_RESPONSE_STATUS = 0x2f,
KMF_ERR_OCSP_NO_BASIC_RESPONSE = 0x30,
KMF_ERR_OCSP_BAD_SIGNER = 0x31,
+
KMF_ERR_OCSP_RESPONSE_SIGNATURE = 0x32,
KMF_ERR_OCSP_UNKNOWN_CERT = 0x33,
KMF_ERR_OCSP_STATUS_TIME_INVALID = 0x34,
@@ -325,7 +324,8 @@ typedef enum {
KMF_ERR_SENSITIVE_KEY = 0x51,
KMF_ERR_UNEXTRACTABLE_KEY = 0x52,
KMF_ERR_KEY_MISMATCH = 0x53,
- KMF_ERR_ATTR_NOT_FOUND = 0x54
+ KMF_ERR_ATTR_NOT_FOUND = 0x54,
+ KMF_ERR_KMF_CONF = 0x55
} KMF_RETURN;
/* Data structures for OCSP support */
diff --git a/usr/src/lib/libkmf/libkmf/common/certop.c b/usr/src/lib/libkmf/libkmf/common/certop.c
index 4d5e151ce7..5889ffe77e 100644
--- a/usr/src/lib/libkmf/libkmf/common/certop.c
+++ b/usr/src/lib/libkmf/libkmf/common/certop.c
@@ -1371,7 +1371,7 @@ cert_crl_check(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
issuer_cert == NULL)
return (KMF_ERR_BAD_PARAMETER);
- if (!VALID_KEYSTORE_TYPE(*kstype))
+ if (!is_valid_keystore_type(*kstype))
return (KMF_ERR_BAD_PARAMETER);
policy = handle->policy;
@@ -1985,7 +1985,7 @@ find_issuer_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
issuer_cert == NULL)
return (KMF_ERR_BAD_PARAMETER);
- if (!VALID_KEYSTORE_TYPE(*kstype))
+ if (!is_valid_keystore_type(*kstype))
return (KMF_ERR_BAD_PARAMETER);
kmf_set_attr_at_index(fc_attrlist, fc_numattr, KMF_KEYSTORE_TYPE_ATTR,
@@ -2117,7 +2117,7 @@ find_ta_cert(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE *kstype,
user_issuerDN == NULL)
return (KMF_ERR_BAD_PARAMETER);
- if (!VALID_KEYSTORE_TYPE(*kstype))
+ if (!is_valid_keystore_type(*kstype))
return (KMF_ERR_BAD_PARAMETER);
/* Get the TA name and serial number from the policy */
diff --git a/usr/src/lib/libkmf/libkmf/common/generalop.c b/usr/src/lib/libkmf/libkmf/common/generalop.c
index 1e2f2504a4..e5a19df4b5 100644
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c
+++ b/usr/src/lib/libkmf/libkmf/common/generalop.c
@@ -159,6 +159,22 @@ static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
static void free_extensions(KMF_X509_EXTENSIONS *extns);
static void DestroyPlugin(KMF_PLUGIN *);
+#if defined(__sparcv9)
+#define ISA_PATH "/sparcv9"
+#elif defined(__sparc)
+#define ISA_PATH "/"
+#elif defined(__i386)
+#define ISA_PATH "/"
+#elif defined(__amd64)
+#define ISA_PATH "/amd64"
+#endif
+
+#define DEFAULT_KEYSTORE_NUM 3
+static int kstore_num = DEFAULT_KEYSTORE_NUM;
+conf_entrylist_t *extra_plugin_list = NULL;
+static boolean_t check_extra_plugin = B_FALSE;
+mutex_t extra_plugin_lock = DEFAULTMUTEX;
+
KMF_RETURN
init_pk11()
{
@@ -186,6 +202,7 @@ FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
{
KMF_PLUGIN_LIST *node;
KMF_RETURN ret = KMF_OK;
+ KMF_PLUGIN *pluginrec = NULL;
if (handle == NULL)
return (NULL);
@@ -196,10 +213,12 @@ FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
while (node != NULL && node->plugin->type != kstype)
node = node->next;
- /* If the plugin was not found, try to initialize it here. */
- if (node == NULL) {
+ if (node != NULL)
+ return (node->plugin);
+
+ /* The plugin was not found, try to initialize it here. */
+ if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
int i;
- KMF_PLUGIN *pluginrec = NULL;
int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
for (i = 0; i < numitems; i++) {
if (plugin_list[i].kstype == kstype) {
@@ -209,21 +228,80 @@ FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
}
}
- /* No matching plugins found in the available list */
- if (ret != KMF_OK || pluginrec == NULL)
+ goto out;
+
+ } else {
+ /*
+ * Not a built-in plugin. Check if it is in the
+ * extra_plugin_list. If it is, try to initialize it here.
+ */
+ conf_entrylist_t *phead = extra_plugin_list;
+ char realpath[MAXPATHLEN];
+
+ while (phead != NULL) {
+ if (phead->entry->kstype == kstype)
+ break;
+ else
+ phead = phead->next;
+ }
+
+ if (phead == NULL)
return (NULL);
- ret = AddPlugin(handle, pluginrec);
- if (ret != KMF_OK) {
- DestroyPlugin(pluginrec);
- pluginrec = NULL;
+ /*
+ * Get the absolute path of the module.
+ * - If modulepath is not a full path, then prepend it
+ * with KMF_PLUGIN_PATH.
+ * - If modulepath is a full path and contain $ISA, then
+ * subsitute the architecture dependent path.
+ */
+ (void) memset(realpath, 0, sizeof (realpath));
+ if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
+ (void) snprintf(realpath, MAXPATHLEN, "%s%s",
+ KMF_PLUGIN_PATH, phead->entry->modulepath);
+ } else {
+ char *buf = phead->entry->modulepath;
+ char *isa;
+
+ if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
+ char *isa_str;
+
+ (void) strncpy(realpath, buf, isa - buf);
+ isa_str = strdup(ISA_PATH);
+ if (isa_str == NULL) /* not enough memory */
+ return (NULL);
+
+ (void) strncat(realpath, isa_str,
+ strlen(isa_str));
+ free(isa_str);
+
+ isa += strlen(PKCS11_ISA);
+ (void) strlcat(realpath, isa, MAXPATHLEN);
+ } else {
+ (void) snprintf(realpath, MAXPATHLEN, "%s",
+ phead->entry->modulepath);
+ }
}
- return (pluginrec);
- } else {
- return (node->plugin);
+
+ ret = InitializePlugin(phead->entry->kstype, realpath,
+ &pluginrec);
+ goto out;
+ }
+
+out:
+ if (ret != KMF_OK || pluginrec == NULL)
+ /* No matching plugins found in the built-in list */
+ return (NULL);
+
+ ret = AddPlugin(handle, pluginrec);
+ if (ret != KMF_OK) {
+ DestroyPlugin(pluginrec);
+ pluginrec = NULL;
}
+ return (pluginrec);
}
+
static KMF_RETURN
InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
{
@@ -361,6 +439,46 @@ kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
(void) memset(handle, 0, sizeof (KMF_HANDLE));
handle->plugins = NULL;
+ /*
+ * When this function is called the first time, get the additional
+ * plugins from the config file.
+ */
+ (void) mutex_lock(&extra_plugin_lock);
+ if (!check_extra_plugin) {
+
+ ret = get_entrylist(&extra_plugin_list);
+ check_extra_plugin = B_TRUE;
+
+ /*
+ * Assign the kstype number to the additional plugins here.
+ * The global kstore_num will be protected by the mutex lock.
+ */
+ if (ret == KMF_OK) {
+ conf_entrylist_t *phead = extra_plugin_list;
+ while (phead != NULL) {
+ phead->entry->kstype = ++kstore_num;
+ phead = phead->next;
+ }
+ }
+
+ /*
+ * If the KMF configuration file does not exist or cannot be
+ * parsed correctly, we will give a warning in syslog and
+ * continue on as there is no extra plugins in the system.
+ */
+ if (ret == KMF_ERR_KMF_CONF) {
+ cryptoerror(LOG_WARNING, "KMF was unable to parse "
+ "the private KMF config file.\n");
+ ret = KMF_OK;
+ }
+
+ if (ret != KMF_OK) {
+ (void) mutex_unlock(&extra_plugin_lock);
+ goto errout;
+ }
+ }
+ (void) mutex_unlock(&extra_plugin_lock);
+
/* Initialize the handle with the policy */
ret = kmf_set_policy((void *)handle,
policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
@@ -2145,6 +2263,286 @@ kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
return (rv);
}
+
+void
+free_entry(conf_entry_t *entry)
+{
+ if (entry == NULL)
+ return;
+ free(entry->keystore);
+ free(entry->modulepath);
+ free(entry->option);
+}
+
+void
+free_entrylist(conf_entrylist_t *list)
+{
+ conf_entrylist_t *next;
+
+ while (list != NULL) {
+ next = list->next;
+ free_entry(list->entry);
+ free(list);
+ list = next;
+ }
+}
+
+static KMF_RETURN
+parse_entry(char *buf, conf_entry_t **entry)
+{
+ KMF_RETURN ret = KMF_OK;
+ conf_entry_t *tmp = NULL;
+ char *token1;
+ char *token2;
+ char *token3;
+ char *lasts;
+ char *value;
+
+ if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL)
+ return (KMF_ERR_KMF_CONF);
+
+ if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL)
+ return (KMF_ERR_MEMORY);
+
+ if ((tmp->keystore = strdup(token1)) == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto end;
+ }
+
+ if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) {
+ ret = KMF_ERR_KMF_CONF;
+ goto end;
+ }
+
+ /* need to get token3 first to satisfy nested strtok invocations */
+ token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts);
+
+ /* parse token2 */
+ if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) {
+ ret = KMF_ERR_KMF_CONF;
+ goto end;
+ }
+
+ if (value = strpbrk(token2, SEP_EQUAL)) {
+ value++; /* get rid of = */
+ } else {
+ ret = KMF_ERR_KMF_CONF;
+ goto end;
+ }
+
+ if ((tmp->modulepath = strdup(value)) == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto end;
+ }
+
+ /* parse token3, if it exists */
+ if (token3 != NULL) {
+ if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION))
+ != 0) {
+ ret = KMF_ERR_KMF_CONF;
+ goto end;
+ }
+
+ if (value = strpbrk(token3, SEP_EQUAL)) {
+ value++; /* get rid of = */
+ } else {
+ ret = KMF_ERR_KMF_CONF;
+ goto end;
+ }
+
+ if ((tmp->option = strdup(value)) == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto end;
+ }
+ }
+
+ *entry = tmp;
+
+end:
+ if (ret != KMF_OK) {
+ free_entry(tmp);
+ free(tmp);
+ }
+ return (ret);
+}
+
+
+conf_entry_t *
+dup_entry(conf_entry_t *entry)
+{
+ conf_entry_t *rtn_entry;
+
+ if (entry == NULL)
+ return (NULL);
+
+ rtn_entry = malloc(sizeof (conf_entry_t));
+ if (rtn_entry == NULL)
+ return (NULL);
+
+ if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL)
+ goto out;
+
+ if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL)
+ goto out;
+
+ if (entry->option != NULL &&
+ (rtn_entry->option = strdup(entry->modulepath)) == NULL)
+ goto out;
+
+ return (rtn_entry);
+
+out:
+ free_entry(rtn_entry);
+ return (NULL);
+}
+
+
+/*
+ * This function takes a keystore_name as input and returns
+ * the KMF_KEYSTORE_TYPE value assigned to it. If the "option"
+ * argument is not NULL, this function also returns the option string
+ * if there is an option string for the plugin module.
+ */
+KMF_RETURN
+kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name,
+ KMF_KEYSTORE_TYPE *kstype, char **option)
+{
+ KMF_RETURN ret = KMF_OK;
+ conf_entrylist_t *phead = extra_plugin_list;
+ boolean_t is_default = B_TRUE;
+
+ /*
+ * Although handle is not really used in the function, we will
+ * check the handle to make sure that kmf_intialize() is called
+ * before this function.
+ */
+ if (handle == NULL || keystore_name == NULL || kstype == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ if (strcmp(keystore_name, "pkcs11") == 0) {
+ *kstype = KMF_KEYSTORE_PK11TOKEN;
+ } else if (strcmp(keystore_name, "file") == 0) {
+ *kstype = KMF_KEYSTORE_OPENSSL;
+ } else if (strcmp(keystore_name, "nss") == 0) {
+ *kstype = KMF_KEYSTORE_NSS;
+ } else {
+ is_default = B_FALSE;
+ }
+
+ if (is_default) {
+ if (option != NULL)
+ *option = NULL;
+ goto out;
+ }
+
+ /* Not a built-in plugin; check if it is in extra_plugin_list. */
+ while (phead != NULL) {
+ if (strcmp(phead->entry->keystore, keystore_name) == 0)
+ break;
+ phead = phead->next;
+ }
+
+ if (phead == NULL) {
+ ret = KMF_ERR_PLUGIN_NOTFOUND;
+ goto out;
+ }
+
+ /* found it */
+ *kstype = phead->entry->kstype;
+ if (option != NULL) {
+ if (phead->entry->option == NULL)
+ *option = NULL;
+ else {
+ *option = strdup(phead->entry->option);
+ if (*option == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto out;
+ }
+ }
+ }
+
+out:
+ return (ret);
+}
+
+/*
+ * Retrieve the non-default plugin list from the kmf.conf file.
+ */
+KMF_RETURN
+get_entrylist(conf_entrylist_t **entlist)
+{
+ KMF_RETURN rv = KMF_OK;
+ FILE *pfile;
+ conf_entry_t *entry;
+ conf_entrylist_t *rtnlist = NULL;
+ conf_entrylist_t *ptmp;
+ conf_entrylist_t *pcur;
+ char buffer[MAXPATHLEN];
+ size_t len;
+
+ if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) {
+ cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF);
+ return (KMF_ERR_KMF_CONF);
+ }
+
+ while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
+ if (buffer[0] == '#' || buffer[0] == ' ' ||
+ buffer[0] == '\n'|| buffer[0] == '\t') {
+ continue; /* ignore comment lines */
+ }
+
+ len = strlen(buffer);
+ if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
+ len--;
+ }
+ buffer[len] = '\0';
+
+ rv = parse_entry(buffer, &entry);
+ if (rv != KMF_OK) {
+ goto end;
+ }
+
+ if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) {
+ rv = KMF_ERR_MEMORY;
+ goto end;
+ }
+ ptmp->entry = entry;
+ ptmp->next = NULL;
+
+ if (rtnlist == NULL) {
+ rtnlist = pcur = ptmp;
+ } else {
+ pcur->next = ptmp;
+ pcur = ptmp;
+ }
+ }
+
+end:
+ (void) fclose(pfile);
+
+ if (rv == KMF_OK) {
+ *entlist = rtnlist;
+ } else if (rtnlist != NULL) {
+ free_entrylist(rtnlist);
+ *entlist = NULL;
+ kstore_num = DEFAULT_KEYSTORE_NUM;
+ }
+
+ return (rv);
+}
+
+
+boolean_t
+is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)
+{
+
+ if (kstype > 0 && kstype <= kstore_num)
+ return (B_TRUE);
+ else
+ return (B_FALSE);
+}
+
+
/*
* This API is used by elfsign. We must keep it in old API form.
*/
diff --git a/usr/src/lib/libkmf/libkmf/common/llib-lkmf b/usr/src/lib/libkmf/libkmf/common/llib-lkmf
index 114e823e4d..355ed9bb21 100644
--- a/usr/src/lib/libkmf/libkmf/common/llib-lkmf
+++ b/usr/src/lib/libkmf/libkmf/common/llib-lkmf
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,3 +29,4 @@
/* PROTOLIB1 */
#include <kmfapi.h>
#include <kmfpolicy.h>
+#include <kmfapiP.h>
diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
index 31ef381e6d..4b658709c5 100644
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
@@ -232,6 +232,7 @@ SUNW_1.1 {
kmf_get_ocsp_status_for_cert;
kmf_get_pk11_handle;
kmf_get_plugin_error_str;
+ kmf_get_plugin_info;
kmf_get_policy;
kmf_get_string_attr;
kmf_get_sym_key_value;
@@ -318,6 +319,10 @@ SUNWprivate_1.1 {
KMF_SignDataWithKey;
KMF_VerifyCertWithCert;
KMF_VerifyDataWithCert;
+ dup_entry;
+ free_entry;
+ free_entrylist;
+ get_entrylist;
parsePolicyElement;
PKCS_AcquirePublicKeyHandle;
PKCS_GetDefaultSignatureMode;