Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/keys/trusted-keys/trusted_dcp.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2021 sigma star gmbh
4
*/
5
6
#include <crypto/aead.h>
7
#include <crypto/aes.h>
8
#include <crypto/algapi.h>
9
#include <crypto/gcm.h>
10
#include <crypto/skcipher.h>
11
#include <keys/trusted-type.h>
12
#include <linux/key-type.h>
13
#include <linux/module.h>
14
#include <linux/printk.h>
15
#include <linux/random.h>
16
#include <linux/scatterlist.h>
17
#include <soc/fsl/dcp.h>
18
19
#define DCP_BLOB_VERSION 1
20
#define DCP_BLOB_AUTHLEN 16
21
22
/**
23
* DOC: dcp blob format
24
*
25
* The Data Co-Processor (DCP) provides hardware-bound AES keys using its
26
* AES encryption engine only. It does not provide direct key sealing/unsealing.
27
* To make DCP hardware encryption keys usable as trust source, we define
28
* our own custom format that uses a hardware-bound key to secure the sealing
29
* key stored in the key blob.
30
*
31
* Whenever a new trusted key using DCP is generated, we generate a random 128-bit
32
* blob encryption key (BEK) and 128-bit nonce. The BEK and nonce are used to
33
* encrypt the trusted key payload using AES-128-GCM.
34
*
35
* The BEK itself is encrypted using the hardware-bound key using the DCP's AES
36
* encryption engine with AES-128-ECB. The encrypted BEK, generated nonce,
37
* BEK-encrypted payload and authentication tag make up the blob format together
38
* with a version number, payload length and authentication tag.
39
*/
40
41
/**
42
* struct dcp_blob_fmt - DCP BLOB format.
43
*
44
* @fmt_version: Format version, currently being %1.
45
* @blob_key: Random AES 128 key which is used to encrypt @payload,
46
* @blob_key itself is encrypted with OTP or UNIQUE device key in
47
* AES-128-ECB mode by DCP.
48
* @nonce: Random nonce used for @payload encryption.
49
* @payload_len: Length of the plain text @payload.
50
* @payload: The payload itself, encrypted using AES-128-GCM and @blob_key,
51
* GCM auth tag of size DCP_BLOB_AUTHLEN is attached at the end of it.
52
*
53
* The total size of a DCP BLOB is sizeof(struct dcp_blob_fmt) + @payload_len +
54
* DCP_BLOB_AUTHLEN.
55
*/
56
struct dcp_blob_fmt {
57
__u8 fmt_version;
58
__u8 blob_key[AES_KEYSIZE_128];
59
__u8 nonce[AES_KEYSIZE_128];
60
__le32 payload_len;
61
__u8 payload[];
62
} __packed;
63
64
static bool use_otp_key;
65
module_param_named(dcp_use_otp_key, use_otp_key, bool, 0);
66
MODULE_PARM_DESC(dcp_use_otp_key, "Use OTP instead of UNIQUE key for sealing");
67
68
static bool skip_zk_test;
69
module_param_named(dcp_skip_zk_test, skip_zk_test, bool, 0);
70
MODULE_PARM_DESC(dcp_skip_zk_test, "Don't test whether device keys are zero'ed");
71
72
static unsigned int calc_blob_len(unsigned int payload_len)
73
{
74
return sizeof(struct dcp_blob_fmt) + payload_len + DCP_BLOB_AUTHLEN;
75
}
76
77
static int do_dcp_crypto(u8 *in, u8 *out, bool do_encrypt)
78
{
79
struct skcipher_request *req = NULL;
80
struct scatterlist src_sg, dst_sg;
81
struct crypto_skcipher *tfm;
82
u8 paes_key[DCP_PAES_KEYSIZE];
83
DECLARE_CRYPTO_WAIT(wait);
84
int res = 0;
85
86
if (use_otp_key)
87
paes_key[0] = DCP_PAES_KEY_OTP;
88
else
89
paes_key[0] = DCP_PAES_KEY_UNIQUE;
90
91
tfm = crypto_alloc_skcipher("ecb-paes-dcp", CRYPTO_ALG_INTERNAL,
92
CRYPTO_ALG_INTERNAL);
93
if (IS_ERR(tfm)) {
94
res = PTR_ERR(tfm);
95
tfm = NULL;
96
goto out;
97
}
98
99
req = skcipher_request_alloc(tfm, GFP_NOFS);
100
if (!req) {
101
res = -ENOMEM;
102
goto out;
103
}
104
105
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
106
CRYPTO_TFM_REQ_MAY_SLEEP,
107
crypto_req_done, &wait);
108
res = crypto_skcipher_setkey(tfm, paes_key, sizeof(paes_key));
109
if (res < 0)
110
goto out;
111
112
sg_init_one(&src_sg, in, AES_KEYSIZE_128);
113
sg_init_one(&dst_sg, out, AES_KEYSIZE_128);
114
skcipher_request_set_crypt(req, &src_sg, &dst_sg, AES_KEYSIZE_128,
115
NULL);
116
117
if (do_encrypt)
118
res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
119
else
120
res = crypto_wait_req(crypto_skcipher_decrypt(req), &wait);
121
122
out:
123
skcipher_request_free(req);
124
crypto_free_skcipher(tfm);
125
126
return res;
127
}
128
129
static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce,
130
bool do_encrypt)
131
{
132
struct aead_request *aead_req = NULL;
133
struct scatterlist src_sg, dst_sg;
134
struct crypto_aead *aead;
135
int ret;
136
DECLARE_CRYPTO_WAIT(wait);
137
138
aead = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
139
if (IS_ERR(aead)) {
140
ret = PTR_ERR(aead);
141
goto out;
142
}
143
144
ret = crypto_aead_setauthsize(aead, DCP_BLOB_AUTHLEN);
145
if (ret < 0) {
146
pr_err("Can't set crypto auth tag len: %d\n", ret);
147
goto free_aead;
148
}
149
150
aead_req = aead_request_alloc(aead, GFP_KERNEL);
151
if (!aead_req) {
152
ret = -ENOMEM;
153
goto free_aead;
154
}
155
156
sg_init_one(&src_sg, in, len);
157
if (do_encrypt) {
158
/*
159
* If we encrypt our buffer has extra space for the auth tag.
160
*/
161
sg_init_one(&dst_sg, out, len + DCP_BLOB_AUTHLEN);
162
} else {
163
sg_init_one(&dst_sg, out, len);
164
}
165
166
aead_request_set_crypt(aead_req, &src_sg, &dst_sg, len, nonce);
167
aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP,
168
crypto_req_done, &wait);
169
aead_request_set_ad(aead_req, 0);
170
171
if (crypto_aead_setkey(aead, key, AES_KEYSIZE_128)) {
172
pr_err("Can't set crypto AEAD key\n");
173
ret = -EINVAL;
174
goto free_req;
175
}
176
177
if (do_encrypt)
178
ret = crypto_wait_req(crypto_aead_encrypt(aead_req), &wait);
179
else
180
ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &wait);
181
182
free_req:
183
aead_request_free(aead_req);
184
free_aead:
185
crypto_free_aead(aead);
186
out:
187
return ret;
188
}
189
190
static int decrypt_blob_key(u8 *encrypted_key, u8 *plain_key)
191
{
192
return do_dcp_crypto(encrypted_key, plain_key, false);
193
}
194
195
static int encrypt_blob_key(u8 *plain_key, u8 *encrypted_key)
196
{
197
return do_dcp_crypto(plain_key, encrypted_key, true);
198
}
199
200
static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob)
201
{
202
struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob;
203
int blen, ret;
204
u8 *plain_blob_key;
205
206
blen = calc_blob_len(p->key_len);
207
if (blen > MAX_BLOB_SIZE)
208
return -E2BIG;
209
210
plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL);
211
if (!plain_blob_key)
212
return -ENOMEM;
213
214
b->fmt_version = DCP_BLOB_VERSION;
215
get_random_bytes(b->nonce, AES_KEYSIZE_128);
216
get_random_bytes(plain_blob_key, AES_KEYSIZE_128);
217
218
ret = do_aead_crypto(p->key, b->payload, p->key_len, plain_blob_key,
219
b->nonce, true);
220
if (ret) {
221
pr_err("Unable to encrypt blob payload: %i\n", ret);
222
goto out;
223
}
224
225
ret = encrypt_blob_key(plain_blob_key, b->blob_key);
226
if (ret) {
227
pr_err("Unable to encrypt blob key: %i\n", ret);
228
goto out;
229
}
230
231
put_unaligned_le32(p->key_len, &b->payload_len);
232
p->blob_len = blen;
233
ret = 0;
234
235
out:
236
memzero_explicit(plain_blob_key, AES_KEYSIZE_128);
237
kfree(plain_blob_key);
238
239
return ret;
240
}
241
242
static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob)
243
{
244
struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob;
245
int blen, ret;
246
u8 *plain_blob_key = NULL;
247
248
if (b->fmt_version != DCP_BLOB_VERSION) {
249
pr_err("DCP blob has bad version: %i, expected %i\n",
250
b->fmt_version, DCP_BLOB_VERSION);
251
ret = -EINVAL;
252
goto out;
253
}
254
255
p->key_len = le32_to_cpu(b->payload_len);
256
blen = calc_blob_len(p->key_len);
257
if (blen != p->blob_len) {
258
pr_err("DCP blob has bad length: %i != %i\n", blen,
259
p->blob_len);
260
ret = -EINVAL;
261
goto out;
262
}
263
264
plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL);
265
if (!plain_blob_key) {
266
ret = -ENOMEM;
267
goto out;
268
}
269
270
ret = decrypt_blob_key(b->blob_key, plain_blob_key);
271
if (ret) {
272
pr_err("Unable to decrypt blob key: %i\n", ret);
273
goto out;
274
}
275
276
ret = do_aead_crypto(b->payload, p->key, p->key_len + DCP_BLOB_AUTHLEN,
277
plain_blob_key, b->nonce, false);
278
if (ret) {
279
pr_err("Unwrap of DCP payload failed: %i\n", ret);
280
goto out;
281
}
282
283
ret = 0;
284
out:
285
if (plain_blob_key) {
286
memzero_explicit(plain_blob_key, AES_KEYSIZE_128);
287
kfree(plain_blob_key);
288
}
289
290
return ret;
291
}
292
293
static int test_for_zero_key(void)
294
{
295
/*
296
* Encrypting a plaintext of all 0x55 bytes will yield
297
* this ciphertext in case the DCP test key is used.
298
*/
299
static const u8 bad[] = {0x9a, 0xda, 0xe0, 0x54, 0xf6, 0x3d, 0xfa, 0xff,
300
0x5e, 0xa1, 0x8e, 0x45, 0xed, 0xf6, 0xea, 0x6f};
301
void *buf = NULL;
302
int ret = 0;
303
304
if (skip_zk_test)
305
goto out;
306
307
buf = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL);
308
if (!buf) {
309
ret = -ENOMEM;
310
goto out;
311
}
312
313
memset(buf, 0x55, AES_BLOCK_SIZE);
314
315
ret = do_dcp_crypto(buf, buf, true);
316
if (ret)
317
goto out;
318
319
if (memcmp(buf, bad, AES_BLOCK_SIZE) == 0) {
320
pr_warn("Device neither in secure nor trusted mode!\n");
321
ret = -EINVAL;
322
}
323
out:
324
kfree(buf);
325
return ret;
326
}
327
328
static int trusted_dcp_init(void)
329
{
330
int ret;
331
332
if (use_otp_key)
333
pr_info("Using DCP OTP key\n");
334
335
ret = test_for_zero_key();
336
if (ret) {
337
pr_warn("Test for zero'ed keys failed: %i\n", ret);
338
339
return -EINVAL;
340
}
341
342
return register_key_type(&key_type_trusted);
343
}
344
345
static void trusted_dcp_exit(void)
346
{
347
unregister_key_type(&key_type_trusted);
348
}
349
350
struct trusted_key_ops dcp_trusted_key_ops = {
351
.exit = trusted_dcp_exit,
352
.init = trusted_dcp_init,
353
.seal = trusted_dcp_seal,
354
.unseal = trusted_dcp_unseal,
355
.migratable = 0,
356
};
357
358