Path: blob/master/security/keys/trusted-keys/trusted_core.c
26442 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 <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>2627static char *trusted_rng = "default";28module_param_named(rng, trusted_rng, charp, 0);29MODULE_PARM_DESC(rng, "Select trusted key RNG");3031static char *trusted_key_source;32module_param_named(source, trusted_key_source, charp, 0);33MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam or dcp)");3435static const struct trusted_key_source trusted_key_sources[] = {36#if defined(CONFIG_TRUSTED_KEYS_TPM)37{ "tpm", &trusted_key_tpm_ops },38#endif39#if defined(CONFIG_TRUSTED_KEYS_TEE)40{ "tee", &trusted_key_tee_ops },41#endif42#if defined(CONFIG_TRUSTED_KEYS_CAAM)43{ "caam", &trusted_key_caam_ops },44#endif45#if defined(CONFIG_TRUSTED_KEYS_DCP)46{ "dcp", &dcp_trusted_key_ops },47#endif48};4950DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal);51DEFINE_STATIC_CALL_NULL(trusted_key_unseal,52*trusted_key_sources[0].ops->unseal);53DEFINE_STATIC_CALL_NULL(trusted_key_get_random,54*trusted_key_sources[0].ops->get_random);55static void (*trusted_key_exit)(void);56static unsigned char migratable;5758enum {59Opt_err,60Opt_new, Opt_load, Opt_update,61};6263static const match_table_t key_tokens = {64{Opt_new, "new"},65{Opt_load, "load"},66{Opt_update, "update"},67{Opt_err, NULL}68};6970/*71* datablob_parse - parse the keyctl data and fill in the72* payload structure73*74* On success returns 0, otherwise -EINVAL.75*/76static int datablob_parse(char **datablob, struct trusted_key_payload *p)77{78substring_t args[MAX_OPT_ARGS];79long keylen;80int ret = -EINVAL;81int key_cmd;82char *c;8384/* main command */85c = strsep(datablob, " \t");86if (!c)87return -EINVAL;88key_cmd = match_token(c, key_tokens, args);89switch (key_cmd) {90case Opt_new:91/* first argument is key size */92c = strsep(datablob, " \t");93if (!c)94return -EINVAL;95ret = kstrtol(c, 10, &keylen);96if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)97return -EINVAL;98p->key_len = keylen;99ret = Opt_new;100break;101case Opt_load:102/* first argument is sealed blob */103c = strsep(datablob, " \t");104if (!c)105return -EINVAL;106p->blob_len = strlen(c) / 2;107if (p->blob_len > MAX_BLOB_SIZE)108return -EINVAL;109ret = hex2bin(p->blob, c, p->blob_len);110if (ret < 0)111return -EINVAL;112ret = Opt_load;113break;114case Opt_update:115ret = Opt_update;116break;117case Opt_err:118return -EINVAL;119}120return ret;121}122123static struct trusted_key_payload *trusted_payload_alloc(struct key *key)124{125struct trusted_key_payload *p = NULL;126int ret;127128ret = key_payload_reserve(key, sizeof(*p));129if (ret < 0)130goto err;131p = kzalloc(sizeof(*p), GFP_KERNEL);132if (!p)133goto err;134135p->migratable = migratable;136err:137return p;138}139140/*141* trusted_instantiate - create a new trusted key142*143* Unseal an existing trusted blob or, for a new key, get a144* random key, then seal and create a trusted key-type key,145* adding it to the specified keyring.146*147* On success, return 0. Otherwise return errno.148*/149static int trusted_instantiate(struct key *key,150struct key_preparsed_payload *prep)151{152struct trusted_key_payload *payload = NULL;153size_t datalen = prep->datalen;154char *datablob, *orig_datablob;155int ret = 0;156int key_cmd;157size_t key_len;158159if (datalen <= 0 || datalen > 32767 || !prep->data)160return -EINVAL;161162orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);163if (!datablob)164return -ENOMEM;165memcpy(datablob, prep->data, datalen);166datablob[datalen] = '\0';167168payload = trusted_payload_alloc(key);169if (!payload) {170ret = -ENOMEM;171goto out;172}173174key_cmd = datablob_parse(&datablob, payload);175if (key_cmd < 0) {176ret = key_cmd;177goto out;178}179180dump_payload(payload);181182switch (key_cmd) {183case Opt_load:184ret = static_call(trusted_key_unseal)(payload, datablob);185dump_payload(payload);186if (ret < 0)187pr_info("key_unseal failed (%d)\n", ret);188break;189case Opt_new:190key_len = payload->key_len;191ret = static_call(trusted_key_get_random)(payload->key,192key_len);193if (ret < 0)194goto out;195196if (ret != key_len) {197pr_info("key_create failed (%d)\n", ret);198ret = -EIO;199goto out;200}201202ret = static_call(trusted_key_seal)(payload, datablob);203if (ret < 0)204pr_info("key_seal failed (%d)\n", ret);205break;206default:207ret = -EINVAL;208}209out:210kfree_sensitive(orig_datablob);211if (!ret)212rcu_assign_keypointer(key, payload);213else214kfree_sensitive(payload);215return ret;216}217218static void trusted_rcu_free(struct rcu_head *rcu)219{220struct trusted_key_payload *p;221222p = container_of(rcu, struct trusted_key_payload, rcu);223kfree_sensitive(p);224}225226/*227* trusted_update - reseal an existing key with new PCR values228*/229static int trusted_update(struct key *key, struct key_preparsed_payload *prep)230{231struct trusted_key_payload *p;232struct trusted_key_payload *new_p;233size_t datalen = prep->datalen;234char *datablob, *orig_datablob;235int ret = 0;236237if (key_is_negative(key))238return -ENOKEY;239p = key->payload.data[0];240if (!p->migratable)241return -EPERM;242if (datalen <= 0 || datalen > 32767 || !prep->data)243return -EINVAL;244245orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);246if (!datablob)247return -ENOMEM;248249new_p = trusted_payload_alloc(key);250if (!new_p) {251ret = -ENOMEM;252goto out;253}254255memcpy(datablob, prep->data, datalen);256datablob[datalen] = '\0';257ret = datablob_parse(&datablob, new_p);258if (ret != Opt_update) {259ret = -EINVAL;260kfree_sensitive(new_p);261goto out;262}263264/* copy old key values, and reseal with new pcrs */265new_p->migratable = p->migratable;266new_p->key_len = p->key_len;267memcpy(new_p->key, p->key, p->key_len);268dump_payload(p);269dump_payload(new_p);270271ret = static_call(trusted_key_seal)(new_p, datablob);272if (ret < 0) {273pr_info("key_seal failed (%d)\n", ret);274kfree_sensitive(new_p);275goto out;276}277278rcu_assign_keypointer(key, new_p);279call_rcu(&p->rcu, trusted_rcu_free);280out:281kfree_sensitive(orig_datablob);282return ret;283}284285/*286* trusted_read - copy the sealed blob data to userspace in hex.287* On success, return to userspace the trusted key datablob size.288*/289static long trusted_read(const struct key *key, char *buffer,290size_t buflen)291{292const struct trusted_key_payload *p;293char *bufp;294int i;295296p = dereference_key_locked(key);297if (!p)298return -EINVAL;299300if (buffer && buflen >= 2 * p->blob_len) {301bufp = buffer;302for (i = 0; i < p->blob_len; i++)303bufp = hex_byte_pack(bufp, p->blob[i]);304}305return 2 * p->blob_len;306}307308/*309* trusted_destroy - clear and free the key's payload310*/311static void trusted_destroy(struct key *key)312{313kfree_sensitive(key->payload.data[0]);314}315316struct key_type key_type_trusted = {317.name = "trusted",318.instantiate = trusted_instantiate,319.update = trusted_update,320.destroy = trusted_destroy,321.describe = user_describe,322.read = trusted_read,323};324EXPORT_SYMBOL_GPL(key_type_trusted);325326static int kernel_get_random(unsigned char *key, size_t key_len)327{328return get_random_bytes_wait(key, key_len) ?: key_len;329}330331static int __init init_trusted(void)332{333int (*get_random)(unsigned char *key, size_t key_len);334int i, ret = 0;335336for (i = 0; i < ARRAY_SIZE(trusted_key_sources); i++) {337if (trusted_key_source &&338strncmp(trusted_key_source, trusted_key_sources[i].name,339strlen(trusted_key_sources[i].name)))340continue;341342/*343* We always support trusted.rng="kernel" and "default" as344* well as trusted.rng=$trusted.source if the trust source345* defines its own get_random callback.346*/347get_random = trusted_key_sources[i].ops->get_random;348if (trusted_rng && strcmp(trusted_rng, "default")) {349if (!strcmp(trusted_rng, "kernel")) {350get_random = kernel_get_random;351} else if (strcmp(trusted_rng, trusted_key_sources[i].name) ||352!get_random) {353pr_warn("Unsupported RNG. Supported: kernel");354if (get_random)355pr_cont(", %s", trusted_key_sources[i].name);356pr_cont(", default\n");357return -EINVAL;358}359}360361if (!get_random)362get_random = kernel_get_random;363364ret = trusted_key_sources[i].ops->init();365if (!ret) {366static_call_update(trusted_key_seal, trusted_key_sources[i].ops->seal);367static_call_update(trusted_key_unseal, trusted_key_sources[i].ops->unseal);368static_call_update(trusted_key_get_random, get_random);369370trusted_key_exit = trusted_key_sources[i].ops->exit;371migratable = trusted_key_sources[i].ops->migratable;372}373374if (!ret || ret != -ENODEV)375break;376}377378/*379* encrypted_keys.ko depends on successful load of this module even if380* trusted key implementation is not found.381*/382if (ret == -ENODEV)383return 0;384385return ret;386}387388static void __exit cleanup_trusted(void)389{390if (trusted_key_exit)391(*trusted_key_exit)();392}393394late_initcall(init_trusted);395module_exit(cleanup_trusted);396397MODULE_DESCRIPTION("Trusted Key type");398MODULE_LICENSE("GPL");399400401