OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From d2e808b0dcca1b5e850274f770775c355ae36c48 Mon Sep 17 00:00:00 2001 |
2 | From: Biwen Li <biwen.li@nxp.com> |
||
3 | Date: Tue, 30 Oct 2018 18:27:03 +0800 |
||
4 | Subject: [PATCH 34/40] platfrom-security: support layerscape |
||
5 | This is an integrated patch of platform-security for |
||
6 | layerscape |
||
7 | |||
8 | Signed-off-by: Sahil Malhotra <sahil.malhotra@nxp.com> |
||
9 | Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com> |
||
10 | Signed-off-by: Biwen Li <biwen.li@nxp.com> |
||
11 | --- |
||
12 | Documentation/security/keys/secure-key.rst | 67 ++ |
||
13 | MAINTAINERS | 12 + |
||
14 | drivers/tee/optee/Kconfig | 8 + |
||
15 | drivers/tee/optee/core.c | 2 +- |
||
16 | include/keys/secure-type.h | 33 + |
||
17 | security/keys/Kconfig | 11 + |
||
18 | security/keys/Makefile | 5 + |
||
19 | security/keys/encrypted-keys/Makefile | 2 + |
||
20 | security/keys/encrypted-keys/encrypted.c | 13 +- |
||
21 | security/keys/encrypted-keys/encrypted.h | 13 + |
||
22 | .../keys/encrypted-keys/masterkey_secure.c | 37 ++ |
||
23 | security/keys/secure_key.c | 339 ++++++++++ |
||
24 | security/keys/securekey_desc.c | 608 ++++++++++++++++++ |
||
25 | security/keys/securekey_desc.h | 141 ++++ |
||
26 | 14 files changed, 1288 insertions(+), 3 deletions(-) |
||
27 | create mode 100644 Documentation/security/keys/secure-key.rst |
||
28 | create mode 100644 include/keys/secure-type.h |
||
29 | create mode 100644 security/keys/encrypted-keys/masterkey_secure.c |
||
30 | create mode 100644 security/keys/secure_key.c |
||
31 | create mode 100644 security/keys/securekey_desc.c |
||
32 | create mode 100644 security/keys/securekey_desc.h |
||
33 | |||
34 | --- /dev/null |
||
35 | +++ b/Documentation/security/keys/secure-key.rst |
||
36 | @@ -0,0 +1,67 @@ |
||
37 | +========== |
||
38 | +Secure Key |
||
39 | +========== |
||
40 | + |
||
41 | +Secure key is the new type added to kernel key ring service. |
||
42 | +Secure key is a symmetric type key of minimum length 32 bytes |
||
43 | +and with maximum possible length to be 128 bytes. It is produced |
||
44 | +in kernel using the CAAM crypto engine. Userspace can only see |
||
45 | +the blob for the corresponding key. All the blobs are displayed |
||
46 | +or loaded in hex ascii. |
||
47 | + |
||
48 | +Secure key can be created on platforms which supports CAAM |
||
49 | +hardware block. Secure key can also be used as a master key to |
||
50 | +create the encrypted keys along with the existing key types in |
||
51 | +kernel. |
||
52 | + |
||
53 | +Secure key uses CAAM hardware to generate the key and blobify its |
||
54 | +content for userspace. Generated blobs are tied up with the hardware |
||
55 | +secret key stored in CAAM, hence the same blob will not be able to |
||
56 | +de-blobify with the different secret key on another machine. |
||
57 | + |
||
58 | +Usage:: |
||
59 | + |
||
60 | + keyctl add secure <name> "new <keylen>" <ring> |
||
61 | + keyctl load secure <name> "load <hex_blob>" <ring> |
||
62 | + keyctl print <key_id> |
||
63 | + |
||
64 | +"keyctl add secure" option will create the random data of the |
||
65 | +specified key len using CAAM and store it as a key in kernel. |
||
66 | +Key contents will be displayed as blobs to the user in hex ascii. |
||
67 | +User can input key len from 32 bytes to 128 bytes. |
||
68 | + |
||
69 | +"keyctl load secure" option will load the blob contents. In kernel, |
||
70 | +key will be deirved using input blob and CAAM, along with the secret |
||
71 | +key stored in CAAM. |
||
72 | + |
||
73 | +"keyctl print" will return the hex string of the blob corresponding to |
||
74 | +key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are |
||
75 | +the header bytes added by the CAAM. |
||
76 | + |
||
77 | +Example of secure key usage:: |
||
78 | + |
||
79 | +1. Create the secure key with name kmk-master of length 32 bytes:: |
||
80 | + |
||
81 | + $ keyctl add secure kmk-master "new 32" @u |
||
82 | + 46001928 |
||
83 | + |
||
84 | + $keyctl show |
||
85 | + Session Keyring |
||
86 | + 1030783626 --alswrv 0 65534 keyring: _uid_ses.0 |
||
87 | + 695927745 --alswrv 0 65534 \_ keyring: _uid.0 |
||
88 | + 46001928 --als-rv 0 0 \_ secure: kmk-master |
||
89 | + |
||
90 | +2. Print the blob contents for the kmk-master key:: |
||
91 | + |
||
92 | + $ keyctl print 46001928 |
||
93 | + d9743445b640f3d59c1670dddc0bc9c2 |
||
94 | + 34fc9aab7dd05c965e6120025012f029b |
||
95 | + 07faa4776c4f6ed02899e35a135531e9a |
||
96 | + 6e5c2b51132f9d5aef28f68738e658296 |
||
97 | + 3fe583177cfe50d2542b659a13039 |
||
98 | + |
||
99 | + $ keyctl pipe 46001928 > secure_key.blob |
||
100 | + |
||
101 | +3. Load the blob in the user key ring:: |
||
102 | + |
||
103 | + $ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u |
||
104 | --- a/MAINTAINERS |
||
105 | +++ b/MAINTAINERS |
||
106 | @@ -7645,6 +7645,18 @@ F: include/keys/trusted-type.h |
||
107 | F: security/keys/trusted.c |
||
108 | F: security/keys/trusted.h |
||
109 | |||
110 | +KEYS-SECURE |
||
111 | +M: Udit Agarwal <udit.agarwal@nxp.com> |
||
112 | +R: Sahil Malhotra <sahil.malhotra@nxp.com> |
||
113 | +L: linux-security-module@vger.kernel.org |
||
114 | +L: keyrings@vger.kernel.org |
||
115 | +S: Supported |
||
116 | +F: include/keys/secure-type.h |
||
117 | +F: security/keys/secure_key.c |
||
118 | +F: security/keys/securekey_desc.c |
||
119 | +F: security/keys/securekey_desc.h |
||
120 | +F: security/keys/encrypted-keys/masterkey_secure.c |
||
121 | + |
||
122 | KEYS/KEYRINGS: |
||
123 | M: David Howells <dhowells@redhat.com> |
||
124 | L: keyrings@vger.kernel.org |
||
125 | --- a/drivers/tee/optee/Kconfig |
||
126 | +++ b/drivers/tee/optee/Kconfig |
||
127 | @@ -5,3 +5,11 @@ config OPTEE |
||
128 | help |
||
129 | This implements the OP-TEE Trusted Execution Environment (TEE) |
||
130 | driver. |
||
131 | + |
||
132 | +config OPTEE_SHM_NUM_PRIV_PAGES |
||
133 | + int "Private Shared Memory Pages" |
||
134 | + default 1 |
||
135 | + depends on OPTEE |
||
136 | + help |
||
137 | + This sets the number of private shared memory pages to be |
||
138 | + used by OP-TEE TEE driver. |
||
139 | --- a/drivers/tee/optee/core.c |
||
140 | +++ b/drivers/tee/optee/core.c |
||
141 | @@ -31,7 +31,7 @@ |
||
142 | |||
143 | #define DRIVER_NAME "optee" |
||
144 | |||
145 | -#define OPTEE_SHM_NUM_PRIV_PAGES 1 |
||
146 | +#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES |
||
147 | |||
148 | /** |
||
149 | * optee_from_msg_param() - convert from OPTEE_MSG parameters to |
||
150 | --- /dev/null |
||
151 | +++ b/include/keys/secure-type.h |
||
152 | @@ -0,0 +1,33 @@ |
||
153 | +/* SPDX-License-Identifier: GPL-2.0 */ |
||
154 | +/* |
||
155 | + * Copyright (C) 2018 NXP. |
||
156 | + * |
||
157 | + */ |
||
158 | + |
||
159 | +#ifndef _KEYS_SECURE_TYPE_H |
||
160 | +#define _KEYS_SECURE_TYPE_H |
||
161 | + |
||
162 | +#include <linux/key.h> |
||
163 | +#include <linux/rcupdate.h> |
||
164 | + |
||
165 | +/* Minimum key size to be used is 32 bytes and maximum key size fixed |
||
166 | + * is 128 bytes. |
||
167 | + * Blob size to be kept is Maximum key size + blob header added by CAAM. |
||
168 | + */ |
||
169 | + |
||
170 | +#define MIN_KEY_SIZE 32 |
||
171 | +#define MAX_KEY_SIZE 128 |
||
172 | +#define BLOB_HEADER_SIZE 48 |
||
173 | + |
||
174 | +#define MAX_BLOB_SIZE (MAX_KEY_SIZE + BLOB_HEADER_SIZE) |
||
175 | + |
||
176 | +struct secure_key_payload { |
||
177 | + struct rcu_head rcu; |
||
178 | + unsigned int key_len; |
||
179 | + unsigned int blob_len; |
||
180 | + unsigned char key[MAX_KEY_SIZE + 1]; |
||
181 | + unsigned char blob[MAX_BLOB_SIZE]; |
||
182 | +}; |
||
183 | + |
||
184 | +extern struct key_type key_type_secure; |
||
185 | +#endif |
||
186 | --- a/security/keys/Kconfig |
||
187 | +++ b/security/keys/Kconfig |
||
188 | @@ -71,6 +71,17 @@ config TRUSTED_KEYS |
||
189 | |||
190 | If you are unsure as to whether this is required, answer N. |
||
191 | |||
192 | +config SECURE_KEYS |
||
193 | + tristate "SECURE_KEYS" |
||
194 | + depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR |
||
195 | + help |
||
196 | + This option provide support for creating secure-type key and blobs |
||
197 | + in kernel. Secure keys are random number symmetric keys generated |
||
198 | + from CAAM. The CAAM creates the blobs for the random key. |
||
199 | + Userspace will only be able to see the blob. |
||
200 | + |
||
201 | + If you are unsure as to whether this is required, answer N. |
||
202 | + |
||
203 | config ENCRYPTED_KEYS |
||
204 | tristate "ENCRYPTED KEYS" |
||
205 | depends on KEYS |
||
206 | --- a/security/keys/Makefile |
||
207 | +++ b/security/keys/Makefile |
||
208 | @@ -28,4 +28,9 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o |
||
209 | # |
||
210 | obj-$(CONFIG_BIG_KEYS) += big_key.o |
||
211 | obj-$(CONFIG_TRUSTED_KEYS) += trusted.o |
||
212 | +CFLAGS_secure_key.o += -I$(obj)/../../drivers/crypto/caam/ |
||
213 | +CFLAGS_securekey_desc.o += -I$(obj)/../../drivers/crypto/caam/ |
||
214 | +obj-$(CONFIG_SECURE_KEYS) += securekey.o |
||
215 | +securekey-y := securekey_desc.o \ |
||
216 | + secure_key.o |
||
217 | obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ |
||
218 | --- a/security/keys/encrypted-keys/Makefile |
||
219 | +++ b/security/keys/encrypted-keys/Makefile |
||
220 | @@ -7,5 +7,7 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypte |
||
221 | |||
222 | encrypted-keys-y := encrypted.o ecryptfs_format.o |
||
223 | masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o |
||
224 | +masterkey-$(CONFIG_SECURE_KEYS) := masterkey_secure.o |
||
225 | masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o |
||
226 | +masterkey-$(CONFIG_SECURE_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_secure.o |
||
227 | encrypted-keys-y += $(masterkey-y) $(masterkey-m-m) |
||
228 | --- a/security/keys/encrypted-keys/encrypted.c |
||
229 | +++ b/security/keys/encrypted-keys/encrypted.c |
||
230 | @@ -39,6 +39,7 @@ |
||
231 | #include "ecryptfs_format.h" |
||
232 | |||
233 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; |
||
234 | +static const char KEY_SECURE_PREFIX[] = "secure:"; |
||
235 | static const char KEY_USER_PREFIX[] = "user:"; |
||
236 | static const char hash_alg[] = "sha256"; |
||
237 | static const char hmac_alg[] = "hmac(sha256)"; |
||
238 | @@ -49,6 +50,7 @@ static unsigned int ivsize; |
||
239 | static int blksize; |
||
240 | |||
241 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) |
||
242 | +#define KEY_SECURE_PREFIX_LEN (sizeof(KEY_SECURE_PREFIX) - 1) |
||
243 | #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1) |
||
244 | #define KEY_ECRYPTFS_DESC_LEN 16 |
||
245 | #define HASH_SIZE SHA256_DIGEST_SIZE |
||
246 | @@ -125,7 +127,7 @@ static int valid_ecryptfs_desc(const cha |
||
247 | /* |
||
248 | * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key |
||
249 | * |
||
250 | - * key-type:= "trusted:" | "user:" |
||
251 | + * key-type:= "trusted:" | "user:" | "secure:" |
||
252 | * desc:= master-key description |
||
253 | * |
||
254 | * Verify that 'key-type' is valid and that 'desc' exists. On key update, |
||
255 | @@ -140,6 +142,8 @@ static int valid_master_desc(const char |
||
256 | |||
257 | if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) |
||
258 | prefix_len = KEY_TRUSTED_PREFIX_LEN; |
||
259 | + else if (!strncmp(new_desc, KEY_SECURE_PREFIX, KEY_SECURE_PREFIX_LEN)) |
||
260 | + prefix_len = KEY_SECURE_PREFIX_LEN; |
||
261 | else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) |
||
262 | prefix_len = KEY_USER_PREFIX_LEN; |
||
263 | else |
||
264 | @@ -358,7 +362,7 @@ static int calc_hmac(u8 *digest, const u |
||
265 | |||
266 | enum derived_key_type { ENC_KEY, AUTH_KEY }; |
||
267 | |||
268 | -/* Derive authentication/encryption key from trusted key */ |
||
269 | +/* Derive authentication/encryption key from trusted/secure key */ |
||
270 | static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, |
||
271 | const u8 *master_key, size_t master_keylen) |
||
272 | { |
||
273 | @@ -429,6 +433,11 @@ static struct key *request_master_key(st |
||
274 | mkey = request_trusted_key(epayload->master_desc + |
||
275 | KEY_TRUSTED_PREFIX_LEN, |
||
276 | master_key, master_keylen); |
||
277 | + } else if (!strncmp(epayload->master_desc, KEY_SECURE_PREFIX, |
||
278 | + KEY_SECURE_PREFIX_LEN)) { |
||
279 | + mkey = request_secure_key(epayload->master_desc + |
||
280 | + KEY_SECURE_PREFIX_LEN, |
||
281 | + master_key, master_keylen); |
||
282 | } else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX, |
||
283 | KEY_USER_PREFIX_LEN)) { |
||
284 | mkey = request_user_key(epayload->master_desc + |
||
285 | --- a/security/keys/encrypted-keys/encrypted.h |
||
286 | +++ b/security/keys/encrypted-keys/encrypted.h |
||
287 | @@ -16,6 +16,19 @@ static inline struct key *request_truste |
||
288 | } |
||
289 | #endif |
||
290 | |||
291 | +#if defined(CONFIG_SECURE_KEYS) |
||
292 | +extern struct key *request_secure_key(const char *secure_desc, |
||
293 | + const u8 **master_key, |
||
294 | + size_t *master_keylen); |
||
295 | +#else |
||
296 | +static inline struct key *request_secure_key(const char *secure_desc, |
||
297 | + const u8 **master_key, |
||
298 | + size_t *master_keylen) |
||
299 | +{ |
||
300 | + return ERR_PTR(-EOPNOTSUPP); |
||
301 | +} |
||
302 | +#endif |
||
303 | + |
||
304 | #if ENCRYPTED_DEBUG |
||
305 | static inline void dump_master_key(const u8 *master_key, size_t master_keylen) |
||
306 | { |
||
307 | --- /dev/null |
||
308 | +++ b/security/keys/encrypted-keys/masterkey_secure.c |
||
309 | @@ -0,0 +1,37 @@ |
||
310 | +// SPDX-License-Identifier: GPL-2.0 |
||
311 | +/* |
||
312 | + * Copyright (C) 2018 NXP. |
||
313 | + * |
||
314 | + */ |
||
315 | + |
||
316 | +#include <linux/uaccess.h> |
||
317 | +#include <linux/module.h> |
||
318 | +#include <linux/err.h> |
||
319 | +#include <keys/secure-type.h> |
||
320 | +#include <keys/encrypted-type.h> |
||
321 | +#include "encrypted.h" |
||
322 | + |
||
323 | +/* |
||
324 | + * request_secure_key - request the secure key |
||
325 | + * |
||
326 | + * Secure keys and their blobs are derived from CAAM hardware. |
||
327 | + * Userspace manages secure key-type data, but key data is not |
||
328 | + * visible in plain form. It is presented as blobs. |
||
329 | + */ |
||
330 | +struct key *request_secure_key(const char *secure_desc, |
||
331 | + const u8 **master_key, size_t *master_keylen) |
||
332 | +{ |
||
333 | + struct secure_key_payload *spayload; |
||
334 | + struct key *skey; |
||
335 | + |
||
336 | + skey = request_key(&key_type_secure, secure_desc, NULL); |
||
337 | + if (IS_ERR(skey)) |
||
338 | + goto error; |
||
339 | + |
||
340 | + down_read(&skey->sem); |
||
341 | + spayload = skey->payload.data[0]; |
||
342 | + *master_key = spayload->key; |
||
343 | + *master_keylen = spayload->key_len; |
||
344 | +error: |
||
345 | + return skey; |
||
346 | +} |
||
347 | --- /dev/null |
||
348 | +++ b/security/keys/secure_key.c |
||
349 | @@ -0,0 +1,339 @@ |
||
350 | +// SPDX-License-Identifier: GPL-2.0 |
||
351 | +/* Copyright (C) 2018 NXP |
||
352 | + * Secure key is generated using NXP CAAM hardware block. CAAM generates the |
||
353 | + * random number (used as a key) and creates its blob for the user. |
||
354 | + */ |
||
355 | + |
||
356 | +#include <linux/slab.h> |
||
357 | +#include <linux/parser.h> |
||
358 | +#include <linux/string.h> |
||
359 | +#include <linux/key-type.h> |
||
360 | +#include <linux/rcupdate.h> |
||
361 | +#include <keys/secure-type.h> |
||
362 | +#include <linux/completion.h> |
||
363 | + |
||
364 | +#include "securekey_desc.h" |
||
365 | + |
||
366 | +static const char hmac_alg[] = "hmac(sha1)"; |
||
367 | +static const char hash_alg[] = "sha1"; |
||
368 | + |
||
369 | +static struct crypto_shash *hashalg; |
||
370 | +static struct crypto_shash *hmacalg; |
||
371 | + |
||
372 | +enum { |
||
373 | + error = -1, |
||
374 | + new_key, |
||
375 | + load_blob, |
||
376 | +}; |
||
377 | + |
||
378 | +static const match_table_t key_tokens = { |
||
379 | + {new_key, "new"}, |
||
380 | + {load_blob, "load"}, |
||
381 | + {error, NULL} |
||
382 | +}; |
||
383 | + |
||
384 | +static struct secure_key_payload *secure_payload_alloc(struct key *key) |
||
385 | +{ |
||
386 | + struct secure_key_payload *sec_key = NULL; |
||
387 | + int ret = 0; |
||
388 | + |
||
389 | + ret = key_payload_reserve(key, sizeof(*sec_key)); |
||
390 | + if (ret < 0) |
||
391 | + goto out; |
||
392 | + |
||
393 | + sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL); |
||
394 | + if (!sec_key) |
||
395 | + goto out; |
||
396 | + |
||
397 | +out: |
||
398 | + return sec_key; |
||
399 | +} |
||
400 | + |
||
401 | +/* |
||
402 | + * parse_inputdata - parse the keyctl input data and fill in the |
||
403 | + * payload structure for key or its blob. |
||
404 | + * param[in]: data pointer to the data to be parsed for creating key. |
||
405 | + * param[in]: p pointer to secure key payload structure to fill parsed data |
||
406 | + * On success returns 0, otherwise -EINVAL. |
||
407 | + */ |
||
408 | +static int parse_inputdata(char *data, struct secure_key_payload *p) |
||
409 | +{ |
||
410 | + substring_t args[MAX_OPT_ARGS]; |
||
411 | + long keylen = 0; |
||
412 | + int ret = -EINVAL; |
||
413 | + int key_cmd = -EINVAL; |
||
414 | + char *c = NULL; |
||
415 | + |
||
416 | + c = strsep(&data, " \t"); |
||
417 | + if (!c) { |
||
418 | + ret = -EINVAL; |
||
419 | + goto out; |
||
420 | + } |
||
421 | + |
||
422 | + /* Get the keyctl command i.e. new_key or load_blob etc */ |
||
423 | + key_cmd = match_token(c, key_tokens, args); |
||
424 | + |
||
425 | + switch (key_cmd) { |
||
426 | + case new_key: |
||
427 | + /* first argument is key size */ |
||
428 | + c = strsep(&data, " \t"); |
||
429 | + if (!c) { |
||
430 | + ret = -EINVAL; |
||
431 | + goto out; |
||
432 | + } |
||
433 | + |
||
434 | + ret = kstrtol(c, 10, &keylen); |
||
435 | + if (ret < 0 || keylen < MIN_KEY_SIZE || |
||
436 | + keylen > MAX_KEY_SIZE) { |
||
437 | + ret = -EINVAL; |
||
438 | + goto out; |
||
439 | + } |
||
440 | + |
||
441 | + p->key_len = keylen; |
||
442 | + ret = new_key; |
||
443 | + |
||
444 | + break; |
||
445 | + case load_blob: |
||
446 | + /* first argument is blob data for CAAM*/ |
||
447 | + c = strsep(&data, " \t"); |
||
448 | + if (!c) { |
||
449 | + ret = -EINVAL; |
||
450 | + goto out; |
||
451 | + } |
||
452 | + |
||
453 | + /* Blob_len = No of characters in blob/2 */ |
||
454 | + p->blob_len = strlen(c) / 2; |
||
455 | + if (p->blob_len > MAX_BLOB_SIZE) { |
||
456 | + ret = -EINVAL; |
||
457 | + goto out; |
||
458 | + } |
||
459 | + |
||
460 | + ret = hex2bin(p->blob, c, p->blob_len); |
||
461 | + if (ret < 0) { |
||
462 | + ret = -EINVAL; |
||
463 | + goto out; |
||
464 | + } |
||
465 | + ret = load_blob; |
||
466 | + |
||
467 | + break; |
||
468 | + case error: |
||
469 | + ret = -EINVAL; |
||
470 | + break; |
||
471 | + } |
||
472 | + |
||
473 | +out: |
||
474 | + return ret; |
||
475 | +} |
||
476 | + |
||
477 | +/* |
||
478 | + * secure_instantiate - create a new secure type key. |
||
479 | + * Supports the operation to generate a new key. A random number |
||
480 | + * is generated from CAAM as key data and the corresponding red blob |
||
481 | + * is formed and stored as key_blob. |
||
482 | + * Also supports the operation to load the blob and key is derived using |
||
483 | + * that blob from CAAM. |
||
484 | + * On success, return 0. Otherwise return errno. |
||
485 | + */ |
||
486 | +static int secure_instantiate(struct key *key, |
||
487 | + struct key_preparsed_payload *prep) |
||
488 | +{ |
||
489 | + struct secure_key_payload *payload = NULL; |
||
490 | + size_t datalen = prep->datalen; |
||
491 | + char *data = NULL; |
||
492 | + int key_cmd = 0; |
||
493 | + int ret = 0; |
||
494 | + enum sk_req_type sk_op_type; |
||
495 | + struct device *dev = NULL; |
||
496 | + |
||
497 | + if (datalen <= 0 || datalen > 32767 || !prep->data) { |
||
498 | + ret = -EINVAL; |
||
499 | + goto out; |
||
500 | + } |
||
501 | + |
||
502 | + data = kmalloc(datalen + 1, GFP_KERNEL); |
||
503 | + if (!data) { |
||
504 | + ret = -ENOMEM; |
||
505 | + goto out; |
||
506 | + } |
||
507 | + |
||
508 | + memcpy(data, prep->data, datalen); |
||
509 | + data[datalen] = '\0'; |
||
510 | + |
||
511 | + payload = secure_payload_alloc(key); |
||
512 | + if (!payload) { |
||
513 | + ret = -ENOMEM; |
||
514 | + goto out; |
||
515 | + } |
||
516 | + |
||
517 | + /* Allocate caam job ring for operation to be performed from CAAM */ |
||
518 | + dev = caam_jr_alloc(); |
||
519 | + if (!dev) { |
||
520 | + pr_info("caam_jr_alloc failed\n"); |
||
521 | + ret = -ENODEV; |
||
522 | + goto out; |
||
523 | + } |
||
524 | + |
||
525 | + key_cmd = parse_inputdata(data, payload); |
||
526 | + if (key_cmd < 0) { |
||
527 | + ret = key_cmd; |
||
528 | + goto out; |
||
529 | + } |
||
530 | + |
||
531 | + switch (key_cmd) { |
||
532 | + case load_blob: |
||
533 | + /* |
||
534 | + * Red blob decryption to be done for load operation |
||
535 | + * to derive the key. |
||
536 | + */ |
||
537 | + sk_op_type = sk_red_blob_dec; |
||
538 | + ret = key_deblob(payload, sk_op_type, dev); |
||
539 | + if (ret != 0) { |
||
540 | + pr_info("secure_key: key_blob decap fail (%d)\n", ret); |
||
541 | + goto out; |
||
542 | + } |
||
543 | + break; |
||
544 | + case new_key: |
||
545 | + /* Get Random number from caam of the specified length */ |
||
546 | + sk_op_type = sk_get_random; |
||
547 | + ret = caam_get_random(payload, sk_op_type, dev); |
||
548 | + if (ret != 0) { |
||
549 | + pr_info("secure_key: get_random fail (%d)\n", ret); |
||
550 | + goto out; |
||
551 | + } |
||
552 | + |
||
553 | + /* Generate red blob of key random bytes with CAAM */ |
||
554 | + sk_op_type = sk_red_blob_enc; |
||
555 | + ret = key_blob(payload, sk_op_type, dev); |
||
556 | + if (ret != 0) { |
||
557 | + pr_info("secure_key: key_blob encap fail (%d)\n", ret); |
||
558 | + goto out; |
||
559 | + } |
||
560 | + break; |
||
561 | + default: |
||
562 | + ret = -EINVAL; |
||
563 | + goto out; |
||
564 | + } |
||
565 | +out: |
||
566 | + if (data) |
||
567 | + kzfree(data); |
||
568 | + if (dev) |
||
569 | + caam_jr_free(dev); |
||
570 | + |
||
571 | + if (!ret) |
||
572 | + rcu_assign_keypointer(key, payload); |
||
573 | + else |
||
574 | + kzfree(payload); |
||
575 | + |
||
576 | + return ret; |
||
577 | +} |
||
578 | + |
||
579 | +/* |
||
580 | + * secure_read - copy the blob data to userspace in hex. |
||
581 | + * param[in]: key pointer to key struct |
||
582 | + * param[in]: buffer pointer to user data for creating key |
||
583 | + * param[in]: buflen is the length of the buffer |
||
584 | + * On success, return to userspace the secure key data size. |
||
585 | + */ |
||
586 | +static long secure_read(const struct key *key, char __user *buffer, |
||
587 | + size_t buflen) |
||
588 | +{ |
||
589 | + const struct secure_key_payload *p = NULL; |
||
590 | + char *ascii_buf; |
||
591 | + char *bufp; |
||
592 | + int i; |
||
593 | + |
||
594 | + p = dereference_key_locked(key); |
||
595 | + if (!p) |
||
596 | + return -EINVAL; |
||
597 | + |
||
598 | + if (buffer && buflen >= 2 * p->blob_len) { |
||
599 | + ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); |
||
600 | + if (!ascii_buf) |
||
601 | + return -ENOMEM; |
||
602 | + |
||
603 | + bufp = ascii_buf; |
||
604 | + for (i = 0; i < p->blob_len; i++) |
||
605 | + bufp = hex_byte_pack(bufp, p->blob[i]); |
||
606 | + if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { |
||
607 | + kzfree(ascii_buf); |
||
608 | + return -EFAULT; |
||
609 | + } |
||
610 | + kzfree(ascii_buf); |
||
611 | + } |
||
612 | + return 2 * p->blob_len; |
||
613 | +} |
||
614 | + |
||
615 | +/* |
||
616 | + * secure_destroy - clear and free the key's payload |
||
617 | + */ |
||
618 | +static void secure_destroy(struct key *key) |
||
619 | +{ |
||
620 | + kzfree(key->payload.data[0]); |
||
621 | +} |
||
622 | + |
||
623 | +struct key_type key_type_secure = { |
||
624 | + .name = "secure", |
||
625 | + .instantiate = secure_instantiate, |
||
626 | + .destroy = secure_destroy, |
||
627 | + .read = secure_read, |
||
628 | +}; |
||
629 | +EXPORT_SYMBOL_GPL(key_type_secure); |
||
630 | + |
||
631 | +static void secure_shash_release(void) |
||
632 | +{ |
||
633 | + if (hashalg) |
||
634 | + crypto_free_shash(hashalg); |
||
635 | + if (hmacalg) |
||
636 | + crypto_free_shash(hmacalg); |
||
637 | +} |
||
638 | + |
||
639 | +static int __init secure_shash_alloc(void) |
||
640 | +{ |
||
641 | + int ret; |
||
642 | + |
||
643 | + hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC); |
||
644 | + if (IS_ERR(hmacalg)) { |
||
645 | + pr_info("secure_key: could not allocate crypto %s\n", |
||
646 | + hmac_alg); |
||
647 | + return PTR_ERR(hmacalg); |
||
648 | + } |
||
649 | + |
||
650 | + hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC); |
||
651 | + if (IS_ERR(hashalg)) { |
||
652 | + pr_info("secure_key: could not allocate crypto %s\n", |
||
653 | + hash_alg); |
||
654 | + ret = PTR_ERR(hashalg); |
||
655 | + goto hashalg_fail; |
||
656 | + } |
||
657 | + |
||
658 | + return 0; |
||
659 | + |
||
660 | +hashalg_fail: |
||
661 | + crypto_free_shash(hmacalg); |
||
662 | + return ret; |
||
663 | +} |
||
664 | + |
||
665 | +static int __init init_secure_key(void) |
||
666 | +{ |
||
667 | + int ret; |
||
668 | + |
||
669 | + ret = secure_shash_alloc(); |
||
670 | + if (ret < 0) |
||
671 | + return ret; |
||
672 | + |
||
673 | + ret = register_key_type(&key_type_secure); |
||
674 | + if (ret < 0) |
||
675 | + secure_shash_release(); |
||
676 | + return ret; |
||
677 | +} |
||
678 | + |
||
679 | +static void __exit cleanup_secure_key(void) |
||
680 | +{ |
||
681 | + secure_shash_release(); |
||
682 | + unregister_key_type(&key_type_secure); |
||
683 | +} |
||
684 | + |
||
685 | +late_initcall(init_secure_key); |
||
686 | +module_exit(cleanup_secure_key); |
||
687 | + |
||
688 | +MODULE_LICENSE("GPL"); |
||
689 | --- /dev/null |
||
690 | +++ b/security/keys/securekey_desc.c |
||
691 | @@ -0,0 +1,608 @@ |
||
692 | +// SPDX-License-Identifier: GPL-2.0 |
||
693 | +/* |
||
694 | + * Copyright (C) 2018 NXP |
||
695 | + * |
||
696 | + */ |
||
697 | + |
||
698 | +#include <keys/secure-type.h> |
||
699 | +#include "securekey_desc.h" |
||
700 | + |
||
701 | +/* key modifier for blob encapsulation & decapsulation descriptor */ |
||
702 | +u8 key_modifier[] = "SECURE_KEY"; |
||
703 | +u32 key_modifier_len = 10; |
||
704 | + |
||
705 | +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc) |
||
706 | +{ |
||
707 | + struct sk_fetch_rnd_data *fetch_rnd_data = NULL; |
||
708 | + struct random_desc *rnd_desc = NULL; |
||
709 | + size_t len = 0; |
||
710 | + u32 *desc = skreq->hwdesc; |
||
711 | + |
||
712 | + init_job_desc(desc, 0); |
||
713 | + |
||
714 | + fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data; |
||
715 | + rnd_desc = &skdesc->dma_u.random_descp; |
||
716 | + len = fetch_rnd_data->key_len; |
||
717 | + |
||
718 | + /* command 0x82500000 */ |
||
719 | + append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG | |
||
720 | + OP_ALG_ALGSEL_RNG); |
||
721 | + /* command 0x60340000 | len */ |
||
722 | + append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len); |
||
723 | + append_ptr(desc, rnd_desc->rnd_data); |
||
724 | +} |
||
725 | + |
||
726 | +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc) |
||
727 | +{ |
||
728 | + struct redblob_encap_desc *red_blob_desc = |
||
729 | + &skdesc->dma_u.redblob_encapdesc; |
||
730 | + struct sk_red_blob_encap *red_blob_req = |
||
731 | + &skreq->req_u.sk_red_blob_encap; |
||
732 | + u32 *desc = skreq->hwdesc; |
||
733 | + |
||
734 | + init_job_desc(desc, 0); |
||
735 | + |
||
736 | + /* Load class 2 key with key modifier. */ |
||
737 | + append_key_as_imm(desc, key_modifier, key_modifier_len, |
||
738 | + key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG); |
||
739 | + |
||
740 | + /* SEQ IN PTR Command. */ |
||
741 | + append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz, |
||
742 | + 0); |
||
743 | + |
||
744 | + /* SEQ OUT PTR Command. */ |
||
745 | + append_seq_out_ptr(desc, red_blob_desc->redblob, |
||
746 | + red_blob_req->redblob_sz, 0); |
||
747 | + |
||
748 | + /* RedBlob encapsulation PROTOCOL Command. */ |
||
749 | + append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); |
||
750 | +} |
||
751 | + |
||
752 | +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc) |
||
753 | + * brief CAAM Descriptor creator from redblob to plaindata. |
||
754 | + * param[in] skreq Pointer to secure key request structure |
||
755 | + * param[in] skdesc Pointer to secure key descriptor structure |
||
756 | + */ |
||
757 | +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc) |
||
758 | +{ |
||
759 | + struct redblob_decap_desc *red_blob_desc = |
||
760 | + &skdesc->dma_u.redblob_decapdesc; |
||
761 | + struct sk_red_blob_decap *red_blob_req = |
||
762 | + &skreq->req_u.sk_red_blob_decap; |
||
763 | + u32 *desc = skreq->hwdesc; |
||
764 | + |
||
765 | + init_job_desc(desc, 0); |
||
766 | + |
||
767 | + /* Load class 2 key with key modifier. */ |
||
768 | + append_key_as_imm(desc, key_modifier, key_modifier_len, |
||
769 | + key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG); |
||
770 | + |
||
771 | + /* SEQ IN PTR Command. */ |
||
772 | + append_seq_in_ptr(desc, red_blob_desc->redblob, |
||
773 | + red_blob_req->redblob_sz, 0); |
||
774 | + |
||
775 | + /* SEQ OUT PTR Command. */ |
||
776 | + append_seq_out_ptr(desc, red_blob_desc->out_data, |
||
777 | + red_blob_req->data_sz, 0); |
||
778 | + |
||
779 | + /* RedBlob decapsulation PROTOCOL Command. */ |
||
780 | + append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); |
||
781 | +} |
||
782 | + |
||
783 | +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req, |
||
784 | + * struct sk_desc *skdesc) |
||
785 | + * brief DMA map the buffer virtual pointers to physical address. |
||
786 | + * param[in] dev Pointer to job ring device structure |
||
787 | + * param[in] req Pointer to secure key request structure |
||
788 | + * param[in] skdesc Pointer to secure key descriptor structure |
||
789 | + * return 0 on success, error value otherwise. |
||
790 | + */ |
||
791 | +int caam_sk_get_random_map(struct device *dev, struct sk_req *req, |
||
792 | + struct sk_desc *skdesc) |
||
793 | +{ |
||
794 | + struct sk_fetch_rnd_data *fetch_rnd_data; |
||
795 | + struct random_desc *rnd_desc; |
||
796 | + |
||
797 | + fetch_rnd_data = &req->req_u.sk_fetch_rnd_data; |
||
798 | + rnd_desc = &skdesc->dma_u.random_descp; |
||
799 | + |
||
800 | + rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data, |
||
801 | + fetch_rnd_data->key_len, DMA_FROM_DEVICE); |
||
802 | + |
||
803 | + if (dma_mapping_error(dev, rnd_desc->rnd_data)) { |
||
804 | + dev_err(dev, "Unable to map memory\n"); |
||
805 | + goto sk_random_map_fail; |
||
806 | + } |
||
807 | + return 0; |
||
808 | + |
||
809 | +sk_random_map_fail: |
||
810 | + return -ENOMEM; |
||
811 | +} |
||
812 | + |
||
813 | +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req, |
||
814 | + * struct sk_desc *skdesc) |
||
815 | + * brief DMA map the buffer virtual pointers to physical address. |
||
816 | + * param[in] dev Pointer to job ring device structure |
||
817 | + * param[in] req Pointer to secure key request structure |
||
818 | + * param[in] skdesc Pointer to secure key descriptor structure |
||
819 | + * return 0 on success, error value otherwise. |
||
820 | + */ |
||
821 | +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req, |
||
822 | + struct sk_desc *skdesc) |
||
823 | +{ |
||
824 | + struct sk_red_blob_encap *red_blob_encap; |
||
825 | + struct redblob_encap_desc *red_blob_desc; |
||
826 | + |
||
827 | + red_blob_encap = &req->req_u.sk_red_blob_encap; |
||
828 | + red_blob_desc = &skdesc->dma_u.redblob_encapdesc; |
||
829 | + |
||
830 | + red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data, |
||
831 | + red_blob_encap->data_sz, DMA_TO_DEVICE); |
||
832 | + if (dma_mapping_error(dev, red_blob_desc->in_data)) { |
||
833 | + dev_err(dev, "Unable to map memory\n"); |
||
834 | + goto sk_data_fail; |
||
835 | + } |
||
836 | + |
||
837 | + red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob, |
||
838 | + red_blob_encap->redblob_sz, DMA_FROM_DEVICE); |
||
839 | + if (dma_mapping_error(dev, red_blob_desc->redblob)) { |
||
840 | + dev_err(dev, "Unable to map memory\n"); |
||
841 | + goto sk_redblob_fail; |
||
842 | + } |
||
843 | + |
||
844 | + return 0; |
||
845 | + |
||
846 | +sk_redblob_fail: |
||
847 | + dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz, |
||
848 | + DMA_TO_DEVICE); |
||
849 | +sk_data_fail: |
||
850 | + return -ENOMEM; |
||
851 | +} |
||
852 | + |
||
853 | +/* static int caam_sk_redblob_decap_map(struct device *dev, |
||
854 | + * struct sk_req *req, |
||
855 | + * struct sk_desc *skdesc) |
||
856 | + * brief DMA map the buffer virtual pointers to physical address. |
||
857 | + * param[in] dev Pointer to job ring device structure |
||
858 | + * param[in] req Pointer to secure key request structure |
||
859 | + * param[in] skdesc Pointer to secure key descriptor structure |
||
860 | + * return 0 on success, error value otherwise. |
||
861 | + */ |
||
862 | +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req, |
||
863 | + struct sk_desc *skdesc) |
||
864 | +{ |
||
865 | + struct sk_red_blob_decap *red_blob_decap; |
||
866 | + struct redblob_decap_desc *red_blob_desc; |
||
867 | + |
||
868 | + red_blob_decap = &req->req_u.sk_red_blob_decap; |
||
869 | + red_blob_desc = &skdesc->dma_u.redblob_decapdesc; |
||
870 | + |
||
871 | + red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob, |
||
872 | + red_blob_decap->redblob_sz, DMA_TO_DEVICE); |
||
873 | + if (dma_mapping_error(dev, red_blob_desc->redblob)) { |
||
874 | + dev_err(dev, "Unable to map memory\n"); |
||
875 | + goto sk_redblob_fail; |
||
876 | + } |
||
877 | + |
||
878 | + red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data, |
||
879 | + red_blob_decap->data_sz, DMA_FROM_DEVICE); |
||
880 | + if (dma_mapping_error(dev, red_blob_desc->out_data)) { |
||
881 | + dev_err(dev, "Unable to map memory\n"); |
||
882 | + goto sk_data_fail; |
||
883 | + } |
||
884 | + |
||
885 | + return 0; |
||
886 | + |
||
887 | +sk_data_fail: |
||
888 | + dma_unmap_single(dev, red_blob_desc->redblob, |
||
889 | + red_blob_decap->redblob_sz, DMA_TO_DEVICE); |
||
890 | +sk_redblob_fail: |
||
891 | + return -ENOMEM; |
||
892 | +} |
||
893 | + |
||
894 | +/* @fn void securekey_unmap(struct device *dev, |
||
895 | + * struct sk_desc *skdesc, struct sk_req *req) |
||
896 | + * @brief DMA unmap the buffer pointers. |
||
897 | + * @param[in] dev Pointer to job ring device structure |
||
898 | + * @param[in] skdesc Pointer to secure key descriptor structure |
||
899 | + * @param[in] req Pointer to secure key request structure |
||
900 | + */ |
||
901 | +void securekey_unmap(struct device *dev, |
||
902 | + struct sk_desc *skdesc, struct sk_req *req) |
||
903 | +{ |
||
904 | + |
||
905 | + switch (req->type) { |
||
906 | + case sk_get_random: |
||
907 | + { |
||
908 | + struct sk_fetch_rnd_data *fetch_rnd_data; |
||
909 | + struct random_desc *rnd_desc; |
||
910 | + |
||
911 | + fetch_rnd_data = &req->req_u.sk_fetch_rnd_data; |
||
912 | + rnd_desc = &skdesc->dma_u.random_descp; |
||
913 | + |
||
914 | + /* Unmap Descriptor buffer pointers. */ |
||
915 | + dma_unmap_single(dev, rnd_desc->rnd_data, |
||
916 | + fetch_rnd_data->key_len, |
||
917 | + DMA_FROM_DEVICE); |
||
918 | + break; |
||
919 | + } |
||
920 | + case sk_red_blob_enc: |
||
921 | + { |
||
922 | + struct sk_red_blob_encap *red_blob_encap; |
||
923 | + struct redblob_encap_desc *red_blob_desc; |
||
924 | + |
||
925 | + red_blob_encap = &req->req_u.sk_red_blob_encap; |
||
926 | + red_blob_desc = &skdesc->dma_u.redblob_encapdesc; |
||
927 | + |
||
928 | + /* Unmap Descriptor buffer pointers. */ |
||
929 | + dma_unmap_single(dev, red_blob_desc->in_data, |
||
930 | + red_blob_encap->data_sz, |
||
931 | + DMA_TO_DEVICE); |
||
932 | + |
||
933 | + dma_unmap_single(dev, red_blob_desc->redblob, |
||
934 | + red_blob_encap->redblob_sz, |
||
935 | + DMA_FROM_DEVICE); |
||
936 | + |
||
937 | + break; |
||
938 | + } |
||
939 | + case sk_red_blob_dec: |
||
940 | + { |
||
941 | + struct sk_red_blob_decap *red_blob_decap; |
||
942 | + struct redblob_decap_desc *red_blob_desc; |
||
943 | + |
||
944 | + red_blob_decap = &req->req_u.sk_red_blob_decap; |
||
945 | + red_blob_desc = &skdesc->dma_u.redblob_decapdesc; |
||
946 | + |
||
947 | + /* Unmap Descriptor buffer pointers. */ |
||
948 | + dma_unmap_single(dev, red_blob_desc->redblob, |
||
949 | + red_blob_decap->redblob_sz, |
||
950 | + DMA_TO_DEVICE); |
||
951 | + |
||
952 | + dma_unmap_single(dev, red_blob_desc->out_data, |
||
953 | + red_blob_decap->data_sz, |
||
954 | + DMA_FROM_DEVICE); |
||
955 | + |
||
956 | + break; |
||
957 | + } |
||
958 | + default: |
||
959 | + dev_err(dev, "Unable to find request type\n"); |
||
960 | + break; |
||
961 | + } |
||
962 | + kfree(skdesc); |
||
963 | +} |
||
964 | + |
||
965 | +/* int caam_securekey_desc_init(struct device *dev, struct sk_req *req) |
||
966 | + * brief CAAM Descriptor creator for secure key operations. |
||
967 | + * param[in] dev Pointer to job ring device structure |
||
968 | + * param[in] req Pointer to secure key request structure |
||
969 | + * return 0 on success, error value otherwise. |
||
970 | + */ |
||
971 | +int caam_securekey_desc_init(struct device *dev, struct sk_req *req) |
||
972 | +{ |
||
973 | + struct sk_desc *skdesc = NULL; |
||
974 | + int ret = 0; |
||
975 | + |
||
976 | + switch (req->type) { |
||
977 | + case sk_get_random: |
||
978 | + { |
||
979 | + skdesc = kmalloc(sizeof(*skdesc), GFP_DMA); |
||
980 | + if (!skdesc) { |
||
981 | + ret = -ENOMEM; |
||
982 | + goto out; |
||
983 | + } |
||
984 | + skdesc->req_type = req->type; |
||
985 | + |
||
986 | + if (caam_sk_get_random_map(dev, req, skdesc)) { |
||
987 | + dev_err(dev, "caam get_random map fail\n"); |
||
988 | + ret = -ENOMEM; |
||
989 | + goto out; |
||
990 | + } |
||
991 | + caam_sk_rng_desc(req, skdesc); |
||
992 | + break; |
||
993 | + } |
||
994 | + case sk_red_blob_enc: |
||
995 | + { |
||
996 | + skdesc = kmalloc(sizeof(*skdesc), GFP_DMA); |
||
997 | + if (!skdesc) { |
||
998 | + ret = -ENOMEM; |
||
999 | + goto out; |
||
1000 | + } |
||
1001 | + |
||
1002 | + skdesc->req_type = req->type; |
||
1003 | + |
||
1004 | + if (caam_sk_redblob_encap_map(dev, req, skdesc)) { |
||
1005 | + dev_err(dev, "caam redblob_encap map fail\n"); |
||
1006 | + ret = -ENOMEM; |
||
1007 | + goto out; |
||
1008 | + } |
||
1009 | + |
||
1010 | + /* Descriptor function to create redblob from data. */ |
||
1011 | + caam_sk_redblob_encap_desc(req, skdesc); |
||
1012 | + break; |
||
1013 | + } |
||
1014 | + |
||
1015 | + case sk_red_blob_dec: |
||
1016 | + { |
||
1017 | + skdesc = kmalloc(sizeof(*skdesc), GFP_DMA); |
||
1018 | + if (!skdesc) { |
||
1019 | + ret = -ENOMEM; |
||
1020 | + goto out; |
||
1021 | + } |
||
1022 | + |
||
1023 | + skdesc->req_type = req->type; |
||
1024 | + |
||
1025 | + if (caam_sk_redblob_decap_map(dev, req, skdesc)) { |
||
1026 | + dev_err(dev, "caam redblob_decap map fail\n"); |
||
1027 | + ret = -ENOMEM; |
||
1028 | + goto out; |
||
1029 | + } |
||
1030 | + |
||
1031 | + /* Descriptor function to decap data from redblob. */ |
||
1032 | + caam_sk_redblob_decap_desc(req, skdesc); |
||
1033 | + break; |
||
1034 | + } |
||
1035 | + default: |
||
1036 | + pr_debug("Unknown request type\n"); |
||
1037 | + ret = -EINVAL; |
||
1038 | + goto out; |
||
1039 | + } |
||
1040 | + |
||
1041 | + req->desc_pointer = (void *)skdesc; |
||
1042 | + |
||
1043 | +out: |
||
1044 | + return ret; |
||
1045 | +} |
||
1046 | + |
||
1047 | +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret, |
||
1048 | + * void *context) |
||
1049 | + * brief callback function to be called when descriptor executed. |
||
1050 | + * param[in] dev Pointer to device structure |
||
1051 | + * param[in] desc descriptor pointer |
||
1052 | + * param[in] ret return status of Job submitted |
||
1053 | + * param[in] context void pointer |
||
1054 | + */ |
||
1055 | +static void caam_op_done(struct device *dev, u32 *desc, u32 ret, |
||
1056 | + void *context) |
||
1057 | +{ |
||
1058 | + struct sk_req *req = context; |
||
1059 | + |
||
1060 | + if (ret) { |
||
1061 | + dev_err(dev, "caam op done err: %x\n", ret); |
||
1062 | + /* print the error source name. */ |
||
1063 | + caam_jr_strstatus(dev, ret); |
||
1064 | + } |
||
1065 | + /* Call securekey_unmap function for unmapping the buffer pointers. */ |
||
1066 | + securekey_unmap(dev, req->desc_pointer, req); |
||
1067 | + |
||
1068 | + req->ret = ret; |
||
1069 | + complete(&req->comp); |
||
1070 | +} |
||
1071 | + |
||
1072 | + |
||
1073 | +/* static int sk_job_submit(struct device *jrdev, struct sk_req *req) |
||
1074 | + * brief Enqueue a Job descriptor to Job ring and wait until SEC returns. |
||
1075 | + * param[in] jrdev Pointer to job ring device structure |
||
1076 | + * param[in] req Pointer to secure key request structure |
||
1077 | + * return 0 on success, error value otherwise. |
||
1078 | + */ |
||
1079 | +static int sk_job_submit(struct device *jrdev, struct sk_req *req) |
||
1080 | +{ |
||
1081 | + int ret; |
||
1082 | + |
||
1083 | + init_completion(&req->comp); |
||
1084 | + |
||
1085 | + /* caam_jr_enqueue function for Enqueue a job descriptor */ |
||
1086 | + ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req); |
||
1087 | + if (!ret) |
||
1088 | + wait_for_completion_interruptible(&req->comp); |
||
1089 | + |
||
1090 | + ret = req->ret; |
||
1091 | + return ret; |
||
1092 | +} |
||
1093 | + |
||
1094 | +/* caam_get_random(struct secure_key_payload *p, enum sk_req_type fetch_rnd, |
||
1095 | + * struct device *dev) |
||
1096 | + * Create the random number of the specified length using CAAM block |
||
1097 | + * param[in]: out pointer to place the random bytes |
||
1098 | + * param[in]: length for the random data bytes. |
||
1099 | + * param[in]: dev Pointer to job ring device structure |
||
1100 | + * If operation is successful return 0, otherwise error. |
||
1101 | + */ |
||
1102 | +int caam_get_random(struct secure_key_payload *p, enum sk_req_type fetch_rnd, |
||
1103 | + struct device *dev) |
||
1104 | +{ |
||
1105 | + struct sk_fetch_rnd_data *fetch_rnd_data = NULL; |
||
1106 | + struct sk_req *req = NULL; |
||
1107 | + int ret = 0; |
||
1108 | + void *temp = NULL; |
||
1109 | + |
||
1110 | + req = kmalloc(sizeof(struct sk_req), GFP_DMA); |
||
1111 | + if (!req) { |
||
1112 | + ret = -ENOMEM; |
||
1113 | + goto out; |
||
1114 | + } |
||
1115 | + |
||
1116 | + req->type = fetch_rnd; |
||
1117 | + fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data); |
||
1118 | + |
||
1119 | + /* initialise with key length */ |
||
1120 | + fetch_rnd_data->key_len = p->key_len; |
||
1121 | + |
||
1122 | + temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA); |
||
1123 | + if (!temp) { |
||
1124 | + ret = -ENOMEM; |
||
1125 | + goto out; |
||
1126 | + } |
||
1127 | + fetch_rnd_data->data = temp; |
||
1128 | + |
||
1129 | + ret = caam_securekey_desc_init(dev, req); |
||
1130 | + |
||
1131 | + if (ret) { |
||
1132 | + pr_info("caam_securekey_desc_init failed\n"); |
||
1133 | + goto out; |
||
1134 | + } |
||
1135 | + |
||
1136 | + ret = sk_job_submit(dev, req); |
||
1137 | + if (!ret) { |
||
1138 | + /*Copy output to key buffer. */ |
||
1139 | + memcpy(p->key, fetch_rnd_data->data, p->key_len); |
||
1140 | + } else { |
||
1141 | + ret = -EINVAL; |
||
1142 | + } |
||
1143 | + |
||
1144 | +out: |
||
1145 | + if (req) |
||
1146 | + kfree(req); |
||
1147 | + |
||
1148 | + if (temp) |
||
1149 | + kfree(temp); |
||
1150 | + |
||
1151 | + return ret; |
||
1152 | +} |
||
1153 | +EXPORT_SYMBOL(caam_get_random); |
||
1154 | + |
||
1155 | +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type |
||
1156 | + * struct device *dev) |
||
1157 | + * Deblobify the blob to get the key data and fill in secure key payload struct |
||
1158 | + * param[in] p pointer to the secure key payload |
||
1159 | + * param[in] decap_type operation to be done. |
||
1160 | + * param[in] dev dev Pointer to job ring device structure |
||
1161 | + * If operation is successful return 0, otherwise error. |
||
1162 | + */ |
||
1163 | +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type, |
||
1164 | + struct device *dev) |
||
1165 | +{ |
||
1166 | + unsigned int blob_len; |
||
1167 | + struct sk_red_blob_decap *d_blob; |
||
1168 | + struct sk_req *req = NULL; |
||
1169 | + int total_sz = 0, *temp = NULL, ret = 0; |
||
1170 | + |
||
1171 | + req = kmalloc(sizeof(struct sk_req), GFP_DMA); |
||
1172 | + if (!req) { |
||
1173 | + ret = -ENOMEM; |
||
1174 | + goto out; |
||
1175 | + } |
||
1176 | + |
||
1177 | + d_blob = &(req->req_u.sk_red_blob_decap); |
||
1178 | + blob_len = p->blob_len; |
||
1179 | + req->type = decap_type; |
||
1180 | + |
||
1181 | + /* |
||
1182 | + * Red blob size is the blob_len filled in payload struct |
||
1183 | + * Data_sz i.e. key is the blob_len - blob header size |
||
1184 | + */ |
||
1185 | + |
||
1186 | + d_blob->redblob_sz = blob_len; |
||
1187 | + d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ); |
||
1188 | + total_sz = d_blob->data_sz + d_blob->redblob_sz; |
||
1189 | + |
||
1190 | + temp = kmalloc(total_sz, GFP_DMA); |
||
1191 | + if (!temp) { |
||
1192 | + ret = -ENOMEM; |
||
1193 | + goto out; |
||
1194 | + } |
||
1195 | + |
||
1196 | + req->mem_pointer = temp; |
||
1197 | + d_blob->redblob = temp; |
||
1198 | + d_blob->data = d_blob->redblob + d_blob->redblob_sz; |
||
1199 | + memcpy(d_blob->redblob, p->blob, blob_len); |
||
1200 | + |
||
1201 | + ret = caam_securekey_desc_init(dev, req); |
||
1202 | + |
||
1203 | + if (ret) { |
||
1204 | + pr_info("caam_securekey_desc_init: Failed\n"); |
||
1205 | + goto out; |
||
1206 | + } |
||
1207 | + |
||
1208 | + ret = sk_job_submit(dev, req); |
||
1209 | + if (!ret) { |
||
1210 | + /*Copy output to key buffer. */ |
||
1211 | + p->key_len = d_blob->data_sz; |
||
1212 | + memcpy(p->key, d_blob->data, p->key_len); |
||
1213 | + } else { |
||
1214 | + ret = -EINVAL; |
||
1215 | + } |
||
1216 | + |
||
1217 | +out: |
||
1218 | + if (temp) |
||
1219 | + kfree(temp); |
||
1220 | + if (req) |
||
1221 | + kfree(req); |
||
1222 | + return ret; |
||
1223 | +} |
||
1224 | +EXPORT_SYMBOL(key_deblob); |
||
1225 | + |
||
1226 | +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type, |
||
1227 | + * struct device *dev) |
||
1228 | + * To blobify the key data to get the blob. This blob can only be seen by |
||
1229 | + * userspace. |
||
1230 | + * param[in] p pointer to the secure key payload |
||
1231 | + * param[in] decap_type operation to be done. |
||
1232 | + * param[in] dev dev Pointer to job ring device structure |
||
1233 | + * If operation is successful return 0, otherwise error. |
||
1234 | + */ |
||
1235 | +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type, |
||
1236 | + struct device *dev) |
||
1237 | +{ |
||
1238 | + unsigned int key_len; |
||
1239 | + struct sk_red_blob_encap *k_blob; |
||
1240 | + struct sk_req *req = NULL; |
||
1241 | + int total_sz = 0, *temp = NULL, ret = 0; |
||
1242 | + |
||
1243 | + req = kmalloc(sizeof(struct sk_req), GFP_DMA); |
||
1244 | + if (!req) { |
||
1245 | + ret = -ENOMEM; |
||
1246 | + goto out; |
||
1247 | + } |
||
1248 | + |
||
1249 | + key_len = p->key_len; |
||
1250 | + |
||
1251 | + req->type = encap_type; |
||
1252 | + k_blob = &(req->req_u.sk_red_blob_encap); |
||
1253 | + |
||
1254 | + /* |
||
1255 | + * Data_sz i.e. key len and the corresponding blob_len is |
||
1256 | + * key_len + BLOB header size. |
||
1257 | + */ |
||
1258 | + |
||
1259 | + k_blob->data_sz = key_len; |
||
1260 | + k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ; |
||
1261 | + total_sz = k_blob->data_sz + k_blob->redblob_sz; |
||
1262 | + |
||
1263 | + temp = kmalloc(total_sz, GFP_DMA); |
||
1264 | + if (!temp) { |
||
1265 | + ret = -ENOMEM; |
||
1266 | + goto out; |
||
1267 | + } |
||
1268 | + |
||
1269 | + req->mem_pointer = temp; |
||
1270 | + k_blob->data = temp; |
||
1271 | + |
||
1272 | + k_blob->redblob = k_blob->data + k_blob->data_sz; |
||
1273 | + memcpy(k_blob->data, p->key, key_len); |
||
1274 | + |
||
1275 | + ret = caam_securekey_desc_init(dev, req); |
||
1276 | + |
||
1277 | + if (ret) { |
||
1278 | + pr_info("caam_securekey_desc_init failed\n"); |
||
1279 | + goto out; |
||
1280 | + } |
||
1281 | + |
||
1282 | + ret = sk_job_submit(dev, req); |
||
1283 | + if (!ret) { |
||
1284 | + /*Copy output to key buffer. */ |
||
1285 | + p->blob_len = k_blob->redblob_sz; |
||
1286 | + memcpy(p->blob, k_blob->redblob, p->blob_len); |
||
1287 | + } else { |
||
1288 | + ret = -EINVAL; |
||
1289 | + } |
||
1290 | + |
||
1291 | +out: |
||
1292 | + if (temp) |
||
1293 | + kfree(req->mem_pointer); |
||
1294 | + if (req) |
||
1295 | + kfree(req); |
||
1296 | + return ret; |
||
1297 | + |
||
1298 | +} |
||
1299 | +EXPORT_SYMBOL(key_blob); |
||
1300 | --- /dev/null |
||
1301 | +++ b/security/keys/securekey_desc.h |
||
1302 | @@ -0,0 +1,141 @@ |
||
1303 | +/* SPDX-License-Identifier: GPL-2.0 */ |
||
1304 | +/* |
||
1305 | + * Copyright 2018 NXP |
||
1306 | + * |
||
1307 | + */ |
||
1308 | +#ifndef _SECUREKEY_DESC_H_ |
||
1309 | +#define _SECUREKEY_DESC_H_ |
||
1310 | + |
||
1311 | +#include "compat.h" |
||
1312 | +#include "regs.h" |
||
1313 | +#include "intern.h" |
||
1314 | +#include "desc.h" |
||
1315 | +#include "desc_constr.h" |
||
1316 | +#include "jr.h" |
||
1317 | +#include "error.h" |
||
1318 | +#include "pdb.h" |
||
1319 | + |
||
1320 | +#define SK_BLOB_KEY_SZ 32 /* Blob key size. */ |
||
1321 | +#define SK_BLOB_MAC_SZ 16 /* Blob MAC size. */ |
||
1322 | + |
||
1323 | +/* |
||
1324 | + * brief defines different kinds of operations supported by this module. |
||
1325 | + */ |
||
1326 | +enum sk_req_type { |
||
1327 | + sk_get_random, |
||
1328 | + sk_red_blob_enc, |
||
1329 | + sk_red_blob_dec, |
||
1330 | +}; |
||
1331 | + |
||
1332 | + |
||
1333 | +/* |
||
1334 | + * struct random_des |
||
1335 | + * param[out] rnd_data output buffer for random data. |
||
1336 | + */ |
||
1337 | +struct random_desc { |
||
1338 | + dma_addr_t rnd_data; |
||
1339 | +}; |
||
1340 | + |
||
1341 | +/* struct redblob_encap_desc |
||
1342 | + * details Structure containing dma address for redblob encapsulation. |
||
1343 | + * param[in] in_data input data to redblob encap descriptor. |
||
1344 | + * param[out] redblob output buffer for redblob. |
||
1345 | + */ |
||
1346 | +struct redblob_encap_desc { |
||
1347 | + dma_addr_t in_data; |
||
1348 | + dma_addr_t redblob; |
||
1349 | +}; |
||
1350 | + |
||
1351 | +/* struct redblob_decap_desc |
||
1352 | + * details Structure containing dma address for redblob decapsulation. |
||
1353 | + * param[in] redblob input buffer to redblob decap descriptor. |
||
1354 | + * param[out] out_data output data from redblob decap descriptor. |
||
1355 | + */ |
||
1356 | +struct redblob_decap_desc { |
||
1357 | + dma_addr_t redblob; |
||
1358 | + dma_addr_t out_data; |
||
1359 | +}; |
||
1360 | + |
||
1361 | +/* struct sk_desc |
||
1362 | + * details Structure for securekey descriptor creation. |
||
1363 | + * param[in] req_type operation supported. |
||
1364 | + * param[in] dma_u union of struct for supported operation. |
||
1365 | + */ |
||
1366 | +struct sk_desc { |
||
1367 | + u32 req_type; |
||
1368 | + union { |
||
1369 | + struct redblob_encap_desc redblob_encapdesc; |
||
1370 | + struct redblob_decap_desc redblob_decapdesc; |
||
1371 | + struct random_desc random_descp; |
||
1372 | + } dma_u; |
||
1373 | +}; |
||
1374 | + |
||
1375 | +/* struct sk_fetch_rnd_data |
||
1376 | + * decriptor structure containing key length. |
||
1377 | + */ |
||
1378 | +struct sk_fetch_rnd_data { |
||
1379 | + void *data; |
||
1380 | + size_t key_len; |
||
1381 | +}; |
||
1382 | + |
||
1383 | +/* struct sk_red_blob_encap |
||
1384 | + * details Structure containing buffer pointers for redblob encapsulation. |
||
1385 | + * param[in] data Input data. |
||
1386 | + * param[in] data_sz size of Input data. |
||
1387 | + * param[out] redblob output buffer for redblob. |
||
1388 | + * param[in] redblob_sz size of redblob. |
||
1389 | + */ |
||
1390 | +struct sk_red_blob_encap { |
||
1391 | + void *data; |
||
1392 | + uint32_t data_sz; |
||
1393 | + void *redblob; |
||
1394 | + uint32_t redblob_sz; |
||
1395 | +}; |
||
1396 | + |
||
1397 | +/* struct sk_red_blob_decap |
||
1398 | + * details Structure containing buffer pointers for redblob decapsulation. |
||
1399 | + * param[in] redblob Input redblob. |
||
1400 | + * param[in] redblob_sz size of redblob. |
||
1401 | + * param[out] data output buffer for data. |
||
1402 | + * param[in] data_sz size of output data. |
||
1403 | + */ |
||
1404 | +struct sk_red_blob_decap { |
||
1405 | + void *redblob; |
||
1406 | + uint32_t redblob_sz; |
||
1407 | + void *data; |
||
1408 | + uint32_t data_sz; |
||
1409 | +}; |
||
1410 | + |
||
1411 | +/* struct sk_req |
||
1412 | + * details Structure for securekey request creation. |
||
1413 | + * param[in] type operation supported. |
||
1414 | + * param[in] req_u union of struct for supported operation. |
||
1415 | + * param[out] ret return status of CAAM operation. |
||
1416 | + * param[in] mem_pointer memory pointer for allocated kernel memory. |
||
1417 | + * param[in] desc_pointer Pointer to securekey descriptor creation structure. |
||
1418 | + * param[in] comp struct completion object. |
||
1419 | + * param[in] hwdesc contains descriptor instructions. |
||
1420 | + */ |
||
1421 | +struct sk_req { |
||
1422 | + enum sk_req_type type; |
||
1423 | + void *arg; |
||
1424 | + union { |
||
1425 | + struct sk_red_blob_encap sk_red_blob_encap; |
||
1426 | + struct sk_red_blob_decap sk_red_blob_decap; |
||
1427 | + struct sk_fetch_rnd_data sk_fetch_rnd_data; |
||
1428 | + } req_u; |
||
1429 | + int ret; |
||
1430 | + void *mem_pointer; |
||
1431 | + void *desc_pointer; |
||
1432 | + struct completion comp; |
||
1433 | + u32 hwdesc[MAX_CAAM_DESCSIZE]; |
||
1434 | +}; |
||
1435 | + |
||
1436 | +int caam_get_random(struct secure_key_payload *p, enum sk_req_type fetch_rnd, |
||
1437 | + struct device *dev); |
||
1438 | +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type, |
||
1439 | + struct device *dev); |
||
1440 | +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type, |
||
1441 | + struct device *dev); |
||
1442 | + |
||
1443 | +#endif /*_SECUREKEY_DESC_H_*/ |