Adds utility function in TEE subsystem for client UUID generation. This

function is also used in the optee driver.
 -----BEGIN PGP SIGNATURE-----
 
 iQJOBAABCgA4FiEEFV+gSSXZJY9ZyuB5LinzTIcAHJcFAl66eh4aHGplbnMud2lr
 bGFuZGVyQGxpbmFyby5vcmcACgkQLinzTIcAHJeZ5w/+O2C1ixl3tt40mVjCFkpT
 TCKy4lJXQWXegYZ7epJAImRM82ogVoOItEhOtrSmodnENJLVgH8TUBuPiTwh4kb6
 sSQ2zEPoOvA+3HtnnPaxZKuttMvL9MMvAoNH8Mg6ZEaBxG0r6zqiff8vPtfGlM/r
 BSy/vH0rxYo1qX4twUHu6GSVWJLC2aSm/eO6BWri5kGHPgR1QOjeXXmotecx9h/b
 6cxxRa6FG8nuXuqemMfdtk2j2PMsp639ziTD8cKKR7ncsiUqGtbvonRbeOOBTrHL
 aimLgGtIe7hgObspVrH9pvh9ZpTjH34ffQatfAnZROkWKxWhdab9RbrycoFsVRWq
 hc62KfuSA3zFHMx4/q0QIiE0TYXnrIjmHziIBKjQs1w3ZdjcQl2OB1guE20xuhWd
 LCDZEV2E954113DOQ4kCV9Yh5psDJ0jhjAZrrAdRMX6JZuZ3jzr5hA0BDtSOjKLs
 PqQ2TUI+95YZVLI7QdqBCf9Z3HXlI9a3TwOCVzDYy1m0InvzHXwHD6DhdobNhd+J
 rQEKvMog5hhe/C3W9agl8Hi2BXNLsepcwUBRx6CsyaZMXBBUxbPeWR6ZnqlRAkYS
 FyNbC82yoOYtOYdnOLHwIarr65uGhO5PFY/g5o6k2vuu2WeI7tr9wlGMgBbBb2wT
 EnGClHSHcOkmsYyJJ6TX2sw=
 =dx75
 -----END PGP SIGNATURE-----

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 <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2020-05-25 23:15:02 +02:00
commit be4ad166b4
4 changed files with 174 additions and 1 deletions

View File

@ -3,6 +3,7 @@
config TEE
tristate "Trusted Execution Environment support"
depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD
select CRYPTO_SHA1
select DMA_SHARED_BUFFER
select GENERIC_ALLOCATOR
help

View File

@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx,
msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
OPTEE_MSG_ATTR_META;
memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
msg_arg->params[1].u.value.c = arg->clnt_login;
rc = tee_session_calc_client_uuid((uuid_t *)&msg_arg->params[1].u.value,
arg->clnt_login, arg->clnt_uuid);
if (rc)
goto out;
rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
if (rc)
goto out;

View File

