Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tee: add support for session's client UUID generation #5

Open
wants to merge 2 commits into
base: poplar-4.9
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/tee/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generic Trusted Execution Environment Configuration
config TEE
tristate "Trusted Execution Environment support"
select CRYPTO_SHA1
select DMA_SHARED_BUFFER
select GENERIC_ALLOCATOR
help
Expand Down
6 changes: 5 additions & 1 deletion drivers/tee/optee/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,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;
Expand Down
143 changes: 143 additions & 0 deletions drivers/tee/tee_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,33 @@

#include <linux/cdev.h>
#include <linux/device.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.
Expand Down Expand Up @@ -116,6 +131,134 @@ 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 (IS_ERR(desc)) {
rc = PTR_ERR(desc);
goto out;
}

desc->tfm = shash;

rc = crypto_shash_init(desc);
if (rc < 0)
goto out2;

rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns));
if (rc < 0)
goto out2;

rc = crypto_shash_update(desc, (const u8 *)name, size);
if (rc < 0)
goto out2;

rc = crypto_shash_final(desc, hash);
if (rc < 0)
goto out2;

memcpy(uuid->b, hash, UUID_SIZE);

/* Tag for version 5 */
uuid->b[6] = (hash[6] & 0x0F) | 0x50;
uuid->b[8] = (hash[8] & 0x3F) | 0x80;

out2:
kfree(desc);

out:
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])
{
const char *application_id = NULL;
gid_t ns_grp = (gid_t)-1;
kgid_t grp = INVALID_GID;
char *name = NULL;
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:
scnprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x",
current_euid().val);
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;
}

scnprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x", grp.val);
break;

default:
rc = -EINVAL;
goto out;
}

rc = uuid_v5(uuid, &tee_client_uuid_ns, name, strlen(name));
out:
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)
{
Expand Down
16 changes: 16 additions & 0 deletions include/linux/tee_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,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
* @teedev: device used to allocate the object
Expand Down