Skip to content

Commit baa151f

Browse files
vesajaaskelainenjforissier
authored andcommitted
tee: add support for session's client UUID generation
TEE Client API defines that from user space only information needed for specified login operations is group identifier for group based logins. REE kernel is expected to formulate trustworthy client UUID and pass that to TEE environment. REE kernel is required to verify that provided group identifier for group based logins matches calling processes group memberships. TEE specification only defines that the information passed from REE environment to TEE environment is encoded into on UUID. In order to guarantee trustworthiness of client UUID user space is not allowed to freely pass client UUID. UUIDv5 form is used encode variable amount of information needed for different login types. Signed-off-by: Vesa Jääskeläinen <[email protected]>
1 parent 1149e7d commit baa151f

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
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
6+
select CRYPTO_SHA1
67
select DMA_SHARED_BUFFER
78
select GENERIC_ALLOCATOR
89
help

drivers/tee/tee_core.c

Lines changed: 143 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.
@@ -111,6 +126,134 @@ static int tee_release(struct inode *inode, struct file *filp)
111126
return 0;
112127
}
113128

129+
/**
130+
* uuid_v5() - Calculate UUIDv5
131+
* @uuid: Resulting UUID
132+
* @ns: Name space ID for UUIDv5 function
133+
* @name: Name for UUIDv5 function
134+
* @size: Size of name
135+
*
136+
* UUIDv5 is specific in RFC 4122.
137+
*
138+
* This implements section (for SHA-1):
139+
* 4.3. Algorithm for Creating a Name-Based UUID
140+
*/
141+
static int uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
142+
size_t size)
143+
{
144+
unsigned char hash[SHA1_DIGEST_SIZE];
145+
struct crypto_shash *shash = NULL;
146+
struct shash_desc *desc = NULL;
147+
int rc;
148+
149+
shash = crypto_alloc_shash("sha1", 0, 0);
150+
if (IS_ERR(shash)) {
151+
rc = PTR_ERR(shash);
152+
pr_err("shash(sha1) allocation failed\n");
153+
return rc;
154+
}
155+
156+
desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash),
157+
GFP_KERNEL);
158+
if (IS_ERR(desc)) {
159+
rc = PTR_ERR(desc);
160+
goto out;
161+
}
162+
163+
desc->tfm = shash;
164+
165+
rc = crypto_shash_init(desc);
166+
if (rc < 0)
167+
goto out2;
168+
169+
rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns));
170+
if (rc < 0)
171+
goto out2;
172+
173+
rc = crypto_shash_update(desc, (const u8 *)name, size);
174+
if (rc < 0)
175+
goto out2;
176+
177+
rc = crypto_shash_final(desc, hash);
178+
if (rc < 0)
179+
goto out2;
180+
181+
memcpy(uuid->b, hash, UUID_SIZE);
182+
183+
/* Tag for version 5 */
184+
uuid->b[6] = (hash[6] & 0x0F) | 0x50;
185+
uuid->b[8] = (hash[8] & 0x3F) | 0x80;
186+
187+
out2:
188+
kfree(desc);
189+
190+
out:
191+
crypto_free_shash(shash);
192+
return rc;
193+
}
194+
195+
int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
196+
const u8 connection_data[TEE_IOCTL_UUID_LEN])
197+
{
198+
const char *application_id = NULL;
199+
gid_t ns_grp = (gid_t)-1;
200+
kgid_t grp = INVALID_GID;
201+
char *name = NULL;
202+
int rc;
203+
204+
if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
205+
/* Nil UUID to be passed to TEE environment */
206+
uuid_copy(uuid, &uuid_null);
207+
return 0;
208+
}
209+
210+
/*
211+
* In Linux environment client UUID is based on UUIDv5.
212+
*
213+
* Determine client UUID with following semantics for 'name':
214+
*
215+
* For TEEC_LOGIN_USER:
216+
* uid=<uid>
217+
*
218+
* For TEEC_LOGIN_GROUP:
219+
* gid=<gid>
220+
*
221+
*/
222+
223+
name = kzalloc(TEE_UUID_NS_NAME_SIZE, GFP_KERNEL);
224+
if (!name)
225+
return -ENOMEM;
226+
227+
switch (connection_method) {
228+
case TEE_IOCTL_LOGIN_USER:
229+
scnprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x",
230+
current_euid().val);
231+
break;
232+
233+
case TEE_IOCTL_LOGIN_GROUP:
234+
memcpy(&ns_grp, connection_data, sizeof(gid_t));
235+
grp = make_kgid(current_user_ns(), ns_grp);
236+
if (!gid_valid(grp) || !in_egroup_p(grp)) {
237+
rc = -EPERM;
238+
goto out;
239+
}
240+
241+
scnprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x", grp.val);
242+
break;
243+
244+
default:
245+
rc = -EINVAL;
246+
goto out;
247+
}
248+
249+
rc = uuid_v5(uuid, &tee_client_uuid_ns, name, strlen(name));
250+
out:
251+
kfree(name);
252+
253+
return rc;
254+
}
255+
EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid);
256+
114257
static int tee_ioctl_version(struct tee_context *ctx,
115258
struct tee_ioctl_version_data __user *uvers)
116259
{

include/linux/tee_drv.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,22 @@ int tee_device_register(struct tee_device *teedev);
169169
*/
170170
void tee_device_unregister(struct tee_device *teedev);
171171

172+
/**
173+
* tee_session_calc_client_uuid() - Calculates client UUID for session
174+
* @uuid: Resulting UUID
175+
* @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*)
176+
* @connectuon_data: Connection data for opening session
177+
*
178+
* Based on connection method calculates UUIDv5 based client UUID.
179+
*
180+
* For group based logins verifies that calling process has specified
181+
* credentials.
182+
*
183+
* @return < 0 on failure
184+
*/
185+
int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
186+
const u8 connection_data[TEE_IOCTL_UUID_LEN]);
187+
172188
/**
173189
* struct tee_shm - shared memory object
174190
* @teedev: device used to allocate the object

0 commit comments

Comments
 (0)