File Index
Files and directories
Sign in
FILE

trusted_caam.c

File preview with syntax highlighting.

linux-6.19.14/security/keys/trusted-keys/trusted_caam.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
  4 * Copyright 2025 NXP
  5 */
  6
  7#include <keys/trusted_caam.h>
  8#include <keys/trusted-type.h>
  9#include <linux/build_bug.h>
 10#include <linux/key-type.h>
 11#include <linux/parser.h>
 12#include <soc/fsl/caam-blob.h>
 13
 14static struct caam_blob_priv *blobifier;
 15
 16#define KEYMOD "SECURE_KEY"
 17
 18static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN);
 19static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN);
 20
 21enum {
 22	opt_err,
 23	opt_key_enc_algo,
 24};
 25
 26static const match_table_t key_tokens = {
 27	{opt_key_enc_algo, "key_enc_algo=%s"},
 28	{opt_err, NULL}
 29};
 30
 31#ifdef CAAM_DEBUG
 32static inline void dump_options(const struct caam_pkey_info *pkey_info)
 33{
 34	pr_info("key encryption algo %d\n", pkey_info->key_enc_algo);
 35}
 36#else
 37static inline void dump_options(const struct caam_pkey_info *pkey_info)
 38{
 39}
 40#endif
 41
 42static int get_pkey_options(char *c,
 43			    struct caam_pkey_info *pkey_info)
 44{
 45	substring_t args[MAX_OPT_ARGS];
 46	unsigned long token_mask = 0;
 47	u16 key_enc_algo;
 48	char *p = c;
 49	int token;
 50	int res;
 51
 52	if (!c)
 53		return 0;
 54
 55	while ((p = strsep(&c, " \t"))) {
 56		if (*p == '\0' || *p == ' ' || *p == '\t')
 57			continue;
 58		token = match_token(p, key_tokens, args);
 59		if (test_and_set_bit(token, &token_mask))
 60			return -EINVAL;
 61
 62		switch (token) {
 63		case opt_key_enc_algo:
 64			res = kstrtou16(args[0].from, 16, &key_enc_algo);
 65			if (res < 0)
 66				return -EINVAL;
 67			pkey_info->key_enc_algo = key_enc_algo;
 68			break;
 69		default:
 70			return -EINVAL;
 71		}
 72	}
 73	return 0;
 74}
 75
 76static bool is_key_pkey(char **datablob)
 77{
 78	char *c = NULL;
 79
 80	do {
 81		/* Second argument onwards,
 82		 * determine if tied to HW
 83		 */
 84		c = strsep(datablob, " \t");
 85		if (c && (strcmp(c, "pk") == 0))
 86			return true;
 87	} while (c);
 88
 89	return false;
 90}
 91
 92static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob)
 93{
 94	int ret;
 95	struct caam_blob_info info = {
 96		.input  = p->key,  .input_len   = p->key_len,
 97		.output = p->blob, .output_len  = MAX_BLOB_SIZE,
 98		.key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1,
 99	};
100
101	/*
102	 * If it is to be treated as protected key,
103	 * read next arguments too.
104	 */
105	if (is_key_pkey(&datablob)) {
106		info.pkey_info.plain_key_sz = p->key_len;
107		info.pkey_info.is_pkey = 1;
108		ret = get_pkey_options(datablob, &info.pkey_info);
109		if (ret < 0)
110			return 0;
111		dump_options(&info.pkey_info);
112	}
113
114	ret = caam_encap_blob(blobifier, &info);
115	if (ret)
116		return ret;
117
118	p->blob_len = info.output_len;
119	if (info.pkey_info.is_pkey) {
120		p->key_len = p->blob_len + sizeof(struct caam_pkey_info);
121		memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info));
122		memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len);
123	}
124
125	return 0;
126}
127
128static int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob)
129{
130	int ret;
131	struct caam_blob_info info = {
132		.input   = p->blob,  .input_len  = p->blob_len,
133		.output  = p->key,   .output_len = MAX_KEY_SIZE,
134		.key_mod = KEYMOD,  .key_mod_len = sizeof(KEYMOD) - 1,
135	};
136
137	if (is_key_pkey(&datablob)) {
138		info.pkey_info.plain_key_sz = p->blob_len - CAAM_BLOB_OVERHEAD;
139		info.pkey_info.is_pkey = 1;
140		ret = get_pkey_options(datablob, &info.pkey_info);
141		if (ret < 0)
142			return 0;
143		dump_options(&info.pkey_info);
144
145		p->key_len = p->blob_len + sizeof(struct caam_pkey_info);
146		memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info));
147		memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len);
148
149		return 0;
150	}
151
152	ret = caam_decap_blob(blobifier, &info);
153	if (ret)
154		return ret;
155
156	p->key_len = info.output_len;
157
158	return 0;
159}
160
161static int trusted_caam_init(void)
162{
163	int ret;
164
165	blobifier = caam_blob_gen_init();
166	if (IS_ERR(blobifier))
167		return PTR_ERR(blobifier);
168
169	ret = register_key_type(&key_type_trusted);
170	if (ret)
171		caam_blob_gen_exit(blobifier);
172
173	return ret;
174}
175
176static void trusted_caam_exit(void)
177{
178	unregister_key_type(&key_type_trusted);
179	caam_blob_gen_exit(blobifier);
180}
181
182struct trusted_key_ops trusted_key_caam_ops = {
183	.migratable = 0, /* non-migratable */
184	.init = trusted_caam_init,
185	.seal = trusted_caam_seal,
186	.unseal = trusted_caam_unseal,
187	.exit = trusted_caam_exit,
188};
~/ Read-only file preview.