Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2025 Canonical Ltd * * Test for TKey uclass and emulator */ #include <dm.h> #include <dm/test.h> #include <test/test.h> #include <test/ut.h> #include <tkey.h> /* Test that we can find a TKey device */ static int dm_test_tkey_find(struct unit_test_state *uts) { struct udevice *dev; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); ut_assertnonnull(dev); ut_asserteq_str("tkey-emul", dev->name); return 0; } DM_TEST(dm_test_tkey_find, UTF_SCAN_FDT); /* Test getting UDI from TKey */ static int dm_test_tkey_get_udi(struct unit_test_state *uts) { u8 udi[TKEY_UDI_SIZE]; struct udevice *dev; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); ut_assertok(tkey_get_udi(dev, udi)); /* Verify emulator returns expected UDI */ ut_asserteq(0xa0, udi[0]); ut_asserteq(0xa1, udi[1]); ut_asserteq(0xa2, udi[2]); ut_asserteq(0xa3, udi[3]); ut_asserteq(0xa4, udi[4]); ut_asserteq(0xa5, udi[5]); ut_asserteq(0xa6, udi[6]); ut_asserteq(0xa7, udi[7]); return 0; } DM_TEST(dm_test_tkey_get_udi, UTF_SCAN_FDT); /* Test getting name and version from TKey */ static int dm_test_tkey_get_name_version(struct unit_test_state *uts) { char name0[TKEY_NAME_SIZE], name1[TKEY_NAME_SIZE]; struct udevice *dev; u32 version; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Get name and version */ ut_assertok(tkey_get_name_version(dev, name0, name1, &version)); /* Verify emulator returns expected values */ ut_asserteq_str("tk1 ", name0); ut_asserteq_str("mkdf", name1); ut_asserteq(4, version); return 0; } DM_TEST(dm_test_tkey_get_name_version, UTF_SCAN_FDT); /* Test checking firmware mode */ static int dm_test_tkey_in_app_mode(struct unit_test_state *uts) { struct udevice *dev; int ret; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Check mode - should be in firmware mode initially */ ret = tkey_in_app_mode(dev); ut_assert(ret >= 0); ut_asserteq(0, ret); /* 0 = firmware mode */ return 0; } DM_TEST(dm_test_tkey_in_app_mode, UTF_SCAN_FDT); /* Test loading an app */ static int dm_test_tkey_load_app(struct unit_test_state *uts) { struct udevice *dev; u8 dummy_app[128]; int ret; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Create a dummy app */ memset(dummy_app, 0x42, sizeof(dummy_app)); /* Load the app */ ret = tkey_load_app(dev, dummy_app, sizeof(dummy_app)); ut_assertok(ret); /* After loading, should be in app mode */ ret = tkey_in_app_mode(dev); ut_assert(ret >= 0); ut_asserteq(1, ret); /* 1 = app mode */ return 0; } DM_TEST(dm_test_tkey_load_app, UTF_SCAN_FDT); /* Test getting public key from signer app */ static int dm_test_tkey_get_pubkey(struct unit_test_state *uts) { u8 pubkey[TKEY_PUBKEY_SIZE]; struct udevice *dev; u8 dummy_app[128]; int i; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Load a dummy app first */ memset(dummy_app, 0x42, sizeof(dummy_app)); ut_assertok(tkey_load_app(dev, dummy_app, sizeof(dummy_app))); /* Get public key */ ut_assertok(tkey_get_pubkey(dev, pubkey)); /* Verify emulator returns expected pattern */ for (i = 0; i < TKEY_PUBKEY_SIZE; i++) ut_asserteq(0x50 + (i & 0xf), pubkey[i]); return 0; } DM_TEST(dm_test_tkey_get_pubkey, UTF_SCAN_FDT); /* Test deriving wrapping key from password */ static int dm_test_tkey_derive_wrapping_key(struct unit_test_state *uts) { u8 wrapping_key[TKEY_WRAPPING_KEY_SIZE]; const char *password = "test_password"; /* Expected BLAKE2b(UDI || password) where UDI = a0a1a2a3a4a5a6a7 */ const u8 expected[TKEY_WRAPPING_KEY_SIZE] = { 0x95, 0x22, 0x9c, 0xd3, 0x76, 0x89, 0x8f, 0x3f, 0xb0, 0x22, 0xa6, 0x27, 0x34, 0x9d, 0xc9, 0x85, 0xbc, 0x46, 0x75, 0xda, 0x58, 0x0d, 0x26, 0x96, 0xbd, 0xd6, 0xf7, 0x1f, 0x48, 0x8e, 0x30, 0x6c, }; struct udevice *dev; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Derive wrapping key from password */ ut_assertok(tkey_derive_wrapping_key(dev, password, wrapping_key)); /* Verify the exact wrapping key value */ ut_asserteq_mem(expected, wrapping_key, TKEY_WRAPPING_KEY_SIZE); return 0; } DM_TEST(dm_test_tkey_derive_wrapping_key, UTF_SCAN_FDT); /* Test deriving disk key with USS */ static int dm_test_tkey_derive_disk_key(struct unit_test_state *uts) { const char *uss = "user_secret"; u8 disk_key[TKEY_DISK_KEY_SIZE]; u8 pubkey[TKEY_PUBKEY_SIZE]; u8 key_hash[TKEY_HASH_SIZE]; /* Expected pubkey from emulator (deterministic pattern) */ const u8 expected_pubkey[TKEY_PUBKEY_SIZE] = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, }; /* Expected disk key: SHA256(pubkey) - from emulator */ const u8 expected_disk_key[TKEY_DISK_KEY_SIZE] = { 0xe9, 0xb0, 0x59, 0x92, 0x68, 0xff, 0x8b, 0x08, 0x3e, 0xf8, 0x0d, 0xbd, 0x04, 0xbe, 0x20, 0x7c, 0xe9, 0xa1, 0x9a, 0x60, 0xa8, 0x88, 0xcc, 0xb3, 0xfe, 0x93, 0x71, 0x0a, 0x0a, 0x70, 0xa3, 0x4e, }; /* Expected key hash: BLAKE2b(disk_key) */ const u8 expected_key_hash[TKEY_HASH_SIZE] = { 0x85, 0x83, 0xa0, 0x8d, 0x6c, 0x53, 0x4e, 0x84, 0xae, 0x81, 0xa8, 0x51, 0x80, 0x71, 0xc1, 0x6a, 0x80, 0x30, 0x89, 0x3d, 0xf0, 0x5f, 0xec, 0xb8, 0x4e, 0x51, 0x44, 0x38, 0x59, 0x1b, 0xa5, 0xed, }; struct udevice *dev; u8 dummy_app[128]; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Create a dummy signer app */ memset(dummy_app, 0x42, sizeof(dummy_app)); /* Derive disk key */ ut_assertok(tkey_derive_disk_key(dev, dummy_app, sizeof(dummy_app), uss, strlen(uss), disk_key, pubkey, key_hash)); ut_asserteq_mem(expected_pubkey, pubkey, TKEY_PUBKEY_SIZE); ut_asserteq_mem(expected_disk_key, disk_key, TKEY_DISK_KEY_SIZE); ut_asserteq_mem(expected_key_hash, key_hash, TKEY_HASH_SIZE); return 0; } DM_TEST(dm_test_tkey_derive_disk_key, UTF_SCAN_FDT); /* Test UDI not available in app mode */ static int dm_test_tkey_udi_app_mode(struct unit_test_state *uts) { u8 udi[TKEY_UDI_SIZE]; struct udevice *dev; u8 dummy_app[128]; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Load an app to enter app mode */ memset(dummy_app, 0x42, sizeof(dummy_app)); ut_assertok(tkey_load_app(dev, dummy_app, sizeof(dummy_app))); /* Verify we're in app mode */ ut_asserteq(1, tkey_in_app_mode(dev)); /* Try to get UDI - emulator returns -EIO for empty response */ ut_asserteq(-EIO, tkey_get_udi(dev, udi)); return 0; } DM_TEST(dm_test_tkey_udi_app_mode, UTF_SCAN_FDT); /* Test loading app with USS */ static int dm_test_tkey_load_app_with_uss(struct unit_test_state *uts) { struct udevice *dev; u8 dummy_app[128]; const char *uss = "my_secret"; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Create a dummy app */ memset(dummy_app, 0x55, sizeof(dummy_app)); /* Load app with USS */ ut_assertok(tkey_load_app_with_uss(dev, dummy_app, sizeof(dummy_app), uss, strlen(uss))); /* Should be in app mode */ ut_asserteq(1, tkey_in_app_mode(dev)); return 0; } DM_TEST(dm_test_tkey_load_app_with_uss, UTF_SCAN_FDT); /* Test basic read/write operations */ static int dm_test_tkey_read_write(struct unit_test_state *uts) { /* Expected USB response: 0x52 0x02 [tk1 ] [mkdf] [version=4] */ static const u8 expected[14] = { 0x52, 0x02, /* USB marker and response type */ 't', 'k', '1', ' ', /* name0 */ 'm', 'k', 'd', 'f', /* name1 */ 0x04, 0x00, 0x00, 0x00, /* version = 4 (little-endian) */ }; struct udevice *dev; u8 write_buf[129]; /* Header + command */ u8 read_buf[256]; ut_assertok(uclass_get_device_by_name(UCLASS_TKEY, "tkey-emul", &dev)); /* Prepare a GET_NAME_VERSION command */ write_buf[0] = 0x10; /* Header: CMD, FIRMWARE endpoint */ write_buf[1] = 0x01; /* CMD_GET_NAME_VERSION */ /* Write the command - should return 2 bytes written */ ut_asserteq(2, tkey_write(dev, write_buf, 2)); /* Read the response - should get exactly 14 bytes */ ut_asserteq(14, tkey_read_all(dev, read_buf, sizeof(read_buf), 1000)); /* Verify full response matches expected */ ut_asserteq_mem(expected, read_buf, 14); return 0; } DM_TEST(dm_test_tkey_read_write, UTF_SCAN_FDT); |