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
3config TEE3config TEE
4 tristate "Trusted Execution Environment support"4 tristate "Trusted Execution Environment support"
5 depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD5 depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD
6 select CRYPTO_SHA1
6 select DMA_SHARED_BUFFER7 select DMA_SHARED_BUFFER
7 select GENERIC_ALLOCATOR8 select GENERIC_ALLOCATOR
8 help9 help
drivers/tee/optee/call.c+5−1
@@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx, · 232 unmodified lines
233 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |233 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
234 OPTEE_MSG_ATTR_META;234 OPTEE_MSG_ATTR_META;
235 memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));235 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));
237 msg_arg->params[1].u.value.c = arg->clnt_login;236 msg_arg->params[1].u.value.c = arg->clnt_login;
238 237
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
239 rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);243 rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
240 if (rc)244 if (rc)
241 goto out;245 goto out;
drivers/tee/tee_core.c+152−0
@@ -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 3220#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 */
32static 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 in37 * 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 */
140static 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
186out_free_desc:
187 kfree(desc);
188
189out_free_shash:
190 crypto_free_shash(shash);
191 return rc;
192}
193
194int 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);
258out_free_name:
259 kfree(name);
260
261 return rc;
262}
263EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid);
264
113static int tee_ioctl_version(struct tee_context *ctx,265static 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{
include/linux/tee_drv.h+16−0
@@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev); · 165 unmodified lines
166 */166 */
167void tee_device_unregister(struct tee_device *teedev);167void tee_device_unregister(struct tee_device *teedev);
168 168
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 */
182int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
183 const u8 connection_data[TEE_IOCTL_UUID_LEN]);
184
169/**185/**
170 * struct tee_shm - shared memory object186 * struct tee_shm - shared memory object
171 * @ctx: context using the object187 * @ctx: context using the object