sock/ssl: Add psk_key and psk_identity options to spdk_sock_impl_opts

Note, this change only sets defaults for the ID/KEY,
more specific use cases like NVMe/TCP may set the ID and KEY on a per connection basis.

Also simplify PSK identity string, that isn't NVMe focused.
NVMe libraries using this will need to construct more complicated
identity strings and pass them to the sock layer.

Example:
  rpc.py sock_impl_set_options -i ssl --psk-key 4321DEADBEEF1234
  rpc.py sock_impl_set_options -i ssl --psk-identity psk.spdk.io

  ./build/examples/perf --psk-key 4321DEADBEEF1234 --psk-identity psk.spdk.io

  ./build/examples/hello_sock --psk-key 4321DEADBEEF1234 --psk-identity psk.spdk.io

Change-Id: I1cb5b0b706bdeafbccbc71f8320bc8e2961cbb55
Signed-off-by: Boris Glimcher <Boris.Glimcher@emc.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13759
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
This commit is contained in:
Boris Glimcher 2022-07-22 17:27:45 +03:00 committed by Jim Harris
parent 21d9b32fa3
commit 6212597bda
13 changed files with 205 additions and 40 deletions

View File

@ -24,6 +24,7 @@ Calculate num_md_pages from num_md_pages_per_cluster_ratio, and pass it to spdk_
### rpc ### rpc
New options `enable_ktls` and `tls_version` were added to the `sock_impl_set_options` structure. New options `enable_ktls` and `tls_version` were added to the `sock_impl_set_options` structure.
New options `psk_key` and `psk_identity` were added to the `sock_impl_set_options` structure.
Added warning message for `bdev_rbd_create`, if it is used without -c. Added warning message for `bdev_rbd_create`, if it is used without -c.
`bdev_rbd_create()` API without specifying -c is deprecated and will be removed in future release. `bdev_rbd_create()` API without specifying -c is deprecated and will be removed in future release.

View File

@ -9743,7 +9743,9 @@ Example response:
"enable_zerocopy_send_client": false, "enable_zerocopy_send_client": false,
"zerocopy_threshold": 0, "zerocopy_threshold": 0,
"tls_version": 13, "tls_version": 13,
"enable_ktls": false "enable_ktls": false,
"psk_key": "1234567890ABCDEF",
"psk_identity": "psk.spdk.io"
} }
} }
~~~ ~~~
@ -9768,6 +9770,8 @@ zerocopy_threshold | Optional | number | Set zerocopy_threshold in
-- | -- | -- | that fall below this threshold may be sent without zerocopy flag set -- | -- | -- | that fall below this threshold may be sent without zerocopy flag set
tls_version | Optional | number | TLS protocol version, e.g. 13 for v1.3 (only applies when impl_name == ssl) tls_version | Optional | number | TLS protocol version, e.g. 13 for v1.3 (only applies when impl_name == ssl)
enable_ktls | Optional | boolean | Enable or disable Kernel TLS (only applies when impl_name == ssl) enable_ktls | Optional | boolean | Enable or disable Kernel TLS (only applies when impl_name == ssl)
psk_key | Optional | string | Default PSK KEY in hexadecimal digits, e.g. 1234567890ABCDEF (only applies when impl_name == ssl)
psk_identity | Optional | string | Default PSK ID, e.g. psk.spdk.io (only applies when impl_name == ssl)
#### Response #### Response
@ -9793,7 +9797,9 @@ Example request:
"enable_zerocopy_send_client": false, "enable_zerocopy_send_client": false,
"zerocopy_threshold": 10240, "zerocopy_threshold": 10240,
"tls_version": 13, "tls_version": 13,
"enable_ktls": false "enable_ktls": false,
"psk_key": "1234567890ABCDEF",
"psk_identity": "psk.spdk.io"
} }
} }
~~~ ~~~

View File

