Skip to content

Commit be4ad16

Browse files
committed
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 Link: https://lore.kernel.org/r/20200512131243.GA10028@jade Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 0417a5c + c5b4312 commit be4ad16

File tree

4 files changed

+174
-1
lines changed

4 files changed

+174
-1
lines changed

drivers/tee/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx,
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

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,33 @@
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)
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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev);
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

0 commit comments

Comments
 (0)