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 struct spdk_keyring_module module2 = { .name = "ut2" }; 89 int rc; 90 91 /* Add a key */ 92 memset(keybuf, 0xa5, UT_KEY_SIZE); 93 opts.size = SPDK_SIZEOF(&opts, ctx); 94 opts.name = "key0"; 95 opts.module = &g_module; 96 opts.ctx = &uopts; 97 rc = spdk_keyring_add_key(&opts); 98 CU_ASSERT_EQUAL(rc, 0); 99 100 /* Get a reference to that key */ 101 key = spdk_keyring_get_key("key0"); 102 CU_ASSERT_PTR_NOT_NULL(key); 103 104 /* Get its keying material */ 105 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 106 CU_ASSERT_EQUAL(rc, UT_KEY_SIZE) 107 CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0); 108 109 /* Remove it and try to get another reference */ 110 spdk_keyring_remove_key("key0", &g_module); 111 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 112 113 /* Now that the key has been remove spdk_key_get_key() should result in an -ENOKEY error */ 114 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 115 CU_ASSERT_EQUAL(rc, -ENOKEY); 116 117 /* Finally, release the reference */ 118 spdk_keyring_put_key(key); 119 120 /* Explicitly specify global keyring */ 121 rc = spdk_keyring_add_key(&opts); 122 CU_ASSERT_EQUAL(rc, 0); 123 key = spdk_keyring_get_key(":key0"); 124 CU_ASSERT_PTR_NOT_NULL(key); 125 126 memset(rcvbuf, 0, UT_KEY_SIZE); 127 rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE); 128 CU_ASSERT_EQUAL(rc, UT_KEY_SIZE) 129 CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0); 130 131 spdk_keyring_put_key(key); 132 133 /* Remove the key without explicitly specifying global keyring */ 134 spdk_keyring_remove_key("key0", &g_module); 135 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 136 CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0")); 137 138 /* Try to create a key with the same name twice */ 139 opts.size = SPDK_SIZEOF(&opts, ctx); 140 opts.name = "key0"; 141 opts.module = &g_module; 142 opts.ctx = &uopts; 143 rc = spdk_keyring_add_key(&opts); 144 CU_ASSERT_EQUAL(rc, 0); 145 rc = spdk_keyring_add_key(&opts); 146 CU_ASSERT_EQUAL(rc, -EEXIST); 147 148 /* Explicitly specify global keyring */ 149 opts.name = ":key0"; 150 rc = spdk_keyring_add_key(&opts); 151 CU_ASSERT_EQUAL(rc, -EEXIST); 152 153 /* Try to remove a key owned by a different module */ 154 spdk_keyring_remove_key("key0", &module2); 155 CU_ASSERT_PTR_NOT_NULL(spdk_keyring_get_key("key0")); 156 CU_ASSERT_PTR_NOT_NULL(spdk_keyring_get_key(":key0")); 157 158 spdk_keyring_remove_key(":key0", &g_module); 159 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 160 CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0")); 161 CU_ASSERT(g_remove_called); 162 g_remove_called = false; 163 164 /* Remove an already removed key */ 165 spdk_keyring_remove_key("key0", &g_module); 166 spdk_keyring_remove_key(":key0", &g_module); 167 CU_ASSERT(!g_remove_called); 168 169 /* Check that an error from module's add_key() results in failure */ 170 g_add_status = -EIO; 171 opts.size = SPDK_SIZEOF(&opts, ctx); 172 opts.name = "key0"; 173 opts.module = &g_module; 174 opts.ctx = &uopts; 175 rc = spdk_keyring_add_key(&opts); 176 CU_ASSERT_EQUAL(rc, -EIO); 177 CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0")); 178 g_add_status = 0; 179 } 180 181 static void 182 test_keyring_get_put(void) 183 { 184 struct spdk_key_opts opts = {}; 185 struct spdk_key *key, *tmp; 186 char keybuf[UT_KEY_SIZE] = {}; 187 struct ut_key_opts uopts = { .buf = keybuf, .len = UT_KEY_SIZE }; 188 int rc, i; 189 190 opts.size = SPDK_SIZEOF(&opts, ctx); 191 opts.name = "key0"; 192 opts.module = &g_module; 193 opts.ctx = &uopts; 194 rc = spdk_keyring_add_key(&opts); 195 CU_ASSERT_EQUAL(rc, 0); 196 197 /* Get multiple references to the same key */ 198 key = spdk_keyring_get_key("key0"); 199 CU_ASSERT_PTR_NOT_NULL(key); 200 #define UT_KEY_REFS 8 201 for (i = 0; i < UT_KEY_REFS; ++i) { 202 tmp = spdk_keyring_get_key("key0"); 203 CU_ASSERT_PTR_EQUAL(key, tmp); 204 } 205 206 /* Remove the key and verify (relying on the address sanitizer to catch any use-after-free 207 * errors) that the reference is still valid 208 */ 209 spdk_keyring_remove_key("key0", &g_module); 210 CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0); 211 212 /* Release all but one reference and verify that it's still valid (again, relying on the 213 * address sanitizer) 214 */ 215 for (i = 0; i < UT_KEY_REFS; ++i) { 216 spdk_keyring_put_key(key); 217 CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0); 218 } 219 220 /* Release the last reference - this should also free the key */ 221 spdk_keyring_put_key(key); 222 } 223 224 int 225 main(int argc, char **argv) 226 { 227 CU_pSuite suite; 228 unsigned int num_failures; 229 230 CU_initialize_registry(); 231 232 suite = CU_add_suite("keyring", NULL, NULL); 233 CU_ADD_TEST(suite, test_keyring_add_remove); 234 CU_ADD_TEST(suite, test_keyring_get_put); 235 236 num_failures = spdk_ut_run_tests(argc, argv, NULL); 237 CU_cleanup_registry(); 238 239 return num_failures; 240 } 241