| @@ -6,18 +6,33 @@ · 5 unmodified lines |
| 6 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 6 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
| 7 | | 7 | |
| 8 | #include <linux/cdev.h> | 8 | #include <linux/cdev.h> |
| | 9 | #include <linux/cred.h> |
| 9 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
| 10 | #include <linux/idr.h> | 11 | #include <linux/idr.h> |
| 11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 12 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 13 | #include <linux/tee_drv.h> | 14 | #include <linux/tee_drv.h> |
| 14 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
| | 16 | #include <crypto/hash.h> |
| | 17 | #include <crypto/sha.h> |
| 15 | #include "tee_private.h" | 18 | #include "tee_private.h" |
| 16 | | 19 | |
| 17 | #define TEE_NUM_DEVICES 32 | 20 | #define TEE_NUM_DEVICES 32 |
| 18 | | 21 | |
| 19 | #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x)) | 22 | #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x)) |
| 20 | | 23 | |
| | 24 | #define TEE_UUID_NS_NAME_SIZE 128 |
| | 25 | |
| | 26 | /* |
| | 27 | * TEE Client UUID name space identifier (UUIDv4) |
| | 28 | * |
| | 29 | * Value here is random UUID that is allocated as name space identifier for |
| | 30 | * forming Client UUID's for TEE environment using UUIDv5 scheme. |
| | 31 | */ |
| | 32 | static const uuid_t tee_client_uuid_ns = UUID_INIT(0x58ac9ca0, 0x2086, 0x4683, |
| | 33 | 0xa1, 0xb8, 0xec, 0x4b, |
| | 34 | 0xc0, 0x8e, 0x01, 0xb6); |
| | 35 | |
| 21 | /* | 36 | /* |
| 22 | * Unprivileged devices in the lower half range and privileged devices in | 37 | * Unprivileged devices in the lower half range and privileged devices in |
| 23 | * the upper half range. | 38 | * the upper half range. |
| @@ -110,6 +125,143 @@ static int tee_release(struct inode *inode, struct file *filp) · 86 unmodified lines |
| 110 | return 0; | 125 | return 0; |
| 111 | } | 126 | } |
| 112 | | 127 | |
| | 128 | /** |
| | 129 | * uuid_v5() - Calculate UUIDv5 |
| | 130 | * @uuid: Resulting UUID |
| | 131 | * @ns: Name space ID for UUIDv5 function |
| | 132 | * @name: Name for UUIDv5 function |
| | 133 | * @size: Size of name |
| | 134 | * |
| | 135 | * UUIDv5 is specific in RFC 4122. |
| | 136 | * |
| | 137 | * This implements section (for SHA-1): |
| | 138 | * 4.3. Algorithm for Creating a Name-Based UUID |
| | 139 | */ |
| | 140 | static int uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name, |
| | 141 | size_t size) |
| | 142 | { |
| | 143 | unsigned char hash[SHA1_DIGEST_SIZE]; |
| | 144 | struct crypto_shash *shash = NULL; |
| | 145 | struct shash_desc *desc = NULL; |
| | 146 | int rc; |
| | 147 | |
| | 148 | shash = crypto_alloc_shash("sha1", 0, 0); |
| | 149 | if (IS_ERR(shash)) { |
| | 150 | rc = PTR_ERR(shash); |
| | 151 | pr_err("shash(sha1) allocation failed\n"); |
| | 152 | return rc; |
| | 153 | } |
| | 154 | |
| | 155 | desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash), |
| | 156 | GFP_KERNEL); |
| | 157 | if (!desc) { |
| | 158 | rc = -ENOMEM; |
| | 159 | goto out_free_shash; |
| | 160 | } |
| | 161 | |
| | 162 | desc->tfm = shash; |
| | 163 | |
| | 164 | rc = crypto_shash_init(desc); |
| | 165 | if (rc < 0) |
| | 166 | goto out_free_desc; |
| | 167 | |
| | 168 | rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns)); |
| | 169 | if (rc < 0) |
| | 170 | goto out_free_desc; |
| | 171 | |
| | 172 | rc = crypto_shash_update(desc, (const u8 *)name, size); |
| | 173 | if (rc < 0) |
| | 174 | goto out_free_desc; |
| | 175 | |
| | 176 | rc = crypto_shash_final(desc, hash); |
| | 177 | if (rc < 0) |
| | 178 | goto out_free_desc; |
| | 179 | |
| | 180 | memcpy(uuid->b, hash, UUID_SIZE); |
| | 181 | |
| | 182 | /* Tag for version 5 */ |
| | 183 | uuid->b[6] = (hash[6] & 0x0F) | 0x50; |
| | 184 | uuid->b[8] = (hash[8] & 0x3F) | 0x80; |
| | 185 | |
| | 186 | out_free_desc: |
| | 187 | kfree(desc); |
| | 188 | |
| | 189 | out_free_shash: |
| | 190 | crypto_free_shash(shash); |
| | 191 | return rc; |
| | 192 | } |
| | 193 | |
| | 194 | int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, |
| | 195 | const u8 connection_data[TEE_IOCTL_UUID_LEN]) |
| | 196 | { |
| | 197 | gid_t ns_grp = (gid_t)-1; |
| | 198 | kgid_t grp = INVALID_GID; |
| | 199 | char *name = NULL; |
| | 200 | int name_len; |
| | 201 | int rc; |
| | 202 | |
| | 203 | if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) { |
| | 204 | /* Nil UUID to be passed to TEE environment */ |
| | 205 | uuid_copy(uuid, &uuid_null); |
| | 206 | return 0; |
| | 207 | } |
| | 208 | |
| | 209 | /* |
| | 210 | * In Linux environment client UUID is based on UUIDv5. |
| | 211 | * |
| | 212 | * Determine client UUID with following semantics for 'name': |
| | 213 | * |
| | 214 | * For TEEC_LOGIN_USER: |
| | 215 | * uid=<uid> |
| | 216 | * |
| | 217 | * For TEEC_LOGIN_GROUP: |
| | 218 | * gid=<gid> |
| | 219 | * |
| | 220 | */ |
| | 221 | |
| | 222 | name = kzalloc(TEE_UUID_NS_NAME_SIZE, GFP_KERNEL); |
| | 223 | if (!name) |
| | 224 | return -ENOMEM; |
| | 225 | |
| | 226 | switch (connection_method) { |
| | 227 | case TEE_IOCTL_LOGIN_USER: |
| | 228 | name_len = snprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x", |
| | 229 | current_euid().val); |
| | 230 | if (name_len >= TEE_UUID_NS_NAME_SIZE) { |
| | 231 | rc = -E2BIG; |
| | 232 | goto out_free_name; |
| | 233 | } |
| | 234 | break; |
| | 235 | |
| | 236 | case TEE_IOCTL_LOGIN_GROUP: |
| | 237 | memcpy(&ns_grp, connection_data, sizeof(gid_t)); |
| | 238 | grp = make_kgid(current_user_ns(), ns_grp); |
| | 239 | if (!gid_valid(grp) || !in_egroup_p(grp)) { |
| | 240 | rc = -EPERM; |
| | 241 | goto out_free_name; |
| | 242 | } |
| | 243 | |
| | 244 | name_len = snprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x", |
| | 245 | grp.val); |
| | 246 | if (name_len >= TEE_UUID_NS_NAME_SIZE) { |
| | 247 | rc = -E2BIG; |
| | 248 | goto out_free_name; |
| | 249 | } |
| | 250 | break; |
| | 251 | |
| | 252 | default: |
| | 253 | rc = -EINVAL; |
| | 254 | goto out_free_name; |
| | 255 | } |
| | 256 | |
| | 257 | rc = uuid_v5(uuid, &tee_client_uuid_ns, name, name_len); |
| | 258 | out_free_name: |
| | 259 | kfree(name); |
| | 260 | |
| | 261 | return rc; |
| | 262 | } |
| | 263 | EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid); |
| | 264 | |
| 113 | static int tee_ioctl_version(struct tee_context *ctx, | 265 | static int tee_ioctl_version(struct tee_context *ctx, |
| 114 | struct tee_ioctl_version_data __user *uvers) | 266 | struct tee_ioctl_version_data __user *uvers) |
| 115 | { | 267 | { |