aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--Makefile-test.am5
-rw-r--r--configure.ac3
-rw-r--r--man/Tss2_Tcti_Mssim_Init.3.in30
-rw-r--r--src/tss2-esys/esys_tcti_default.c2
-rw-r--r--src/tss2-tcti/tcti-mssim.c143
-rw-r--r--src/tss2-tcti/tcti-mssim.h19
-rw-r--r--src/util/key-value-parse.c113
-rw-r--r--src/util/key-value-parse.h49
-rw-r--r--test/integration/context-util.c7
-rw-r--r--test/unit/esys-default-tcti.c4
-rw-r--r--test/unit/key-value-parse.c277
-rw-r--r--test/unit/tcti-mssim.c73
13 files changed, 592 insertions, 134 deletions
diff --git a/.travis.yml b/.travis.yml
index 7c5a67e1..237a9aac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,6 @@ addons:
- autoconf-archive
- cmake
- libgcrypt20-dev
- - liburiparser-dev
- realpath
- lcov
- libssl-dev
diff --git a/Makefile-test.am b/Makefile-test.am
index 7c98647c..8298c943 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -62,6 +62,7 @@ TESTS_UNIT = \
test/unit/CopyCommandHeader \
test/unit/GetNumHandles \
test/unit/io \
+ test/unit/key-value-parse \
test/unit/tcti-device \
test/unit/tcti-mssim \
test/unit/UINT8-marshal \
@@ -211,6 +212,10 @@ test_unit_io_LDADD = $(CMOCKA_LIBS) $(libtss2_mu) $(libutil)
test_unit_io_LDFLAGS = -Wl,--wrap=connect,--wrap=read,--wrap=socket,--wrap=write
test_unit_io_SOURCES = test/unit/io.c
+test_unit_key_value_parse_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
+test_unit_key_value_parse_LDADD = $(CMOCKA_LIBS) $(libutil)
+test_unit_key_value_parse_SOURCES = test/unit/key-value-parse.c
+
test_unit_CommonPreparePrologue_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
test_unit_CommonPreparePrologue_LDFLAGS = -Wl,--unresolved-symbols=ignore-all
test_unit_CommonPreparePrologue_LDADD = $(CMOCKA_LIBS) $(libtss2_sys)
diff --git a/configure.ac b/configure.ac
index 7ec4fded..bf9dd5e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,9 +58,6 @@ AS_IF([test "x$enable_unit" != xno],
[AC_MSG_ERROR([cmocka_err])])])
AM_CONDITIONAL([UNIT], [test "x$enable_unit" != xno])
-# Uriparser library required by simulator TCTI library.
-PKG_CHECK_MODULES([URIPARSER],[liburiparser])
-
AC_ARG_ENABLE([esapi],
[AS_HELP_STRING([--enable-esapi],
[build the esapi layer (default is yes)])],
diff --git a/man/Tss2_Tcti_Mssim_Init.3.in b/man/Tss2_Tcti_Mssim_Init.3.in
index bda75f6c..b40b503e 100644
--- a/man/Tss2_Tcti_Mssim_Init.3.in
+++ b/man/Tss2_Tcti_Mssim_Init.3.in
@@ -52,16 +52,26 @@ function in the section titled
The
.I conf
parameter is a C string used to configure the TCTI context. This
-configuration string is a URI with the IP address and port used to connect
-to an instance of the Microsoft TPM2 simulator. The URI scheme used is the
-non-standard
-.I tcp
-scheme. If a NULL
+configuration string is a series of key / value pairs that specify the host
+and port used to connect to an instance of the Microsoft TPM2 simulator. The
+keys and values are separated by the '=' character, while each key / value
+pair is separated by the ',' character.
+
+The only keys supported in the
+.I conf
+string are
+.B host
+and
+.B port.
+The host may be an IPv4 address, an IPv6 address, or a host name. The port
+must be a valid uint16_t in string form. If a NULL
.I conf
-string is provided then the default of
-.I tcp://127.0.0.1:2321/
-is used. If the URI provided omits the port component then the default port
-of 2321 is used.
+string is provided by the caller then the default of
+"host=localhost,port=2321" is used. If either
+.B host
+or
+.B port
+are omitted then their respective default value will be used.
.sp
Once initialized, the TCTI context returned exposes the Trusted Computing
Group (TCG) defined API for the lowest level communication with the TPM.
@@ -104,7 +114,7 @@ TCTI initialization fragment:
TSS2_RC rc;
TSS2_TCTI_CONTEXT *tcti_context;
size_t size;
-const char *conf = "tcp://127.0.0.1:2321/"
+const char *conf = "host=localhost,port=2321"
rc = Tss2_Tcti_Mssim_Init (NULL, &size, NULL);
if (rc != TSS2_RC_SUCCESS) {
diff --git a/src/tss2-esys/esys_tcti_default.c b/src/tss2-esys/esys_tcti_default.c
index bb501206..8e66b5eb 100644
--- a/src/tss2-esys/esys_tcti_default.c
+++ b/src/tss2-esys/esys_tcti_default.c
@@ -61,7 +61,7 @@ struct {
.description = "Access to /dev/tpmrm0" },
{ .init = Tss2_Tcti_Device_Init, .conf = "/dev/tpm0",
.description = "Access to /dev/tpm0" },
- { .init = Tss2_Tcti_Mssim_Init, .conf = "tcp://127.0.0.1:2321",
+ { .init = Tss2_Tcti_Mssim_Init, .conf = "host=localhost,port=2321",
.description = "Access to Mssim-simulator for tcp://localhost:2321" },
};
diff --git a/src/tss2-tcti/tcti-mssim.c b/src/tss2-tcti/tcti-mssim.c
index a11abcd5..ec0fe044 100644
--- a/src/tss2-tcti/tcti-mssim.c
+++ b/src/tss2-tcti/tcti-mssim.c
@@ -33,19 +33,15 @@
#include <inttypes.h>
#include <unistd.h>
-#include <uriparser/Uri.h>
-
#include "tss2_mu.h"
#include "tss2_tcti_mssim.h"
#include "tcti-mssim.h"
#include "tcti-common.h"
+#include "util/key-value-parse.h"
#define LOGMODULE tcti
#include "util/log.h"
-#define TCTI_SOCKET_DEFAULT_CONF "tcp://127.0.0.1:2321"
-#define TCTI_SOCKET_DEFAULT_PORT 2321
-
/*
* This function wraps the "up-cast" of the opaque TCTI context type to the
* type for the mssim TCTI context. The only safeguard we have to ensure this
@@ -453,71 +449,38 @@ string_to_port (char port_str[6])
return port;
}
/*
- * This function extracts the hostname and port part of the provided conf
- * string (which is really just a URI). The hostname parameter is an output
- * buffer that must be large enough to hold the hostname. HOST_NAME_MAX is
- * probably a good size. The 'port' parameter is an output parameter where
- * we store the port from the URI after we convert it to a uint16.
- * If the URI does not contain a port number then the contents of the 'port'
- * parameter will not be changed.
- * This function returns TSS2_RC_SUCCESS when the 'hostname' and 'port' have
- * been populated successfully. On failure it will return
- * TSS2_TCTI_RC_BAD_VALUE to indicate that the provided conf string contains
- * values that we can't parse or are invalid.
+ * This function is a callback conforming to the KeyValueFunc prototype. It
+ * is called by the key-value-parse module for each key / value pair extracted
+ * from the configuration string. Its sole purpose is to identify valid keys
+ * from the conf string and to store their corresponding values in the
+ * mssim_conf_t structure which is passed through the 'user_data' parameter.
*/
TSS2_RC
-conf_str_to_host_port (
- const char *conf,
- char *hostname,
- uint16_t *port)
+mssim_kv_callback (const key_value_t *key_value,
+ void *user_data)
{
- UriParserStateA state;
- UriUriA uri;
- /* maximum 5 digits in uint16_t + 1 for \0 */
- char port_str[6] = { 0 };
- size_t range;
- TSS2_RC rc = TSS2_RC_SUCCESS;
-
- state.uri = &uri;
- if (uriParseUriA (&state, conf) != URI_SUCCESS) {
- LOG_WARNING ("Failed to parse provided conf string: %s", conf);
- rc = TSS2_TCTI_RC_BAD_VALUE;
- goto out;
- }
-
- /* extract host & domain name / fqdn */
- range = uri.hostText.afterLast - uri.hostText.first;
- if (range > HOST_NAME_MAX) {
- LOG_WARNING ("Provided conf string has hostname that exceeds "
- "HOST_NAME_MAX.");
- rc = TSS2_TCTI_RC_BAD_VALUE;
- goto out;
- }
- strncpy (hostname, uri.hostText.first, range);
+ mssim_conf_t *mssim_conf = (mssim_conf_t*)user_data;
- /* extract port number */
- range = uri.portText.afterLast - uri.portText.first;
- if (range > 5) {
- LOG_WARNING ("conf string contains invalid port.");
- rc = TSS2_TCTI_RC_BAD_VALUE;
- goto out;
- } else if (range == 0) {
- LOG_INFO ("conf string does not contain a port.");
- goto out;
+ LOG_TRACE ("key_value: 0x%" PRIxPTR " and user_data: 0x%" PRIxPTR,
+ (uintptr_t)key_value, (uintptr_t)user_data);
+ if (key_value == NULL || user_data == NULL) {
+ LOG_WARNING ("%s passed NULL parameter", __func__);
+ return TSS2_TCTI_RC_GENERAL_FAILURE;
}
-
- strncpy (port_str, uri.portText.first, range);
- *port = string_to_port (port_str);
- if (*port == 0) {
- LOG_WARNING ("Provided conf string contains invalid port: 0");
- rc = TSS2_TCTI_RC_BAD_VALUE;
- goto out;
+ LOG_DEBUG ("key: %s / value: %s\n", key_value->key, key_value->value);
+ if (strcmp (key_value->key, "host") == 0) {
+ mssim_conf->host = key_value->value;
+ return TSS2_RC_SUCCESS;
+ } else if (strcmp (key_value->key, "port") == 0) {
+ mssim_conf->port = string_to_port (key_value->value);
+ if (mssim_conf->port == 0) {
+ return TSS2_TCTI_RC_BAD_VALUE;
+ }
+ return TSS2_RC_SUCCESS;
+ } else {
+ return TSS2_TCTI_RC_BAD_VALUE;
}
-out:
- uriFreeUriMembersA (&uri);
- return rc;
}
-
void
tcti_mssim_init_context_data (
TSS2_TCTI_COMMON_CONTEXT *tcti_common)
@@ -548,12 +511,11 @@ Tss2_Tcti_Mssim_Init (
TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = (TSS2_TCTI_MSSIM_CONTEXT*)tctiContext;
TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
TSS2_RC rc;
- const char *uri_str = conf != NULL ? conf : TCTI_SOCKET_DEFAULT_CONF;
- char hostname[HOST_NAME_MAX + 1] = { 0 };
- uint16_t port = TCTI_SOCKET_DEFAULT_PORT;
+ char *conf_copy = NULL;
+ mssim_conf_t mssim_conf = MSSIM_CONF_DEFAULT_INIT;
LOG_TRACE ("tctiContext: 0x%" PRIxPTR ", size: 0x%" PRIxPTR ", conf: %s",
- (uintptr_t)tctiContext, (uintptr_t)size, uri_str);
+ (uintptr_t)tctiContext, (uintptr_t)size, conf);
if (size == NULL) {
return TSS2_TCTI_RC_BAD_VALUE;
}
@@ -562,17 +524,41 @@ Tss2_Tcti_Mssim_Init (
return TSS2_RC_SUCCESS;
}
- rc = conf_str_to_host_port (uri_str, hostname, &port);
- if (rc != TSS2_RC_SUCCESS) {
- return rc;
+ if (conf != NULL) {
+ LOG_TRACE ("conf is not NULL");
+ if (strlen (conf) > TCTI_MSSIM_CONF_MAX) {
+ LOG_WARNING ("Provided conf string exceeds maximum of %u",
+ TCTI_MSSIM_CONF_MAX);
+ return TSS2_TCTI_RC_BAD_VALUE;
+ }
+ conf_copy = strdup (conf);
+ if (conf_copy == NULL) {
+ LOG_ERROR ("Failed to allocate buffer: %s", strerror (errno));
+ rc = TSS2_TCTI_RC_GENERAL_FAILURE;
+ goto fail_out;
+ }
+ LOG_DEBUG ("Dup'd conf string to: 0x%" PRIxPTR,
+ (uintptr_t)conf_copy);
+ rc = parse_key_value_string (conf_copy,
+ mssim_kv_callback,
+ &mssim_conf);
+ if (rc != TSS2_RC_SUCCESS) {
+ goto fail_out;
+ }
}
+ LOG_DEBUG ("Initializing mssim TCTI with host: %s, port: %" PRIu16,
+ mssim_conf.host, mssim_conf.port);
- rc = socket_connect (hostname, port, &tcti_mssim->tpm_sock);
+ rc = socket_connect (mssim_conf.host,
+ mssim_conf.port,
+ &tcti_mssim->tpm_sock);
if (rc != TSS2_RC_SUCCESS) {
- return rc;
+ goto fail_out;
}
- rc = socket_connect (hostname, port + 1, &tcti_mssim->platform_sock);
+ rc = socket_connect (mssim_conf.host,
+ mssim_conf.port + 1,
+ &tcti_mssim->platform_sock);
if (rc != TSS2_RC_SUCCESS) {
goto fail_out;
}
@@ -583,13 +569,19 @@ Tss2_Tcti_Mssim_Init (
goto fail_out;
}
+ if (conf_copy != NULL) {
+ free (conf_copy);
+ }
return TSS2_RC_SUCCESS;
fail_out:
+ if (conf_copy != NULL) {
+ free (conf_copy);
+ }
socket_close (&tcti_mssim->tpm_sock);
socket_close (&tcti_mssim->platform_sock);
- return TSS2_TCTI_RC_IO_ERROR;
+ return rc;
}
/* public info structure */
@@ -597,8 +589,7 @@ const TSS2_TCTI_INFO tss2_tcti_info = {
.version = TCTI_VERSION,
.name = "tcti-socket",
.description = "TCTI module for communication with the Microsoft TPM2 Simulator.",
- .config_help = "Connection URI in the form tcp://ip_address[:port]. " \
- "Default is: TCTI_SOCKET_DEFAULT.",
+ .config_help = "Key / value string in the form \"host=localhost,port=2321\".",
.init = Tss2_Tcti_Mssim_Init,
};
diff --git a/src/tss2-tcti/tcti-mssim.h b/src/tss2-tcti/tcti-mssim.h
index dbb750cb..f74fd743 100644
--- a/src/tss2-tcti/tcti-mssim.h
+++ b/src/tss2-tcti/tcti-mssim.h
@@ -28,12 +28,31 @@
#ifndef TCTI_MSSIM_H
#define TCTI_MSSIM_H
+#include <limits.h>
+
#include "tcti-common.h"
#include "util/io.h"
+/*
+ * longest possible conf string:
+ * HOST_NAME_MAX + max char uint16 (5) + strlen ("host=,port=") (11)
+ */
+#define TCTI_MSSIM_CONF_MAX (HOST_NAME_MAX + 16)
+#define TCTI_MSSIM_DEFAULT_HOST "localhost"
+#define TCTI_MSSIM_DEFAULT_PORT 2321
+#define MSSIM_CONF_DEFAULT_INIT { \
+ .host = TCTI_MSSIM_DEFAULT_HOST, \
+ .port = TCTI_MSSIM_DEFAULT_PORT, \
+}
+
#define TCTI_MSSIM_MAGIC 0xf05b04cd9f02728dULL
typedef struct {
+ char *host;
+ uint16_t port;
+} mssim_conf_t;
+
+typedef struct {
TSS2_TCTI_COMMON_CONTEXT common;
SOCKET platform_sock;
SOCKET tpm_sock;
diff --git a/src/util/key-value-parse.c b/src/util/key-value-parse.c
new file mode 100644
index 00000000..597922c4
--- /dev/null
+++ b/src/util/key-value-parse.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "tss2_tpm2_types.h"
+
+#include "util/key-value-parse.h"
+#define LOGMODULE tcti
+#include "util/log.h"
+
+/*
+ * Parse the provided string containing a key / value pair separated by the
+ * '=' character.
+ * NOTE: The 'kv_str' parameter is not 'const' and this function will modify
+ * it as part of the parsing process. The key_value structure will be updated
+ * with references pointing to the appropriate location in the key_value_str
+ * parameter.
+ */
+bool
+parse_key_value (char *key_value_str,
+ key_value_t *key_value)
+{
+ const char *delim = "=";
+ char *tok, *state;
+
+ LOG_TRACE ("key_value_str: \"%s\" and key_value_t: 0x%" PRIxPTR,
+ key_value_str, (uintptr_t)key_value);
+ if (key_value_str == NULL || key_value == NULL) {
+ LOG_WARNING ("received a NULL parameter, all are required");
+ return false;
+ }
+ tok = strtok_r (key_value_str, delim, &state);
+ if (tok == NULL) {
+ LOG_WARNING ("key / value string is null.");
+ return false;
+ }
+ key_value->key = tok;
+
+ tok = strtok_r (NULL, delim, &state);
+ if (tok == NULL) {
+ LOG_WARNING ("key / value string is invalid");
+ return false;
+ }
+ key_value->value = tok;
+
+ return true;
+}
+/*
+ * This function parses the provided configuration string extracting the
+ * key/value pairs. Each key/value pair extracted is stored in a key_value_t
+ * structure and then passed to the provided callback function for processing.
+ *
+ * NOTE: The 'kv_str' parameter is not 'const' and this function will modify
+ * it as part of the parsing process.
+ */
+TSS2_RC
+parse_key_value_string (char *kv_str,
+ KeyValueFunc callback,
+ void *user_data)
+{
+ const char *delim = ",";
+ char *state, *tok;
+ key_value_t key_value = KEY_VALUE_INIT;
+ TSS2_RC rc = TSS2_RC_SUCCESS;
+
+ LOG_TRACE ("kv_str: \"%s\", callback: 0x%" PRIxPTR ", user_data: 0x%"
+ PRIxPTR, kv_str, (uintptr_t)callback,
+ (uintptr_t)user_data);
+ if (kv_str == NULL || callback == NULL || user_data == NULL) {
+ LOG_WARNING ("all parameters are required");
+ return TSS2_TCTI_RC_BAD_VALUE;
+ }
+ for (tok = strtok_r (kv_str, delim, &state);
+ tok;
+ tok = strtok_r (NULL, delim, &state)) {
+ LOG_DEBUG ("parsing key/value: %s", tok);
+ if (parse_key_value (tok, &key_value) != true) {
+ return TSS2_TCTI_RC_BAD_VALUE;
+ }
+ rc = callback (&key_value, user_data);
+ if (rc != TSS2_RC_SUCCESS) {
+ goto out;
+ }
+ }
+out:
+ return rc;
+}
diff --git a/src/util/key-value-parse.h b/src/util/key-value-parse.h
new file mode 100644
index 00000000..7e2e926e
--- /dev/null
+++ b/src/util/key-value-parse.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+
+#include "tss2_tpm2_types.h"
+
+#define KEY_VALUE_INIT { \
+ .key = NULL, \
+ .value = NULL, \
+}
+
+typedef struct {
+ char *key;
+ char *value;
+} key_value_t;
+
+typedef TSS2_RC (*KeyValueFunc) (const key_value_t* key_value,
+ void *user_data);
+bool
+parse_key_value (char *key_value_str,
+ key_value_t *key_value);
+TSS2_RC
+parse_key_value_string (char *kv_str,
+ KeyValueFunc callback,
+ void *user_data);
diff --git a/test/integration/context-util.c b/test/integration/context-util.c
index e4a66e5c..bf50a8ee 100644
--- a/test/integration/context-util.c
+++ b/test/integration/context-util.c
@@ -8,6 +8,7 @@
#include "tss2_tcti_mssim.h"
#include "context-util.h"
+#include "tss2-tcti/tcti-mssim.h"
/*
* Initialize a TSS2_TCTI_CONTEXT for the device TCTI.
@@ -49,14 +50,14 @@ tcti_device_init(char const *device_path)
* function. This structure must be freed by the caller.
*/
TSS2_TCTI_CONTEXT *
-tcti_socket_init(char const *address, uint16_t port)
+tcti_socket_init(char const *host, uint16_t port)
{
size_t size;
TSS2_RC rc;
TSS2_TCTI_CONTEXT *tcti_ctx;
- char conf_str[256] = { 0 };
+ char conf_str[TCTI_MSSIM_CONF_MAX] = { 0 };
- snprintf(conf_str, 256, "tcp://%s:%" PRIu16, address, port);
+ snprintf(conf_str, TCTI_MSSIM_CONF_MAX, "host=%s,port=%" PRIu16, host, port);
rc = Tss2_Tcti_Mssim_Init(NULL, &size, conf_str);
if (rc != TSS2_RC_SUCCESS) {
fprintf(stderr, "Faled to get allocation size for tcti context: "
diff --git a/test/unit/esys-default-tcti.c b/test/unit/esys-default-tcti.c
index 84f653b0..4d155bbb 100644
--- a/test/unit/esys-default-tcti.c
+++ b/test/unit/esys-default-tcti.c
@@ -363,13 +363,13 @@ test_tcti_mssim(void **state)
*/
expect_value(__wrap_Tss2_Tcti_Mssim_Init, tctiContext, NULL);
expect_any(__wrap_Tss2_Tcti_Mssim_Init, size);
- expect_string(__wrap_Tss2_Tcti_Mssim_Init, config, "tcp://127.0.0.1:2321");
+ expect_string(__wrap_Tss2_Tcti_Mssim_Init, config, "host=localhost,port=2321");
will_return(__wrap_Tss2_Tcti_Mssim_Init, lsize);
will_return(__wrap_Tss2_Tcti_Mssim_Init, TSS2_RC_SUCCESS);
expect_any(__wrap_Tss2_Tcti_Mssim_Init, tctiContext);
expect_memory(__wrap_Tss2_Tcti_Mssim_Init, size, &lsize, sizeof(lsize));
- expect_string(__wrap_Tss2_Tcti_Mssim_Init, config, "tcp://127.0.0.1:2321");
+ expect_string(__wrap_Tss2_Tcti_Mssim_Init, config, "host=localhost,port=2321");
will_return(__wrap_Tss2_Tcti_Mssim_Init, lsize);
will_return(__wrap_Tss2_Tcti_Mssim_Init, TSS2_RC_SUCCESS);
diff --git a/test/unit/key-value-parse.c b/test/unit/key-value-parse.c
new file mode 100644
index 00000000..cfa7950b
--- /dev/null
+++ b/test/unit/key-value-parse.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "util/key-value-parse.h"
+
+/*
+ * Ensure that a simple key / value string is parsed into its component parts.
+ */
+static void
+parse_key_value_simple_test (void **state)
+{
+ bool ret;
+ char test_str[] = "key=value";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_true (ret);
+ assert_string_equal (key_value.key, "key");
+ assert_string_equal (key_value.value, "value");
+}
+/*
+ * Ensure that a NULL key/value string causes parse_key_value to return false.
+ */
+static void
+parse_key_value_NULL_string_test (void **state)
+{
+ bool ret;
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (NULL, &key_value);
+ assert_false (ret);
+}
+/*
+ * Ensure that a NULL key_value_t parameter causes parse_key_value to return
+ * false.
+ */
+static void
+parse_key_value_NULL_key_value_test (void **state)
+{
+ bool ret;
+ char test_str[] = "key=value";
+
+ ret = parse_key_value (test_str, NULL);
+ assert_false (ret);
+}
+/*
+ * Ensure that an incomplete key/value string with only the "key=" returns
+ * false.
+ */
+static void
+parse_key_value_no_value_test (void **state)
+{
+ bool ret;
+ char test_str[] = "key=";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_false (ret);
+}
+/*
+ * Ensure that a key/value string with only the "=value" part returns false.
+ */
+static void
+parse_key_value_no_key_test (void **state)
+{
+ bool ret;
+ char test_str[] = "=value";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_false (ret);
+}
+/*
+ * Ensure that a key/value string with the separators in the wrong place
+ * returns false.
+ */
+static void
+parse_key_value_two_seps_test (void **state)
+{
+ bool ret;
+ char test_str[] = "=foo=";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_false (ret);
+}
+/*
+ * Ensure that a key/value string with all separators returns false.
+ */
+static void
+parse_key_value_all_seps_test (void **state)
+{
+ bool ret;
+ char test_str[] = "====";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_false (ret);
+}
+/*
+ * Ensure that a key/value string that alternates strings and separators
+ * will parse the first two and ignore the rest.
+ */
+static void
+parse_key_value_alt_seps_test (void **state)
+{
+ bool ret;
+ char test_str[] = "key=value=key=value";
+ key_value_t key_value = KEY_VALUE_INIT;
+
+ ret = parse_key_value (test_str, &key_value);
+ assert_true (ret);
+ assert_string_equal (key_value.key, "key");
+ assert_string_equal (key_value.value, "value");
+}
+/*
+ * This is a simple data structure used to hold values parsed from a string
+ * of key/value pairs.
+ */
+#define TEST_DATA_INIT { \
+ .value0 = NULL, \
+ .value1 = NULL, \
+}
+typedef struct {
+ char *value0;
+ char *value1;
+} test_data_t;
+/*
+ * This is a callback function used to handle extracted key / value pairs.
+ */
+TSS2_RC
+key_value_callback (const key_value_t *key_value,
+ void *user_data)
+{
+ test_data_t *test_data = (test_data_t*)user_data;
+
+ if (strcmp ("key0", key_value->key) == 0) {
+ test_data->value0 = key_value->value;
+ return TSS2_RC_SUCCESS;
+ } else if (strcmp ("key1", key_value->key) == 0) {
+ test_data->value1 = key_value->value;
+ return TSS2_RC_SUCCESS;
+ } else {
+ return 1;
+ }
+}
+/*
+ * This tests the typical case for the parsing of a string of key / value
+ * pairs.
+ */
+static void
+parse_key_value_string_good_test (void **state)
+{
+ TSS2_RC rc;
+ char test_str[] = "key0=value0,key1=value1";
+ test_data_t test_data = TEST_DATA_INIT;
+
+ rc = parse_key_value_string (test_str, key_value_callback, &test_data);
+ assert_int_equal (rc, TSS2_RC_SUCCESS);
+ assert_string_equal (test_data.value0, "value0");
+ assert_string_equal (test_data.value1, "value1");
+}
+/*
+ * This test ensures that he parse_key_value_string function handles a failed
+ * call to parse a key/value pair properly.
+ */
+static void
+parse_key_value_string_no_value_test (void **state)
+{
+ TSS2_RC rc;
+ char test_str[] = "key0=,key1=value1";
+ test_data_t test_data = TEST_DATA_INIT;
+
+ rc = parse_key_value_string (test_str, key_value_callback, &test_data);
+ assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
+}
+/*
+ * This test ensures that the parse_key_value_string function handles a failed
+ * call to the user provided callback properly. The return value we get from
+ * the parse_key_value_string function is the same value returned by our
+ * callback.
+ */
+static void
+parse_key_value_string_unknown_key_test (void **state)
+{
+ TSS2_RC rc;
+ char test_str[] = "key0=foo=bar,baz=qux";
+ test_data_t test_data = TEST_DATA_INIT;
+
+ rc = parse_key_value_string (test_str, key_value_callback, &test_data);
+ assert_int_equal (rc, 1);
+}
+/*
+ * The following 3 tests ensures that NULL parameters produce an error.
+ */
+static void
+parse_key_value_string_NULL_kv_string_test (void **state)
+{
+ TSS2_RC rc;
+ test_data_t test_data = TEST_DATA_INIT;
+
+ rc = parse_key_value_string (NULL, key_value_callback, &test_data);
+ assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
+}
+static void
+parse_key_value_string_NULL_callback_test (void **state)
+{
+ TSS2_RC rc;
+ char test_str[] = "key0=foo=bar,baz=qux";
+ test_data_t test_data = TEST_DATA_INIT;
+
+ rc = parse_key_value_string (test_str, NULL, &test_data);
+ assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
+}
+static void
+parse_key_value_string_NULL_user_data_test (void **state)
+{
+ TSS2_RC rc;
+ char test_str[] = "key0=foo=bar,baz=qux";
+
+ rc = parse_key_value_string (test_str, key_value_callback, NULL);
+ assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
+}
+
+int
+main(int argc, char* argv[])
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test (parse_key_value_simple_test),
+ cmocka_unit_test (parse_key_value_NULL_string_test),
+ cmocka_unit_test (parse_key_value_NULL_key_value_test),
+ cmocka_unit_test (parse_key_value_no_value_test),
+ cmocka_unit_test (parse_key_value_no_key_test),
+ cmocka_unit_test (parse_key_value_two_seps_test),
+ cmocka_unit_test (parse_key_value_all_seps_test),
+ cmocka_unit_test (parse_key_value_alt_seps_test),
+ cmocka_unit_test (parse_key_value_string_good_test),
+ cmocka_unit_test (parse_key_value_string_no_value_test),
+ cmocka_unit_test (parse_key_value_string_unknown_key_test),
+ cmocka_unit_test (parse_key_value_string_NULL_kv_string_test),
+ cmocka_unit_test (parse_key_value_string_NULL_callback_test),
+ cmocka_unit_test (parse_key_value_string_NULL_user_data_test),
+ };
+ return cmocka_run_group_tests (tests, NULL, NULL);
+}
diff --git a/test/unit/tcti-mssim.c b/test/unit/tcti-mssim.c
index 56246b92..d6a5dc96 100644
--- a/test/unit/tcti-mssim.c
+++ b/test/unit/tcti-mssim.c
@@ -40,17 +40,15 @@
#include "tss2-tcti/tcti-common.h"
#include "tss2-tcti/tcti-mssim.h"
+#include "util/key-value-parse.h"
/*
- * This function is implemented in the socket TCTI module but not exposed
- * through the public headers.
+ * This function is defined in the tcti-mssim module but not exposed through
+ * the header.
*/
TSS2_RC
-conf_str_to_host_port (
- const char *conf,
- char *hostname,
- uint16_t *port);
-
+mssim_kv_callback (const key_value_t *key_value,
+ void *user_data);
/*
* This tests our ability to handle conf strings that have a port
* component. In this case the 'conf_str_to_host_port' function
@@ -61,14 +59,13 @@ static void
conf_str_to_host_port_success_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://127.0.0.1:2321";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port;
+ char conf[] = "host=127.0.0.1,port=2321";
+ mssim_conf_t mssim_conf = { 0 };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_RC_SUCCESS);
- assert_int_equal (port, 2321);
- assert_string_equal (hostname, "127.0.0.1");
+ assert_int_equal (mssim_conf.port, 2321);
+ assert_string_equal (mssim_conf.host, "127.0.0.1");
}
/*
@@ -82,13 +79,16 @@ static void
conf_str_to_host_port_no_port_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://127.0.0.1";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port = NO_PORT_VALUE;
+ char conf[] = "host=127.0.0.1";
+ mssim_conf_t mssim_conf = {
+ .host = "foo",
+ .port = NO_PORT_VALUE,
+ };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_RC_SUCCESS);
- assert_int_equal (port, NO_PORT_VALUE);
+ assert_string_equal (mssim_conf.host, "127.0.0.1");
+ assert_int_equal (mssim_conf.port, NO_PORT_VALUE);
}
/*
@@ -101,14 +101,13 @@ static void
conf_str_to_host_ipv6_port_success_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://[::1]:2321";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port;
+ char conf[] = "host=::1,port=2321";
+ mssim_conf_t mssim_conf = { 0 };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_RC_SUCCESS);
- assert_int_equal (port, 2321);
- assert_string_equal (hostname, "::1");
+ assert_int_equal (mssim_conf.port, 2321);
+ assert_string_equal (mssim_conf.host, "::1");
}
/*
@@ -121,13 +120,13 @@ static void
conf_str_to_host_ipv6_port_no_port_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://[::1]";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port = NO_PORT_VALUE;
+ char conf[] = "host=::1";
+ mssim_conf_t mssim_conf = { .port = NO_PORT_VALUE };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_RC_SUCCESS);
- assert_int_equal (port, NO_PORT_VALUE);
+ assert_int_equal (mssim_conf.port, NO_PORT_VALUE);
+ assert_string_equal (mssim_conf.host, "::1");
}
/*
@@ -137,11 +136,10 @@ static void
conf_str_to_host_port_invalid_port_large_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://127.0.0.1:99999";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port;
+ char conf[] = "host=127.0.0.1,port=99999";
+ mssim_conf_t mssim_conf = { 0 };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
}
/* The 'conf_str_to_host_port' function rejects URIs with port == 0 */
@@ -149,11 +147,10 @@ static void
conf_str_to_host_port_invalid_port_0_test (void **state)
{
TSS2_RC rc;
- char *conf = "tcp://127.0.0.1:0";
- char hostname [HOST_NAME_MAX] = { 0 };
- uint16_t port;
+ char conf[] = "host=127.0.0.1,port=0";
+ mssim_conf_t mssim_conf = { 0 };
- rc = conf_str_to_host_port (conf, hostname, &port);
+ rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
}
@@ -269,7 +266,7 @@ static int
tcti_socket_setup (void **state)
{
printf ("%s: before tcti_socket_init_from_conf\n", __func__);
- *state = tcti_socket_init_from_conf ("tcp://127.0.0.1:666");
+ *state = tcti_socket_init_from_conf ("host=127.0.0.1,port=666");
printf ("%s: done\n", __func__);
return 0;
}