Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistent TLS keys #783

Closed
wants to merge 10 commits into from
16 changes: 8 additions & 8 deletions doc/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@
"description": "Controller DH-HMAC-CHAP key",
"type": "string"
},
"keyring": {
"description": "Keyring for TLS key lookup",
"type": "string"
},
"tls_key": {
"description": "TLS key for the connection",
"type": "string"
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes should be in config-schema.json.in

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course.

"nr_io_queues": {
"description": "Number of I/O queues",
"type": "integer"
Expand Down Expand Up @@ -156,14 +164,6 @@
"type": "boolean",
"default": false
},
"keyring": {
"description": "Keyring for TLS key lookup",
"type": "integer"
},
"tls_key": {
"description": "TLS key for the connection",
"type": "integer"
},
"tls": {
"description": "Enable TLS encryption",
"type": "boolean",
Expand Down
7 changes: 7 additions & 0 deletions src/libnvme.map
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
LIBNVME_1_9 {
global:
nvme_read_key;
nvme_export_tls_key;
nvme_import_tls_key;
};

LIBNVME_1_8 {
global:
nvme_uuid_find;
Expand Down
3 changes: 2 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ sources = [
'nvme/log.c',
'nvme/tree.c',
'nvme/util.c',
'nvme/base64.c'
'nvme/base64.c',
'nvme/crc32.c'
]

mi_sources = [
Expand Down
100 changes: 100 additions & 0 deletions src/nvme/crc32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0-or-later
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library is LGPL 2.1. So this is not compatible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, Rustys code is for crc32c (not crc32), and the crc source code from ccan also has GPLv2. So ccan doesn't help. The second implementation should be fine, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But ever so slightly complicated to use. Switching to the freebsd implementation, which actually has a copy with a permissible license.


/*
* Copyright (C) 2002 Red Hat, Inc.
* This file is part of elfutils.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* * the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version
*
* or
*
* * the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version
*
* or both in parallel, as here.
*
* elfutils is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received copies of the GNU General Public License and
* the GNU Lesser General Public License along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*/

/* https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/crc32.c;hb=575198c29a427392823cc8f2400579a23d06a875 */

#include "crc32.h"

/* Table computed with Mark Adler's makecrc.c utility. */
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
0x2d02ef8d
};

uint32_t crc32(uint32_t crc, unsigned char *buf, size_t len)
{
unsigned char *end;

crc = ~crc;
for (end = buf + len; buf < end; ++buf)
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
return ~crc;
}
11 changes: 11 additions & 0 deletions src/nvme/crc32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again this license doesn't work for the library.


#ifndef crc32_H
#define crc32_H

#include <stdint.h>
#include <stddef.h>

uint32_t crc32(uint32_t crc, unsigned char *buf, size_t len);

#endif
4 changes: 2 additions & 2 deletions src/nvme/fabrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ struct nvme_fabrics_config {
int nr_write_queues;
int nr_poll_queues;
int tos;
int keyring;
int tls_key;
long keyring;
long tls_key;

bool duplicate_connect;
bool disable_sqflow;
Expand Down
84 changes: 65 additions & 19 deletions src/nvme/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,42 @@
#define JSON_UPDATE_BOOL_OPTION(c, k, a, o) \
if (!strcmp(# a, k ) && !c->a) c->a = json_object_get_boolean(o);

static void json_import_nvme_tls_key(nvme_ctrl_t c, const char *keyring_str,
const char *key_str)
{
struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
const char *hostnqn = nvme_host_get_hostnqn(c->s->h);
const char *subsysnqn = nvme_ctrl_get_subsysnqn(c);
int key_len;
unsigned int hmac;
long key_id;
_cleanup_free_ unsigned char *key_data = NULL;

Check failure on line 37 in src/nvme/json.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: Missing a blank line after declarations

key_data = nvme_import_tls_key(key_str, &key_len, &hmac);
if (!key_data)
return;
if (!hostnqn || !subsysnqn) {
nvme_msg(NULL, LOG_ERR, "Invalid NQNs (%s, %s)\n",
hostnqn, subsysnqn);
return;
}
key_id = nvme_insert_tls_key_versioned(keyring_str, "psk",
hostnqn, subsysnqn,
0, hmac, key_data, key_len);
if (key_id <= 0)
nvme_msg(NULL, LOG_ERR, "Failed to insert TLS KEY, error %d\n",
errno);
else {
cfg->tls_key = key_id;
cfg->tls = true;
}
}

static void json_update_attributes(nvme_ctrl_t c,
struct json_object *ctrl_obj)
{
struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
const char *keyring_str = NULL, *key_data = NULL;

json_object_object_foreach(ctrl_obj, key_str, val_obj) {
JSON_UPDATE_INT_OPTION(cfg, key_str,
Expand Down Expand Up @@ -75,21 +107,24 @@
if (!strcmp("keyring", key_str) && cfg->keyring == 0) {
long keyring;

keyring = nvme_lookup_keyring(json_object_get_string(val_obj));
keyring_str = json_object_get_string(val_obj);
keyring = nvme_lookup_keyring(keyring_str);
if (keyring) {
cfg->keyring = keyring;
nvme_set_keyring(cfg->keyring);
}
}
if (!strcmp("tls_key", key_str) && cfg->tls_key == 0) {
long key;

key = nvme_lookup_key("psk",
json_object_get_string(val_obj));
if (key)
cfg->tls_key = key;
}
if (!strcmp("tls_key", key_str) && cfg->tls_key == 0)
key_data = json_object_get_string(val_obj);
}

/*
* We might need the keyring information from the above loop,
* so we can only import the TLS key once all entries are
* processed.
*/
if (key_data)
json_import_nvme_tls_key(c, keyring_str, key_data);
}

static void json_parse_port(nvme_subsystem_t s, struct json_object *port_obj)
Expand Down Expand Up @@ -282,6 +317,7 @@
struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
struct json_object *port_obj = json_object_new_object();
const char *transport, *value;
_cleanup_free_ char *keyring_str = NULL;

transport = nvme_ctrl_get_transport(c);
json_object_object_add(port_obj, "transport",
Expand Down Expand Up @@ -338,21 +374,29 @@
* Store the keyring description in the JSON config file.
*/
if (cfg->keyring) {
_cleanup_free_ char *desc =
nvme_describe_key_serial(cfg->keyring);
keyring_str = nvme_describe_key_serial(cfg->keyring);

if (desc) {
if (keyring_str) {
json_object_object_add(port_obj, "keyring",
json_object_new_string(desc));
json_object_new_string(keyring_str));
}
}
/*
* Store the TLS key in PSK interchange format
*/
if (cfg->tls_key) {
_cleanup_free_ char *desc =
nvme_describe_key_serial(cfg->tls_key);

if (desc) {
json_object_object_add(port_obj, "tls_key",
json_object_new_string(desc));
int key_len;
_cleanup_free_ unsigned char *key_data =
nvme_read_key(keyring_str,
cfg->tls_key, &key_len);

if (key_data) {
_cleanup_free_ char *tls_str =
nvme_export_tls_key(key_data, key_len);

if (tls_str)
json_object_object_add(port_obj, "tls_key",
json_object_new_string(tls_str));
}
}

Expand Down Expand Up @@ -487,6 +531,8 @@
if (value)
json_object_object_add(ctrl_obj, "dhchap_ctrl_key",
json_object_new_string(value));
if (strcmp(transport, "tcp"))
JSON_INT_OPTION(cfg, ctrl_obj, tls_key, 0);
JSON_INT_OPTION(cfg, ctrl_obj, nr_io_queues, 0);
JSON_INT_OPTION(cfg, ctrl_obj, nr_write_queues, 0);
JSON_INT_OPTION(cfg, ctrl_obj, nr_poll_queues, 0);
Expand Down
Loading
Loading