ENTRY("gen-hostnqn", "Generate NVMeoF host NQN", gen_hostnqn_cmd)
ENTRY("show-hostnqn", "Show NVMeoF host NQN", show_hostnqn_cmd)
ENTRY("gen-dhchap-key", "Generate NVMeoF DH-HMAC-CHAP host key", gen_dhchap_key)
+ ENTRY("check-dhchap-key", "Validate NVMeoF DH-HMAC-CHAP host key", check_dhchap_key)
ENTRY("dir-receive", "Submit a Directive Receive command, return results", dir_receive)
ENTRY("dir-send", "Submit a Directive Send command, return results", dir_send)
ENTRY("virt-mgmt", "Manage Flexible Resources between Primary and Secondary Controller ", virtual_mgmt)
return 0;
}
+static int check_dhchap_key(int argc, char **argv, struct command *command, struct plugin *plugin)
+{
+ const char *desc = "Check a DH-HMAC-CHAP host key for usability "\
+ "for NVMe In-Band Authentication.";
+ const char *key = "DH-HMAC-CHAP key (in hexadecimal characters) "\
+ "to be validated.";
+
+ unsigned char decoded_key[128];
+ unsigned int decoded_len;
+ u_int32_t crc = crc32(0L, NULL, 0);
+ u_int32_t key_crc;
+ int err = 0, hmac;
+ struct config {
+ char *key;
+ };
+
+ struct config cfg = {
+ .key = NULL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STR("key", 'k', &cfg.key, key),
+ OPT_END()
+ };
+
+ err = argconfig_parse(argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (!cfg.key) {
+ fprintf(stderr, "Key not specified\n");
+ return -EINVAL;
+ }
+
+ if (sscanf(cfg.key, "DHHC-1:%02x:*s", &hmac) != 1) {
+ fprintf(stderr, "Invalid key header '%s'\n", cfg.key);
+ return -EINVAL;
+ }
+ switch (hmac) {
+ case 0:
+ break;
+ case 1:
+ if (strlen(cfg.key) != 59) {
+ fprintf(stderr, "Invalid key length for SHA(256)\n");
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ if (strlen(cfg.key) != 83) {
+ fprintf(stderr, "Invalid key length for SHA(384)\n");
+ return -EINVAL;
+ }
+ break;
+ case 3:
+ if (strlen(cfg.key) != 103) {
+ fprintf(stderr, "Invalid key length for SHA(512)\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid HMAC identifier %d\n", hmac);
+ return -EINVAL;
+ break;
+ }
+
+ err = base64_decode(cfg.key + 10, strlen(cfg.key) - 11,
+ decoded_key);
+ if (err < 0) {
+ fprintf(stderr, "Base64 decoding failed, error %d\n",
+ err);
+ return err;
+ }
+ decoded_len = err;
+ if (decoded_len < 32) {
+ fprintf(stderr, "Base64 decoding failed (%s, size %u)\n",
+ cfg.key + 10, decoded_len);
+ return -EINVAL;
+ }
+ decoded_len -= 4;
+ if (decoded_len != 32 && decoded_len != 48 && decoded_len != 64) {
+ fprintf(stderr, "Invalid key length %d\n", decoded_len);
+ return -EINVAL;
+ }
+ crc = crc32(crc, decoded_key, decoded_len);
+ key_crc = ((u_int32_t)decoded_key[decoded_len]) |
+ ((u_int32_t)decoded_key[decoded_len + 1] << 8) |
+ ((u_int32_t)decoded_key[decoded_len + 2] << 16) |
+ ((u_int32_t)decoded_key[decoded_len + 3] << 24);
+ if (key_crc != crc) {
+ fprintf(stderr, "CRC mismatch (key %08x, crc %08x)\n",
+ key_crc, crc);
+ return -EINVAL;
+ }
+ printf("Key is valid (HMAC %d, length %d, CRC %08x)\n",
+ hmac, decoded_len, crc);
+ return 0;
+}
+
static int discover_cmd(int argc, char **argv, struct command *command, struct plugin *plugin)
{
const char *desc = "Send Get Log Page request to Discovery Controller.";
*/
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
static const char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return cp - dst;
}
+
+/**
+ * base64_decode() - base64-decode some bytes
+ * @src: the base64-encoded string to decode
+ * @len: number of bytes to decode
+ * @dst: (output) the decoded bytes.
+ *
+ * Decodes the base64-encoded bytes @src according to RFC 4648.
+ *
+ * Return: number of decoded bytes
+ */
+int base64_decode(const char *src, int srclen, unsigned char *dst)
+{
+ u_int32_t ac = 0;
+ int i, bits = 0;
+ unsigned char *bp = dst;
+
+ for (i = 0; i < srclen; i++) {
+ const char *p = strchr(base64_table, src[i]);
+
+ if (src[i] == '=') {
+ ac = (ac << 6);
+ bits += 6;
+ if (bits >= 8)
+ bits -= 8;
+ continue;
+ }
+ if (p == NULL || src[i] == 0)
+ return -EINVAL;
+ ac = (ac << 6) | (p - base64_table);
+ bits += 6;
+ if (bits >= 8) {
+ bits -= 8;
+ *bp++ = (unsigned char)(ac >> bits);
+ }
+ }
+ if (ac && ((1 << bits) - 1))
+ return -EAGAIN;
+
+ return bp - dst;
+}