1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2024 Intel Corporation. All rights reserved. 3 */ 4 #include "spdk_internal/cunit.h" 5 #include "spdk_internal/mock.h" 6 #include "spdk/util.h" 7 8 #include "keyring/keyring.c" 9 10 #include "unit/lib/json_mock.c" 11 12 struct ut_key { 13 #define UT_KEY_SIZE 64 14 char buf[UT_KEY_SIZE]; 15 int len; 16 }; 17 18 struct ut_key_opts { 19 char *buf; 20 int len; 21 }; 22 23 static int g_add_status; 24 25 static int 26 ut_keyring_add_key(struct spdk_key *key, void *ctx) 27 { 28 struct ut_key_opts *opts = ctx; 29 struct ut_key *utkey = spdk_key_get_ctx(key); 30 31 if (g_add_status) { 32 return g_add_status; 33 } 34 35 SPDK_CU_ASSERT_FATAL(opts != NULL); 36 37 /* Use spdk_json_val's start/len to pass a buffer with the key */ 38 memcpy(utkey->buf, opts->buf, opts->len); 39 utkey->len = opts->len; 40 41 return 0; 42 } 43 44 static bool g_remove_called; 45 46 static void 47 ut_keyring_remove_key(struct spdk_key *key) 48 { 49 struct ut_key *utkey = spdk_key_get_ctx(key); 50 51 memset(utkey->buf, 0, utkey->len); 52 g_remove_called = true; 53 } 54 55 static int 56 ut_keyring_get_key(struct spdk_key *key, void *buf, int len) 57 { 58 struct ut_key *utkey = spdk_key_get_ctx(key); 59 60 memcpy(buf, utkey->buf, utkey->len); 61 62 return utkey->len; 63 } 64 65 static size_t 66 ut_keyring_get_ctx_size(void) 67 { 68 return sizeof(struct ut_key); 69 } 70 71 static struct spdk_keyring_module g_module = { 72 .name = "ut", 73 .add_key = ut_keyring_add_key, 74 .remove_key = ut_keyring_remove_key, 75 .get_key = ut_keyring_get_key, 76 .get_ctx_size = ut_keyring_get_ctx_size, 77 }; 78 79 SPDK_KEYRING_REGISTER_MODULE(ut, &g_module); 80 81 static void 82 test_keyring_add_remove(void) 83 { 84 struct spdk_key_opts opts = {}; 85 struct spdk_key *key; 86 char keybuf[UT_KEY_SIZE] = {}, rcvbuf[UT_KEY_SIZE] = {}; 87 struct ut_key_opts uopts = { .buf = keybuf, .len = UT_KEY_SIZE }; 88 int rc; 89 90 /* Add a key */ 91 memset(keybuf, 0xa5, UT_KEY_SIZE); 92 opts.size = SPDK_SIZEOF(&opts, ctx); 93 opts.name = "key0"; 94 opts.module = &g_module; 95 opts.ctx = &uopts; 96 rc = spdk_keyring_add_key(&opts); 97 CU_ASSERT_EQUAL(rc, 0); 98 99 /* Get a reference to that key */ 100 key = spdk_keyring_get_key("key0"); 101 CU_ASSERT_PTR_NOT_NULL(key); 102 103 /* Get its keying material */ 104 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 105 CU_ASSERT_EQUAL(rc, UT_KEY_SIZE) 106 CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0); 107 108 /* Remove it and try to get another reference */ 109 spdk_keyring_remove_key("key0"); 110 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 111 112 /* Now that the key has been remove spdk_key_get_key() should result in an -ENOKEY error */ 113 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 114 CU_ASSERT_EQUAL(rc, -ENOKEY); 115 116 /* Finally, release the reference */ 117 spdk_keyring_put_key(key); 118 119 /* Explicitly specify global keyring */ 120 rc = spdk_keyring_add_key(&opts); 121 CU_ASSERT_EQUAL(rc, 0); 122 key = spdk_keyring_get_key(":key0"); 123 CU_ASSERT_PTR_NOT_NULL(key); 124 125 memset(rcvbuf, 0, UT_KEY_SIZE); 126 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 127 CU_ASSERT_EQUAL(rc, UT_KEY_SIZE) 128 CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0); 129 130 spdk_keyring_put_key(key); 131 132 /* Remove the key without explicitly specyfing global keyring */ 133 spdk_keyring_remove_key("key0"); 134 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 135 CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0")); 136 137 /* Try to create a key with the same name twice */ 138 opts.size = SPDK_SIZEOF(&opts, ctx); 139 opts.name = "key0"; 140 opts.module = &g_module; 141 opts.ctx = &uopts; 142 rc = spdk_keyring_add_key(&opts); 143 CU_ASSERT_EQUAL(rc, 0); 144 rc = spdk_keyring_add_key(&opts); 145 CU_ASSERT_EQUAL(rc, -EEXIST); 146 147 /* Explicitly specify global keyring */ 148 opts.name = ":key0"; 149 rc = spdk_keyring_add_key(&opts); 150 CU_ASSERT_EQUAL(rc, -EEXIST); 151 152 spdk_keyring_remove_key(":key0"); 153 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 154 CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0")); 155 CU_ASSERT(g_remove_called); 156 g_remove_called = false; 157 158 /* Remove an already removed key */ 159 spdk_keyring_remove_key("key0"); 160 spdk_keyring_remove_key(":key0"); 161 CU_ASSERT(!g_remove_called); 162 163 /* Check that an error from module's add_key() results in failure */ 164 g_add_status = -EIO; 165 opts.size = SPDK_SIZEOF(&opts, ctx); 166 opts.name = "key0"; 167 opts.module = &g_module; 168 opts.ctx = &uopts; 169 rc = spdk_keyring_add_key(&opts); 170 CU_ASSERT_EQUAL(rc, -EIO); 171 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 172 g_add_status = 0; 173 } 174 175 static void 176 test_keyring_get_put(void) 177 { 178 struct spdk_key_opts opts = {}; 179 struct spdk_key *key, *tmp; 180 char keybuf[UT_KEY_SIZE] = {}; 181 struct ut_key_opts uopts = { .buf = keybuf, .len = UT_KEY_SIZE }; 182 int rc, i; 183 184 opts.size = SPDK_SIZEOF(&opts, ctx); 185 opts.name = "key0"; 186 opts.module = &g_module; 187 opts.ctx = &uopts; 188 rc = spdk_keyring_add_key(&opts); 189 CU_ASSERT_EQUAL(rc, 0); 190 191 /* Get multiple references to the same key */ 192 key = spdk_keyring_get_key("key0"); 193 CU_ASSERT_PTR_NOT_NULL(key); 194 #define UT_KEY_REFS 8 195 for (i = 0; i < UT_KEY_REFS; ++i) { 196 tmp = spdk_keyring_get_key("key0"); 197 CU_ASSERT_PTR_EQUAL(key, tmp); 198 } 199 200 /* Remove the key and verify (relying on the address sanitizer to catch any use-after-free 201 * errors) that the reference is still valid 202 */ 203 spdk_keyring_remove_key("key0"); 204 CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0); 205 206 /* Release all but one reference and verify that it's still valid (again, relying on the 207 * address sanitizer) 208 */ 209 for (i = 0; i < UT_KEY_REFS; ++i) { 210 spdk_keyring_put_key(key); 211 CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0); 212 } 213 214 /* Release the last reference - this should also free the key */ 215 spdk_keyring_put_key(key); 216 } 217 218 int 219 main(int argc, char **argv) 220 { 221 CU_pSuite suite; 222 unsigned int num_failures; 223 224 CU_initialize_registry(); 225 226 suite = CU_add_suite("keyring", NULL, NULL); 227 CU_ADD_TEST(suite, test_keyring_add_remove); 228 CU_ADD_TEST(suite, test_keyring_get_put); 229 230 num_failures = spdk_ut_run_tests(argc, argv, NULL); 231 CU_cleanup_registry(); 232 233 return num_failures; 234 } 235