History

Merge tag 'tee-login-for-5.8' of git://git.linaro.org/people/jens.wiklander/linux-tee into arm/drivers

Adds utility function in TEE subsystem for client UUID generation. This function is also used in the optee driver. * tag 'tee-login-for-5.8' of git://git.linaro.org/people/jens.wiklander/linux-tee: tee: optee: Add support for session login client UUID generation tee: add support for session's client UUID generation

Arnd Bergmann committed 6 years ago

Commit be4ad162 parents 0417a5c c5b43124 files · +174 −1Browse files

Unified · Split

4 files
  1. drivers/tee/Kconfig +1 −0
  2. drivers/tee/optee/call.c +5 −1
  3. drivers/tee/tee_core.c +152 −0
  4. include/linux/tee_drv.h +16 −0
drivers/tee/Kconfig+1−0
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 config TEE
44 tristate "Trusted Execution Environment support"
55 depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD
6+ select CRYPTO_SHA1
67 select DMA_SHARED_BUFFER
78 select GENERIC_ALLOCATOR
89 help
drivers/tee/optee/call.c+5−1
@@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx, · 232 unmodified lines
233233 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
234234 OPTEE_MSG_ATTR_META;
235235 memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
236− memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
237236 msg_arg->params[1].u.value.c = arg->clnt_login;
238237
238+ rc = tee_session_calc_client_uuid((uuid_t *)&msg_arg->params[1].u.value,
239+ arg->clnt_login, arg->clnt_uuid);
240+ if (rc)
241+ goto out;
242+
239243 rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
240244 if (rc)
241245 goto out;
drivers/tee/tee_core.c+152−0
@@ -6,18 +6,33 @@ · 5 unmodified lines
66 #define pr_fmt(fmt) "%s: " fmt, __func__
77
88 #include <linux/cdev.h>
9+#include <linux/cred.h>
910 #include <linux/fs.h>
1011 #include <linux/idr.h>
1112 #include <linux/module.h>
1213 #include <linux/slab.h>
1314 #include <linux/tee_drv.h>
1415 #include <linux/uaccess.h>
16+#include <crypto/hash.h>
17+#include <crypto/sha.h>
1518 #include "tee_private.h"
1619
1720 #define TEE_NUM_DEVICES 32
1821
1922 #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
2023
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+
2136 /*
2237 * Unprivileged devices in the lower half range and privileged devices in
2338 * the upper half range.
@@ -110,6 +125,143 @@ static int tee_release(struct inode *inode, struct file *filp) · 86 unmodified lines
110125 return 0;
111126 }
112127
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+
113265 static int tee_ioctl_version(struct tee_context *ctx,
114266 struct tee_ioctl_version_data __user *uvers)
115267 {
include/linux/tee_drv.h+16−0
@@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev); · 165 unmodified lines
166166 */
167167 void tee_device_unregister(struct tee_device *teedev);
168168
169+/**
170+ * tee_session_calc_client_uuid() - Calculates client UUID for session
171+ * @uuid: Resulting UUID
172+ * @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*)
173+ * @connectuon_data: Connection data for opening session
174+ *
175+ * Based on connection method calculates UUIDv5 based client UUID.
176+ *
177+ * For group based logins verifies that calling process has specified
178+ * credentials.
179+ *
180+ * @return < 0 on failure
181+ */
182+int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
183+ const u8 connection_data[TEE_IOCTL_UUID_LEN]);
184+
169185 /**
170186 * struct tee_shm - shared memory object
171187 * @ctx: context using the object