Path: blob/master/security/keys/trusted-keys/trusted_core.c
50682 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2010 IBM Corporation3* Copyright (c) 2019-2021, Linaro Limited4*5* See Documentation/security/keys/trusted-encrypted.rst6*/78#include <keys/user-type.h>9#include <keys/trusted-type.h>10#include <keys/trusted_tee.h>11#include <keys/trusted_caam.h>12#include <keys/trusted_dcp.h>13#include <keys/trusted_tpm.h>14#include <keys/trusted_pkwm.h>15#include <linux/capability.h>16#include <linux/err.h>17#include <linux/init.h>18#include <linux/key-type.h>19#include <linux/module.h>20#include <linux/parser.h>21#include <linux/random.h>22#include <linux/rcupdate.h>23#include <linux/slab.h>24#include <linux/static_call.h>25#include <linux/string.h>26#include <linux/uaccess.h>2728static char *trusted_rng = "default";29module_param_named(rng, trusted_rng, charp, 0);30MODULE_PARM_DESC(rng, "Select trusted key RNG");3132static char *trusted_key_source;33module_param_named(source, trusted_key_source, charp, 0);34MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)");3536static const struct trusted_key_source trusted_key_sources[] = {37#if defined(CONFIG_TRUSTED_KEYS_TPM)38{ "tpm", &trusted_key_tpm_ops },39#endif40#if defined(CONFIG_TRUSTED_KEYS_TEE)41{ "tee", &trusted_key_tee_ops },42#endif43#if defined(CONFIG_TRUSTED_KEYS_CAAM)44{ "caam", &trusted_key_caam_ops },45#endif46#if defined(CONFIG_TRUSTED_KEYS_DCP)47{ "dcp", &dcp_trusted_key_ops },48#endif49#if defined(CONFIG_TRUSTED_KEYS_PKWM)50{ "pkwm", &pkwm_trusted_key_ops },51#endif52};5354DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal);55DEFINE_STATIC_CALL_NULL(trusted_key_unseal,56*trusted_key_sources[0].ops->unseal);57DEFINE_STATIC_CALL_NULL(trusted_key_get_random,58*trusted_key_sources[0].ops->get_random);59static void (*trusted_key_exit)(void);60static unsigned char migratable;6162enum {63Opt_err,64Opt_new, Opt_load, Opt_update,65};6667static const match_table_t key_tokens = {68{Opt_new, "new"},69{Opt_load, "load"},70{Opt_update, "update"},71{Opt_err, NULL}72};7374/*75* datablob_parse - parse the keyctl data and fill in the76* payload structure77*78* On success returns 0, otherwise -EINVAL.79*/80static int datablob_parse(char **datablob, struct trusted_key_payload *p)81{82substring_t args[MAX_OPT_ARGS];83long keylen;84int ret = -EINVAL;85int key_cmd;86char *c;8788/* main command */89c = strsep(datablob, " \t");90if (!c)91return -EINVAL;92key_cmd = match_token(c, key_tokens, args);93switch (key_cmd) {94case Opt_new:95/* first argument is key size */96c = strsep(datablob, " \t");97if (!c)98return -EINVAL;99ret = kstrtol(c, 10, &keylen);100if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)101return -EINVAL;102p->key_len = keylen;103ret = Opt_new;104break;105case Opt_load:106/* first argument is sealed blob */107c = strsep(datablob, " \t");108if (!c)109return -EINVAL;110p->blob_len = strlen(c) / 2;111if (p->blob_len > MAX_BLOB_SIZE)112return -EINVAL;113ret = hex2bin(p->blob, c, p->blob_len);114if (ret < 0)115return -EINVAL;116ret = Opt_load;117break;118case Opt_update:119ret = Opt_update;120break;121case Opt_err:122return -EINVAL;123}124return ret;125}126127static struct trusted_key_payload *trusted_payload_alloc(struct key *key)128{129struct trusted_key_payload *p = NULL;130int ret;131132ret = key_payload_reserve(key, sizeof(*p));133if (ret < 0)134goto err;135p = kzalloc(sizeof(*p), GFP_KERNEL);136if (!p)137goto err;138139p->migratable = migratable;140err:141return p;142}143144/*145* trusted_instantiate - create a new trusted key146*147* Unseal an existing trusted blob or, for a new key, get a148* random key, then seal and create a trusted key-type key,149* adding it to the specified keyring.150*151* On success, return 0. Otherwise return errno.152*/153static int trusted_instantiate(struct key *key,154struct key_preparsed_payload *prep)155{156struct trusted_key_payload *payload = NULL;157size_t datalen = prep->datalen;158char *datablob, *orig_datablob;159int ret = 0;160int key_cmd;161size_t key_len;162163if (datalen == 0 || datalen > 32767 || !prep->data)164return -EINVAL;165166orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);167if (!datablob)168return -ENOMEM;169memcpy(datablob, prep->data, datalen);170datablob[datalen] = '\0';171172payload = trusted_payload_alloc(key);173if (!payload) {174ret = -ENOMEM;175goto out;176}177178key_cmd = datablob_parse(&datablob, payload);179if (key_cmd < 0) {180ret = key_cmd;181goto out;182}183184dump_payload(payload);185186switch (key_cmd) {187case Opt_load:188ret = static_call(trusted_key_unseal)(payload, datablob);189dump_payload(payload);190if (ret < 0)191pr_info("key_unseal failed (%d)\n", ret);192break;193case Opt_new:194key_len = payload->key_len;195ret = static_call(trusted_key_get_random)(payload->key,196key_len);197if (ret < 0)198goto out;199200if (ret != key_len) {201pr_info("key_create failed (%d)\n", ret);202ret = -EIO;203goto out;204}205206ret = static_call(trusted_key_seal)(payload, datablob);207if (ret < 0)208pr_info("key_seal failed (%d)\n", ret);209break;210default:211ret = -EINVAL;212}213out:214kfree_sensitive(orig_datablob);215if (!ret)216rcu_assign_keypointer(key, payload);217else218kfree_sensitive(payload);219return ret;220}221222static void trusted_rcu_free(struct rcu_head *rcu)223{224struct trusted_key_payload *p;225226p = container_of(rcu, struct trusted_key_payload, rcu);227kfree_sensitive(p);228}229230/*231* trusted_update - reseal an existing key with new PCR values232*/233static int trusted_update(struct key *key, struct key_preparsed_payload *prep)234{235struct trusted_key_payload *p;236struct trusted_key_payload *new_p;237size_t datalen = prep->datalen;238char *datablob, *orig_datablob;239int ret = 0;240241if (key_is_negative(key))242return -ENOKEY;243p = key->payload.data[0];244if (!p->migratable)245return -EPERM;246if (datalen == 0 || datalen > 32767 || !prep->data)247return -EINVAL;248249orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);250if (!datablob)251return -ENOMEM;252253new_p = trusted_payload_alloc(key);254if (!new_p) {255ret = -ENOMEM;256goto out;257}258259memcpy(datablob, prep->data, datalen);260datablob[datalen] = '\0';261ret = datablob_parse(&datablob, new_p);262if (ret != Opt_update) {263ret = -EINVAL;264kfree_sensitive(new_p);265goto out;266}267268/* copy old key values, and reseal with new pcrs */269new_p->migratable = p->migratable;270new_p->key_len = p->key_len;271memcpy(new_p->key, p->key, p->key_len);272dump_payload(p);273dump_payload(new_p);274275ret = static_call(trusted_key_seal)(new_p, datablob);276if (ret < 0) {277pr_info("key_seal failed (%d)\n", ret);278kfree_sensitive(new_p);279goto out;280}281282rcu_assign_keypointer(key, new_p);283call_rcu(&p->rcu, trusted_rcu_free);284out:285kfree_sensitive(orig_datablob);286return ret;287}288289/*290* trusted_read - copy the sealed blob data to userspace in hex.291* On success, return to userspace the trusted key datablob size.292*/293static long trusted_read(const struct key *key, char *buffer,294size_t buflen)295{296const struct trusted_key_payload *p;297char *bufp;298int i;299300p = dereference_key_locked(key);301if (!p)302return -EINVAL;303304if (buffer && buflen >= 2 * p->blob_len) {305bufp = buffer;306for (i = 0; i < p->blob_len; i++)307bufp = hex_byte_pack(bufp, p->blob[i]);308}309return 2 * p->blob_len;310}311312/*313* trusted_destroy - clear and free the key's payload314*/315static void trusted_destroy(struct key *key)316{317kfree_sensitive(key->payload.data[0]);318}319320struct key_type key_type_trusted = {321.name = "trusted",322.instantiate = trusted_instantiate,323.update = trusted_update,324.destroy = trusted_destroy,325.describe = user_describe,326.read = trusted_read,327};328EXPORT_SYMBOL_GPL(key_type_trusted);329330static int kernel_get_random(unsigned char *key, size_t key_len)331{332return get_random_bytes_wait(key, key_len) ?: key_len;333}334335static int __init init_trusted(void)336{337int (*get_random)(unsigned char *key, size_t key_len);338int i, ret = 0;339340for (i = 0; i < ARRAY_SIZE(trusted_key_sources); i++) {341if (trusted_key_source &&342strncmp(trusted_key_source, trusted_key_sources[i].name,343strlen(trusted_key_sources[i].name)))344continue;345346/*347* We always support trusted.rng="kernel" and "default" as348* well as trusted.rng=$trusted.source if the trust source349* defines its own get_random callback.350*/351get_random = trusted_key_sources[i].ops->get_random;352if (trusted_rng && strcmp(trusted_rng, "default")) {353if (!strcmp(trusted_rng, "kernel")) {354get_random = kernel_get_random;355} else if (strcmp(trusted_rng, trusted_key_sources[i].name) ||356!get_random) {357pr_warn("Unsupported RNG. Supported: kernel");358if (get_random)359pr_cont(", %s", trusted_key_sources[i].name);360pr_cont(", default\n");361return -EINVAL;362}363}364365if (!get_random)366get_random = kernel_get_random;367368ret = trusted_key_sources[i].ops->init();369if (!ret) {370static_call_update(trusted_key_seal, trusted_key_sources[i].ops->seal);371static_call_update(trusted_key_unseal, trusted_key_sources[i].ops->unseal);372static_call_update(trusted_key_get_random, get_random);373374trusted_key_exit = trusted_key_sources[i].ops->exit;375migratable = trusted_key_sources[i].ops->migratable;376}377378if (!ret || ret != -ENODEV)379break;380}381382/*383* encrypted_keys.ko depends on successful load of this module even if384* trusted key implementation is not found.385*/386if (ret == -ENODEV)387return 0;388389return ret;390}391392static void __exit cleanup_trusted(void)393{394if (trusted_key_exit)395(*trusted_key_exit)();396}397398late_initcall(init_trusted);399module_exit(cleanup_trusted);400401MODULE_DESCRIPTION("Trusted Key type");402MODULE_LICENSE("GPL");403404405