@ -291,7 +291,7 @@ static int g_file_optind; /* Index of first filename in argv */
static inline void task_complete(struct perf_task *task); static inline void task_complete(struct perf_task *task);
static void static void
perf_set_sock_opts(const char *impl_name, const char *field, uint32_t val) perf_set_sock_opts(const char *impl_name, const char *field, uint32_t val, const char *valstr)
{ {
struct spdk_sock_impl_opts sock_opts = {}; struct spdk_sock_impl_opts sock_opts = {};
size_t opts_size = sizeof(sock_opts); size_t opts_size = sizeof(sock_opts);
@ -323,6 +323,26 @@ perf_set_sock_opts(const char *impl_name, const char *field, uint32_t val)
sock_opts.tls_version = val; sock_opts.tls_version = val;
} else if (strcmp(field, "ktls") == 0) { } else if (strcmp(field, "ktls") == 0) {
sock_opts.enable_ktls = val; sock_opts.enable_ktls = val;
} else if (strcmp(field, "psk_key") == 0) {
if (!valstr) {
fprintf(stderr, "No socket opts value specified\n");
return;
}
sock_opts.psk_key = strdup(valstr);
if (sock_opts.psk_key == NULL) {
fprintf(stderr, "Failed to allocate psk_key in sock_impl\n");
return;
}
} else if (strcmp(field, "psk_identity") == 0) {
if (!valstr) {
fprintf(stderr, "No socket opts value specified\n");
return;
}
sock_opts.psk_identity = strdup(valstr);
if (sock_opts.psk_identity == NULL) {
fprintf(stderr, "Failed to allocate psk_identity in sock_impl\n");
return;
}
} else { } else {
fprintf(stderr, "Warning: invalid or unprocessed socket opts field: %s\n", field); fprintf(stderr, "Warning: invalid or unprocessed socket opts field: %s\n", field);
return; return;
@ -1790,6 +1810,8 @@ usage(char *program_name)
printf("\t[--disable-ktls disable Kernel TLS. Only valid for ssl impl. Default for ssl impl]\n"); printf("\t[--disable-ktls disable Kernel TLS. Only valid for ssl impl. Default for ssl impl]\n");
printf("\t[--enable-ktls enable Kernel TLS. Only valid for ssl impl]\n"); printf("\t[--enable-ktls enable Kernel TLS. Only valid for ssl impl]\n");
printf("\t[--tls-version <val> TLS version to use. Only valid for ssl impl. Default: 0 (auto-negotiation)]\n"); printf("\t[--tls-version <val> TLS version to use. Only valid for ssl impl. Default: 0 (auto-negotiation)]\n");
printf("\t[--psk-key <val> Default PSK KEY in hexadecimal digits, e.g. 1234567890ABCDEF (only applies when sock_impl == ssl)]\n");
printf("\t[--psk-identity <val> Default PSK ID, e.g. psk.spdk.io (only applies when sock_impl == ssl)]\n");
} }
static void static void
@ -2288,6 +2310,10 @@ static const struct option g_perf_cmdline_opts[] = {
{"enable-ktls", no_argument, NULL, PERF_ENABLE_KTLS}, {"enable-ktls", no_argument, NULL, PERF_ENABLE_KTLS},
#define PERF_TLS_VERSION 262 #define PERF_TLS_VERSION 262
{"tls-version", required_argument, NULL, PERF_TLS_VERSION}, {"tls-version", required_argument, NULL, PERF_TLS_VERSION},
#define PERF_PSK_KEY 263
{"psk-key", required_argument, NULL, PERF_PSK_KEY},
#define PERF_PSK_IDENTITY 264
{"psk-identity ", required_argument, NULL, PERF_PSK_IDENTITY},
/* Should be the last element */ /* Should be the last element */
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -2299,6 +2325,8 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
long int val; long int val;
int rc; int rc;
char *endptr; char *endptr;
bool ssl_used = false;
char *sock_impl = "posix";
while ((op = getopt_long(argc, argv, PERF_GETOPT_SHORT, g_perf_cmdline_opts, &long_idx)) != -1) { while ((op = getopt_long(argc, argv, PERF_GETOPT_SHORT, g_perf_cmdline_opts, &long_idx)) != -1) {
switch (op) { switch (op) {
@ -2469,26 +2497,38 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
g_vmd = true; g_vmd = true;
break; break;
case PERF_DISABLE_KTLS: case PERF_DISABLE_KTLS:
perf_set_sock_opts(optarg, "ktls", 0); ssl_used = true;
perf_set_sock_opts("ssl", "ktls", 0, NULL);
break; break;
case PERF_ENABLE_KTLS: case PERF_ENABLE_KTLS:
perf_set_sock_opts(optarg, "ktls", 1); ssl_used = true;
perf_set_sock_opts("ssl", "ktls", 1, NULL);
break; break;
case PERF_TLS_VERSION: case PERF_TLS_VERSION:
ssl_used = true;
val = spdk_strtol(optarg, 10); val = spdk_strtol(optarg, 10);
if (val < 0) { if (val < 0) {
fprintf(stderr, "Illegal tls version value %s\n", optarg); fprintf(stderr, "Illegal tls version value %s\n", optarg);
return val; return val;
} }
perf_set_sock_opts(optarg, "tls_version", val); perf_set_sock_opts("ssl", "tls_version", val, NULL);
break;
case PERF_PSK_KEY:
ssl_used = true;
perf_set_sock_opts("ssl", "psk_key", 0, optarg);
break;
case PERF_PSK_IDENTITY:
ssl_used = true;
perf_set_sock_opts("ssl", "psk_identity", 0, optarg);
break; break;
case PERF_DISABLE_ZCOPY: case PERF_DISABLE_ZCOPY:
perf_set_sock_opts(optarg, "enable_zerocopy_send_client", 0); perf_set_sock_opts(optarg, "enable_zerocopy_send_client", 0, NULL);
break; break;
case PERF_ENABLE_ZCOPY: case PERF_ENABLE_ZCOPY:
perf_set_sock_opts(optarg, "enable_zerocopy_send_client", 1); perf_set_sock_opts(optarg, "enable_zerocopy_send_client", 1, NULL);
break; break;
case PERF_DEFAULT_SOCK_IMPL: case PERF_DEFAULT_SOCK_IMPL:
sock_impl = optarg;
rc = spdk_sock_set_default_impl(optarg); rc = spdk_sock_set_default_impl(optarg);
if (rc) { if (rc) {
fprintf(stderr, "Failed to set sock impl %s, err %d (%s)\n", optarg, errno, strerror(errno)); fprintf(stderr, "Failed to set sock impl %s, err %d (%s)\n", optarg, errno, strerror(errno));
@ -2547,6 +2587,13 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
g_workload_type = &g_workload_type[4]; g_workload_type = &g_workload_type[4];
} }
if (ssl_used && strncmp(sock_impl, "ssl", 3) != 0) {
fprintf(stderr, "sock impl is not SSL but tried to use one of the SSL only options\n");
usage(argv[0]);
return 1;
}
if (strcmp(g_workload_type, "read") == 0 || strcmp(g_workload_type, "write") == 0) { if (strcmp(g_workload_type, "read") == 0 || strcmp(g_workload_type, "write") == 0) {
g_rw_percentage = strcmp(g_workload_type, "read") == 0 ? 100 : 0; g_rw_percentage = strcmp(g_workload_type, "read") == 0 ? 100 : 0;
if (g_mix_specified) { if (g_mix_specified) {

View File

@ -27,6 +27,8 @@ static int g_zcopy;
static int g_ktls; static int g_ktls;
static int g_tls_version; static int g_tls_version;
static bool g_verbose; static bool g_verbose;
static char *g_psk_key;
static char *g_psk_identity;
/* /*
* We'll use this struct to gather housekeeping hello_context to pass between * We'll use this struct to gather housekeeping hello_context to pass between
@ -40,6 +42,8 @@ struct hello_context_t {
int zcopy; int zcopy;
int ktls; int ktls;
int tls_version; int tls_version;
char *psk_key;
char *psk_identity;
bool verbose; bool verbose;
int bytes_in; int bytes_in;
@ -61,7 +65,9 @@ struct hello_context_t {
static void static void
hello_sock_usage(void) hello_sock_usage(void)
{ {
printf(" -E psk_key Default PSK KEY in hexadecimal digits, e.g. 1234567890ABCDEF (only applies when sock_impl == ssl)\n");
printf(" -H host_addr host address\n"); printf(" -H host_addr host address\n");
printf(" -I psk_id Default PSK ID, e.g. psk.spdk.io (only applies when sock_impl == ssl)\n");
printf(" -P port port number\n"); printf(" -P port port number\n");
printf(" -N sock_impl socket implementation, e.g., -N posix or -N uring\n"); printf(" -N sock_impl socket implementation, e.g., -N posix or -N uring\n");
printf(" -S start in server mode\n"); printf(" -S start in server mode\n");
@ -80,9 +86,15 @@ static int
hello_sock_parse_arg(int ch, char *arg) hello_sock_parse_arg(int ch, char *arg)
{ {
switch (ch) { switch (ch) {
case 'E':
g_psk_key = arg;
break;
case 'H': case 'H':
g_host = arg; g_host = arg;
break; break;
case 'I':
g_psk_identity = arg;
break;
case 'N': case 'N':
g_sock_impl_name = arg; g_sock_impl_name = arg;
break; break;
@ -225,6 +237,8 @@ hello_sock_connect(struct hello_context_t *ctx)
spdk_sock_impl_get_opts(ctx->sock_impl_name, &impl_opts, &impl_opts_size); spdk_sock_impl_get_opts(ctx->sock_impl_name, &impl_opts, &impl_opts_size);
impl_opts.enable_ktls = ctx->ktls; impl_opts.enable_ktls = ctx->ktls;
impl_opts.tls_version = ctx->tls_version; impl_opts.tls_version = ctx->tls_version;
impl_opts.psk_key = ctx->psk_key;
impl_opts.psk_identity = ctx->psk_identity;
opts.opts_size = sizeof(opts); opts.opts_size = sizeof(opts);
spdk_sock_get_default_opts(&opts); spdk_sock_get_default_opts(&opts);
@ -369,6 +383,8 @@ hello_sock_listen(struct hello_context_t *ctx)
spdk_sock_impl_get_opts(ctx->sock_impl_name, &impl_opts, &impl_opts_size); spdk_sock_impl_get_opts(ctx->sock_impl_name, &impl_opts, &impl_opts_size);
impl_opts.enable_ktls = ctx->ktls; impl_opts.enable_ktls = ctx->ktls;
impl_opts.tls_version = ctx->tls_version; impl_opts.tls_version = ctx->tls_version;
impl_opts.psk_key = ctx->psk_key;
impl_opts.psk_identity = ctx->psk_identity;
opts.opts_size = sizeof(opts); opts.opts_size = sizeof(opts);
spdk_sock_get_default_opts(&opts); spdk_sock_get_default_opts(&opts);
@ -443,7 +459,7 @@ main(int argc, char **argv)
opts.name = "hello_sock"; opts.name = "hello_sock";
opts.shutdown_cb = hello_sock_shutdown_cb; opts.shutdown_cb = hello_sock_shutdown_cb;
if ((rc = spdk_app_parse_args(argc, argv, &opts, "H:kKN:P:ST:VzZ", NULL, hello_sock_parse_arg, if ((rc = spdk_app_parse_args(argc, argv, &opts, "E:H:I:kKN:P:ST:VzZ", NULL, hello_sock_parse_arg,
hello_sock_usage)) != SPDK_APP_PARSE_ARGS_SUCCESS) { hello_sock_usage)) != SPDK_APP_PARSE_ARGS_SUCCESS) {
exit(rc); exit(rc);
} }
@ -454,6 +470,8 @@ main(int argc, char **argv)
hello_context.zcopy = g_zcopy; hello_context.zcopy = g_zcopy;
hello_context.ktls = g_ktls; hello_context.ktls = g_ktls;
hello_context.tls_version = g_tls_version; hello_context.tls_version = g_tls_version;
hello_context.psk_key = g_psk_key;
hello_context.psk_identity = g_psk_identity;
hello_context.verbose = g_verbose; hello_context.verbose = g_verbose;
rc = spdk_app_start(&opts, hello_start, &hello_context); rc = spdk_app_start(&opts, hello_start, &hello_context);

View File

@ -138,6 +138,16 @@ struct spdk_sock_impl_opts {
* Enable or disable kernel TLS. Used by ssl socket modules. * Enable or disable kernel TLS. Used by ssl socket modules.
*/ */
bool enable_ktls; bool enable_ktls;
/**
* Set default PSK key. Used by ssl socket module.
*/
char *psk_key;
/**
* Set default PSK identity. Used by ssl socket module.
*/
char *psk_identity;
}; };
/** /**

View File

@ -867,6 +867,12 @@ spdk_sock_write_config_json(struct spdk_json_write_ctx *w)
spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold); spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold);
spdk_json_write_named_uint32(w, "tls_version", opts.tls_version); spdk_json_write_named_uint32(w, "tls_version", opts.tls_version);
spdk_json_write_named_bool(w, "enable_ktls", opts.enable_ktls); spdk_json_write_named_bool(w, "enable_ktls", opts.enable_ktls);
if (opts.psk_key) {
spdk_json_write_named_string(w, "psk_key", opts.psk_key);
}
if (opts.psk_identity) {
spdk_json_write_named_string(w, "psk_identity", opts.psk_identity);
}
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
} else { } else {

View File

@ -54,6 +54,12 @@ rpc_sock_impl_get_options(struct spdk_jsonrpc_request *request,
spdk_json_write_named_uint32(w, "zerocopy_threshold", sock_opts.zerocopy_threshold); spdk_json_write_named_uint32(w, "zerocopy_threshold", sock_opts.zerocopy_threshold);
spdk_json_write_named_uint32(w, "tls_version", sock_opts.tls_version); spdk_json_write_named_uint32(w, "tls_version", sock_opts.tls_version);
spdk_json_write_named_bool(w, "enable_ktls", sock_opts.enable_ktls); spdk_json_write_named_bool(w, "enable_ktls", sock_opts.enable_ktls);
if (sock_opts.psk_key) {
spdk_json_write_named_string(w, "psk_key", sock_opts.psk_key);
}
if (sock_opts.psk_identity) {
spdk_json_write_named_string(w, "psk_identity", sock_opts.psk_identity);
}
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
spdk_jsonrpc_end_result(request, w); spdk_jsonrpc_end_result(request, w);
free(impl_name); free(impl_name);
@ -110,6 +116,14 @@ static const struct spdk_json_object_decoder rpc_sock_impl_set_opts_decoders[] =
{ {
"enable_ktls", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_ktls), "enable_ktls", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_ktls),
spdk_json_decode_bool, true spdk_json_decode_bool, true
},
{
"psk_key", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.psk_key),
spdk_json_decode_string, true
},
{
"psk_identity", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.psk_identity),
spdk_json_decode_string, true
} }
}; };

View File

@ -78,7 +78,9 @@ static struct spdk_sock_impl_opts g_spdk_posix_sock_impl_opts = {
.enable_zerocopy_send_client = false, .enable_zerocopy_send_client = false,
.zerocopy_threshold = 0, .zerocopy_threshold = 0,
.tls_version = 0, .tls_version = 0,
.enable_ktls = false .enable_ktls = false,
.psk_key = NULL,
.psk_identity = NULL
}; };
static struct spdk_sock_map g_map = { static struct spdk_sock_map g_map = {
@ -118,6 +120,8 @@ posix_sock_copy_impl_opts(struct spdk_sock_impl_opts *dest, const struct spdk_so
SET_FIELD(zerocopy_threshold); SET_FIELD(zerocopy_threshold);
SET_FIELD(tls_version); SET_FIELD(tls_version);
SET_FIELD(enable_ktls); SET_FIELD(enable_ktls);
SET_FIELD(psk_key);
SET_FIELD(psk_identity);
#undef SET_FIELD #undef SET_FIELD
#undef FIELD_OK #undef FIELD_OK
@ -498,9 +502,6 @@ posix_fd_create(struct addrinfo *res, struct spdk_sock_opts *opts,
return fd; return fd;
} }
#define PSK_ID "nqn.2014-08.org.nvmexpress:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
#define PSK_KEY "1234567890ABCDEF"
static unsigned int static unsigned int
posix_sock_tls_psk_server_cb(SSL *ssl, posix_sock_tls_psk_server_cb(SSL *ssl,
const char *id, const char *id,
@ -509,24 +510,27 @@ posix_sock_tls_psk_server_cb(SSL *ssl,
{ {
long key_len; long key_len;
unsigned char *default_psk; unsigned char *default_psk;
struct spdk_sock_impl_opts *impl_opts;
if (PSK_KEY == NULL) { impl_opts = SSL_get_app_data(ssl);
if (impl_opts->psk_key == NULL) {
SPDK_ERRLOG("PSK is not set\n"); SPDK_ERRLOG("PSK is not set\n");
goto err; goto err;
} }
SPDK_DEBUGLOG(sock_posix, "Length of Client's PSK ID %lu\n", strlen(PSK_ID)); SPDK_DEBUGLOG(sock_posix, "Length of Client's PSK ID %lu\n", strlen(impl_opts->psk_identity));
if (id == NULL) { if (id == NULL) {
SPDK_ERRLOG("Received empty PSK ID\n"); SPDK_ERRLOG("Received empty PSK ID\n");
goto err; goto err;
} }
SPDK_DEBUGLOG(sock_posix, "Received PSK ID '%s'\n", id); SPDK_DEBUGLOG(sock_posix, "Received PSK ID '%s'\n", id);
if (strcmp(PSK_ID, id) != 0) { if (strcmp(impl_opts->psk_identity, id) != 0) {
SPDK_ERRLOG("Unknown Client's PSK ID\n"); SPDK_ERRLOG("Unknown Client's PSK ID\n");
goto err; goto err;
} }
SPDK_DEBUGLOG(sock_posix, "Length of Client's PSK KEY %u\n", max_psk_len); SPDK_DEBUGLOG(sock_posix, "Length of Client's PSK KEY %u\n", max_psk_len);
default_psk = OPENSSL_hexstr2buf(PSK_KEY, &key_len); default_psk = OPENSSL_hexstr2buf(impl_opts->psk_key, &key_len);
if (default_psk == NULL) { if (default_psk == NULL) {
SPDK_ERRLOG("Could not unhexlify PSK\n"); SPDK_ERRLOG("Could not unhexlify PSK\n");
goto err; goto err;
@ -553,26 +557,29 @@ posix_sock_tls_psk_client_cb(SSL *ssl, const char *hint,
{ {
long key_len; long key_len;
unsigned char *default_psk; unsigned char *default_psk;
struct spdk_sock_impl_opts *impl_opts;
impl_opts = SSL_get_app_data(ssl);
if (hint) { if (hint) {
SPDK_DEBUGLOG(sock_posix, "Received PSK identity hint '%s'\n", hint); SPDK_DEBUGLOG(sock_posix, "Received PSK identity hint '%s'\n", hint);
} }
if (PSK_KEY == NULL) { if (impl_opts->psk_key == NULL) {
SPDK_ERRLOG("PSK is not set\n"); SPDK_ERRLOG("PSK is not set\n");
goto err; goto err;
} }
default_psk = OPENSSL_hexstr2buf(PSK_KEY, &key_len); default_psk = OPENSSL_hexstr2buf(impl_opts->psk_key, &key_len);
if (default_psk == NULL) { if (default_psk == NULL) {
SPDK_ERRLOG("Could not unhexlify PSK\n"); SPDK_ERRLOG("Could not unhexlify PSK\n");
goto err; goto err;
} }
if ((strlen(PSK_ID) + 1 > max_identity_len) if ((strlen(impl_opts->psk_identity) + 1 > max_identity_len)
|| (key_len > max_psk_len)) { || (key_len > max_psk_len)) {
SPDK_ERRLOG("PSK ID or Key buffer is not sufficient\n"); SPDK_ERRLOG("PSK ID or Key buffer is not sufficient\n");
goto err; goto err;
} }
spdk_strcpy_pad(identity, PSK_ID, strlen(PSK_ID), 0); spdk_strcpy_pad(identity, impl_opts->psk_identity, strlen(impl_opts->psk_identity), 0);
SPDK_DEBUGLOG(sock_posix, "Sending PSK identity '%s'\n", identity); SPDK_DEBUGLOG(sock_posix, "Sending PSK identity '%s'\n", identity);
memcpy(psk, default_psk, key_len); memcpy(psk, default_psk, key_len);
@ -658,7 +665,7 @@ err:
} }
static SSL * static SSL *
ssl_sock_connect_loop(SSL_CTX *ctx, int fd) ssl_sock_connect_loop(SSL_CTX *ctx, int fd, struct spdk_sock_impl_opts *impl_opts)
{ {
int rc; int rc;
SSL *ssl; SSL *ssl;
@ -670,6 +677,7 @@ ssl_sock_connect_loop(SSL_CTX *ctx, int fd)
return NULL; return NULL;
} }
SSL_set_fd(ssl, fd); SSL_set_fd(ssl, fd);
SSL_set_app_data(ssl, impl_opts);
SSL_set_psk_client_callback(ssl, posix_sock_tls_psk_client_cb); SSL_set_psk_client_callback(ssl, posix_sock_tls_psk_client_cb);
SPDK_DEBUGLOG(sock_posix, "SSL object creation finished: %p\n", ssl); SPDK_DEBUGLOG(sock_posix, "SSL object creation finished: %p\n", ssl);
SPDK_DEBUGLOG(sock_posix, "%s = SSL_state_string_long(%p)\n", SSL_state_string_long(ssl), ssl); SPDK_DEBUGLOG(sock_posix, "%s = SSL_state_string_long(%p)\n", SSL_state_string_long(ssl), ssl);
@ -696,7 +704,7 @@ ssl_sock_connect_loop(SSL_CTX *ctx, int fd)
} }
static SSL * static SSL *
ssl_sock_accept_loop(SSL_CTX *ctx, int fd) ssl_sock_accept_loop(SSL_CTX *ctx, int fd, struct spdk_sock_impl_opts *impl_opts)
{ {
int rc; int rc;
SSL *ssl; SSL *ssl;
@ -708,6 +716,7 @@ ssl_sock_accept_loop(SSL_CTX *ctx, int fd)
return NULL; return NULL;
} }
SSL_set_fd(ssl, fd); SSL_set_fd(ssl, fd);
SSL_set_app_data(ssl, impl_opts);
SSL_set_psk_server_callback(ssl, posix_sock_tls_psk_server_cb); SSL_set_psk_server_callback(ssl, posix_sock_tls_psk_server_cb);
SPDK_DEBUGLOG(sock_posix, "SSL object creation finished: %p\n", ssl); SPDK_DEBUGLOG(sock_posix, "SSL object creation finished: %p\n", ssl);
SPDK_DEBUGLOG(sock_posix, "%s = SSL_state_string_long(%p)\n", SSL_state_string_long(ssl), ssl); SPDK_DEBUGLOG(sock_posix, "%s = SSL_state_string_long(%p)\n", SSL_state_string_long(ssl), ssl);
@ -934,7 +943,7 @@ retry:
fd = -1; fd = -1;
break; break;
} }
ssl = ssl_sock_connect_loop(ctx, fd); ssl = ssl_sock_connect_loop(ctx, fd, &impl_opts);
if (!ssl) { if (!ssl) {
SPDK_ERRLOG("ssl_sock_connect_loop() failed, errno = %d\n", errno); SPDK_ERRLOG("ssl_sock_connect_loop() failed, errno = %d\n", errno);
close(fd); close(fd);
@ -1037,7 +1046,7 @@ posix_sock_accept(struct spdk_sock *_sock)
/* Establish SSL connection */ /* Establish SSL connection */
if (sock->ctx) { if (sock->ctx) {
ssl = ssl_sock_accept_loop(sock->ctx, fd); ssl = ssl_sock_accept_loop(sock->ctx, fd, &sock->base.impl_opts);
if (!ssl) { if (!ssl) {
SPDK_ERRLOG("ssl_sock_accept_loop() failed, errno = %d\n", errno); SPDK_ERRLOG("ssl_sock_accept_loop() failed, errno = %d\n", errno);
close(fd); close(fd);

View File

@ -97,7 +97,9 @@ static struct spdk_sock_impl_opts g_spdk_uring_sock_impl_opts = {
.enable_zerocopy_send_client = false, .enable_zerocopy_send_client = false,
.zerocopy_threshold = 0, .zerocopy_threshold = 0,
.tls_version = 0, .tls_version = 0,
.enable_ktls = false .enable_ktls = false,
.psk_key = NULL,
.psk_identity = NULL
}; };
static struct spdk_sock_map g_map = { static struct spdk_sock_map g_map = {
@ -138,6 +140,8 @@ uring_sock_copy_impl_opts(struct spdk_sock_impl_opts *dest, const struct spdk_so
SET_FIELD(zerocopy_threshold); SET_FIELD(zerocopy_threshold);
SET_FIELD(tls_version); SET_FIELD(tls_version);
SET_FIELD(enable_ktls); SET_FIELD(enable_ktls);
SET_FIELD(psk_key);
SET_FIELD(psk_identity);
#undef SET_FIELD #undef SET_FIELD
#undef FIELD_OK #undef FIELD_OK

View File

@ -22,7 +22,9 @@ def sock_impl_set_options(client,
enable_zerocopy_send_client=None, enable_zerocopy_send_client=None,
zerocopy_threshold=None, zerocopy_threshold=None,
tls_version=None, tls_version=None,
enable_ktls=None): enable_ktls=None,
psk_key=None,
psk_identity=None):
"""Set parameters for the socket layer implementation. """Set parameters for the socket layer implementation.
Args: Args:
@ -37,6 +39,8 @@ def sock_impl_set_options(client,
zerocopy_threshold: set zerocopy_threshold in bytes(optional) zerocopy_threshold: set zerocopy_threshold in bytes(optional)
tls_version: set TLS protocol version (optional) tls_version: set TLS protocol version (optional)
enable_ktls: enable or disable Kernel TLS (optional) enable_ktls: enable or disable Kernel TLS (optional)
psk_key: set psk_key (optional)
psk_identity: set psk_identity (optional)
""" """
params = {} params = {}
@ -61,6 +65,10 @@ def sock_impl_set_options(client,
params['tls_version'] = tls_version params['tls_version'] = tls_version
if enable_ktls is not None: if enable_ktls is not None:
params['enable_ktls'] = enable_ktls params['enable_ktls'] = enable_ktls
if psk_key is not None:
params['psk_key'] = psk_key
if psk_identity is not None:
params['psk_identity'] = psk_identity
return client.call('sock_impl_set_options', params) return client.call('sock_impl_set_options', params)

View File

@ -2846,7 +2846,9 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
enable_zerocopy_send_client=args.enable_zerocopy_send_client, enable_zerocopy_send_client=args.enable_zerocopy_send_client,
zerocopy_threshold=args.zerocopy_threshold, zerocopy_threshold=args.zerocopy_threshold,
tls_version=args.tls_version, tls_version=args.tls_version,
enable_ktls=args.enable_ktls) enable_ktls=args.enable_ktls,
psk_key=args.psk_key,
psk_identity=args.psk_identity)
p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""")
p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True)
@ -2875,9 +2877,11 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
action='store_true', dest='enable_ktls') action='store_true', dest='enable_ktls')
p.add_argument('--disable-ktls', help='Disable Kernel TLS', p.add_argument('--disable-ktls', help='Disable Kernel TLS',
action='store_false', dest='enable_ktls') action='store_false', dest='enable_ktls')
p.add_argument('--psk-key', help='Set default PSK KEY', dest='psk_key')
p.add_argument('--psk-identity', help='Set default PSK ID', dest='psk_identity')
p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_quickack=None, p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_quickack=None,
enable_placement_id=None, enable_zerocopy_send_server=None, enable_zerocopy_send_client=None, enable_placement_id=None, enable_zerocopy_send_server=None, enable_zerocopy_send_client=None,
zerocopy_threshold=None, tls_version=None, enable_ktls=None) zerocopy_threshold=None, tls_version=None, enable_ktls=None, psk_key=None, psk_identity=None)
def sock_set_default_impl(args): def sock_set_default_impl(args):
print_json(rpc.sock.sock_set_default_impl(args.client, print_json(rpc.sock.sock_set_default_impl(args.client,

View File

@ -67,7 +67,7 @@ iscsitestinit
HELLO_SOCK_APP="${TARGET_NS_CMD[*]} $SPDK_EXAMPLE_DIR/hello_sock" HELLO_SOCK_APP="${TARGET_NS_CMD[*]} $SPDK_EXAMPLE_DIR/hello_sock"
SOCAT_APP="socat" SOCAT_APP="socat"
OPENSSL_APP="openssl" OPENSSL_APP="openssl"
PSK_ID="nqn.2014-08.org.nvmexpress:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6" PSK="-N ssl -E 1234567890ABCDEF -I psk.spdk.io"
# ---------------- # ----------------
# Test client path # Test client path
@ -119,39 +119,39 @@ timing_enter sock_ssl_server
echo "Testing SSL server path" echo "Testing SSL server path"
# start echo server using hello_sock echo server # start echo server using hello_sock echo server
$HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -S -N "ssl" & $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -S $PSK &
server_pid=$! server_pid=$!
trap 'killprocess $server_pid; iscsitestfini; exit 1' SIGINT SIGTERM EXIT trap 'killprocess $server_pid; iscsitestfini; exit 1' SIGINT SIGTERM EXIT
waitforlisten $server_pid waitforlisten $server_pid
# send message using hello_sock client # send message using hello_sock client
message="**MESSAGE:This is a test message from the hello_sock client with ssl**" message="**MESSAGE:This is a test message from the hello_sock client with ssl**"
response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl") response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
# send message using hello_sock client using TLS 1.3 # send message using hello_sock client using TLS 1.3
message="**MESSAGE:This is a test message from the hello_sock client with ssl using TLS 1.3**" message="**MESSAGE:This is a test message from the hello_sock client with ssl using TLS 1.3**"
response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl" -T 13) response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -T 13)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
# send message using hello_sock client using TLS 1.2 # send message using hello_sock client using TLS 1.2
message="**MESSAGE:This is a test message from the hello_sock client with ssl using TLS 1.2**" message="**MESSAGE:This is a test message from the hello_sock client with ssl using TLS 1.2**"
response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl" -T 12) response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -T 12)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
# send message using hello_sock client using incorrect TLS 7 # send message using hello_sock client using incorrect TLS 7
message="**MESSAGE:This is a test message from the hello_sock client with ssl using incorrect TLS 7**" message="**MESSAGE:This is a test message from the hello_sock client with ssl using incorrect TLS 7**"
echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl" -T 7 && exit 1 echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -T 7 && exit 1
# send message using hello_sock client with KTLS disabled # send message using hello_sock client with KTLS disabled
message="**MESSAGE:This is a test message from the hello_sock client with KTLS disabled**" message="**MESSAGE:This is a test message from the hello_sock client with KTLS disabled**"
response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl" -k) response=$(echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -k)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
@ -159,14 +159,14 @@ fi
# send message using hello_sock client with KTLS enabled # send message using hello_sock client with KTLS enabled
message="**MESSAGE:This is a test message from the hello_sock client with KTLS enabled**" message="**MESSAGE:This is a test message from the hello_sock client with KTLS enabled**"
# UT infrastructure so far doesn't support new openssl-3 with this option, so expect a failure # UT infrastructure so far doesn't support new openssl-3 with this option, so expect a failure
echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT -N "ssl" -K && exit 1 echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -K && exit 1
# send message using openssl client using TLS 1.3 # send message using openssl client using TLS 1.3
message="**MESSAGE:This is a test message from the openssl client using TLS 1.3**" message="**MESSAGE:This is a test message from the openssl client using TLS 1.3**"
response=$( ( response=$( (
echo -ne $message echo -ne $message
sleep 2 sleep 2
) | $OPENSSL_APP s_client -debug -state -tlsextdebug -tls1_3 -psk_identity $PSK_ID -psk "1234567890ABCDEF" -connect $TARGET_IP:$ISCSI_PORT) ) | $OPENSSL_APP s_client -debug -state -tlsextdebug -tls1_3 -psk_identity psk.spdk.io -psk "1234567890ABCDEF" -connect $TARGET_IP:$ISCSI_PORT)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
@ -176,11 +176,19 @@ message="**MESSAGE:This is a test message from the openssl client using TLS 1.2*
response=$( ( response=$( (
echo -ne $message echo -ne $message
sleep 2 sleep 2
) | $OPENSSL_APP s_client -debug -state -tlsextdebug -tls1_2 -psk_identity $PSK_ID -psk "1234567890ABCDEF" -connect $TARGET_IP:$ISCSI_PORT) ) | $OPENSSL_APP s_client -debug -state -tlsextdebug -tls1_2 -psk_identity psk.spdk.io -psk "1234567890ABCDEF" -connect $TARGET_IP:$ISCSI_PORT)
if ! echo "$response" | grep -q "$message"; then if ! echo "$response" | grep -q "$message"; then
exit 1 exit 1
fi fi
# send message using hello_sock client with unmatching PSK KEY, expect a failure
message="**MESSAGE:This is a test message from the hello_sock client with unmatching psk_key**"
echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -E 4321DEADBEEF1234 && exit 1
# send message using hello_sock client with unmatching PSK IDENTITY, expect a failure
message="**MESSAGE:This is a test message from the hello_sock client with unmatching psk_key**"
echo $message | $HELLO_SOCK_APP -H $TARGET_IP -P $ISCSI_PORT $PSK -I WRONG_PSK_ID && exit 1
trap '-' SIGINT SIGTERM EXIT trap '-' SIGINT SIGTERM EXIT
# NOTE: socat returns code 143 on SIGINT # NOTE: socat returns code 143 on SIGINT
killprocess $server_pid || true killprocess $server_pid || true

View File

@ -72,6 +72,36 @@ if [[ "$ktls" != "false" ]]; then
exit 1 exit 1
fi fi
# Check default PSK key
key=$($rpc_py sock_impl_get_options -i ssl | jq -r .psk_key)
if [[ "$key" != "null" ]]; then
echo "TLS default key should be empty and not $key"
exit 1
fi
# Check default PSK key set
$rpc_py sock_impl_set_options -i ssl --psk-key 1234567890ABCDEF
key=$($rpc_py sock_impl_get_options -i ssl | jq -r .psk_key)
if [[ "$key" != "1234567890ABCDEF" ]]; then
echo "TLS key was not set correctly $key != 1234567890ABCDEF"
exit 1
fi
# Check default PSK identity
identity=$($rpc_py sock_impl_get_options -i ssl | jq -r .psk_identity)
if [[ "$identity" != "null" ]]; then
echo "TLS default identity should be empty and not $identity"
exit 1
fi
# Check default PSK identity set
$rpc_py sock_impl_set_options -i ssl --psk-identity psk.spdk.io
identity=$($rpc_py sock_impl_get_options -i ssl | jq -r .psk_identity)
if [[ "$identity" != "psk.spdk.io" ]]; then
echo "PSK ID was not set correctly $identity != psk.spdk.io"
exit 1
fi
$rpc_py sock_impl_set_options -i ssl --tls-version 13 $rpc_py sock_impl_set_options -i ssl --tls-version 13
$rpc_py framework_start_init $rpc_py framework_start_init
$rpc_py nvmf_create_transport $NVMF_TRANSPORT_OPTS $rpc_py nvmf_create_transport $NVMF_TRANSPORT_OPTS
@ -84,7 +114,7 @@ $rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 malloc0 -n 1
# Send IO # Send IO
"${NVMF_TARGET_NS_CMD[@]}" $SPDK_EXAMPLE_DIR/perf -S ssl -q 64 -o 4096 -w randrw -M 30 -t 10 \ "${NVMF_TARGET_NS_CMD[@]}" $SPDK_EXAMPLE_DIR/perf -S ssl -q 64 -o 4096 -w randrw -M 30 -t 10 \
-r "trtype:${TEST_TRANSPORT} adrfam:IPv4 traddr:${NVMF_FIRST_TARGET_IP} trsvcid:${NVMF_PORT} \ -r "trtype:${TEST_TRANSPORT} adrfam:IPv4 traddr:${NVMF_FIRST_TARGET_IP} trsvcid:${NVMF_PORT} \
subnqn:nqn.2016-06.io.spdk:cnode1" subnqn:nqn.2016-06.io.spdk:cnode1" --psk-key 1234567890ABCDEF --psk-identity psk.spdk.io
trap - SIGINT SIGTERM EXIT trap - SIGINT SIGTERM EXIT
nvmftestfini nvmftestfini