cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

trusted_core.c (9454B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2010 IBM Corporation
      4 * Copyright (c) 2019-2021, Linaro Limited
      5 *
      6 * See Documentation/security/keys/trusted-encrypted.rst
      7 */
      8
      9#include <keys/user-type.h>
     10#include <keys/trusted-type.h>
     11#include <keys/trusted_tee.h>
     12#include <keys/trusted_caam.h>
     13#include <keys/trusted_tpm.h>
     14#include <linux/capability.h>
     15#include <linux/err.h>
     16#include <linux/init.h>
     17#include <linux/key-type.h>
     18#include <linux/module.h>
     19#include <linux/parser.h>
     20#include <linux/random.h>
     21#include <linux/rcupdate.h>
     22#include <linux/slab.h>
     23#include <linux/static_call.h>
     24#include <linux/string.h>
     25#include <linux/uaccess.h>
     26
     27static char *trusted_rng = "default";
     28module_param_named(rng, trusted_rng, charp, 0);
     29MODULE_PARM_DESC(rng, "Select trusted key RNG");
     30
     31static char *trusted_key_source;
     32module_param_named(source, trusted_key_source, charp, 0);
     33MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee or caam)");
     34
     35static const struct trusted_key_source trusted_key_sources[] = {
     36#if defined(CONFIG_TRUSTED_KEYS_TPM)
     37	{ "tpm", &trusted_key_tpm_ops },
     38#endif
     39#if defined(CONFIG_TRUSTED_KEYS_TEE)
     40	{ "tee", &trusted_key_tee_ops },
     41#endif
     42#if defined(CONFIG_TRUSTED_KEYS_CAAM)
     43	{ "caam", &trusted_key_caam_ops },
     44#endif
     45};
     46
     47DEFINE_STATIC_CALL_NULL(trusted_key_init, *trusted_key_sources[0].ops->init);
     48DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal);
     49DEFINE_STATIC_CALL_NULL(trusted_key_unseal,
     50			*trusted_key_sources[0].ops->unseal);
     51DEFINE_STATIC_CALL_NULL(trusted_key_get_random,
     52			*trusted_key_sources[0].ops->get_random);
     53DEFINE_STATIC_CALL_NULL(trusted_key_exit, *trusted_key_sources[0].ops->exit);
     54static unsigned char migratable;
     55
     56enum {
     57	Opt_err,
     58	Opt_new, Opt_load, Opt_update,
     59};
     60
     61static const match_table_t key_tokens = {
     62	{Opt_new, "new"},
     63	{Opt_load, "load"},
     64	{Opt_update, "update"},
     65	{Opt_err, NULL}
     66};
     67
     68/*
     69 * datablob_parse - parse the keyctl data and fill in the
     70 *                  payload structure
     71 *
     72 * On success returns 0, otherwise -EINVAL.
     73 */
     74static int datablob_parse(char **datablob, struct trusted_key_payload *p)
     75{
     76	substring_t args[MAX_OPT_ARGS];
     77	long keylen;
     78	int ret = -EINVAL;
     79	int key_cmd;
     80	char *c;
     81
     82	/* main command */
     83	c = strsep(datablob, " \t");
     84	if (!c)
     85		return -EINVAL;
     86	key_cmd = match_token(c, key_tokens, args);
     87	switch (key_cmd) {
     88	case Opt_new:
     89		/* first argument is key size */
     90		c = strsep(datablob, " \t");
     91		if (!c)
     92			return -EINVAL;
     93		ret = kstrtol(c, 10, &keylen);
     94		if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
     95			return -EINVAL;
     96		p->key_len = keylen;
     97		ret = Opt_new;
     98		break;
     99	case Opt_load:
    100		/* first argument is sealed blob */
    101		c = strsep(datablob, " \t");
    102		if (!c)
    103			return -EINVAL;
    104		p->blob_len = strlen(c) / 2;
    105		if (p->blob_len > MAX_BLOB_SIZE)
    106			return -EINVAL;
    107		ret = hex2bin(p->blob, c, p->blob_len);
    108		if (ret < 0)
    109			return -EINVAL;
    110		ret = Opt_load;
    111		break;
    112	case Opt_update:
    113		ret = Opt_update;
    114		break;
    115	case Opt_err:
    116		return -EINVAL;
    117	}
    118	return ret;
    119}
    120
    121static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
    122{
    123	struct trusted_key_payload *p = NULL;
    124	int ret;
    125
    126	ret = key_payload_reserve(key, sizeof(*p));
    127	if (ret < 0)
    128		goto err;
    129	p = kzalloc(sizeof(*p), GFP_KERNEL);
    130	if (!p)
    131		goto err;
    132
    133	p->migratable = migratable;
    134err:
    135	return p;
    136}
    137
    138/*
    139 * trusted_instantiate - create a new trusted key
    140 *
    141 * Unseal an existing trusted blob or, for a new key, get a
    142 * random key, then seal and create a trusted key-type key,
    143 * adding it to the specified keyring.
    144 *
    145 * On success, return 0. Otherwise return errno.
    146 */
    147static int trusted_instantiate(struct key *key,
    148			       struct key_preparsed_payload *prep)
    149{
    150	struct trusted_key_payload *payload = NULL;
    151	size_t datalen = prep->datalen;
    152	char *datablob, *orig_datablob;
    153	int ret = 0;
    154	int key_cmd;
    155	size_t key_len;
    156
    157	if (datalen <= 0 || datalen > 32767 || !prep->data)
    158		return -EINVAL;
    159
    160	orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);
    161	if (!datablob)
    162		return -ENOMEM;
    163	memcpy(datablob, prep->data, datalen);
    164	datablob[datalen] = '\0';
    165
    166	payload = trusted_payload_alloc(key);
    167	if (!payload) {
    168		ret = -ENOMEM;
    169		goto out;
    170	}
    171
    172	key_cmd = datablob_parse(&datablob, payload);
    173	if (key_cmd < 0) {
    174		ret = key_cmd;
    175		goto out;
    176	}
    177
    178	dump_payload(payload);
    179
    180	switch (key_cmd) {
    181	case Opt_load:
    182		ret = static_call(trusted_key_unseal)(payload, datablob);
    183		dump_payload(payload);
    184		if (ret < 0)
    185			pr_info("key_unseal failed (%d)\n", ret);
    186		break;
    187	case Opt_new:
    188		key_len = payload->key_len;
    189		ret = static_call(trusted_key_get_random)(payload->key,
    190							  key_len);
    191		if (ret < 0)
    192			goto out;
    193
    194		if (ret != key_len) {
    195			pr_info("key_create failed (%d)\n", ret);
    196			ret = -EIO;
    197			goto out;
    198		}
    199
    200		ret = static_call(trusted_key_seal)(payload, datablob);
    201		if (ret < 0)
    202			pr_info("key_seal failed (%d)\n", ret);
    203		break;
    204	default:
    205		ret = -EINVAL;
    206	}
    207out:
    208	kfree_sensitive(orig_datablob);
    209	if (!ret)
    210		rcu_assign_keypointer(key, payload);
    211	else
    212		kfree_sensitive(payload);
    213	return ret;
    214}
    215
    216static void trusted_rcu_free(struct rcu_head *rcu)
    217{
    218	struct trusted_key_payload *p;
    219
    220	p = container_of(rcu, struct trusted_key_payload, rcu);
    221	kfree_sensitive(p);
    222}
    223
    224/*
    225 * trusted_update - reseal an existing key with new PCR values
    226 */
    227static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
    228{
    229	struct trusted_key_payload *p;
    230	struct trusted_key_payload *new_p;
    231	size_t datalen = prep->datalen;
    232	char *datablob, *orig_datablob;
    233	int ret = 0;
    234
    235	if (key_is_negative(key))
    236		return -ENOKEY;
    237	p = key->payload.data[0];
    238	if (!p->migratable)
    239		return -EPERM;
    240	if (datalen <= 0 || datalen > 32767 || !prep->data)
    241		return -EINVAL;
    242
    243	orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);
    244	if (!datablob)
    245		return -ENOMEM;
    246
    247	new_p = trusted_payload_alloc(key);
    248	if (!new_p) {
    249		ret = -ENOMEM;
    250		goto out;
    251	}
    252
    253	memcpy(datablob, prep->data, datalen);
    254	datablob[datalen] = '\0';
    255	ret = datablob_parse(&datablob, new_p);
    256	if (ret != Opt_update) {
    257		ret = -EINVAL;
    258		kfree_sensitive(new_p);
    259		goto out;
    260	}
    261
    262	/* copy old key values, and reseal with new pcrs */
    263	new_p->migratable = p->migratable;
    264	new_p->key_len = p->key_len;
    265	memcpy(new_p->key, p->key, p->key_len);
    266	dump_payload(p);
    267	dump_payload(new_p);
    268
    269	ret = static_call(trusted_key_seal)(new_p, datablob);
    270	if (ret < 0) {
    271		pr_info("key_seal failed (%d)\n", ret);
    272		kfree_sensitive(new_p);
    273		goto out;
    274	}
    275
    276	rcu_assign_keypointer(key, new_p);
    277	call_rcu(&p->rcu, trusted_rcu_free);
    278out:
    279	kfree_sensitive(orig_datablob);
    280	return ret;
    281}
    282
    283/*
    284 * trusted_read - copy the sealed blob data to userspace in hex.
    285 * On success, return to userspace the trusted key datablob size.
    286 */
    287static long trusted_read(const struct key *key, char *buffer,
    288			 size_t buflen)
    289{
    290	const struct trusted_key_payload *p;
    291	char *bufp;
    292	int i;
    293
    294	p = dereference_key_locked(key);
    295	if (!p)
    296		return -EINVAL;
    297
    298	if (buffer && buflen >= 2 * p->blob_len) {
    299		bufp = buffer;
    300		for (i = 0; i < p->blob_len; i++)
    301			bufp = hex_byte_pack(bufp, p->blob[i]);
    302	}
    303	return 2 * p->blob_len;
    304}
    305
    306/*
    307 * trusted_destroy - clear and free the key's payload
    308 */
    309static void trusted_destroy(struct key *key)
    310{
    311	kfree_sensitive(key->payload.data[0]);
    312}
    313
    314struct key_type key_type_trusted = {
    315	.name = "trusted",
    316	.instantiate = trusted_instantiate,
    317	.update = trusted_update,
    318	.destroy = trusted_destroy,
    319	.describe = user_describe,
    320	.read = trusted_read,
    321};
    322EXPORT_SYMBOL_GPL(key_type_trusted);
    323
    324static int kernel_get_random(unsigned char *key, size_t key_len)
    325{
    326	return get_random_bytes_wait(key, key_len) ?: key_len;
    327}
    328
    329static int __init init_trusted(void)
    330{
    331	int (*get_random)(unsigned char *key, size_t key_len);
    332	int i, ret = 0;
    333
    334	for (i = 0; i < ARRAY_SIZE(trusted_key_sources); i++) {
    335		if (trusted_key_source &&
    336		    strncmp(trusted_key_source, trusted_key_sources[i].name,
    337			    strlen(trusted_key_sources[i].name)))
    338			continue;
    339
    340		/*
    341		 * We always support trusted.rng="kernel" and "default" as
    342		 * well as trusted.rng=$trusted.source if the trust source
    343		 * defines its own get_random callback.
    344		 */
    345		get_random = trusted_key_sources[i].ops->get_random;
    346		if (trusted_rng && strcmp(trusted_rng, "default")) {
    347			if (!strcmp(trusted_rng, "kernel")) {
    348				get_random = kernel_get_random;
    349			} else if (strcmp(trusted_rng, trusted_key_sources[i].name) ||
    350				   !get_random) {
    351				pr_warn("Unsupported RNG. Supported: kernel");
    352				if (get_random)
    353					pr_cont(", %s", trusted_key_sources[i].name);
    354				pr_cont(", default\n");
    355				return -EINVAL;
    356			}
    357		}
    358
    359		if (!get_random)
    360			get_random = kernel_get_random;
    361
    362		static_call_update(trusted_key_init,
    363				   trusted_key_sources[i].ops->init);
    364		static_call_update(trusted_key_seal,
    365				   trusted_key_sources[i].ops->seal);
    366		static_call_update(trusted_key_unseal,
    367				   trusted_key_sources[i].ops->unseal);
    368		static_call_update(trusted_key_get_random,
    369				   get_random);
    370		static_call_update(trusted_key_exit,
    371				   trusted_key_sources[i].ops->exit);
    372		migratable = trusted_key_sources[i].ops->migratable;
    373
    374		ret = static_call(trusted_key_init)();
    375		if (!ret)
    376			break;
    377	}
    378
    379	/*
    380	 * encrypted_keys.ko depends on successful load of this module even if
    381	 * trusted key implementation is not found.
    382	 */
    383	if (ret == -ENODEV)
    384		return 0;
    385
    386	return ret;
    387}
    388
    389static void __exit cleanup_trusted(void)
    390{
    391	static_call_cond(trusted_key_exit)();
    392}
    393
    394late_initcall(init_trusted);
    395module_exit(cleanup_trusted);
    396
    397MODULE_LICENSE("GPL");