1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019-2021 Linaro Ltd. 4 * 5 * Author: 6 * Sumit Garg <sumit.garg@linaro.org> 7 */ 8 9 #include <linux/err.h> 10 #include <linux/key-type.h> 11 #include <linux/module.h> 12 #include <linux/slab.h> 13 #include <linux/string.h> 14 #include <linux/tee_drv.h> 15 #include <linux/uuid.h> 16 17 #include <keys/trusted_tee.h> 18 19 #define DRIVER_NAME "trusted-key-tee" 20 21 /* 22 * Get random data for symmetric key 23 * 24 * [out] memref[0] Random data 25 */ 26 #define TA_CMD_GET_RANDOM 0x0 27 28 /* 29 * Seal trusted key using hardware unique key 30 * 31 * [in] memref[0] Plain key 32 * [out] memref[1] Sealed key datablob 33 */ 34 #define TA_CMD_SEAL 0x1 35 36 /* 37 * Unseal trusted key using hardware unique key 38 * 39 * [in] memref[0] Sealed key datablob 40 * [out] memref[1] Plain key 41 */ 42 #define TA_CMD_UNSEAL 0x2 43 44 /** 45 * struct trusted_key_tee_private - TEE Trusted key private data 46 * @dev: TEE based Trusted key device. 47 * @ctx: TEE context handler. 48 * @session_id: Trusted key TA session identifier. 49 * @shm_pool: Memory pool shared with TEE device. 50 */ 51 struct trusted_key_tee_private { 52 struct device *dev; 53 struct tee_context *ctx; 54 u32 session_id; 55 struct tee_shm *shm_pool; 56 }; 57 58 static struct trusted_key_tee_private pvt_data; 59 60 /* 61 * Have the TEE seal(encrypt) the symmetric key 62 */ 63 static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob) 64 { 65 int ret; 66 struct tee_ioctl_invoke_arg inv_arg; 67 struct tee_param param[4]; 68 struct tee_shm *reg_shm = NULL; 69 70 memset(&inv_arg, 0, sizeof(inv_arg)); 71 memset(¶m, 0, sizeof(param)); 72 73 reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, p->key, 74 sizeof(p->key) + sizeof(p->blob)); 75 if (IS_ERR(reg_shm)) { 76 dev_err(pvt_data.dev, "shm register failed\n"); 77 return PTR_ERR(reg_shm); 78 } 79 80 inv_arg.func = TA_CMD_SEAL; 81 inv_arg.session = pvt_data.session_id; 82 inv_arg.num_params = 4; 83 84 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; 85 param[0].u.memref.shm = reg_shm; 86 param[0].u.memref.size = p->key_len; 87 param[0].u.memref.shm_offs = 0; 88 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 89 param[1].u.memref.shm = reg_shm; 90 param[1].u.memref.size = sizeof(p->blob); 91 param[1].u.memref.shm_offs = sizeof(p->key); 92 93 ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param); 94 if ((ret < 0) || (inv_arg.ret != 0)) { 95 dev_err(pvt_data.dev, "TA_CMD_SEAL invoke err: %x\n", 96 inv_arg.ret); 97 ret = -EFAULT; 98 } else { 99 p->blob_len = param[1].u.memref.size; 100 } 101 102 tee_shm_free(reg_shm); 103 104 return ret; 105 } 106 107 /* 108 * Have the TEE unseal(decrypt) the symmetric key 109 */ 110 static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob) 111 { 112 int ret; 113 struct tee_ioctl_invoke_arg inv_arg; 114 struct tee_param param[4]; 115 struct tee_shm *reg_shm = NULL; 116 117 memset(&inv_arg, 0, sizeof(inv_arg)); 118 memset(¶m, 0, sizeof(param)); 119 120 reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, p->key, 121 sizeof(p->key) + sizeof(p->blob)); 122 if (IS_ERR(reg_shm)) { 123 dev_err(pvt_data.dev, "shm register failed\n"); 124 return PTR_ERR(reg_shm); 125 } 126 127 inv_arg.func = TA_CMD_UNSEAL; 128 inv_arg.session = pvt_data.session_id; 129 inv_arg.num_params = 4; 130 131 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; 132 param[0].u.memref.shm = reg_shm; 133 param[0].u.memref.size = p->blob_len; 134 param[0].u.memref.shm_offs = sizeof(p->key); 135 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 136 param[1].u.memref.shm = reg_shm; 137 param[1].u.memref.size = sizeof(p->key); 138 param[1].u.memref.shm_offs = 0; 139 140 ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param); 141 if ((ret < 0) || (inv_arg.ret != 0)) { 142 dev_err(pvt_data.dev, "TA_CMD_UNSEAL invoke err: %x\n", 143 inv_arg.ret); 144 ret = -EFAULT; 145 } else { 146 p->key_len = param[1].u.memref.size; 147 } 148 149 tee_shm_free(reg_shm); 150 151 return ret; 152 } 153 154 /* 155 * Have the TEE generate random symmetric key 156 */ 157 static int trusted_tee_get_random(unsigned char *key, size_t key_len) 158 { 159 int ret; 160 struct tee_ioctl_invoke_arg inv_arg; 161 struct tee_param param[4]; 162 struct tee_shm *reg_shm = NULL; 163 164 memset(&inv_arg, 0, sizeof(inv_arg)); 165 memset(¶m, 0, sizeof(param)); 166 167 reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len); 168 if (IS_ERR(reg_shm)) { 169 dev_err(pvt_data.dev, "key shm register failed\n"); 170 return PTR_ERR(reg_shm); 171 } 172 173 inv_arg.func = TA_CMD_GET_RANDOM; 174 inv_arg.session = pvt_data.session_id; 175 inv_arg.num_params = 4; 176 177 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 178 param[0].u.memref.shm = reg_shm; 179 param[0].u.memref.size = key_len; 180 param[0].u.memref.shm_offs = 0; 181 182 ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param); 183 if ((ret < 0) || (inv_arg.ret != 0)) { 184 dev_err(pvt_data.dev, "TA_CMD_GET_RANDOM invoke err: %x\n", 185 inv_arg.ret); 186 ret = -EFAULT; 187 } else { 188 ret = param[0].u.memref.size; 189 } 190 191 tee_shm_free(reg_shm); 192 193 return ret; 194 } 195 196 static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) 197 { 198 if (ver->impl_id == TEE_IMPL_ID_OPTEE && 199 ver->gen_caps & TEE_GEN_CAP_REG_MEM) 200 return 1; 201 else 202 return 0; 203 } 204 205 static int trusted_key_probe(struct device *dev) 206 { 207 struct tee_client_device *rng_device = to_tee_client_device(dev); 208 int ret; 209 struct tee_ioctl_open_session_arg sess_arg; 210 211 memset(&sess_arg, 0, sizeof(sess_arg)); 212 213 pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, 214 NULL); 215 if (IS_ERR(pvt_data.ctx)) 216 return -ENODEV; 217 218 memcpy(sess_arg.uuid, rng_device->id.uuid.b, TEE_IOCTL_UUID_LEN); 219 sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; 220 sess_arg.num_params = 0; 221 222 ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL); 223 if ((ret < 0) || (sess_arg.ret != 0)) { 224 dev_err(dev, "tee_client_open_session failed, err: %x\n", 225 sess_arg.ret); 226 ret = -EINVAL; 227 goto out_ctx; 228 } 229 pvt_data.session_id = sess_arg.session; 230 231 ret = register_key_type(&key_type_trusted); 232 if (ret < 0) 233 goto out_sess; 234 235 pvt_data.dev = dev; 236 237 return 0; 238 239 out_sess: 240 tee_client_close_session(pvt_data.ctx, pvt_data.session_id); 241 out_ctx: 242 tee_client_close_context(pvt_data.ctx); 243 244 return ret; 245 } 246 247 static int trusted_key_remove(struct device *dev) 248 { 249 unregister_key_type(&key_type_trusted); 250 tee_client_close_session(pvt_data.ctx, pvt_data.session_id); 251 tee_client_close_context(pvt_data.ctx); 252 253 return 0; 254 } 255 256 static const struct tee_client_device_id trusted_key_id_table[] = { 257 {UUID_INIT(0xf04a0fe7, 0x1f5d, 0x4b9b, 258 0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c)}, 259 {} 260 }; 261 MODULE_DEVICE_TABLE(tee, trusted_key_id_table); 262 263 static struct tee_client_driver trusted_key_driver = { 264 .id_table = trusted_key_id_table, 265 .driver = { 266 .name = DRIVER_NAME, 267 .bus = &tee_bus_type, 268 .probe = trusted_key_probe, 269 .remove = trusted_key_remove, 270 }, 271 }; 272 273 static int trusted_tee_init(void) 274 { 275 return driver_register(&trusted_key_driver.driver); 276 } 277 278 static void trusted_tee_exit(void) 279 { 280 driver_unregister(&trusted_key_driver.driver); 281 } 282 283 struct trusted_key_ops trusted_key_tee_ops = { 284 .migratable = 0, /* non-migratable */ 285 .init = trusted_tee_init, 286 .seal = trusted_tee_seal, 287 .unseal = trusted_tee_unseal, 288 .get_random = trusted_tee_get_random, 289 .exit = trusted_tee_exit, 290 }; 291