Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/keys/trusted-keys/trusted_caam.c
51031 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2021 Pengutronix, Ahmad Fatoum <[email protected]>
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
14
static struct caam_blob_priv *blobifier;
15
16
#define KEYMOD "SECURE_KEY"
17
18
static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN);
19
static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN);
20
21
enum {
22
opt_err,
23
opt_key_enc_algo,
24
};
25
26
static 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
32
static 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
37
static inline void dump_options(const struct caam_pkey_info *pkey_info)
38
{
39
}
40
#endif
41
42
static 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
76
static 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
92
static 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
128
static 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
161
static 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
176
static void trusted_caam_exit(void)
177
{
178
unregister_key_type(&key_type_trusted);
179
caam_blob_gen_exit(blobifier);
180
}
181
182
struct 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
};
189
190