Path: blob/master/security/keys/trusted-keys/trusted_caam.c
51031 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2021 Pengutronix, Ahmad Fatoum <[email protected]>3* Copyright 2025 NXP4*/56#include <keys/trusted_caam.h>7#include <keys/trusted-type.h>8#include <linux/build_bug.h>9#include <linux/key-type.h>10#include <linux/parser.h>11#include <soc/fsl/caam-blob.h>1213static struct caam_blob_priv *blobifier;1415#define KEYMOD "SECURE_KEY"1617static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN);18static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN);1920enum {21opt_err,22opt_key_enc_algo,23};2425static const match_table_t key_tokens = {26{opt_key_enc_algo, "key_enc_algo=%s"},27{opt_err, NULL}28};2930#ifdef CAAM_DEBUG31static inline void dump_options(const struct caam_pkey_info *pkey_info)32{33pr_info("key encryption algo %d\n", pkey_info->key_enc_algo);34}35#else36static inline void dump_options(const struct caam_pkey_info *pkey_info)37{38}39#endif4041static int get_pkey_options(char *c,42struct caam_pkey_info *pkey_info)43{44substring_t args[MAX_OPT_ARGS];45unsigned long token_mask = 0;46u16 key_enc_algo;47char *p = c;48int token;49int res;5051if (!c)52return 0;5354while ((p = strsep(&c, " \t"))) {55if (*p == '\0' || *p == ' ' || *p == '\t')56continue;57token = match_token(p, key_tokens, args);58if (test_and_set_bit(token, &token_mask))59return -EINVAL;6061switch (token) {62case opt_key_enc_algo:63res = kstrtou16(args[0].from, 16, &key_enc_algo);64if (res < 0)65return -EINVAL;66pkey_info->key_enc_algo = key_enc_algo;67break;68default:69return -EINVAL;70}71}72return 0;73}7475static bool is_key_pkey(char **datablob)76{77char *c = NULL;7879do {80/* Second argument onwards,81* determine if tied to HW82*/83c = strsep(datablob, " \t");84if (c && (strcmp(c, "pk") == 0))85return true;86} while (c);8788return false;89}9091static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob)92{93int ret;94struct caam_blob_info info = {95.input = p->key, .input_len = p->key_len,96.output = p->blob, .output_len = MAX_BLOB_SIZE,97.key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1,98};99100/*101* If it is to be treated as protected key,102* read next arguments too.103*/104if (is_key_pkey(&datablob)) {105info.pkey_info.plain_key_sz = p->key_len;106info.pkey_info.is_pkey = 1;107ret = get_pkey_options(datablob, &info.pkey_info);108if (ret < 0)109return 0;110dump_options(&info.pkey_info);111}112113ret = caam_encap_blob(blobifier, &info);114if (ret)115return ret;116117p->blob_len = info.output_len;118if (info.pkey_info.is_pkey) {119p->key_len = p->blob_len + sizeof(struct caam_pkey_info);120memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info));121memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len);122}123124return 0;125}126127static int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob)128{129int ret;130struct caam_blob_info info = {131.input = p->blob, .input_len = p->blob_len,132.output = p->key, .output_len = MAX_KEY_SIZE,133.key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1,134};135136if (is_key_pkey(&datablob)) {137info.pkey_info.plain_key_sz = p->blob_len - CAAM_BLOB_OVERHEAD;138info.pkey_info.is_pkey = 1;139ret = get_pkey_options(datablob, &info.pkey_info);140if (ret < 0)141return 0;142dump_options(&info.pkey_info);143144p->key_len = p->blob_len + sizeof(struct caam_pkey_info);145memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info));146memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len);147148return 0;149}150151ret = caam_decap_blob(blobifier, &info);152if (ret)153return ret;154155p->key_len = info.output_len;156157return 0;158}159160static int trusted_caam_init(void)161{162int ret;163164blobifier = caam_blob_gen_init();165if (IS_ERR(blobifier))166return PTR_ERR(blobifier);167168ret = register_key_type(&key_type_trusted);169if (ret)170caam_blob_gen_exit(blobifier);171172return ret;173}174175static void trusted_caam_exit(void)176{177unregister_key_type(&key_type_trusted);178caam_blob_gen_exit(blobifier);179}180181struct trusted_key_ops trusted_key_caam_ops = {182.migratable = 0, /* non-migratable */183.init = trusted_caam_init,184.seal = trusted_caam_seal,185.unseal = trusted_caam_unseal,186.exit = trusted_caam_exit,187};188189190