@ -6,18 +6,33 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/cdev.h>
#include <linux/cred.h>
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
#include <linux/uaccess.h>
#include <crypto/hash.h>
#include <crypto/sha.h>
#include "tee_private.h"
#define TEE_NUM_DEVICES 32
#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
#define TEE_UUID_NS_NAME_SIZE 128
/*
* TEE Client UUID name space identifier (UUIDv4)
*
* Value here is random UUID that is allocated as name space identifier for
* forming Client UUID's for TEE environment using UUIDv5 scheme.
*/
static const uuid_t tee_client_uuid_ns = UUID_INIT(0x58ac9ca0, 0x2086, 0x4683,
0xa1, 0xb8, 0xec, 0x4b,
0xc0, 0x8e, 0x01, 0xb6);
/*
* Unprivileged devices in the lower half range and privileged devices in
* the upper half range.
@ -110,6 +125,143 @@ static int tee_release(struct inode *inode, struct file *filp)
return 0;
}
/**
* uuid_v5() - Calculate UUIDv5
* @uuid: Resulting UUID
* @ns: Name space ID for UUIDv5 function
* @name: Name for UUIDv5 function
* @size: Size of name
*
* UUIDv5 is specific in RFC 4122.
*
* This implements section (for SHA-1):
* 4.3. Algorithm for Creating a Name-Based UUID
*/
static int uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
size_t size)
{
unsigned char hash[SHA1_DIGEST_SIZE];
struct crypto_shash *shash = NULL;
struct shash_desc *desc = NULL;
int rc;
shash = crypto_alloc_shash("sha1", 0, 0);
if (IS_ERR(shash)) {
rc = PTR_ERR(shash);
pr_err("shash(sha1) allocation failed\n");
return rc;
}
desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash),
GFP_KERNEL);
if (!desc) {
rc = -ENOMEM;
goto out_free_shash;
}
desc->tfm = shash;
rc = crypto_shash_init(desc);
if (rc < 0)
goto out_free_desc;
rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns));
if (rc < 0)
goto out_free_desc;
rc = crypto_shash_update(desc, (const u8 *)name, size);
if (rc < 0)
goto out_free_desc;
rc = crypto_shash_final(desc, hash);
if (rc < 0)
goto out_free_desc;
memcpy(uuid->b, hash, UUID_SIZE);
/* Tag for version 5 */
uuid->b[6] = (hash[6] & 0x0F) | 0x50;
uuid->b[8] = (hash[8] & 0x3F) | 0x80;
out_free_desc:
kfree(desc);
out_free_shash:
crypto_free_shash(shash);
return rc;
}
int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
const u8 connection_data[TEE_IOCTL_UUID_LEN])
{
gid_t ns_grp = (gid_t)-1;
kgid_t grp = INVALID_GID;
char *name = NULL;
int name_len;
int rc;
if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
/* Nil UUID to be passed to TEE environment */
uuid_copy(uuid, &uuid_null);
return 0;
}
/*
* In Linux environment client UUID is based on UUIDv5.
*
* Determine client UUID with following semantics for 'name':
*
* For TEEC_LOGIN_USER:
* uid=<uid>
*
* For TEEC_LOGIN_GROUP:
* gid=<gid>
*
*/
name = kzalloc(TEE_UUID_NS_NAME_SIZE, GFP_KERNEL);
if (!name)
return -ENOMEM;
switch (connection_method) {
case TEE_IOCTL_LOGIN_USER:
name_len = snprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x",
current_euid().val);
if (name_len >= TEE_UUID_NS_NAME_SIZE) {
rc = -E2BIG;
goto out_free_name;
}
break;
case TEE_IOCTL_LOGIN_GROUP:
memcpy(&ns_grp, connection_data, sizeof(gid_t));
grp = make_kgid(current_user_ns(), ns_grp);
if (!gid_valid(grp) || !in_egroup_p(grp)) {
rc = -EPERM;
goto out_free_name;
}
name_len = snprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x",
grp.val);
if (name_len >= TEE_UUID_NS_NAME_SIZE) {
rc = -E2BIG;
goto out_free_name;
}
break;
default:
rc = -EINVAL;
goto out_free_name;
}
rc = uuid_v5(uuid, &tee_client_uuid_ns, name, name_len);
out_free_name:
kfree(name);
return rc;
}
EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid);
static int tee_ioctl_version(struct tee_context *ctx,
struct tee_ioctl_version_data __user *uvers)
{

View File

@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev);
*/
void tee_device_unregister(struct tee_device *teedev);
/**
* tee_session_calc_client_uuid() - Calculates client UUID for session
* @uuid: Resulting UUID
* @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*)
* @connectuon_data: Connection data for opening session
*
* Based on connection method calculates UUIDv5 based client UUID.
*
* For group based logins verifies that calling process has specified
* credentials.
*
* @return < 0 on failure
*/
int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
const u8 connection_data[TEE_IOCTL_UUID_LEN]);
/**
* struct tee_shm - shared memory object
* @ctx: context using the object