11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V.
40f50ba5aSJens Wiklander * Copyright (c) 2020, 2022-2023 Linaro Limited
590040fa4SSohaib ul Hassan * Copyright (c) 2022, Technology Innovation Institute (TII)
6b0104773SPascal Brand */
78ddf5a4eSEtienne Carriere
88ddf5a4eSEtienne Carriere #include <assert.h>
9d9281a0cSJens Wiklander #include <bitstring.h>
10b60e1ceeSJoakim Bech #include <compiler.h>
11688c335dSJerome Forissier #include <config.h>
12e1770e71SJens Wiklander #include <crypto/crypto.h>
13b0104773SPascal Brand #include <kernel/tee_ta_manager.h>
14c40a6505SJens Wiklander #include <kernel/user_access.h>
15ef142203SJens Wiklander #include <memtag.h>
1689c9728dSJens Wiklander #include <mm/vm.h>
1770b61310SJerome Forissier #include <stdlib_ext.h>
18ffe04039SJerome Forissier #include <string_ext.h>
192ffdd194SJens Wiklander #include <string.h>
20e1770e71SJens Wiklander #include <sys/queue.h>
21c40a6505SJens Wiklander #include <tee_api_defines_extensions.h>
22e1770e71SJens Wiklander #include <tee_api_types.h>
23e1770e71SJens Wiklander #include <tee/tee_cryp_utl.h>
24e1770e71SJens Wiklander #include <tee/tee_obj.h>
250f50ba5aSJens Wiklander #include <tee/tee_pobj.h>
26e1770e71SJens Wiklander #include <tee/tee_svc_cryp.h>
270f50ba5aSJens Wiklander #include <tee/tee_svc_storage.h>
28e1770e71SJens Wiklander #include <tee/tee_svc.h>
29e1770e71SJens Wiklander #include <trace.h>
30e1770e71SJens Wiklander #include <utee_defines.h>
3180ddeac7SJerome Forissier #include <util.h>
32cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
33cdb198a7SJerome Forissier #include <tee/tee_cryp_hkdf.h>
34cdb198a7SJerome Forissier #endif
35cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
368854d3c6SJerome Forissier #include <tee/tee_cryp_concat_kdf.h>
378854d3c6SJerome Forissier #endif
380f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
390f2293b7SJerome Forissier #include <tee/tee_cryp_pbkdf2.h>
400f2293b7SJerome Forissier #endif
418854d3c6SJerome Forissier
4234a08becSJoakim Bech enum cryp_state {
4334a08becSJoakim Bech CRYP_STATE_INITIALIZED = 0,
4434a08becSJoakim Bech CRYP_STATE_UNINITIALIZED
4534a08becSJoakim Bech };
4634a08becSJoakim Bech
4752ee414bSJens Wiklander typedef void (*tee_cryp_ctx_finalize_func_t) (void *ctx);
48b0104773SPascal Brand struct tee_cryp_state {
49b0104773SPascal Brand TAILQ_ENTRY(tee_cryp_state) link;
50b0104773SPascal Brand uint32_t algo;
51b0104773SPascal Brand uint32_t mode;
52e86f1266SJens Wiklander vaddr_t key1;
53e86f1266SJens Wiklander vaddr_t key2;
54b0104773SPascal Brand void *ctx;
55b0104773SPascal Brand tee_cryp_ctx_finalize_func_t ctx_finalize;
5634a08becSJoakim Bech enum cryp_state state;
57b0104773SPascal Brand };
58b0104773SPascal Brand
59b0104773SPascal Brand struct tee_cryp_obj_secret {
60b0104773SPascal Brand uint32_t key_size;
6140a4fd66SJens Wiklander uint32_t alloc_size;
62b0104773SPascal Brand
63b0104773SPascal Brand /*
64b0104773SPascal Brand * Pseudo code visualize layout of structure
65b0104773SPascal Brand * Next follows data, such as:
6640a4fd66SJens Wiklander * uint8_t data[alloc_size]
6740a4fd66SJens Wiklander * key_size must never exceed alloc_size
68b0104773SPascal Brand */
69b0104773SPascal Brand };
70b0104773SPascal Brand
71d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_OPTIONAL BIT(0)
72d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_REQUIRED BIT(1)
73d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_OPTIONAL_GROUP BIT(2)
74d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_SIZE_INDICATOR BIT(3)
75d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_GEN_KEY_OPT BIT(4)
76d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_GEN_KEY_REQ BIT(5)
77d9281a0cSJens Wiklander #define TEE_TYPE_ATTR_BIGNUM_MAXBITS BIT(6)
78b0104773SPascal Brand
79b0104773SPascal Brand /* Handle storing of generic secret keys of varying lengths */
8040a4fd66SJens Wiklander #define ATTR_OPS_INDEX_SECRET 0
81ffe04039SJerome Forissier /* Convert to/from big-endian byte array and provider-specific bignum */
8240a4fd66SJens Wiklander #define ATTR_OPS_INDEX_BIGNUM 1
83b0104773SPascal Brand /* Convert to/from value attribute depending on direction */
8440a4fd66SJens Wiklander #define ATTR_OPS_INDEX_VALUE 2
8590040fa4SSohaib ul Hassan /* Convert to/from curve25519 attribute depending on direction */
8690040fa4SSohaib ul Hassan #define ATTR_OPS_INDEX_25519 3
8734ce35b1Sloubaihui #define ATTR_OPS_INDEX_448 4
8890040fa4SSohaib ul Hassan
8990040fa4SSohaib ul Hassan /* Curve25519 key bytes size is always 32 bytes*/
9090040fa4SSohaib ul Hassan #define KEY_SIZE_BYTES_25519 UL(32)
9134ce35b1Sloubaihui #define KEY_SIZE_BYTES_448 UL(56)
920aaad418SValerii Chubar /* TEE Internal Core API v1.3.1, Table 6-8 */
930aaad418SValerii Chubar #define TEE_ED25519_CTX_MAX_LENGTH 255
94b0104773SPascal Brand
95b0104773SPascal Brand struct tee_cryp_obj_type_attrs {
96b0104773SPascal Brand uint32_t attr_id;
97b0104773SPascal Brand uint16_t flags;
9840a4fd66SJens Wiklander uint16_t ops_index;
99b0104773SPascal Brand uint16_t raw_offs;
100b0104773SPascal Brand uint16_t raw_size;
101b0104773SPascal Brand };
102b0104773SPascal Brand
103b0104773SPascal Brand #define RAW_DATA(_x, _y) \
1042ffdd194SJens Wiklander .raw_offs = offsetof(_x, _y), .raw_size = MEMBER_SIZE(_x, _y)
105b0104773SPascal Brand
106b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs
107b0104773SPascal Brand tee_cryp_obj_secret_value_attrs[] = {
108b0104773SPascal Brand {
109b0104773SPascal Brand .attr_id = TEE_ATTR_SECRET_VALUE,
110b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
11140a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_SECRET,
112b0104773SPascal Brand .raw_offs = 0,
113b0104773SPascal Brand .raw_size = 0
114b0104773SPascal Brand },
115b0104773SPascal Brand };
116b0104773SPascal Brand
117b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_pub_key_attrs[] = {
118b0104773SPascal Brand {
119b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_MODULUS,
120b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
12140a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
122ffe04039SJerome Forissier RAW_DATA(struct rsa_public_key, n)
123b0104773SPascal Brand },
124b0104773SPascal Brand
125b0104773SPascal Brand {
126b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT,
127b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED,
12840a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
129ffe04039SJerome Forissier RAW_DATA(struct rsa_public_key, e)
130b0104773SPascal Brand },
131b0104773SPascal Brand };
132b0104773SPascal Brand
133b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_keypair_attrs[] = {
134b0104773SPascal Brand {
135b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_MODULUS,
136b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
13740a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
138ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, n)
139b0104773SPascal Brand },
140b0104773SPascal Brand
141b0104773SPascal Brand {
142b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT,
143d1272505SJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_OPT,
14440a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
145ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, e)
146b0104773SPascal Brand },
147b0104773SPascal Brand
148b0104773SPascal Brand {
149b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_PRIVATE_EXPONENT,
150b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED,
15140a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
152ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, d)
153b0104773SPascal Brand },
154b0104773SPascal Brand
155b0104773SPascal Brand {
156b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_PRIME1,
157b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP,
15840a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
159ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, p)
160b0104773SPascal Brand },
161b0104773SPascal Brand
162b0104773SPascal Brand {
163b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_PRIME2,
164b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP,
16540a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
166ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, q)
167b0104773SPascal Brand },
168b0104773SPascal Brand
169b0104773SPascal Brand {
170b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_EXPONENT1,
171b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP,
17240a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
173ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, dp)
174b0104773SPascal Brand },
175b0104773SPascal Brand
176b0104773SPascal Brand {
177b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_EXPONENT2,
178b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP,
17940a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
180ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, dq)
181b0104773SPascal Brand },
182b0104773SPascal Brand
183b0104773SPascal Brand {
184b0104773SPascal Brand .attr_id = TEE_ATTR_RSA_COEFFICIENT,
185b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP,
18640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
187ffe04039SJerome Forissier RAW_DATA(struct rsa_keypair, qp)
188b0104773SPascal Brand },
189b0104773SPascal Brand };
190b0104773SPascal Brand
191b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_pub_key_attrs[] = {
192b0104773SPascal Brand {
193b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_PRIME,
194b20d0295SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS |
195b20d0295SJerome Forissier TEE_TYPE_ATTR_SIZE_INDICATOR,
19640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
197ffe04039SJerome Forissier RAW_DATA(struct dsa_public_key, p)
198b0104773SPascal Brand },
199b0104773SPascal Brand
200b0104773SPascal Brand {
201b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_SUBPRIME,
202b20d0295SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
20340a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
204ffe04039SJerome Forissier RAW_DATA(struct dsa_public_key, q)
205b0104773SPascal Brand },
206b0104773SPascal Brand
207b0104773SPascal Brand {
208b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_BASE,
209d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS,
21040a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
211ffe04039SJerome Forissier RAW_DATA(struct dsa_public_key, g)
212b0104773SPascal Brand },
213b0104773SPascal Brand
214b0104773SPascal Brand {
215b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE,
216d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS,
21740a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
218ffe04039SJerome Forissier RAW_DATA(struct dsa_public_key, y)
219b0104773SPascal Brand },
220b0104773SPascal Brand };
221b0104773SPascal Brand
222b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_keypair_attrs[] = {
223b0104773SPascal Brand {
224b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_PRIME,
225d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ |
226b20d0295SJerome Forissier TEE_TYPE_ATTR_BIGNUM_MAXBITS | TEE_TYPE_ATTR_SIZE_INDICATOR,
22740a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
228ffe04039SJerome Forissier RAW_DATA(struct dsa_keypair, p)
229b0104773SPascal Brand },
230b0104773SPascal Brand
231b0104773SPascal Brand {
232b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_SUBPRIME,
233b20d0295SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ,
23440a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
235ffe04039SJerome Forissier RAW_DATA(struct dsa_keypair, q)
236b0104773SPascal Brand },
237b0104773SPascal Brand
238b0104773SPascal Brand {
239b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_BASE,
240d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ |
241d9281a0cSJens Wiklander TEE_TYPE_ATTR_BIGNUM_MAXBITS,
24240a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
243ffe04039SJerome Forissier RAW_DATA(struct dsa_keypair, g)
244b0104773SPascal Brand },
245b0104773SPascal Brand
246b0104773SPascal Brand {
247b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_PRIVATE_VALUE,
248d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS,
24940a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
250ffe04039SJerome Forissier RAW_DATA(struct dsa_keypair, x)
251b0104773SPascal Brand },
252b0104773SPascal Brand
253b0104773SPascal Brand {
254b0104773SPascal Brand .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE,
255d9281a0cSJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS,
25640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
257ffe04039SJerome Forissier RAW_DATA(struct dsa_keypair, y)
258b0104773SPascal Brand },
259b0104773SPascal Brand };
260b0104773SPascal Brand
261b0104773SPascal Brand static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dh_keypair_attrs[] = {
262b0104773SPascal Brand {
263b0104773SPascal Brand .attr_id = TEE_ATTR_DH_PRIME,
264b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR |
265b0104773SPascal Brand TEE_TYPE_ATTR_GEN_KEY_REQ,
26640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
267ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, p)
268b0104773SPascal Brand },
269b0104773SPascal Brand
270b0104773SPascal Brand {
271b0104773SPascal Brand .attr_id = TEE_ATTR_DH_BASE,
272b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ,
27340a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
274ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, g)
275b0104773SPascal Brand },
276b0104773SPascal Brand
277b0104773SPascal Brand {
278b0104773SPascal Brand .attr_id = TEE_ATTR_DH_PUBLIC_VALUE,
279b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED,
28040a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
281ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, y)
282b0104773SPascal Brand },
283b0104773SPascal Brand
284b0104773SPascal Brand {
285b0104773SPascal Brand .attr_id = TEE_ATTR_DH_PRIVATE_VALUE,
286b0104773SPascal Brand .flags = TEE_TYPE_ATTR_REQUIRED,
28740a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
288ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, x)
289b0104773SPascal Brand },
290b0104773SPascal Brand
291b0104773SPascal Brand {
292b0104773SPascal Brand .attr_id = TEE_ATTR_DH_SUBPRIME,
293b0104773SPascal Brand .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP | TEE_TYPE_ATTR_GEN_KEY_OPT,
29440a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
295ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, q)
296b0104773SPascal Brand },
297b0104773SPascal Brand
298b0104773SPascal Brand {
299b0104773SPascal Brand .attr_id = TEE_ATTR_DH_X_BITS,
300b0104773SPascal Brand .flags = TEE_TYPE_ATTR_GEN_KEY_OPT,
30140a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_VALUE,
302ffe04039SJerome Forissier RAW_DATA(struct dh_keypair, xbits)
303b0104773SPascal Brand },
304b0104773SPascal Brand };
305b0104773SPascal Brand
306cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
307cdb198a7SJerome Forissier static const struct tee_cryp_obj_type_attrs
308cdb198a7SJerome Forissier tee_cryp_obj_hkdf_ikm_attrs[] = {
309cdb198a7SJerome Forissier {
310cdb198a7SJerome Forissier .attr_id = TEE_ATTR_HKDF_IKM,
311cdb198a7SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
31240a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_SECRET,
313cdb198a7SJerome Forissier .raw_offs = 0,
314cdb198a7SJerome Forissier .raw_size = 0
315cdb198a7SJerome Forissier },
316cdb198a7SJerome Forissier };
317cdb198a7SJerome Forissier #endif
318cdb198a7SJerome Forissier
3198854d3c6SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
3208854d3c6SJerome Forissier static const struct tee_cryp_obj_type_attrs
3218854d3c6SJerome Forissier tee_cryp_obj_concat_kdf_z_attrs[] = {
3228854d3c6SJerome Forissier {
3238854d3c6SJerome Forissier .attr_id = TEE_ATTR_CONCAT_KDF_Z,
3248854d3c6SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
32540a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_SECRET,
3268854d3c6SJerome Forissier .raw_offs = 0,
3278854d3c6SJerome Forissier .raw_size = 0
3288854d3c6SJerome Forissier },
3298854d3c6SJerome Forissier };
3308854d3c6SJerome Forissier #endif
3318854d3c6SJerome Forissier
3320f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
3330f2293b7SJerome Forissier static const struct tee_cryp_obj_type_attrs
3340f2293b7SJerome Forissier tee_cryp_obj_pbkdf2_passwd_attrs[] = {
3350f2293b7SJerome Forissier {
3360f2293b7SJerome Forissier .attr_id = TEE_ATTR_PBKDF2_PASSWORD,
3370f2293b7SJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
33840a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_SECRET,
3390f2293b7SJerome Forissier .raw_offs = 0,
3400f2293b7SJerome Forissier .raw_size = 0
3410f2293b7SJerome Forissier },
3420f2293b7SJerome Forissier };
3430f2293b7SJerome Forissier #endif
3440f2293b7SJerome Forissier
345aeb0d927SCedric Chaumont static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_pub_key_attrs[] = {
346aeb0d927SCedric Chaumont {
347aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X,
348aeb0d927SCedric Chaumont .flags = TEE_TYPE_ATTR_REQUIRED,
34940a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
350aeb0d927SCedric Chaumont RAW_DATA(struct ecc_public_key, x)
351aeb0d927SCedric Chaumont },
352aeb0d927SCedric Chaumont
353aeb0d927SCedric Chaumont {
354aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y,
355aeb0d927SCedric Chaumont .flags = TEE_TYPE_ATTR_REQUIRED,
35640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
357aeb0d927SCedric Chaumont RAW_DATA(struct ecc_public_key, y)
358aeb0d927SCedric Chaumont },
359aeb0d927SCedric Chaumont
360aeb0d927SCedric Chaumont {
361aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_CURVE,
3625b385b3fSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR,
36340a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_VALUE,
364aeb0d927SCedric Chaumont RAW_DATA(struct ecc_public_key, curve)
365aeb0d927SCedric Chaumont },
366aeb0d927SCedric Chaumont };
367aeb0d927SCedric Chaumont
368aeb0d927SCedric Chaumont static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_keypair_attrs[] = {
369aeb0d927SCedric Chaumont {
370aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE,
371aeb0d927SCedric Chaumont .flags = TEE_TYPE_ATTR_REQUIRED,
37240a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
373aeb0d927SCedric Chaumont RAW_DATA(struct ecc_keypair, d)
374aeb0d927SCedric Chaumont },
375aeb0d927SCedric Chaumont
376aeb0d927SCedric Chaumont {
377aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X,
378aeb0d927SCedric Chaumont .flags = TEE_TYPE_ATTR_REQUIRED,
37940a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
380aeb0d927SCedric Chaumont RAW_DATA(struct ecc_keypair, x)
381aeb0d927SCedric Chaumont },
382aeb0d927SCedric Chaumont
383aeb0d927SCedric Chaumont {
384aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y,
385aeb0d927SCedric Chaumont .flags = TEE_TYPE_ATTR_REQUIRED,
38640a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_BIGNUM,
387aeb0d927SCedric Chaumont RAW_DATA(struct ecc_keypair, y)
388aeb0d927SCedric Chaumont },
389aeb0d927SCedric Chaumont
390aeb0d927SCedric Chaumont {
391aeb0d927SCedric Chaumont .attr_id = TEE_ATTR_ECC_CURVE,
392d1272505SJens Wiklander .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR |
393d1272505SJens Wiklander TEE_TYPE_ATTR_GEN_KEY_REQ,
39440a4fd66SJens Wiklander .ops_index = ATTR_OPS_INDEX_VALUE,
395aeb0d927SCedric Chaumont RAW_DATA(struct ecc_keypair, curve)
396aeb0d927SCedric Chaumont },
397aeb0d927SCedric Chaumont };
398aeb0d927SCedric Chaumont
399c2e89f8dSJerome Forissier static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_pub_key_attrs[] = {
400c2e89f8dSJerome Forissier {
401c2e89f8dSJerome Forissier .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X,
402c2e89f8dSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
403c2e89f8dSJerome Forissier .ops_index = ATTR_OPS_INDEX_BIGNUM,
404c2e89f8dSJerome Forissier RAW_DATA(struct ecc_public_key, x)
405c2e89f8dSJerome Forissier },
406c2e89f8dSJerome Forissier
407c2e89f8dSJerome Forissier {
408c2e89f8dSJerome Forissier .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y,
409c2e89f8dSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
410c2e89f8dSJerome Forissier .ops_index = ATTR_OPS_INDEX_BIGNUM,
411c2e89f8dSJerome Forissier RAW_DATA(struct ecc_public_key, y)
412c2e89f8dSJerome Forissier },
413c2e89f8dSJerome Forissier };
414c2e89f8dSJerome Forissier
415c2e89f8dSJerome Forissier static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_keypair_attrs[] = {
416c2e89f8dSJerome Forissier {
417c2e89f8dSJerome Forissier .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE,
418c2e89f8dSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
419c2e89f8dSJerome Forissier .ops_index = ATTR_OPS_INDEX_BIGNUM,
420c2e89f8dSJerome Forissier RAW_DATA(struct ecc_keypair, d)
421c2e89f8dSJerome Forissier },
422c2e89f8dSJerome Forissier
423c2e89f8dSJerome Forissier {
424c2e89f8dSJerome Forissier .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X,
425c2e89f8dSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
426c2e89f8dSJerome Forissier .ops_index = ATTR_OPS_INDEX_BIGNUM,
427c2e89f8dSJerome Forissier RAW_DATA(struct ecc_keypair, x)
428c2e89f8dSJerome Forissier },
429c2e89f8dSJerome Forissier
430c2e89f8dSJerome Forissier {
431c2e89f8dSJerome Forissier .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y,
432c2e89f8dSJerome Forissier .flags = TEE_TYPE_ATTR_REQUIRED,
433c2e89f8dSJerome Forissier .ops_index = ATTR_OPS_INDEX_BIGNUM,
434c2e89f8dSJerome Forissier RAW_DATA(struct ecc_keypair, y)
435c2e89f8dSJerome Forissier },
436c2e89f8dSJerome Forissier };
437c2e89f8dSJerome Forissier
43890040fa4SSohaib ul Hassan static
43990040fa4SSohaib ul Hassan const struct tee_cryp_obj_type_attrs tee_cryp_obj_x25519_keypair_attrs[] = {
44090040fa4SSohaib ul Hassan {
44190040fa4SSohaib ul Hassan .attr_id = TEE_ATTR_X25519_PRIVATE_VALUE,
44290040fa4SSohaib ul Hassan .flags = TEE_TYPE_ATTR_REQUIRED,
44390040fa4SSohaib ul Hassan .ops_index = ATTR_OPS_INDEX_25519,
44446e25a17Sloubaihui RAW_DATA(struct montgomery_keypair, priv)
44590040fa4SSohaib ul Hassan },
44690040fa4SSohaib ul Hassan
44790040fa4SSohaib ul Hassan {
44890040fa4SSohaib ul Hassan .attr_id = TEE_ATTR_X25519_PUBLIC_VALUE,
44990040fa4SSohaib ul Hassan .flags = TEE_TYPE_ATTR_REQUIRED,
45090040fa4SSohaib ul Hassan .ops_index = ATTR_OPS_INDEX_25519,
45146e25a17Sloubaihui RAW_DATA(struct montgomery_keypair, pub)
45290040fa4SSohaib ul Hassan },
45390040fa4SSohaib ul Hassan };
45490040fa4SSohaib ul Hassan
4550aaad418SValerii Chubar static
45634ce35b1Sloubaihui const struct tee_cryp_obj_type_attrs tee_cryp_obj_x448_keypair_attrs[] = {
45734ce35b1Sloubaihui {
45834ce35b1Sloubaihui .attr_id = TEE_ATTR_X448_PRIVATE_VALUE,
45934ce35b1Sloubaihui .flags = TEE_TYPE_ATTR_REQUIRED,
46034ce35b1Sloubaihui .ops_index = ATTR_OPS_INDEX_448,
46134ce35b1Sloubaihui RAW_DATA(struct montgomery_keypair, priv)
46234ce35b1Sloubaihui },
46334ce35b1Sloubaihui
46434ce35b1Sloubaihui {
46534ce35b1Sloubaihui .attr_id = TEE_ATTR_X448_PUBLIC_VALUE,
46634ce35b1Sloubaihui .flags = TEE_TYPE_ATTR_REQUIRED,
46734ce35b1Sloubaihui .ops_index = ATTR_OPS_INDEX_448,
46834ce35b1Sloubaihui RAW_DATA(struct montgomery_keypair, pub)
46934ce35b1Sloubaihui },
47034ce35b1Sloubaihui };
47134ce35b1Sloubaihui
47234ce35b1Sloubaihui static
4730aaad418SValerii Chubar const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_pub_key_attrs[] = {
4740aaad418SValerii Chubar {
4750aaad418SValerii Chubar .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE,
4760aaad418SValerii Chubar .flags = TEE_TYPE_ATTR_REQUIRED,
4770aaad418SValerii Chubar .ops_index = ATTR_OPS_INDEX_25519,
478c4cab13eSClement Faure RAW_DATA(struct ed25519_public_key, pub)
4790aaad418SValerii Chubar },
4800aaad418SValerii Chubar };
4810aaad418SValerii Chubar
4820aaad418SValerii Chubar static
4830aaad418SValerii Chubar const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_keypair_attrs[] = {
4840aaad418SValerii Chubar {
4850aaad418SValerii Chubar .attr_id = TEE_ATTR_ED25519_PRIVATE_VALUE,
4860aaad418SValerii Chubar .flags = TEE_TYPE_ATTR_REQUIRED,
4870aaad418SValerii Chubar .ops_index = ATTR_OPS_INDEX_25519,
4880aaad418SValerii Chubar RAW_DATA(struct ed25519_keypair, priv)
4890aaad418SValerii Chubar },
4900aaad418SValerii Chubar
4910aaad418SValerii Chubar {
4920aaad418SValerii Chubar .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE,
4930aaad418SValerii Chubar .flags = TEE_TYPE_ATTR_REQUIRED,
4940aaad418SValerii Chubar .ops_index = ATTR_OPS_INDEX_25519,
4950aaad418SValerii Chubar RAW_DATA(struct ed25519_keypair, pub)
4960aaad418SValerii Chubar },
4970aaad418SValerii Chubar };
4980aaad418SValerii Chubar
499b0104773SPascal Brand struct tee_cryp_obj_type_props {
500b0104773SPascal Brand TEE_ObjectType obj_type;
501b0104773SPascal Brand uint16_t min_size; /* may not be smaller than this */
502b0104773SPascal Brand uint16_t max_size; /* may not be larger than this */
503b0104773SPascal Brand uint16_t alloc_size; /* this many bytes are allocated to hold data */
504b0104773SPascal Brand uint8_t quanta; /* may only be an multiple of this */
505b0104773SPascal Brand
506b0104773SPascal Brand uint8_t num_type_attrs;
507b0104773SPascal Brand const struct tee_cryp_obj_type_attrs *type_attrs;
508b0104773SPascal Brand };
509b0104773SPascal Brand
510b0104773SPascal Brand #define PROP(obj_type, quanta, min_size, max_size, alloc_size, type_attrs) \
511b0104773SPascal Brand { (obj_type), (min_size), (max_size), (alloc_size), (quanta), \
512b8d220d2SPascal Brand ARRAY_SIZE(type_attrs), (type_attrs) }
513b0104773SPascal Brand
514b0104773SPascal Brand static const struct tee_cryp_obj_type_props tee_cryp_obj_props[] = {
515b0104773SPascal Brand PROP(TEE_TYPE_AES, 64, 128, 256, /* valid sizes 128, 192, 256 */
516b0104773SPascal Brand 256 / 8 + sizeof(struct tee_cryp_obj_secret),
517b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
518c56cc686SJens Wiklander PROP(TEE_TYPE_DES, 64, 64, 64,
519c56cc686SJens Wiklander /* Valid size 64 with parity */
520b0104773SPascal Brand 64 / 8 + sizeof(struct tee_cryp_obj_secret),
521b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
522c56cc686SJens Wiklander PROP(TEE_TYPE_DES3, 64, 128, 192,
523c56cc686SJens Wiklander /* Valid sizes 128, 192 with parity */
524b0104773SPascal Brand 192 / 8 + sizeof(struct tee_cryp_obj_secret),
525b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
526ade6f848SJerome Forissier PROP(TEE_TYPE_SM4, 128, 128, 128,
527ade6f848SJerome Forissier 128 / 8 + sizeof(struct tee_cryp_obj_secret),
528ade6f848SJerome Forissier tee_cryp_obj_secret_value_attrs),
529b0104773SPascal Brand PROP(TEE_TYPE_HMAC_MD5, 8, 64, 512,
530b0104773SPascal Brand 512 / 8 + sizeof(struct tee_cryp_obj_secret),
531b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
5323d70a974SIgor Opaniuk #if defined(CFG_HMAC_64_1024_RANGE)
5333d70a974SIgor Opaniuk PROP(TEE_TYPE_HMAC_SHA1, 8, 64, 1024,
5343d70a974SIgor Opaniuk 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
5353d70a974SIgor Opaniuk tee_cryp_obj_secret_value_attrs),
5363d70a974SIgor Opaniuk PROP(TEE_TYPE_HMAC_SHA224, 8, 64, 1024,
5373d70a974SIgor Opaniuk 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
5383d70a974SIgor Opaniuk tee_cryp_obj_secret_value_attrs),
5393d70a974SIgor Opaniuk PROP(TEE_TYPE_HMAC_SHA256, 8, 64, 1024,
5403d70a974SIgor Opaniuk 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
5413d70a974SIgor Opaniuk tee_cryp_obj_secret_value_attrs),
5423d70a974SIgor Opaniuk PROP(TEE_TYPE_HMAC_SHA384, 8, 64, 1024,
5433d70a974SIgor Opaniuk 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
5443d70a974SIgor Opaniuk tee_cryp_obj_secret_value_attrs),
5453d70a974SIgor Opaniuk PROP(TEE_TYPE_HMAC_SHA512, 8, 64, 1024,
5463d70a974SIgor Opaniuk 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
5473d70a974SIgor Opaniuk tee_cryp_obj_secret_value_attrs),
5483d70a974SIgor Opaniuk #else
549b0104773SPascal Brand PROP(TEE_TYPE_HMAC_SHA1, 8, 80, 512,
550b0104773SPascal Brand 512 / 8 + sizeof(struct tee_cryp_obj_secret),
551b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
552b0104773SPascal Brand PROP(TEE_TYPE_HMAC_SHA224, 8, 112, 512,
553b0104773SPascal Brand 512 / 8 + sizeof(struct tee_cryp_obj_secret),
554b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
555b0104773SPascal Brand PROP(TEE_TYPE_HMAC_SHA256, 8, 192, 1024,
556b0104773SPascal Brand 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
557b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
558b0104773SPascal Brand PROP(TEE_TYPE_HMAC_SHA384, 8, 256, 1024,
559b0104773SPascal Brand 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
560b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
561b0104773SPascal Brand PROP(TEE_TYPE_HMAC_SHA512, 8, 256, 1024,
562b0104773SPascal Brand 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
563b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
5643d70a974SIgor Opaniuk #endif
565260b4028SJens Wiklander PROP(TEE_TYPE_HMAC_SHA3_224, 8, 192, 1024,
566260b4028SJens Wiklander 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
567260b4028SJens Wiklander tee_cryp_obj_secret_value_attrs),
568260b4028SJens Wiklander PROP(TEE_TYPE_HMAC_SHA3_256, 8, 256, 1024,
569260b4028SJens Wiklander 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
570260b4028SJens Wiklander tee_cryp_obj_secret_value_attrs),
571260b4028SJens Wiklander PROP(TEE_TYPE_HMAC_SHA3_384, 8, 256, 1024,
572260b4028SJens Wiklander 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
573260b4028SJens Wiklander tee_cryp_obj_secret_value_attrs),
574260b4028SJens Wiklander PROP(TEE_TYPE_HMAC_SHA3_512, 8, 256, 1024,
575260b4028SJens Wiklander 1024 / 8 + sizeof(struct tee_cryp_obj_secret),
576260b4028SJens Wiklander tee_cryp_obj_secret_value_attrs),
57747645577SJerome Forissier PROP(TEE_TYPE_HMAC_SM3, 8, 80, 1024,
57847645577SJerome Forissier 512 / 8 + sizeof(struct tee_cryp_obj_secret),
57947645577SJerome Forissier tee_cryp_obj_secret_value_attrs),
580b0104773SPascal Brand PROP(TEE_TYPE_GENERIC_SECRET, 8, 0, 4096,
581b0104773SPascal Brand 4096 / 8 + sizeof(struct tee_cryp_obj_secret),
582b0104773SPascal Brand tee_cryp_obj_secret_value_attrs),
583cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
584cdb198a7SJerome Forissier PROP(TEE_TYPE_HKDF_IKM, 8, 0, 4096,
585cdb198a7SJerome Forissier 4096 / 8 + sizeof(struct tee_cryp_obj_secret),
586cdb198a7SJerome Forissier tee_cryp_obj_hkdf_ikm_attrs),
587cdb198a7SJerome Forissier #endif
5888854d3c6SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
5898854d3c6SJerome Forissier PROP(TEE_TYPE_CONCAT_KDF_Z, 8, 0, 4096,
5908854d3c6SJerome Forissier 4096 / 8 + sizeof(struct tee_cryp_obj_secret),
5918854d3c6SJerome Forissier tee_cryp_obj_concat_kdf_z_attrs),
5928854d3c6SJerome Forissier #endif
5930f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
5940f2293b7SJerome Forissier PROP(TEE_TYPE_PBKDF2_PASSWORD, 8, 0, 4096,
5950f2293b7SJerome Forissier 4096 / 8 + sizeof(struct tee_cryp_obj_secret),
5960f2293b7SJerome Forissier tee_cryp_obj_pbkdf2_passwd_attrs),
5970f2293b7SJerome Forissier #endif
598bdc919a5SJerome Forissier PROP(TEE_TYPE_RSA_PUBLIC_KEY, 1, 256, CFG_CORE_BIGNUM_MAX_BITS,
599ffe04039SJerome Forissier sizeof(struct rsa_public_key),
600b0104773SPascal Brand tee_cryp_obj_rsa_pub_key_attrs),
601b0104773SPascal Brand
602bdc919a5SJerome Forissier PROP(TEE_TYPE_RSA_KEYPAIR, 1, 256, CFG_CORE_BIGNUM_MAX_BITS,
603ffe04039SJerome Forissier sizeof(struct rsa_keypair),
604b0104773SPascal Brand tee_cryp_obj_rsa_keypair_attrs),
605b0104773SPascal Brand
606aeb0d927SCedric Chaumont PROP(TEE_TYPE_DSA_PUBLIC_KEY, 64, 512, 3072,
607ffe04039SJerome Forissier sizeof(struct dsa_public_key),
608b0104773SPascal Brand tee_cryp_obj_dsa_pub_key_attrs),
609b0104773SPascal Brand
610aeb0d927SCedric Chaumont PROP(TEE_TYPE_DSA_KEYPAIR, 64, 512, 3072,
611ffe04039SJerome Forissier sizeof(struct dsa_keypair),
612b0104773SPascal Brand tee_cryp_obj_dsa_keypair_attrs),
613b0104773SPascal Brand
614b0104773SPascal Brand PROP(TEE_TYPE_DH_KEYPAIR, 1, 256, 2048,
615ffe04039SJerome Forissier sizeof(struct dh_keypair),
616b0104773SPascal Brand tee_cryp_obj_dh_keypair_attrs),
617aeb0d927SCedric Chaumont
618aeb0d927SCedric Chaumont PROP(TEE_TYPE_ECDSA_PUBLIC_KEY, 1, 192, 521,
619aeb0d927SCedric Chaumont sizeof(struct ecc_public_key),
620aeb0d927SCedric Chaumont tee_cryp_obj_ecc_pub_key_attrs),
621aeb0d927SCedric Chaumont
622aeb0d927SCedric Chaumont PROP(TEE_TYPE_ECDSA_KEYPAIR, 1, 192, 521,
623aeb0d927SCedric Chaumont sizeof(struct ecc_keypair),
624aeb0d927SCedric Chaumont tee_cryp_obj_ecc_keypair_attrs),
625aeb0d927SCedric Chaumont
626aeb0d927SCedric Chaumont PROP(TEE_TYPE_ECDH_PUBLIC_KEY, 1, 192, 521,
627aeb0d927SCedric Chaumont sizeof(struct ecc_public_key),
628aeb0d927SCedric Chaumont tee_cryp_obj_ecc_pub_key_attrs),
629aeb0d927SCedric Chaumont
630aeb0d927SCedric Chaumont PROP(TEE_TYPE_ECDH_KEYPAIR, 1, 192, 521,
631aeb0d927SCedric Chaumont sizeof(struct ecc_keypair),
632aeb0d927SCedric Chaumont tee_cryp_obj_ecc_keypair_attrs),
63391fc6bd8SJerome Forissier
6340f151943SJerome Forissier PROP(TEE_TYPE_SM2_DSA_PUBLIC_KEY, 1, 256, 256,
6350f151943SJerome Forissier sizeof(struct ecc_public_key),
636c2e89f8dSJerome Forissier tee_cryp_obj_sm2_pub_key_attrs),
6370f151943SJerome Forissier
6380f151943SJerome Forissier PROP(TEE_TYPE_SM2_DSA_KEYPAIR, 1, 256, 256,
6390f151943SJerome Forissier sizeof(struct ecc_keypair),
640c2e89f8dSJerome Forissier tee_cryp_obj_sm2_keypair_attrs),
6410f151943SJerome Forissier
64291fc6bd8SJerome Forissier PROP(TEE_TYPE_SM2_PKE_PUBLIC_KEY, 1, 256, 256,
64391fc6bd8SJerome Forissier sizeof(struct ecc_public_key),
644c2e89f8dSJerome Forissier tee_cryp_obj_sm2_pub_key_attrs),
64591fc6bd8SJerome Forissier
64691fc6bd8SJerome Forissier PROP(TEE_TYPE_SM2_PKE_KEYPAIR, 1, 256, 256,
64791fc6bd8SJerome Forissier sizeof(struct ecc_keypair),
648c2e89f8dSJerome Forissier tee_cryp_obj_sm2_keypair_attrs),
6495b385b3fSJerome Forissier
6505b385b3fSJerome Forissier PROP(TEE_TYPE_SM2_KEP_PUBLIC_KEY, 1, 256, 256,
6515b385b3fSJerome Forissier sizeof(struct ecc_public_key),
652c2e89f8dSJerome Forissier tee_cryp_obj_sm2_pub_key_attrs),
6535b385b3fSJerome Forissier
6545b385b3fSJerome Forissier PROP(TEE_TYPE_SM2_KEP_KEYPAIR, 1, 256, 256,
6555b385b3fSJerome Forissier sizeof(struct ecc_keypair),
656c2e89f8dSJerome Forissier tee_cryp_obj_sm2_keypair_attrs),
65790040fa4SSohaib ul Hassan
65890040fa4SSohaib ul Hassan PROP(TEE_TYPE_X25519_KEYPAIR, 1, 256, 256,
65946e25a17Sloubaihui sizeof(struct montgomery_keypair),
66090040fa4SSohaib ul Hassan tee_cryp_obj_x25519_keypair_attrs),
6610aaad418SValerii Chubar
66234ce35b1Sloubaihui PROP(TEE_TYPE_X448_KEYPAIR, 1, 448, 448,
66334ce35b1Sloubaihui sizeof(struct montgomery_keypair),
66434ce35b1Sloubaihui tee_cryp_obj_x448_keypair_attrs),
66534ce35b1Sloubaihui
6660aaad418SValerii Chubar PROP(TEE_TYPE_ED25519_PUBLIC_KEY, 1, 256, 256,
667c4cab13eSClement Faure sizeof(struct ed25519_public_key),
6680aaad418SValerii Chubar tee_cryp_obj_ed25519_pub_key_attrs),
6690aaad418SValerii Chubar
6700aaad418SValerii Chubar PROP(TEE_TYPE_ED25519_KEYPAIR, 1, 256, 256,
6710aaad418SValerii Chubar sizeof(struct ed25519_keypair),
6720aaad418SValerii Chubar tee_cryp_obj_ed25519_keypair_attrs),
673b0104773SPascal Brand };
674b0104773SPascal Brand
67540a4fd66SJens Wiklander struct attr_ops {
67640a4fd66SJens Wiklander TEE_Result (*from_user)(void *attr, const void *buffer, size_t size);
67700b3b9a2SJens Wiklander TEE_Result (*to_user)(void *attr, struct ts_session *sess,
67840a4fd66SJens Wiklander void *buffer, uint64_t *size);
679bd3efa26SZeng Tao TEE_Result (*to_binary)(void *attr, void *data, size_t data_len,
68040a4fd66SJens Wiklander size_t *offs);
68140a4fd66SJens Wiklander bool (*from_binary)(void *attr, const void *data, size_t data_len,
68240a4fd66SJens Wiklander size_t *offs);
68340a4fd66SJens Wiklander TEE_Result (*from_obj)(void *attr, void *src_attr);
68440a4fd66SJens Wiklander void (*free)(void *attr);
68540a4fd66SJens Wiklander void (*clear)(void *attr);
68640a4fd66SJens Wiklander };
68740a4fd66SJens Wiklander
op_u32_to_binary_helper(uint32_t v,uint8_t * data,size_t data_len,size_t * offs)688bd3efa26SZeng Tao static TEE_Result op_u32_to_binary_helper(uint32_t v, uint8_t *data,
68940a4fd66SJens Wiklander size_t data_len, size_t *offs)
69040a4fd66SJens Wiklander {
69140a4fd66SJens Wiklander uint32_t field;
692bd3efa26SZeng Tao size_t next_offs;
69340a4fd66SJens Wiklander
694bd3efa26SZeng Tao if (ADD_OVERFLOW(*offs, sizeof(field), &next_offs))
695bd3efa26SZeng Tao return TEE_ERROR_OVERFLOW;
696bd3efa26SZeng Tao
697bd3efa26SZeng Tao if (data && next_offs <= data_len) {
69840a4fd66SJens Wiklander field = TEE_U32_TO_BIG_ENDIAN(v);
69940a4fd66SJens Wiklander memcpy(data + *offs, &field, sizeof(field));
70040a4fd66SJens Wiklander }
701bd3efa26SZeng Tao (*offs) = next_offs;
702bd3efa26SZeng Tao
703bd3efa26SZeng Tao return TEE_SUCCESS;
70440a4fd66SJens Wiklander }
70540a4fd66SJens Wiklander
op_u32_from_binary_helper(uint32_t * v,const uint8_t * data,size_t data_len,size_t * offs)70640a4fd66SJens Wiklander static bool op_u32_from_binary_helper(uint32_t *v, const uint8_t *data,
70740a4fd66SJens Wiklander size_t data_len, size_t *offs)
70840a4fd66SJens Wiklander {
70940a4fd66SJens Wiklander uint32_t field;
71040a4fd66SJens Wiklander
71140a4fd66SJens Wiklander if (!data || (*offs + sizeof(field)) > data_len)
71240a4fd66SJens Wiklander return false;
71340a4fd66SJens Wiklander
71440a4fd66SJens Wiklander memcpy(&field, data + *offs, sizeof(field));
71540a4fd66SJens Wiklander *v = TEE_U32_FROM_BIG_ENDIAN(field);
71640a4fd66SJens Wiklander (*offs) += sizeof(field);
71740a4fd66SJens Wiklander return true;
71840a4fd66SJens Wiklander }
71940a4fd66SJens Wiklander
op_attr_secret_value_from_user(void * attr,const void * buffer,size_t size)72040a4fd66SJens Wiklander static TEE_Result op_attr_secret_value_from_user(void *attr, const void *buffer,
72140a4fd66SJens Wiklander size_t size)
72240a4fd66SJens Wiklander {
723a844a0b8SSeonghyun Park TEE_Result res = TEE_SUCCESS;
72440a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
72540a4fd66SJens Wiklander
72640a4fd66SJens Wiklander /* Data size has to fit in allocated buffer */
72740a4fd66SJens Wiklander if (size > key->alloc_size)
72840a4fd66SJens Wiklander return TEE_ERROR_SECURITY;
729a844a0b8SSeonghyun Park res = copy_from_user(key + 1, buffer, size);
730a844a0b8SSeonghyun Park if (!res)
73140a4fd66SJens Wiklander key->key_size = size;
732a844a0b8SSeonghyun Park
733a844a0b8SSeonghyun Park return res;
73440a4fd66SJens Wiklander }
73540a4fd66SJens Wiklander
op_attr_secret_value_to_user(void * attr,struct ts_session * sess __unused,void * buffer,uint64_t * size)73640a4fd66SJens Wiklander static TEE_Result op_attr_secret_value_to_user(void *attr,
73700b3b9a2SJens Wiklander struct ts_session *sess __unused,
73840a4fd66SJens Wiklander void *buffer, uint64_t *size)
73940a4fd66SJens Wiklander {
74040a4fd66SJens Wiklander TEE_Result res;
74140a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
74240a4fd66SJens Wiklander uint64_t s;
74340a4fd66SJens Wiklander uint64_t key_size;
74440a4fd66SJens Wiklander
745c40a6505SJens Wiklander res = copy_from_user(&s, size, sizeof(s));
74640a4fd66SJens Wiklander if (res != TEE_SUCCESS)
74740a4fd66SJens Wiklander return res;
74840a4fd66SJens Wiklander
74940a4fd66SJens Wiklander key_size = key->key_size;
750c40a6505SJens Wiklander res = copy_to_user(size, &key_size, sizeof(key_size));
75140a4fd66SJens Wiklander if (res != TEE_SUCCESS)
75240a4fd66SJens Wiklander return res;
75340a4fd66SJens Wiklander
75409bce883SJens Wiklander if (s < key->key_size || !buffer)
75540a4fd66SJens Wiklander return TEE_ERROR_SHORT_BUFFER;
75640a4fd66SJens Wiklander
757c40a6505SJens Wiklander return copy_to_user(buffer, key + 1, key->key_size);
75840a4fd66SJens Wiklander }
75940a4fd66SJens Wiklander
op_attr_secret_value_to_binary(void * attr,void * data,size_t data_len,size_t * offs)760bd3efa26SZeng Tao static TEE_Result op_attr_secret_value_to_binary(void *attr, void *data,
76140a4fd66SJens Wiklander size_t data_len, size_t *offs)
76240a4fd66SJens Wiklander {
763bd3efa26SZeng Tao TEE_Result res;
76440a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
765bd3efa26SZeng Tao size_t next_offs;
76640a4fd66SJens Wiklander
767bd3efa26SZeng Tao res = op_u32_to_binary_helper(key->key_size, data, data_len, offs);
768bd3efa26SZeng Tao if (res != TEE_SUCCESS)
769bd3efa26SZeng Tao return res;
770bd3efa26SZeng Tao
771bd3efa26SZeng Tao if (ADD_OVERFLOW(*offs, key->key_size, &next_offs))
772bd3efa26SZeng Tao return TEE_ERROR_OVERFLOW;
773bd3efa26SZeng Tao
774bd3efa26SZeng Tao if (data && next_offs <= data_len)
77540a4fd66SJens Wiklander memcpy((uint8_t *)data + *offs, key + 1, key->key_size);
776bd3efa26SZeng Tao (*offs) = next_offs;
777bd3efa26SZeng Tao
778bd3efa26SZeng Tao return TEE_SUCCESS;
77940a4fd66SJens Wiklander }
78040a4fd66SJens Wiklander
op_attr_secret_value_from_binary(void * attr,const void * data,size_t data_len,size_t * offs)78140a4fd66SJens Wiklander static bool op_attr_secret_value_from_binary(void *attr, const void *data,
78240a4fd66SJens Wiklander size_t data_len, size_t *offs)
78340a4fd66SJens Wiklander {
78440a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
78540a4fd66SJens Wiklander uint32_t s;
78640a4fd66SJens Wiklander
78740a4fd66SJens Wiklander if (!op_u32_from_binary_helper(&s, data, data_len, offs))
78840a4fd66SJens Wiklander return false;
78940a4fd66SJens Wiklander
79040a4fd66SJens Wiklander if ((*offs + s) > data_len)
79140a4fd66SJens Wiklander return false;
79240a4fd66SJens Wiklander
79340a4fd66SJens Wiklander /* Data size has to fit in allocated buffer */
79440a4fd66SJens Wiklander if (s > key->alloc_size)
79540a4fd66SJens Wiklander return false;
79640a4fd66SJens Wiklander key->key_size = s;
79740a4fd66SJens Wiklander memcpy(key + 1, (const uint8_t *)data + *offs, s);
79840a4fd66SJens Wiklander (*offs) += s;
79940a4fd66SJens Wiklander return true;
80040a4fd66SJens Wiklander }
80140a4fd66SJens Wiklander
80240a4fd66SJens Wiklander
op_attr_secret_value_from_obj(void * attr,void * src_attr)80340a4fd66SJens Wiklander static TEE_Result op_attr_secret_value_from_obj(void *attr, void *src_attr)
80440a4fd66SJens Wiklander {
80540a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
80640a4fd66SJens Wiklander struct tee_cryp_obj_secret *src_key = src_attr;
80740a4fd66SJens Wiklander
80840a4fd66SJens Wiklander if (src_key->key_size > key->alloc_size)
80940a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
81040a4fd66SJens Wiklander memcpy(key + 1, src_key + 1, src_key->key_size);
81140a4fd66SJens Wiklander key->key_size = src_key->key_size;
81240a4fd66SJens Wiklander return TEE_SUCCESS;
81340a4fd66SJens Wiklander }
81440a4fd66SJens Wiklander
op_attr_secret_value_clear(void * attr)81540a4fd66SJens Wiklander static void op_attr_secret_value_clear(void *attr)
81640a4fd66SJens Wiklander {
81740a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = attr;
81840a4fd66SJens Wiklander
81940a4fd66SJens Wiklander key->key_size = 0;
820e55ecd13SStefan Schmidt memzero_explicit(key + 1, key->alloc_size);
82140a4fd66SJens Wiklander }
82240a4fd66SJens Wiklander
op_attr_bignum_from_user(void * attr,const void * buffer,size_t size)82340a4fd66SJens Wiklander static TEE_Result op_attr_bignum_from_user(void *attr, const void *buffer,
82440a4fd66SJens Wiklander size_t size)
82540a4fd66SJens Wiklander {
826a844a0b8SSeonghyun Park TEE_Result res = TEE_SUCCESS;
82740a4fd66SJens Wiklander struct bignum **bn = attr;
828a844a0b8SSeonghyun Park void *bbuf = NULL;
82940a4fd66SJens Wiklander
830a844a0b8SSeonghyun Park res = bb_memdup_user(buffer, size, &bbuf);
831a844a0b8SSeonghyun Park if (res)
832a844a0b8SSeonghyun Park return res;
833a844a0b8SSeonghyun Park
834a844a0b8SSeonghyun Park res = crypto_bignum_bin2bn(bbuf, size, *bn);
835a844a0b8SSeonghyun Park
836a844a0b8SSeonghyun Park bb_free(bbuf, size);
837a844a0b8SSeonghyun Park
838a844a0b8SSeonghyun Park return res;
83940a4fd66SJens Wiklander }
84040a4fd66SJens Wiklander
op_attr_bignum_to_user(void * attr,struct ts_session * sess __unused,void * buffer,uint64_t * size)84140a4fd66SJens Wiklander static TEE_Result op_attr_bignum_to_user(void *attr,
842a844a0b8SSeonghyun Park struct ts_session *sess __unused,
84340a4fd66SJens Wiklander void *buffer, uint64_t *size)
84440a4fd66SJens Wiklander {
8451936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
84640a4fd66SJens Wiklander struct bignum **bn = attr;
8471936dfc7SJens Wiklander uint64_t req_size = 0;
8481936dfc7SJens Wiklander uint64_t s = 0;
849a844a0b8SSeonghyun Park void *bbuf = NULL;
85040a4fd66SJens Wiklander
851c40a6505SJens Wiklander res = copy_from_user(&s, size, sizeof(s));
85240a4fd66SJens Wiklander if (res != TEE_SUCCESS)
85340a4fd66SJens Wiklander return res;
85440a4fd66SJens Wiklander
85533790cc1SJens Wiklander req_size = crypto_bignum_num_bytes(*bn);
856c40a6505SJens Wiklander res = copy_to_user(size, &req_size, sizeof(req_size));
85740a4fd66SJens Wiklander if (res != TEE_SUCCESS)
85840a4fd66SJens Wiklander return res;
85940a4fd66SJens Wiklander if (!req_size)
86040a4fd66SJens Wiklander return TEE_SUCCESS;
86109bce883SJens Wiklander if (s < req_size || !buffer)
86240a4fd66SJens Wiklander return TEE_ERROR_SHORT_BUFFER;
86340a4fd66SJens Wiklander
864a844a0b8SSeonghyun Park bbuf = bb_alloc(req_size);
865a844a0b8SSeonghyun Park if (!bbuf)
866a844a0b8SSeonghyun Park return TEE_ERROR_OUT_OF_MEMORY;
867adf8325bSJerome Forissier
86840a4fd66SJens Wiklander /*
86940a4fd66SJens Wiklander * Write the bignum (wich raw data points to) into an array of
87040a4fd66SJens Wiklander * bytes (stored in buffer)
87140a4fd66SJens Wiklander */
872a844a0b8SSeonghyun Park crypto_bignum_bn2bin(*bn, bbuf);
873a844a0b8SSeonghyun Park res = copy_to_user(buffer, bbuf, req_size);
874a844a0b8SSeonghyun Park
875a844a0b8SSeonghyun Park bb_free(bbuf, req_size);
876a844a0b8SSeonghyun Park return res;
87740a4fd66SJens Wiklander }
87840a4fd66SJens Wiklander
op_attr_bignum_to_binary(void * attr,void * data,size_t data_len,size_t * offs)879bd3efa26SZeng Tao static TEE_Result op_attr_bignum_to_binary(void *attr, void *data,
880bd3efa26SZeng Tao size_t data_len, size_t *offs)
88140a4fd66SJens Wiklander {
882bd3efa26SZeng Tao TEE_Result res;
88340a4fd66SJens Wiklander struct bignum **bn = attr;
88433790cc1SJens Wiklander uint32_t n = crypto_bignum_num_bytes(*bn);
885bd3efa26SZeng Tao size_t next_offs;
88640a4fd66SJens Wiklander
887bd3efa26SZeng Tao res = op_u32_to_binary_helper(n, data, data_len, offs);
888bd3efa26SZeng Tao if (res != TEE_SUCCESS)
889bd3efa26SZeng Tao return res;
89040a4fd66SJens Wiklander
891bd3efa26SZeng Tao if (ADD_OVERFLOW(*offs, n, &next_offs))
892bd3efa26SZeng Tao return TEE_ERROR_OVERFLOW;
893bd3efa26SZeng Tao
894bd3efa26SZeng Tao if (data && next_offs <= data_len)
89533790cc1SJens Wiklander crypto_bignum_bn2bin(*bn, (uint8_t *)data + *offs);
896bd3efa26SZeng Tao (*offs) = next_offs;
897bd3efa26SZeng Tao
898bd3efa26SZeng Tao return TEE_SUCCESS;
89940a4fd66SJens Wiklander }
90040a4fd66SJens Wiklander
op_attr_bignum_from_binary(void * attr,const void * data,size_t data_len,size_t * offs)90140a4fd66SJens Wiklander static bool op_attr_bignum_from_binary(void *attr, const void *data,
90240a4fd66SJens Wiklander size_t data_len, size_t *offs)
90340a4fd66SJens Wiklander {
90440a4fd66SJens Wiklander struct bignum **bn = attr;
90540a4fd66SJens Wiklander uint32_t n;
90640a4fd66SJens Wiklander
90740a4fd66SJens Wiklander if (!op_u32_from_binary_helper(&n, data, data_len, offs))
90840a4fd66SJens Wiklander return false;
90940a4fd66SJens Wiklander
91040a4fd66SJens Wiklander if ((*offs + n) > data_len)
91140a4fd66SJens Wiklander return false;
91233790cc1SJens Wiklander if (crypto_bignum_bin2bn((const uint8_t *)data + *offs, n, *bn))
91340a4fd66SJens Wiklander return false;
91440a4fd66SJens Wiklander (*offs) += n;
91540a4fd66SJens Wiklander return true;
91640a4fd66SJens Wiklander }
91740a4fd66SJens Wiklander
op_attr_bignum_from_obj(void * attr,void * src_attr)91840a4fd66SJens Wiklander static TEE_Result op_attr_bignum_from_obj(void *attr, void *src_attr)
91940a4fd66SJens Wiklander {
92040a4fd66SJens Wiklander struct bignum **bn = attr;
92140a4fd66SJens Wiklander struct bignum **src_bn = src_attr;
92240a4fd66SJens Wiklander
92333790cc1SJens Wiklander crypto_bignum_copy(*bn, *src_bn);
92440a4fd66SJens Wiklander return TEE_SUCCESS;
92540a4fd66SJens Wiklander }
92640a4fd66SJens Wiklander
op_attr_bignum_clear(void * attr)92740a4fd66SJens Wiklander static void op_attr_bignum_clear(void *attr)
92840a4fd66SJens Wiklander {
92940a4fd66SJens Wiklander struct bignum **bn = attr;
93040a4fd66SJens Wiklander
93133790cc1SJens Wiklander crypto_bignum_clear(*bn);
93240a4fd66SJens Wiklander }
93340a4fd66SJens Wiklander
op_attr_bignum_free(void * attr)93440a4fd66SJens Wiklander static void op_attr_bignum_free(void *attr)
93540a4fd66SJens Wiklander {
93640a4fd66SJens Wiklander struct bignum **bn = attr;
93740a4fd66SJens Wiklander
938e2ec831cSJihwan Park crypto_bignum_free(bn);
93940a4fd66SJens Wiklander }
94040a4fd66SJens Wiklander
op_attr_value_from_user(void * attr,const void * buffer,size_t size)94140a4fd66SJens Wiklander static TEE_Result op_attr_value_from_user(void *attr, const void *buffer,
94240a4fd66SJens Wiklander size_t size)
94340a4fd66SJens Wiklander {
94440a4fd66SJens Wiklander uint32_t *v = attr;
94540a4fd66SJens Wiklander
94640a4fd66SJens Wiklander if (size != sizeof(uint32_t) * 2)
94740a4fd66SJens Wiklander return TEE_ERROR_GENERIC; /* "can't happen */
94840a4fd66SJens Wiklander
94940a4fd66SJens Wiklander /* Note that only the first value is copied */
95040a4fd66SJens Wiklander memcpy(v, buffer, sizeof(uint32_t));
95140a4fd66SJens Wiklander return TEE_SUCCESS;
95240a4fd66SJens Wiklander }
95340a4fd66SJens Wiklander
op_attr_value_to_user(void * attr,struct ts_session * sess __unused,void * buffer,uint64_t * size)954eebf7990SJens Wiklander static TEE_Result op_attr_value_to_user(void *attr,
95500b3b9a2SJens Wiklander struct ts_session *sess __unused,
95640a4fd66SJens Wiklander void *buffer, uint64_t *size)
95740a4fd66SJens Wiklander {
95840a4fd66SJens Wiklander TEE_Result res;
95940a4fd66SJens Wiklander uint32_t *v = attr;
96040a4fd66SJens Wiklander uint64_t s;
96140a4fd66SJens Wiklander uint32_t value[2] = { *v };
96240a4fd66SJens Wiklander uint64_t req_size = sizeof(value);
96340a4fd66SJens Wiklander
964c40a6505SJens Wiklander res = copy_from_user(&s, size, sizeof(s));
96540a4fd66SJens Wiklander if (res != TEE_SUCCESS)
96640a4fd66SJens Wiklander return res;
96740a4fd66SJens Wiklander
96809bce883SJens Wiklander if (s < req_size || !buffer)
96940a4fd66SJens Wiklander return TEE_ERROR_SHORT_BUFFER;
97040a4fd66SJens Wiklander
971c40a6505SJens Wiklander return copy_to_user(buffer, value, req_size);
97240a4fd66SJens Wiklander }
97340a4fd66SJens Wiklander
op_attr_value_to_binary(void * attr,void * data,size_t data_len,size_t * offs)974bd3efa26SZeng Tao static TEE_Result op_attr_value_to_binary(void *attr, void *data,
975bd3efa26SZeng Tao size_t data_len, size_t *offs)
97640a4fd66SJens Wiklander {
97740a4fd66SJens Wiklander uint32_t *v = attr;
97840a4fd66SJens Wiklander
979bd3efa26SZeng Tao return op_u32_to_binary_helper(*v, data, data_len, offs);
98040a4fd66SJens Wiklander }
98140a4fd66SJens Wiklander
op_attr_value_from_binary(void * attr,const void * data,size_t data_len,size_t * offs)98240a4fd66SJens Wiklander static bool op_attr_value_from_binary(void *attr, const void *data,
98340a4fd66SJens Wiklander size_t data_len, size_t *offs)
98440a4fd66SJens Wiklander {
98540a4fd66SJens Wiklander uint32_t *v = attr;
98640a4fd66SJens Wiklander
98740a4fd66SJens Wiklander return op_u32_from_binary_helper(v, data, data_len, offs);
98840a4fd66SJens Wiklander }
98940a4fd66SJens Wiklander
op_attr_value_from_obj(void * attr,void * src_attr)99040a4fd66SJens Wiklander static TEE_Result op_attr_value_from_obj(void *attr, void *src_attr)
99140a4fd66SJens Wiklander {
99240a4fd66SJens Wiklander uint32_t *v = attr;
99340a4fd66SJens Wiklander uint32_t *src_v = src_attr;
99440a4fd66SJens Wiklander
99540a4fd66SJens Wiklander *v = *src_v;
99640a4fd66SJens Wiklander return TEE_SUCCESS;
99740a4fd66SJens Wiklander }
99840a4fd66SJens Wiklander
op_attr_value_clear(void * attr)99940a4fd66SJens Wiklander static void op_attr_value_clear(void *attr)
100040a4fd66SJens Wiklander {
100140a4fd66SJens Wiklander uint32_t *v = attr;
100240a4fd66SJens Wiklander
100340a4fd66SJens Wiklander *v = 0;
100440a4fd66SJens Wiklander }
100540a4fd66SJens Wiklander
op_attr_25519_from_user(void * attr,const void * buffer,size_t size)100690040fa4SSohaib ul Hassan static TEE_Result op_attr_25519_from_user(void *attr, const void *buffer,
100790040fa4SSohaib ul Hassan size_t size)
100890040fa4SSohaib ul Hassan {
100990040fa4SSohaib ul Hassan uint8_t **key = attr;
101090040fa4SSohaib ul Hassan
101190040fa4SSohaib ul Hassan if (size != KEY_SIZE_BYTES_25519 || !*key)
101290040fa4SSohaib ul Hassan return TEE_ERROR_SECURITY;
101390040fa4SSohaib ul Hassan
1014a844a0b8SSeonghyun Park return copy_from_user(*key, buffer, size);
101590040fa4SSohaib ul Hassan }
101690040fa4SSohaib ul Hassan
op_attr_25519_to_user(void * attr,struct ts_session * sess __unused,void * buffer,uint64_t * size)101790040fa4SSohaib ul Hassan static TEE_Result op_attr_25519_to_user(void *attr,
101890040fa4SSohaib ul Hassan struct ts_session *sess __unused,
101990040fa4SSohaib ul Hassan void *buffer, uint64_t *size)
102090040fa4SSohaib ul Hassan {
102190040fa4SSohaib ul Hassan TEE_Result res = TEE_ERROR_GENERIC;
102290040fa4SSohaib ul Hassan uint8_t **key = attr;
102390040fa4SSohaib ul Hassan uint64_t s = 0;
102490040fa4SSohaib ul Hassan uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519;
102590040fa4SSohaib ul Hassan
102690040fa4SSohaib ul Hassan res = copy_from_user(&s, size, sizeof(s));
102790040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
102890040fa4SSohaib ul Hassan return res;
102990040fa4SSohaib ul Hassan
103090040fa4SSohaib ul Hassan res = copy_to_user(size, &key_size, sizeof(key_size));
103190040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
103290040fa4SSohaib ul Hassan return res;
103390040fa4SSohaib ul Hassan
103490040fa4SSohaib ul Hassan if (s < key_size || !buffer)
103590040fa4SSohaib ul Hassan return TEE_ERROR_SHORT_BUFFER;
103690040fa4SSohaib ul Hassan
103790040fa4SSohaib ul Hassan return copy_to_user(buffer, *key, key_size);
103890040fa4SSohaib ul Hassan }
103990040fa4SSohaib ul Hassan
op_attr_25519_to_binary(void * attr,void * data,size_t data_len,size_t * offs)104090040fa4SSohaib ul Hassan static TEE_Result op_attr_25519_to_binary(void *attr, void *data,
104190040fa4SSohaib ul Hassan size_t data_len, size_t *offs)
104290040fa4SSohaib ul Hassan {
104390040fa4SSohaib ul Hassan TEE_Result res = TEE_ERROR_GENERIC;
104490040fa4SSohaib ul Hassan uint8_t **key = attr;
104590040fa4SSohaib ul Hassan size_t next_offs = 0;
104690040fa4SSohaib ul Hassan uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519;
104790040fa4SSohaib ul Hassan
104890040fa4SSohaib ul Hassan res = op_u32_to_binary_helper(key_size, data, data_len, offs);
104990040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
105090040fa4SSohaib ul Hassan return res;
105190040fa4SSohaib ul Hassan
105290040fa4SSohaib ul Hassan if (ADD_OVERFLOW(*offs, key_size, &next_offs))
105390040fa4SSohaib ul Hassan return TEE_ERROR_OVERFLOW;
105490040fa4SSohaib ul Hassan
105590040fa4SSohaib ul Hassan if (data && next_offs <= data_len)
105690040fa4SSohaib ul Hassan memcpy((uint8_t *)data + *offs, *key, key_size);
105790040fa4SSohaib ul Hassan *offs = next_offs;
105890040fa4SSohaib ul Hassan
105990040fa4SSohaib ul Hassan return TEE_SUCCESS;
106090040fa4SSohaib ul Hassan }
106190040fa4SSohaib ul Hassan
op_attr_25519_from_binary(void * attr,const void * data,size_t data_len,size_t * offs)106290040fa4SSohaib ul Hassan static bool op_attr_25519_from_binary(void *attr, const void *data,
106390040fa4SSohaib ul Hassan size_t data_len, size_t *offs)
106490040fa4SSohaib ul Hassan {
106590040fa4SSohaib ul Hassan uint8_t **key = attr;
106690040fa4SSohaib ul Hassan uint32_t s = 0;
106790040fa4SSohaib ul Hassan
106890040fa4SSohaib ul Hassan if (!op_u32_from_binary_helper(&s, data, data_len, offs))
106990040fa4SSohaib ul Hassan return false;
107090040fa4SSohaib ul Hassan
107190040fa4SSohaib ul Hassan if (*offs + s > data_len)
107290040fa4SSohaib ul Hassan return false;
107390040fa4SSohaib ul Hassan
107490040fa4SSohaib ul Hassan if (s > (uint32_t)KEY_SIZE_BYTES_25519)
107590040fa4SSohaib ul Hassan return false;
107690040fa4SSohaib ul Hassan
107790040fa4SSohaib ul Hassan memcpy(*key, (const uint8_t *)data + *offs, s);
107890040fa4SSohaib ul Hassan *offs += s;
107990040fa4SSohaib ul Hassan return true;
108090040fa4SSohaib ul Hassan }
108190040fa4SSohaib ul Hassan
op_attr_25519_from_obj(void * attr,void * src_attr)108290040fa4SSohaib ul Hassan static TEE_Result op_attr_25519_from_obj(void *attr, void *src_attr)
108390040fa4SSohaib ul Hassan {
108490040fa4SSohaib ul Hassan uint8_t **key = attr;
108590040fa4SSohaib ul Hassan uint8_t **src_key = src_attr;
108690040fa4SSohaib ul Hassan
108790040fa4SSohaib ul Hassan if (!*key || !*src_key)
108890040fa4SSohaib ul Hassan return TEE_ERROR_SECURITY;
108990040fa4SSohaib ul Hassan
109090040fa4SSohaib ul Hassan memcpy(*key, *src_key, KEY_SIZE_BYTES_25519);
109190040fa4SSohaib ul Hassan
109290040fa4SSohaib ul Hassan return TEE_SUCCESS;
109390040fa4SSohaib ul Hassan }
109490040fa4SSohaib ul Hassan
op_attr_25519_clear(void * attr)109590040fa4SSohaib ul Hassan static void op_attr_25519_clear(void *attr)
109690040fa4SSohaib ul Hassan {
109790040fa4SSohaib ul Hassan uint8_t **key = attr;
109890040fa4SSohaib ul Hassan
109990040fa4SSohaib ul Hassan assert(*key);
110090040fa4SSohaib ul Hassan
110190040fa4SSohaib ul Hassan memzero_explicit(*key, KEY_SIZE_BYTES_25519);
110290040fa4SSohaib ul Hassan }
110390040fa4SSohaib ul Hassan
op_attr_25519_free(void * attr)110490040fa4SSohaib ul Hassan static void op_attr_25519_free(void *attr)
110590040fa4SSohaib ul Hassan {
110690040fa4SSohaib ul Hassan uint8_t **key = attr;
110790040fa4SSohaib ul Hassan
110890040fa4SSohaib ul Hassan op_attr_25519_clear(attr);
110990040fa4SSohaib ul Hassan free(*key);
111090040fa4SSohaib ul Hassan }
111190040fa4SSohaib ul Hassan
111240a4fd66SJens Wiklander static const struct attr_ops attr_ops[] = {
111340a4fd66SJens Wiklander [ATTR_OPS_INDEX_SECRET] = {
111440a4fd66SJens Wiklander .from_user = op_attr_secret_value_from_user,
111540a4fd66SJens Wiklander .to_user = op_attr_secret_value_to_user,
111640a4fd66SJens Wiklander .to_binary = op_attr_secret_value_to_binary,
111740a4fd66SJens Wiklander .from_binary = op_attr_secret_value_from_binary,
111840a4fd66SJens Wiklander .from_obj = op_attr_secret_value_from_obj,
111940a4fd66SJens Wiklander .free = op_attr_secret_value_clear, /* not a typo */
112040a4fd66SJens Wiklander .clear = op_attr_secret_value_clear,
112140a4fd66SJens Wiklander },
112240a4fd66SJens Wiklander [ATTR_OPS_INDEX_BIGNUM] = {
112340a4fd66SJens Wiklander .from_user = op_attr_bignum_from_user,
112440a4fd66SJens Wiklander .to_user = op_attr_bignum_to_user,
112540a4fd66SJens Wiklander .to_binary = op_attr_bignum_to_binary,
112640a4fd66SJens Wiklander .from_binary = op_attr_bignum_from_binary,
112740a4fd66SJens Wiklander .from_obj = op_attr_bignum_from_obj,
112840a4fd66SJens Wiklander .free = op_attr_bignum_free,
112940a4fd66SJens Wiklander .clear = op_attr_bignum_clear,
113040a4fd66SJens Wiklander },
113140a4fd66SJens Wiklander [ATTR_OPS_INDEX_VALUE] = {
113240a4fd66SJens Wiklander .from_user = op_attr_value_from_user,
113340a4fd66SJens Wiklander .to_user = op_attr_value_to_user,
113440a4fd66SJens Wiklander .to_binary = op_attr_value_to_binary,
113540a4fd66SJens Wiklander .from_binary = op_attr_value_from_binary,
113640a4fd66SJens Wiklander .from_obj = op_attr_value_from_obj,
113740a4fd66SJens Wiklander .free = op_attr_value_clear, /* not a typo */
113840a4fd66SJens Wiklander .clear = op_attr_value_clear,
113940a4fd66SJens Wiklander },
114090040fa4SSohaib ul Hassan [ATTR_OPS_INDEX_25519] = {
114190040fa4SSohaib ul Hassan .from_user = op_attr_25519_from_user,
114290040fa4SSohaib ul Hassan .to_user = op_attr_25519_to_user,
114390040fa4SSohaib ul Hassan .to_binary = op_attr_25519_to_binary,
114490040fa4SSohaib ul Hassan .from_binary = op_attr_25519_from_binary,
114590040fa4SSohaib ul Hassan .from_obj = op_attr_25519_from_obj,
114690040fa4SSohaib ul Hassan .free = op_attr_25519_free,
114790040fa4SSohaib ul Hassan .clear = op_attr_25519_clear,
114890040fa4SSohaib ul Hassan },
114940a4fd66SJens Wiklander };
115040a4fd66SJens Wiklander
get_user_u64_as_size_t(size_t * dst,uint64_t * src)115184e9c40bSJens Wiklander static TEE_Result get_user_u64_as_size_t(size_t *dst, uint64_t *src)
115284e9c40bSJens Wiklander {
115384e9c40bSJens Wiklander uint64_t d = 0;
1154c40a6505SJens Wiklander TEE_Result res = copy_from_user(&d, src, sizeof(d));
115584e9c40bSJens Wiklander
115684e9c40bSJens Wiklander /*
115784e9c40bSJens Wiklander * On 32-bit systems a size_t can't hold a uint64_t so we need to
115884e9c40bSJens Wiklander * check that the value isn't too large.
115984e9c40bSJens Wiklander */
116084e9c40bSJens Wiklander if (!res && ADD_OVERFLOW(0, d, dst))
116184e9c40bSJens Wiklander return TEE_ERROR_OVERFLOW;
116284e9c40bSJens Wiklander
116384e9c40bSJens Wiklander return res;
116484e9c40bSJens Wiklander }
116584e9c40bSJens Wiklander
put_user_u64(uint64_t * dst,size_t value)116684e9c40bSJens Wiklander static TEE_Result put_user_u64(uint64_t *dst, size_t value)
116784e9c40bSJens Wiklander {
116884e9c40bSJens Wiklander uint64_t v = value;
116984e9c40bSJens Wiklander
1170c40a6505SJens Wiklander return copy_to_user(dst, &v, sizeof(v));
117184e9c40bSJens Wiklander }
117284e9c40bSJens Wiklander
syscall_cryp_obj_get_info(unsigned long obj,struct utee_object_info * info)117375d6a373SJens Wiklander TEE_Result syscall_cryp_obj_get_info(unsigned long obj,
117475d6a373SJens Wiklander struct utee_object_info *info)
1175b0104773SPascal Brand {
117600b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
117775d6a373SJens Wiklander struct utee_object_info o_info = { };
117800b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
117900b3b9a2SJens Wiklander struct tee_obj *o = NULL;
1180b0104773SPascal Brand
11818684fde8SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx),
1182c40a6505SJens Wiklander uref_to_vaddr(obj), &o);
1183b0104773SPascal Brand if (res != TEE_SUCCESS)
1184a2e9a830SCedric Chaumont goto exit;
1185a2e9a830SCedric Chaumont
118675d6a373SJens Wiklander o_info.obj_type = o->info.objectType;
118775d6a373SJens Wiklander o_info.obj_size = o->info.objectSize;
118875d6a373SJens Wiklander o_info.max_obj_size = o->info.maxObjectSize;
11890f50ba5aSJens Wiklander if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
11900f50ba5aSJens Wiklander tee_pobj_lock_usage(o->pobj);
11910f50ba5aSJens Wiklander o_info.obj_usage = o->pobj->obj_info_usage;
11920f50ba5aSJens Wiklander tee_pobj_unlock_usage(o->pobj);
11930f50ba5aSJens Wiklander } else {
119475d6a373SJens Wiklander o_info.obj_usage = o->info.objectUsage;
11950f50ba5aSJens Wiklander }
119675d6a373SJens Wiklander o_info.data_size = o->info.dataSize;
119775d6a373SJens Wiklander o_info.data_pos = o->info.dataPosition;
119875d6a373SJens Wiklander o_info.handle_flags = o->info.handleFlags;
119975d6a373SJens Wiklander res = copy_to_user_private(info, &o_info, sizeof(o_info));
1200a2e9a830SCedric Chaumont
1201a2e9a830SCedric Chaumont exit:
1202b0104773SPascal Brand return res;
1203b0104773SPascal Brand }
1204b0104773SPascal Brand
syscall_cryp_obj_restrict_usage(unsigned long obj,unsigned long usage)1205e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj,
1206e86f1266SJens Wiklander unsigned long usage)
1207b0104773SPascal Brand {
120800b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
120900b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
121000b3b9a2SJens Wiklander struct tee_obj *o = NULL;
1211b0104773SPascal Brand
1212c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
12130f50ba5aSJens Wiklander if (res)
12140f50ba5aSJens Wiklander return res;
1215b0104773SPascal Brand
12160f50ba5aSJens Wiklander if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
12170f50ba5aSJens Wiklander uint32_t new_usage = 0;
12180f50ba5aSJens Wiklander
12190f50ba5aSJens Wiklander tee_pobj_lock_usage(o->pobj);
12200f50ba5aSJens Wiklander new_usage = o->pobj->obj_info_usage & usage;
12210f50ba5aSJens Wiklander res = tee_svc_storage_write_usage(o, new_usage);
12220f50ba5aSJens Wiklander if (!res)
12230f50ba5aSJens Wiklander o->pobj->obj_info_usage = new_usage;
12240f50ba5aSJens Wiklander tee_pobj_unlock_usage(o->pobj);
12250f50ba5aSJens Wiklander } else {
1226b0104773SPascal Brand o->info.objectUsage &= usage;
12270f50ba5aSJens Wiklander }
1228b0104773SPascal Brand
1229a2e9a830SCedric Chaumont return res;
1230b0104773SPascal Brand }
1231b0104773SPascal Brand
tee_svc_cryp_obj_find_type_attr_idx(uint32_t attr_id,const struct tee_cryp_obj_type_props * type_props)1232b0104773SPascal Brand static int tee_svc_cryp_obj_find_type_attr_idx(
1233b0104773SPascal Brand uint32_t attr_id,
1234b0104773SPascal Brand const struct tee_cryp_obj_type_props *type_props)
1235b0104773SPascal Brand {
1236b0104773SPascal Brand size_t n;
1237b0104773SPascal Brand
1238b0104773SPascal Brand for (n = 0; n < type_props->num_type_attrs; n++) {
1239b0104773SPascal Brand if (attr_id == type_props->type_attrs[n].attr_id)
1240b0104773SPascal Brand return n;
1241b0104773SPascal Brand }
1242b0104773SPascal Brand return -1;
1243b0104773SPascal Brand }
1244b0104773SPascal Brand
tee_svc_find_type_props(TEE_ObjectType obj_type)1245b0104773SPascal Brand static const struct tee_cryp_obj_type_props *tee_svc_find_type_props(
1246b0104773SPascal Brand TEE_ObjectType obj_type)
1247b0104773SPascal Brand {
1248b0104773SPascal Brand size_t n;
1249b0104773SPascal Brand
1250b8d220d2SPascal Brand for (n = 0; n < ARRAY_SIZE(tee_cryp_obj_props); n++) {
1251b0104773SPascal Brand if (tee_cryp_obj_props[n].obj_type == obj_type)
1252b0104773SPascal Brand return tee_cryp_obj_props + n;
1253b0104773SPascal Brand }
1254b0104773SPascal Brand
1255b0104773SPascal Brand return NULL;
1256b0104773SPascal Brand }
1257b0104773SPascal Brand
1258050ba678SJerome Forissier /* Set an attribute on an object */
set_attribute(struct tee_obj * o,const struct tee_cryp_obj_type_props * props,uint32_t attr)1259050ba678SJerome Forissier static void set_attribute(struct tee_obj *o,
1260050ba678SJerome Forissier const struct tee_cryp_obj_type_props *props,
1261050ba678SJerome Forissier uint32_t attr)
1262050ba678SJerome Forissier {
1263050ba678SJerome Forissier int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props);
1264050ba678SJerome Forissier
1265050ba678SJerome Forissier if (idx < 0)
1266050ba678SJerome Forissier return;
1267050ba678SJerome Forissier o->have_attrs |= BIT(idx);
1268050ba678SJerome Forissier }
1269050ba678SJerome Forissier
1270050ba678SJerome Forissier /* Get an attribute on an object */
get_attribute(const struct tee_obj * o,const struct tee_cryp_obj_type_props * props,uint32_t attr)1271050ba678SJerome Forissier static uint32_t get_attribute(const struct tee_obj *o,
1272050ba678SJerome Forissier const struct tee_cryp_obj_type_props *props,
1273050ba678SJerome Forissier uint32_t attr)
1274050ba678SJerome Forissier {
1275050ba678SJerome Forissier int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props);
1276050ba678SJerome Forissier
1277050ba678SJerome Forissier if (idx < 0)
1278050ba678SJerome Forissier return 0;
1279050ba678SJerome Forissier return o->have_attrs & BIT(idx);
1280050ba678SJerome Forissier }
1281050ba678SJerome Forissier
syscall_cryp_obj_get_attr(unsigned long obj,unsigned long attr_id,void * buffer,uint64_t * size)1282e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id,
1283e86f1266SJens Wiklander void *buffer, uint64_t *size)
1284b0104773SPascal Brand {
128500b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
128600b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
128700b3b9a2SJens Wiklander struct tee_obj *o = NULL;
128800b3b9a2SJens Wiklander const struct tee_cryp_obj_type_props *type_props = NULL;
128900b3b9a2SJens Wiklander int idx = 0;
129000b3b9a2SJens Wiklander const struct attr_ops *ops = NULL;
129100b3b9a2SJens Wiklander void *attr = NULL;
12920f50ba5aSJens Wiklander uint32_t obj_usage = 0;
1293b0104773SPascal Brand
1294c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
1295b0104773SPascal Brand if (res != TEE_SUCCESS)
1296b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1297b0104773SPascal Brand
1298b0104773SPascal Brand /* Check that the object is initialized */
1299a2e9a830SCedric Chaumont if (!(o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED))
1300a2e9a830SCedric Chaumont return TEE_ERROR_BAD_PARAMETERS;
1301b0104773SPascal Brand
1302b0104773SPascal Brand /* Check that getting the attribute is allowed */
13030f50ba5aSJens Wiklander if (!(attr_id & TEE_ATTR_FLAG_PUBLIC)) {
13040f50ba5aSJens Wiklander if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
13050f50ba5aSJens Wiklander tee_pobj_lock_usage(o->pobj);
13060f50ba5aSJens Wiklander obj_usage = o->pobj->obj_info_usage;
13070f50ba5aSJens Wiklander tee_pobj_unlock_usage(o->pobj);
13080f50ba5aSJens Wiklander } else {
13090f50ba5aSJens Wiklander obj_usage = o->info.objectUsage;
13100f50ba5aSJens Wiklander }
13110f50ba5aSJens Wiklander if (!(obj_usage & TEE_USAGE_EXTRACTABLE))
1312a2e9a830SCedric Chaumont return TEE_ERROR_BAD_PARAMETERS;
13130f50ba5aSJens Wiklander }
1314b0104773SPascal Brand
1315b0104773SPascal Brand type_props = tee_svc_find_type_props(o->info.objectType);
1316ffe04039SJerome Forissier if (!type_props) {
1317b0104773SPascal Brand /* Unknown object type, "can't happen" */
1318b0104773SPascal Brand return TEE_ERROR_BAD_STATE;
1319b0104773SPascal Brand }
1320b0104773SPascal Brand
1321b0104773SPascal Brand idx = tee_svc_cryp_obj_find_type_attr_idx(attr_id, type_props);
1322b0104773SPascal Brand if ((idx < 0) || ((o->have_attrs & (1 << idx)) == 0))
1323b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1324b0104773SPascal Brand
132540a4fd66SJens Wiklander ops = attr_ops + type_props->type_attrs[idx].ops_index;
132640a4fd66SJens Wiklander attr = (uint8_t *)o->attr + type_props->type_attrs[idx].raw_offs;
132740a4fd66SJens Wiklander return ops->to_user(attr, sess, buffer, size);
1328b0104773SPascal Brand }
1329b0104773SPascal Brand
tee_obj_attr_free(struct tee_obj * o)133040a4fd66SJens Wiklander void tee_obj_attr_free(struct tee_obj *o)
1331ffe04039SJerome Forissier {
133240a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp;
133340a4fd66SJens Wiklander size_t n;
133440a4fd66SJens Wiklander
133540a4fd66SJens Wiklander if (!o->attr)
133640a4fd66SJens Wiklander return;
133740a4fd66SJens Wiklander tp = tee_svc_find_type_props(o->info.objectType);
133840a4fd66SJens Wiklander if (!tp)
133940a4fd66SJens Wiklander return;
134040a4fd66SJens Wiklander
134140a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
134240a4fd66SJens Wiklander const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n;
134340a4fd66SJens Wiklander
134440a4fd66SJens Wiklander attr_ops[ta->ops_index].free((uint8_t *)o->attr + ta->raw_offs);
134540a4fd66SJens Wiklander }
1346ffe04039SJerome Forissier }
1347ffe04039SJerome Forissier
tee_obj_attr_clear(struct tee_obj * o)134840a4fd66SJens Wiklander void tee_obj_attr_clear(struct tee_obj *o)
1349ffe04039SJerome Forissier {
135040a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp;
135140a4fd66SJens Wiklander size_t n;
1352ffe04039SJerome Forissier
135340a4fd66SJens Wiklander if (!o->attr)
135440a4fd66SJens Wiklander return;
135540a4fd66SJens Wiklander tp = tee_svc_find_type_props(o->info.objectType);
135640a4fd66SJens Wiklander if (!tp)
135740a4fd66SJens Wiklander return;
135840a4fd66SJens Wiklander
135940a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
136040a4fd66SJens Wiklander const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n;
136140a4fd66SJens Wiklander
136240a4fd66SJens Wiklander attr_ops[ta->ops_index].clear((uint8_t *)o->attr +
136340a4fd66SJens Wiklander ta->raw_offs);
136440a4fd66SJens Wiklander }
1365ffe04039SJerome Forissier }
1366ffe04039SJerome Forissier
tee_obj_attr_to_binary(struct tee_obj * o,void * data,size_t * data_len)136740a4fd66SJens Wiklander TEE_Result tee_obj_attr_to_binary(struct tee_obj *o, void *data,
136840a4fd66SJens Wiklander size_t *data_len)
1369b0104773SPascal Brand {
137040a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp;
137140a4fd66SJens Wiklander size_t n;
137240a4fd66SJens Wiklander size_t offs = 0;
137353620831SJerome Forissier size_t len = data ? *data_len : 0;
1374bd3efa26SZeng Tao TEE_Result res;
1375b0104773SPascal Brand
137640a4fd66SJens Wiklander if (o->info.objectType == TEE_TYPE_DATA) {
137740a4fd66SJens Wiklander *data_len = 0;
137840a4fd66SJens Wiklander return TEE_SUCCESS; /* pure data object */
137940a4fd66SJens Wiklander }
138040a4fd66SJens Wiklander if (!o->attr)
138140a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
138240a4fd66SJens Wiklander tp = tee_svc_find_type_props(o->info.objectType);
138340a4fd66SJens Wiklander if (!tp)
138440a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
138540a4fd66SJens Wiklander
138640a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
138740a4fd66SJens Wiklander const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n;
138840a4fd66SJens Wiklander void *attr = (uint8_t *)o->attr + ta->raw_offs;
138940a4fd66SJens Wiklander
1390bd3efa26SZeng Tao res = attr_ops[ta->ops_index].to_binary(attr, data, len, &offs);
1391bd3efa26SZeng Tao if (res != TEE_SUCCESS)
1392bd3efa26SZeng Tao return res;
139340a4fd66SJens Wiklander }
139440a4fd66SJens Wiklander
139540a4fd66SJens Wiklander *data_len = offs;
1396ff2757d5SJens Wiklander if (data && offs > len)
139753620831SJerome Forissier return TEE_ERROR_SHORT_BUFFER;
139853620831SJerome Forissier return TEE_SUCCESS;
139940a4fd66SJens Wiklander }
140040a4fd66SJens Wiklander
tee_obj_attr_from_binary(struct tee_obj * o,const void * data,size_t data_len)140140a4fd66SJens Wiklander TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data,
140240a4fd66SJens Wiklander size_t data_len)
140340a4fd66SJens Wiklander {
140440a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp;
140540a4fd66SJens Wiklander size_t n;
140640a4fd66SJens Wiklander size_t offs = 0;
140740a4fd66SJens Wiklander
140840a4fd66SJens Wiklander if (o->info.objectType == TEE_TYPE_DATA)
140940a4fd66SJens Wiklander return TEE_SUCCESS; /* pure data object */
141040a4fd66SJens Wiklander if (!o->attr)
141140a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
141240a4fd66SJens Wiklander tp = tee_svc_find_type_props(o->info.objectType);
141340a4fd66SJens Wiklander if (!tp)
141440a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
141540a4fd66SJens Wiklander
141640a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
141740a4fd66SJens Wiklander const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n;
141840a4fd66SJens Wiklander void *attr = (uint8_t *)o->attr + ta->raw_offs;
141940a4fd66SJens Wiklander
142040a4fd66SJens Wiklander if (!attr_ops[ta->ops_index].from_binary(attr, data, data_len,
142140a4fd66SJens Wiklander &offs))
142240a4fd66SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT;
142340a4fd66SJens Wiklander }
142440a4fd66SJens Wiklander return TEE_SUCCESS;
142540a4fd66SJens Wiklander }
142640a4fd66SJens Wiklander
tee_obj_attr_copy_from(struct tee_obj * o,const struct tee_obj * src)142740a4fd66SJens Wiklander TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src)
142840a4fd66SJens Wiklander {
142940a4fd66SJens Wiklander TEE_Result res;
143040a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp;
143140a4fd66SJens Wiklander const struct tee_cryp_obj_type_attrs *ta;
143240a4fd66SJens Wiklander size_t n;
143340a4fd66SJens Wiklander uint32_t have_attrs = 0;
143440a4fd66SJens Wiklander void *attr;
143540a4fd66SJens Wiklander void *src_attr;
143640a4fd66SJens Wiklander
143740a4fd66SJens Wiklander if (o->info.objectType == TEE_TYPE_DATA)
143840a4fd66SJens Wiklander return TEE_SUCCESS; /* pure data object */
143940a4fd66SJens Wiklander if (!o->attr)
144040a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
144140a4fd66SJens Wiklander tp = tee_svc_find_type_props(o->info.objectType);
144240a4fd66SJens Wiklander if (!tp)
144340a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
144440a4fd66SJens Wiklander
144540a4fd66SJens Wiklander if (o->info.objectType == src->info.objectType) {
144640a4fd66SJens Wiklander have_attrs = src->have_attrs;
144740a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
144840a4fd66SJens Wiklander ta = tp->type_attrs + n;
144940a4fd66SJens Wiklander attr = (uint8_t *)o->attr + ta->raw_offs;
145040a4fd66SJens Wiklander src_attr = (uint8_t *)src->attr + ta->raw_offs;
145140a4fd66SJens Wiklander res = attr_ops[ta->ops_index].from_obj(attr, src_attr);
1452b0104773SPascal Brand if (res != TEE_SUCCESS)
1453b0104773SPascal Brand return res;
145440a4fd66SJens Wiklander }
145540a4fd66SJens Wiklander } else {
145640a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *tp_src;
145740a4fd66SJens Wiklander int idx;
145840a4fd66SJens Wiklander
145940a4fd66SJens Wiklander if (o->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) {
146040a4fd66SJens Wiklander if (src->info.objectType != TEE_TYPE_RSA_KEYPAIR)
146140a4fd66SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
146240a4fd66SJens Wiklander } else if (o->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY) {
146340a4fd66SJens Wiklander if (src->info.objectType != TEE_TYPE_DSA_KEYPAIR)
146440a4fd66SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
146540a4fd66SJens Wiklander } else if (o->info.objectType == TEE_TYPE_ECDSA_PUBLIC_KEY) {
146640a4fd66SJens Wiklander if (src->info.objectType != TEE_TYPE_ECDSA_KEYPAIR)
146740a4fd66SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
146840a4fd66SJens Wiklander } else if (o->info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY) {
146940a4fd66SJens Wiklander if (src->info.objectType != TEE_TYPE_ECDH_KEYPAIR)
147040a4fd66SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
14710f151943SJerome Forissier } else if (o->info.objectType == TEE_TYPE_SM2_DSA_PUBLIC_KEY) {
14720f151943SJerome Forissier if (src->info.objectType != TEE_TYPE_SM2_DSA_KEYPAIR)
14730f151943SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
147491fc6bd8SJerome Forissier } else if (o->info.objectType == TEE_TYPE_SM2_PKE_PUBLIC_KEY) {
147591fc6bd8SJerome Forissier if (src->info.objectType != TEE_TYPE_SM2_PKE_KEYPAIR)
147691fc6bd8SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
14775b385b3fSJerome Forissier } else if (o->info.objectType == TEE_TYPE_SM2_KEP_PUBLIC_KEY) {
14785b385b3fSJerome Forissier if (src->info.objectType != TEE_TYPE_SM2_KEP_KEYPAIR)
14795b385b3fSJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
14800aaad418SValerii Chubar } else if (o->info.objectType == TEE_TYPE_ED25519_PUBLIC_KEY) {
14810aaad418SValerii Chubar if (src->info.objectType != TEE_TYPE_ED25519_KEYPAIR)
14820aaad418SValerii Chubar return TEE_ERROR_BAD_PARAMETERS;
1483d684a4efSSohaib ul Hassan } else if (o->info.objectType == TEE_TYPE_X25519_PUBLIC_KEY) {
1484d684a4efSSohaib ul Hassan if (src->info.objectType != TEE_TYPE_X25519_KEYPAIR)
1485d684a4efSSohaib ul Hassan return TEE_ERROR_BAD_PARAMETERS;
148634ce35b1Sloubaihui } else if (o->info.objectType == TEE_TYPE_X448_PUBLIC_KEY) {
148734ce35b1Sloubaihui if (src->info.objectType != TEE_TYPE_X448_KEYPAIR)
148834ce35b1Sloubaihui return TEE_ERROR_BAD_PARAMETERS;
148940a4fd66SJens Wiklander } else {
149040a4fd66SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
149140a4fd66SJens Wiklander }
149240a4fd66SJens Wiklander
149340a4fd66SJens Wiklander tp_src = tee_svc_find_type_props(src->info.objectType);
149440a4fd66SJens Wiklander if (!tp_src)
149540a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
149640a4fd66SJens Wiklander
149740a4fd66SJens Wiklander have_attrs = BIT32(tp->num_type_attrs) - 1;
149840a4fd66SJens Wiklander for (n = 0; n < tp->num_type_attrs; n++) {
149940a4fd66SJens Wiklander ta = tp->type_attrs + n;
150040a4fd66SJens Wiklander
150140a4fd66SJens Wiklander idx = tee_svc_cryp_obj_find_type_attr_idx(ta->attr_id,
150240a4fd66SJens Wiklander tp_src);
150340a4fd66SJens Wiklander if (idx < 0)
150440a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
150540a4fd66SJens Wiklander
150640a4fd66SJens Wiklander attr = (uint8_t *)o->attr + ta->raw_offs;
150740a4fd66SJens Wiklander src_attr = (uint8_t *)src->attr +
150840a4fd66SJens Wiklander tp_src->type_attrs[idx].raw_offs;
150940a4fd66SJens Wiklander res = attr_ops[ta->ops_index].from_obj(attr, src_attr);
151040a4fd66SJens Wiklander if (res != TEE_SUCCESS)
151140a4fd66SJens Wiklander return res;
151240a4fd66SJens Wiklander }
151340a4fd66SJens Wiklander }
151440a4fd66SJens Wiklander
151540a4fd66SJens Wiklander o->have_attrs = have_attrs;
151640a4fd66SJens Wiklander return TEE_SUCCESS;
151740a4fd66SJens Wiklander }
151840a4fd66SJens Wiklander
is_gp_legacy_des_key_size(TEE_ObjectType type,size_t sz)1519c56cc686SJens Wiklander static bool is_gp_legacy_des_key_size(TEE_ObjectType type, size_t sz)
1520c56cc686SJens Wiklander {
1521c56cc686SJens Wiklander return IS_ENABLED(CFG_COMPAT_GP10_DES) &&
1522c56cc686SJens Wiklander ((type == TEE_TYPE_DES && sz == 56) ||
1523c56cc686SJens Wiklander (type == TEE_TYPE_DES3 && (sz == 112 || sz == 168)));
1524c56cc686SJens Wiklander }
1525c56cc686SJens Wiklander
check_key_size(const struct tee_cryp_obj_type_props * props,size_t key_size)1526c56cc686SJens Wiklander static TEE_Result check_key_size(const struct tee_cryp_obj_type_props *props,
1527c56cc686SJens Wiklander size_t key_size)
1528c56cc686SJens Wiklander {
1529c56cc686SJens Wiklander size_t sz = key_size;
1530c56cc686SJens Wiklander
1531c56cc686SJens Wiklander /*
1532c56cc686SJens Wiklander * In GP Internal API Specification 1.0 the partity bits aren't
1533c56cc686SJens Wiklander * counted when telling the size of the key in bits so add them
1534c56cc686SJens Wiklander * here if missing.
1535c56cc686SJens Wiklander */
1536c56cc686SJens Wiklander if (is_gp_legacy_des_key_size(props->obj_type, sz))
1537c56cc686SJens Wiklander sz += sz / 7;
1538c56cc686SJens Wiklander
1539c56cc686SJens Wiklander if (sz % props->quanta != 0)
1540c56cc686SJens Wiklander return TEE_ERROR_NOT_SUPPORTED;
1541c56cc686SJens Wiklander if (sz < props->min_size)
1542c56cc686SJens Wiklander return TEE_ERROR_NOT_SUPPORTED;
1543c56cc686SJens Wiklander if (sz > props->max_size)
1544c56cc686SJens Wiklander return TEE_ERROR_NOT_SUPPORTED;
1545c56cc686SJens Wiklander
1546c56cc686SJens Wiklander return TEE_SUCCESS;
1547c56cc686SJens Wiklander }
1548c56cc686SJens Wiklander
tee_obj_set_type(struct tee_obj * o,uint32_t obj_type,size_t max_key_size)154940a4fd66SJens Wiklander TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type,
155040a4fd66SJens Wiklander size_t max_key_size)
155140a4fd66SJens Wiklander {
155240a4fd66SJens Wiklander TEE_Result res = TEE_SUCCESS;
155340a4fd66SJens Wiklander const struct tee_cryp_obj_type_props *type_props;
155440a4fd66SJens Wiklander
155540a4fd66SJens Wiklander /* Can only set type for newly allocated objs */
155640a4fd66SJens Wiklander if (o->attr)
155740a4fd66SJens Wiklander return TEE_ERROR_BAD_STATE;
1558b0104773SPascal Brand
1559b0104773SPascal Brand /*
1560181f0998SJens Wiklander * Verify that maxObjectSize is supported and find out how
1561b0104773SPascal Brand * much should be allocated.
1562b0104773SPascal Brand */
1563b0104773SPascal Brand
156440a4fd66SJens Wiklander if (obj_type == TEE_TYPE_DATA) {
156540a4fd66SJens Wiklander if (max_key_size)
156640a4fd66SJens Wiklander return TEE_ERROR_NOT_SUPPORTED;
156740a4fd66SJens Wiklander } else {
1568b0104773SPascal Brand /* Find description of object */
1569b0104773SPascal Brand type_props = tee_svc_find_type_props(obj_type);
1570ffe04039SJerome Forissier if (!type_props)
1571b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED;
1572b0104773SPascal Brand
1573c56cc686SJens Wiklander /* Check that max_key_size follows restrictions */
1574c56cc686SJens Wiklander res = check_key_size(type_props, max_key_size);
1575c56cc686SJens Wiklander if (res)
1576c56cc686SJens Wiklander return res;
1577b0104773SPascal Brand
157840a4fd66SJens Wiklander o->attr = calloc(1, type_props->alloc_size);
157940a4fd66SJens Wiklander if (!o->attr)
1580b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY;
1581b0104773SPascal Brand }
1582b0104773SPascal Brand
1583ffe04039SJerome Forissier /* If we have a key structure, pre-allocate the bignums inside */
1584ffe04039SJerome Forissier switch (obj_type) {
1585ffe04039SJerome Forissier case TEE_TYPE_RSA_PUBLIC_KEY:
1586291e5450SJens Wiklander res = crypto_acipher_alloc_rsa_public_key(o->attr,
158740a4fd66SJens Wiklander max_key_size);
1588ffe04039SJerome Forissier break;
1589ffe04039SJerome Forissier case TEE_TYPE_RSA_KEYPAIR:
1590291e5450SJens Wiklander res = crypto_acipher_alloc_rsa_keypair(o->attr, max_key_size);
1591ffe04039SJerome Forissier break;
1592ffe04039SJerome Forissier case TEE_TYPE_DSA_PUBLIC_KEY:
1593291e5450SJens Wiklander res = crypto_acipher_alloc_dsa_public_key(o->attr,
159440a4fd66SJens Wiklander max_key_size);
1595ffe04039SJerome Forissier break;
1596ffe04039SJerome Forissier case TEE_TYPE_DSA_KEYPAIR:
1597291e5450SJens Wiklander res = crypto_acipher_alloc_dsa_keypair(o->attr, max_key_size);
1598ffe04039SJerome Forissier break;
1599ffe04039SJerome Forissier case TEE_TYPE_DH_KEYPAIR:
1600291e5450SJens Wiklander res = crypto_acipher_alloc_dh_keypair(o->attr, max_key_size);
1601ffe04039SJerome Forissier break;
1602aeb0d927SCedric Chaumont case TEE_TYPE_ECDSA_PUBLIC_KEY:
1603aeb0d927SCedric Chaumont case TEE_TYPE_ECDH_PUBLIC_KEY:
16040f151943SJerome Forissier case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
160591fc6bd8SJerome Forissier case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
16065b385b3fSJerome Forissier case TEE_TYPE_SM2_KEP_PUBLIC_KEY:
1607df00cf59SCedric Neveux res = crypto_acipher_alloc_ecc_public_key(o->attr, obj_type,
160840a4fd66SJens Wiklander max_key_size);
1609aeb0d927SCedric Chaumont break;
1610aeb0d927SCedric Chaumont case TEE_TYPE_ECDSA_KEYPAIR:
1611aeb0d927SCedric Chaumont case TEE_TYPE_ECDH_KEYPAIR:
16120f151943SJerome Forissier case TEE_TYPE_SM2_DSA_KEYPAIR:
161391fc6bd8SJerome Forissier case TEE_TYPE_SM2_PKE_KEYPAIR:
16145b385b3fSJerome Forissier case TEE_TYPE_SM2_KEP_KEYPAIR:
1615df00cf59SCedric Neveux res = crypto_acipher_alloc_ecc_keypair(o->attr, obj_type,
1616df00cf59SCedric Neveux max_key_size);
1617aeb0d927SCedric Chaumont break;
161890040fa4SSohaib ul Hassan case TEE_TYPE_X25519_KEYPAIR:
161990040fa4SSohaib ul Hassan res = crypto_acipher_alloc_x25519_keypair(o->attr,
162090040fa4SSohaib ul Hassan max_key_size);
162190040fa4SSohaib ul Hassan break;
162234ce35b1Sloubaihui case TEE_TYPE_X448_KEYPAIR:
162334ce35b1Sloubaihui res = crypto_acipher_alloc_x448_keypair(o->attr,
162434ce35b1Sloubaihui max_key_size);
162534ce35b1Sloubaihui break;
16260aaad418SValerii Chubar case TEE_TYPE_ED25519_KEYPAIR:
16270aaad418SValerii Chubar res = crypto_acipher_alloc_ed25519_keypair(o->attr,
16280aaad418SValerii Chubar max_key_size);
16290aaad418SValerii Chubar break;
1630c4cab13eSClement Faure case TEE_TYPE_ED25519_PUBLIC_KEY:
1631c4cab13eSClement Faure res = crypto_acipher_alloc_ed25519_public_key(o->attr,
1632c4cab13eSClement Faure max_key_size);
1633c4cab13eSClement Faure break;
1634ffe04039SJerome Forissier default:
163540a4fd66SJens Wiklander if (obj_type != TEE_TYPE_DATA) {
163640a4fd66SJens Wiklander struct tee_cryp_obj_secret *key = o->attr;
163740a4fd66SJens Wiklander
163840a4fd66SJens Wiklander key->alloc_size = type_props->alloc_size -
163940a4fd66SJens Wiklander sizeof(*key);
164040a4fd66SJens Wiklander }
1641ffe04039SJerome Forissier break;
1642ffe04039SJerome Forissier }
1643ffe04039SJerome Forissier
164440a4fd66SJens Wiklander if (res != TEE_SUCCESS)
164540a4fd66SJens Wiklander return res;
164640a4fd66SJens Wiklander
1647b0104773SPascal Brand o->info.objectType = obj_type;
1648181f0998SJens Wiklander o->info.maxObjectSize = max_key_size;
16490f50ba5aSJens Wiklander if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)
16500f50ba5aSJens Wiklander o->pobj->obj_info_usage = TEE_USAGE_DEFAULT;
16510f50ba5aSJens Wiklander else
1652b0104773SPascal Brand o->info.objectUsage = TEE_USAGE_DEFAULT;
1653b0104773SPascal Brand
165440a4fd66SJens Wiklander return TEE_SUCCESS;
165540a4fd66SJens Wiklander }
165640a4fd66SJens Wiklander
syscall_cryp_obj_alloc(unsigned long obj_type,unsigned long max_key_size,uint32_t * obj)165740a4fd66SJens Wiklander TEE_Result syscall_cryp_obj_alloc(unsigned long obj_type,
165840a4fd66SJens Wiklander unsigned long max_key_size, uint32_t *obj)
165940a4fd66SJens Wiklander {
166000b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
166100b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
166200b3b9a2SJens Wiklander struct tee_obj *o = NULL;
166340a4fd66SJens Wiklander
166440a4fd66SJens Wiklander
166540a4fd66SJens Wiklander o = tee_obj_alloc();
166640a4fd66SJens Wiklander if (!o)
166740a4fd66SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
166840a4fd66SJens Wiklander
166940a4fd66SJens Wiklander res = tee_obj_set_type(o, obj_type, max_key_size);
167040a4fd66SJens Wiklander if (res != TEE_SUCCESS) {
167140a4fd66SJens Wiklander tee_obj_free(o);
167240a4fd66SJens Wiklander return res;
167340a4fd66SJens Wiklander }
167440a4fd66SJens Wiklander
16758684fde8SJens Wiklander tee_obj_add(to_user_ta_ctx(sess->ctx), o);
1676b0104773SPascal Brand
1677c40a6505SJens Wiklander res = copy_kaddr_to_uref(obj, o);
1678b0104773SPascal Brand if (res != TEE_SUCCESS)
16798684fde8SJens Wiklander tee_obj_close(to_user_ta_ctx(sess->ctx), o);
1680b0104773SPascal Brand return res;
1681b0104773SPascal Brand }
1682b0104773SPascal Brand
syscall_cryp_obj_close(unsigned long obj)1683e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_close(unsigned long obj)
1684b0104773SPascal Brand {
168500b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
168600b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
168700b3b9a2SJens Wiklander struct tee_obj *o = NULL;
1688b0104773SPascal Brand
1689c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
1690b0104773SPascal Brand if (res != TEE_SUCCESS)
1691b0104773SPascal Brand return res;
1692b0104773SPascal Brand
1693b0104773SPascal Brand /*
1694b0104773SPascal Brand * If it's busy it's used by an operation, a client should never have
1695b0104773SPascal Brand * this handle.
1696b0104773SPascal Brand */
1697b0104773SPascal Brand if (o->busy)
1698b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1699b0104773SPascal Brand
17008684fde8SJens Wiklander tee_obj_close(to_user_ta_ctx(sess->ctx), o);
1701b0104773SPascal Brand return TEE_SUCCESS;
1702b0104773SPascal Brand }
1703b0104773SPascal Brand
syscall_cryp_obj_reset(unsigned long obj)1704e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_reset(unsigned long obj)
1705b0104773SPascal Brand {
170600b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
170700b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
170800b3b9a2SJens Wiklander struct tee_obj *o = NULL;
1709b0104773SPascal Brand
1710c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
1711b0104773SPascal Brand if (res != TEE_SUCCESS)
1712b0104773SPascal Brand return res;
1713b0104773SPascal Brand
1714b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) == 0) {
171540a4fd66SJens Wiklander tee_obj_attr_clear(o);
1716181f0998SJens Wiklander o->info.objectSize = 0;
1717b0104773SPascal Brand o->info.objectUsage = TEE_USAGE_DEFAULT;
1718b0104773SPascal Brand } else {
1719b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
1720b0104773SPascal Brand }
1721b0104773SPascal Brand
17228017a714SPascal Brand /* the object is no more initialized */
17238017a714SPascal Brand o->info.handleFlags &= ~TEE_HANDLE_FLAG_INITIALIZED;
17248017a714SPascal Brand
1725b0104773SPascal Brand return TEE_SUCCESS;
1726b0104773SPascal Brand }
1727b0104773SPascal Brand
copy_in_attrs(struct user_ta_ctx * utc,const struct utee_attribute * usr_attrs,uint32_t attr_count,TEE_Attribute * attrs)17288684fde8SJens Wiklander static TEE_Result copy_in_attrs(struct user_ta_ctx *utc,
1729e86f1266SJens Wiklander const struct utee_attribute *usr_attrs,
1730177603c7SJens Wiklander uint32_t attr_count, TEE_Attribute *attrs)
1731c2e1a053SJerome Forissier {
17321936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
1733bd81e5b9SJerome Forissier size_t size = 0;
17341936dfc7SJens Wiklander uint32_t n = 0;
1735a844a0b8SSeonghyun Park struct utee_attribute *usr_attrs_bbuf = NULL;
1736bd81e5b9SJerome Forissier
1737bd81e5b9SJerome Forissier if (MUL_OVERFLOW(sizeof(struct utee_attribute), attr_count, &size))
1738bd81e5b9SJerome Forissier return TEE_ERROR_OVERFLOW;
1739c2e1a053SJerome Forissier
1740a844a0b8SSeonghyun Park usr_attrs_bbuf = bb_alloc(size);
1741a844a0b8SSeonghyun Park if (!usr_attrs_bbuf)
1742a844a0b8SSeonghyun Park return TEE_ERROR_OUT_OF_MEMORY;
1743ef142203SJens Wiklander
1744a844a0b8SSeonghyun Park res = copy_from_user(usr_attrs_bbuf, usr_attrs, size);
1745a844a0b8SSeonghyun Park if (res)
1746a844a0b8SSeonghyun Park goto out;
1747c2e1a053SJerome Forissier
1748c2e1a053SJerome Forissier for (n = 0; n < attr_count; n++) {
1749a844a0b8SSeonghyun Park attrs[n].attributeID = usr_attrs_bbuf[n].attribute_id;
1750b9416909SJens Wiklander if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) {
1751a844a0b8SSeonghyun Park attrs[n].content.value.a = usr_attrs_bbuf[n].a;
1752a844a0b8SSeonghyun Park attrs[n].content.value.b = usr_attrs_bbuf[n].b;
1753e86f1266SJens Wiklander } else {
1754a844a0b8SSeonghyun Park uintptr_t buf = usr_attrs_bbuf[n].a;
1755a844a0b8SSeonghyun Park size_t len = usr_attrs_bbuf[n].b;
17561936dfc7SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_READ |
17571936dfc7SJens Wiklander TEE_MEMORY_ACCESS_ANY_OWNER;
1758e86f1266SJens Wiklander
1759ef142203SJens Wiklander buf = memtag_strip_tag_vaddr((void *)buf);
1760ef142203SJens Wiklander
176189c9728dSJens Wiklander res = vm_check_access_rights(&utc->uctx, flags, buf,
176289c9728dSJens Wiklander len);
1763c2e1a053SJerome Forissier if (res != TEE_SUCCESS)
1764a844a0b8SSeonghyun Park goto out;
1765e86f1266SJens Wiklander attrs[n].content.ref.buffer = (void *)buf;
1766e86f1266SJens Wiklander attrs[n].content.ref.length = len;
1767e86f1266SJens Wiklander }
1768c2e1a053SJerome Forissier }
1769c2e1a053SJerome Forissier
1770a844a0b8SSeonghyun Park out:
1771a844a0b8SSeonghyun Park bb_free(usr_attrs_bbuf, size);
1772a844a0b8SSeonghyun Park return res;
1773c2e1a053SJerome Forissier }
1774c2e1a053SJerome Forissier
1775b0104773SPascal Brand enum attr_usage {
1776b0104773SPascal Brand ATTR_USAGE_POPULATE,
1777b0104773SPascal Brand ATTR_USAGE_GENERATE_KEY
1778b0104773SPascal Brand };
1779b0104773SPascal Brand
tee_svc_cryp_check_attr(enum attr_usage usage,const struct tee_cryp_obj_type_props * type_props,const TEE_Attribute * attrs,uint32_t attr_count)1780177603c7SJens Wiklander static TEE_Result tee_svc_cryp_check_attr(enum attr_usage usage,
1781c2e1a053SJerome Forissier const struct tee_cryp_obj_type_props
1782c2e1a053SJerome Forissier *type_props,
1783177603c7SJens Wiklander const TEE_Attribute *attrs,
1784b0104773SPascal Brand uint32_t attr_count)
1785b0104773SPascal Brand {
1786d1272505SJens Wiklander uint32_t required_flag = 0;
1787d1272505SJens Wiklander uint32_t opt_flag = 0;
1788d1272505SJens Wiklander bool all_opt_needed = false;
1789b0104773SPascal Brand uint32_t req_attrs = 0;
1790b0104773SPascal Brand uint32_t opt_grp_attrs = 0;
1791b0104773SPascal Brand uint32_t attrs_found = 0;
1792d1272505SJens Wiklander size_t n = 0;
1793d1272505SJens Wiklander uint32_t bit = 0;
1794d1272505SJens Wiklander uint32_t flags = 0;
1795d1272505SJens Wiklander int idx = 0;
1796b0104773SPascal Brand
1797b0104773SPascal Brand if (usage == ATTR_USAGE_POPULATE) {
1798b0104773SPascal Brand required_flag = TEE_TYPE_ATTR_REQUIRED;
1799b0104773SPascal Brand opt_flag = TEE_TYPE_ATTR_OPTIONAL_GROUP;
1800b0104773SPascal Brand all_opt_needed = true;
1801b0104773SPascal Brand } else {
1802b0104773SPascal Brand required_flag = TEE_TYPE_ATTR_GEN_KEY_REQ;
1803b0104773SPascal Brand opt_flag = TEE_TYPE_ATTR_GEN_KEY_OPT;
1804b0104773SPascal Brand all_opt_needed = false;
1805b0104773SPascal Brand }
1806b0104773SPascal Brand
1807b0104773SPascal Brand /*
1808b0104773SPascal Brand * First find out which attributes are required and which belong to
1809b0104773SPascal Brand * the optional group
1810b0104773SPascal Brand */
1811b0104773SPascal Brand for (n = 0; n < type_props->num_type_attrs; n++) {
1812aeb0d927SCedric Chaumont bit = 1 << n;
1813aeb0d927SCedric Chaumont flags = type_props->type_attrs[n].flags;
1814b0104773SPascal Brand
1815b0104773SPascal Brand if (flags & required_flag)
1816b0104773SPascal Brand req_attrs |= bit;
1817b0104773SPascal Brand else if (flags & opt_flag)
1818b0104773SPascal Brand opt_grp_attrs |= bit;
1819b0104773SPascal Brand }
1820b0104773SPascal Brand
1821b0104773SPascal Brand /*
1822b0104773SPascal Brand * Verify that all required attributes are in place and
1823b0104773SPascal Brand * that the same attribute isn't repeated.
1824b0104773SPascal Brand */
1825b0104773SPascal Brand for (n = 0; n < attr_count; n++) {
1826aeb0d927SCedric Chaumont idx = tee_svc_cryp_obj_find_type_attr_idx(
1827aeb0d927SCedric Chaumont attrs[n].attributeID,
1828b0104773SPascal Brand type_props);
1829b0104773SPascal Brand
1830aeb0d927SCedric Chaumont /* attribute not defined in current object type */
1831aeb0d927SCedric Chaumont if (idx < 0)
1832aeb0d927SCedric Chaumont return TEE_ERROR_ITEM_NOT_FOUND;
1833aeb0d927SCedric Chaumont
1834aeb0d927SCedric Chaumont bit = 1 << idx;
1835aeb0d927SCedric Chaumont
1836aeb0d927SCedric Chaumont /* attribute not repeated */
1837b0104773SPascal Brand if ((attrs_found & bit) != 0)
1838b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1839b0104773SPascal Brand
1840d1272505SJens Wiklander /*
1841d1272505SJens Wiklander * Attribute not defined in current object type for this
1842d1272505SJens Wiklander * usage.
1843d1272505SJens Wiklander */
1844d1272505SJens Wiklander if (!(bit & (req_attrs | opt_grp_attrs)))
1845d1272505SJens Wiklander return TEE_ERROR_ITEM_NOT_FOUND;
1846d1272505SJens Wiklander
1847b0104773SPascal Brand attrs_found |= bit;
1848b0104773SPascal Brand }
1849b0104773SPascal Brand /* Required attribute missing */
1850b0104773SPascal Brand if ((attrs_found & req_attrs) != req_attrs)
1851b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1852b0104773SPascal Brand
1853b0104773SPascal Brand /*
1854b0104773SPascal Brand * If the flag says that "if one of the optional attributes are included
1855b0104773SPascal Brand * all of them has to be included" this must be checked.
1856b0104773SPascal Brand */
1857b0104773SPascal Brand if (all_opt_needed && (attrs_found & opt_grp_attrs) != 0 &&
1858b0104773SPascal Brand (attrs_found & opt_grp_attrs) != opt_grp_attrs)
1859b0104773SPascal Brand return TEE_ERROR_ITEM_NOT_FOUND;
1860b0104773SPascal Brand
1861b0104773SPascal Brand return TEE_SUCCESS;
1862b0104773SPascal Brand }
1863b0104773SPascal Brand
get_ec_key_size(uint32_t curve,size_t * key_size)1864afd1381fSSahil Malhotra static TEE_Result get_ec_key_size(uint32_t curve, size_t *key_size)
1865afd1381fSSahil Malhotra {
1866afd1381fSSahil Malhotra switch (curve) {
1867afd1381fSSahil Malhotra case TEE_ECC_CURVE_NIST_P192:
1868afd1381fSSahil Malhotra *key_size = 192;
1869afd1381fSSahil Malhotra break;
1870afd1381fSSahil Malhotra case TEE_ECC_CURVE_NIST_P224:
1871afd1381fSSahil Malhotra *key_size = 224;
1872afd1381fSSahil Malhotra break;
1873afd1381fSSahil Malhotra case TEE_ECC_CURVE_NIST_P256:
1874afd1381fSSahil Malhotra *key_size = 256;
1875afd1381fSSahil Malhotra break;
1876afd1381fSSahil Malhotra case TEE_ECC_CURVE_NIST_P384:
1877afd1381fSSahil Malhotra *key_size = 384;
1878afd1381fSSahil Malhotra break;
1879afd1381fSSahil Malhotra case TEE_ECC_CURVE_NIST_P521:
1880afd1381fSSahil Malhotra *key_size = 521;
1881afd1381fSSahil Malhotra break;
188291fc6bd8SJerome Forissier case TEE_ECC_CURVE_SM2:
188303e07432SValerii Chubar case TEE_ECC_CURVE_25519:
188491fc6bd8SJerome Forissier *key_size = 256;
188591fc6bd8SJerome Forissier break;
1886afd1381fSSahil Malhotra default:
1887afd1381fSSahil Malhotra return TEE_ERROR_NOT_SUPPORTED;
1888afd1381fSSahil Malhotra }
1889afd1381fSSahil Malhotra
1890afd1381fSSahil Malhotra return TEE_SUCCESS;
1891afd1381fSSahil Malhotra }
1892afd1381fSSahil Malhotra
tee_svc_cryp_obj_populate_type(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,const TEE_Attribute * attrs,uint32_t attr_count)1893b0104773SPascal Brand static TEE_Result tee_svc_cryp_obj_populate_type(
1894b0104773SPascal Brand struct tee_obj *o,
1895b0104773SPascal Brand const struct tee_cryp_obj_type_props *type_props,
1896b0104773SPascal Brand const TEE_Attribute *attrs,
1897b0104773SPascal Brand uint32_t attr_count)
1898b0104773SPascal Brand {
1899d9281a0cSJens Wiklander TEE_Result res = TEE_SUCCESS;
1900b0104773SPascal Brand uint32_t have_attrs = 0;
1901b0104773SPascal Brand size_t obj_size = 0;
1902d9281a0cSJens Wiklander size_t n = 0;
1903d9281a0cSJens Wiklander int idx = 0;
1904d9281a0cSJens Wiklander const struct attr_ops *ops = NULL;
1905d9281a0cSJens Wiklander void *attr = NULL;
1906aeb0d927SCedric Chaumont
1907aeb0d927SCedric Chaumont for (n = 0; n < attr_count; n++) {
1908aeb0d927SCedric Chaumont idx = tee_svc_cryp_obj_find_type_attr_idx(
1909aeb0d927SCedric Chaumont attrs[n].attributeID,
1910b0104773SPascal Brand type_props);
1911aeb0d927SCedric Chaumont /* attribute not defined in current object type */
1912b0104773SPascal Brand if (idx < 0)
1913aeb0d927SCedric Chaumont return TEE_ERROR_ITEM_NOT_FOUND;
1914aeb0d927SCedric Chaumont
191540a4fd66SJens Wiklander have_attrs |= BIT32(idx);
191640a4fd66SJens Wiklander ops = attr_ops + type_props->type_attrs[idx].ops_index;
191740a4fd66SJens Wiklander attr = (uint8_t *)o->attr +
191840a4fd66SJens Wiklander type_props->type_attrs[idx].raw_offs;
1919b9416909SJens Wiklander if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE)
192040a4fd66SJens Wiklander res = ops->from_user(attr, &attrs[n].content.value,
192140a4fd66SJens Wiklander sizeof(attrs[n].content.value));
192240a4fd66SJens Wiklander else
192340a4fd66SJens Wiklander res = ops->from_user(attr, attrs[n].content.ref.buffer,
192440a4fd66SJens Wiklander attrs[n].content.ref.length);
1925b0104773SPascal Brand if (res != TEE_SUCCESS)
1926b0104773SPascal Brand return res;
1927b0104773SPascal Brand
1928b0104773SPascal Brand /*
1929d9281a0cSJens Wiklander * The attribute that gives the size of the object is
1930d9281a0cSJens Wiklander * flagged with TEE_TYPE_ATTR_SIZE_INDICATOR.
1931b0104773SPascal Brand */
1932b0104773SPascal Brand if (type_props->type_attrs[idx].flags &
1933afd1381fSSahil Malhotra TEE_TYPE_ATTR_SIZE_INDICATOR) {
1934d9281a0cSJens Wiklander /* There should be only one */
1935d9281a0cSJens Wiklander if (obj_size)
1936d9281a0cSJens Wiklander return TEE_ERROR_BAD_STATE;
1937d9281a0cSJens Wiklander
1938afd1381fSSahil Malhotra /*
1939afd1381fSSahil Malhotra * For ECDSA/ECDH we need to translate curve into
1940afd1381fSSahil Malhotra * object size
1941afd1381fSSahil Malhotra */
1942afd1381fSSahil Malhotra if (attrs[n].attributeID == TEE_ATTR_ECC_CURVE) {
1943afd1381fSSahil Malhotra res = get_ec_key_size(attrs[n].content.value.a,
1944afd1381fSSahil Malhotra &obj_size);
1945afd1381fSSahil Malhotra if (res != TEE_SUCCESS)
1946afd1381fSSahil Malhotra return res;
1947afd1381fSSahil Malhotra } else {
1948dbc27a6fSJens Wiklander TEE_ObjectType obj_type = o->info.objectType;
1949181f0998SJens Wiklander size_t sz = o->info.maxObjectSize;
1950dbc27a6fSJens Wiklander
1951d9281a0cSJens Wiklander obj_size = attrs[n].content.ref.length * 8;
1952c56cc686SJens Wiklander /* Drop the parity bits for legacy objects */
1953c56cc686SJens Wiklander if (is_gp_legacy_des_key_size(obj_type, sz))
1954dbc27a6fSJens Wiklander obj_size -= obj_size / 8;
1955afd1381fSSahil Malhotra }
1956181f0998SJens Wiklander if (obj_size > o->info.maxObjectSize)
195773e18e2dSJens Wiklander return TEE_ERROR_BAD_STATE;
1958766cff40SJerome Forissier res = check_key_size(type_props, obj_size);
1959766cff40SJerome Forissier if (res != TEE_SUCCESS)
1960766cff40SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
1961afd1381fSSahil Malhotra }
1962d9281a0cSJens Wiklander
1963d9281a0cSJens Wiklander /*
1964d9281a0cSJens Wiklander * Bignum attributes limited by the number of bits in
1965181f0998SJens Wiklander * o->info.objectSize are flagged with
1966d9281a0cSJens Wiklander * TEE_TYPE_ATTR_BIGNUM_MAXBITS.
1967d9281a0cSJens Wiklander */
1968d9281a0cSJens Wiklander if (type_props->type_attrs[idx].flags &
1969d9281a0cSJens Wiklander TEE_TYPE_ATTR_BIGNUM_MAXBITS) {
1970f5348ecbSJens Wiklander if (crypto_bignum_num_bits(*(struct bignum **)attr) >
1971f5348ecbSJens Wiklander o->info.maxObjectSize)
1972d9281a0cSJens Wiklander return TEE_ERROR_BAD_STATE;
1973d9281a0cSJens Wiklander }
1974b0104773SPascal Brand }
1975b0104773SPascal Brand
1976b0104773SPascal Brand o->have_attrs = have_attrs;
1977181f0998SJens Wiklander o->info.objectSize = obj_size;
1978c56cc686SJens Wiklander /*
1979c56cc686SJens Wiklander * In GP Internal API Specification 1.0 the partity bits aren't
1980c56cc686SJens Wiklander * counted when telling the size of the key in bits so remove the
1981c56cc686SJens Wiklander * parity bits here.
1982c56cc686SJens Wiklander */
1983181f0998SJens Wiklander if (is_gp_legacy_des_key_size(o->info.objectType,
1984181f0998SJens Wiklander o->info.maxObjectSize))
1985181f0998SJens Wiklander o->info.objectSize -= o->info.objectSize / 8;
1986aeb0d927SCedric Chaumont
1987b0104773SPascal Brand return TEE_SUCCESS;
1988b0104773SPascal Brand }
1989b0104773SPascal Brand
syscall_cryp_obj_populate(unsigned long obj,struct utee_attribute * usr_attrs,unsigned long attr_count)1990e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_populate(unsigned long obj,
1991e86f1266SJens Wiklander struct utee_attribute *usr_attrs,
1992e86f1266SJens Wiklander unsigned long attr_count)
1993b0104773SPascal Brand {
199400b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
199500b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
199600b3b9a2SJens Wiklander struct tee_obj *o = NULL;
199700b3b9a2SJens Wiklander const struct tee_cryp_obj_type_props *type_props = NULL;
1998177603c7SJens Wiklander TEE_Attribute *attrs = NULL;
19999ff77e1eSJens Wiklander size_t alloc_size = 0;
2000b0104773SPascal Brand
2001c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
2002b0104773SPascal Brand if (res != TEE_SUCCESS)
2003b0104773SPascal Brand return res;
2004b0104773SPascal Brand
2005b0104773SPascal Brand /* Must be a transient object */
2006b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
2007b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2008b0104773SPascal Brand
2009b0104773SPascal Brand /* Must not be initialized already */
2010b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
2011b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2012b0104773SPascal Brand
2013b0104773SPascal Brand type_props = tee_svc_find_type_props(o->info.objectType);
2014ffe04039SJerome Forissier if (!type_props)
2015b0104773SPascal Brand return TEE_ERROR_NOT_IMPLEMENTED;
2016b0104773SPascal Brand
2017b60e1ceeSJoakim Bech if (MUL_OVERFLOW(sizeof(TEE_Attribute), attr_count, &alloc_size))
2018b60e1ceeSJoakim Bech return TEE_ERROR_OVERFLOW;
2019b60e1ceeSJoakim Bech
2020b60e1ceeSJoakim Bech attrs = malloc(alloc_size);
2021177603c7SJens Wiklander if (!attrs)
2022177603c7SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
2023b60e1ceeSJoakim Bech
20248684fde8SJens Wiklander res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_attrs, attr_count,
20258684fde8SJens Wiklander attrs);
2026b0104773SPascal Brand if (res != TEE_SUCCESS)
2027177603c7SJens Wiklander goto out;
2028177603c7SJens Wiklander
2029177603c7SJens Wiklander res = tee_svc_cryp_check_attr(ATTR_USAGE_POPULATE, type_props,
2030177603c7SJens Wiklander attrs, attr_count);
2031177603c7SJens Wiklander if (res != TEE_SUCCESS)
2032177603c7SJens Wiklander goto out;
2033b0104773SPascal Brand
2034c2e1a053SJerome Forissier res = tee_svc_cryp_obj_populate_type(o, type_props, attrs, attr_count);
2035b0104773SPascal Brand if (res == TEE_SUCCESS)
2036b0104773SPascal Brand o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
2037b0104773SPascal Brand
2038177603c7SJens Wiklander out:
203970b61310SJerome Forissier free_wipe(attrs);
2040b0104773SPascal Brand return res;
2041b0104773SPascal Brand }
2042b0104773SPascal Brand
syscall_cryp_obj_copy(unsigned long dst,unsigned long src)2043e86f1266SJens Wiklander TEE_Result syscall_cryp_obj_copy(unsigned long dst, unsigned long src)
2044b0104773SPascal Brand {
204500b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
204600b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
204700b3b9a2SJens Wiklander struct tee_obj *dst_o = NULL;
204800b3b9a2SJens Wiklander struct tee_obj *src_o = NULL;
2049b0104773SPascal Brand
20508684fde8SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx),
2051c40a6505SJens Wiklander uref_to_vaddr(dst), &dst_o);
2052b0104773SPascal Brand if (res != TEE_SUCCESS)
2053b0104773SPascal Brand return res;
2054b0104773SPascal Brand
20558684fde8SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx),
2056c40a6505SJens Wiklander uref_to_vaddr(src), &src_o);
2057b0104773SPascal Brand if (res != TEE_SUCCESS)
2058b0104773SPascal Brand return res;
2059b0104773SPascal Brand
2060b0104773SPascal Brand if ((src_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
2061b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2062b0104773SPascal Brand if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
2063b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2064b0104773SPascal Brand if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
2065b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2066b0104773SPascal Brand
206740a4fd66SJens Wiklander res = tee_obj_attr_copy_from(dst_o, src_o);
206840a4fd66SJens Wiklander if (res != TEE_SUCCESS)
206940a4fd66SJens Wiklander return res;
2070b0104773SPascal Brand
2071b0104773SPascal Brand dst_o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
2072181f0998SJens Wiklander dst_o->info.objectSize = src_o->info.objectSize;
20730f50ba5aSJens Wiklander if (src_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
20740f50ba5aSJens Wiklander tee_pobj_lock_usage(src_o->pobj);
20750f50ba5aSJens Wiklander dst_o->info.objectUsage = src_o->pobj->obj_info_usage;
20760f50ba5aSJens Wiklander tee_pobj_unlock_usage(src_o->pobj);
20770f50ba5aSJens Wiklander } else {
2078b0104773SPascal Brand dst_o->info.objectUsage = src_o->info.objectUsage;
20790f50ba5aSJens Wiklander }
2080b0104773SPascal Brand return TEE_SUCCESS;
2081b0104773SPascal Brand }
2082b0104773SPascal Brand
check_pub_rsa_key(struct bignum * e)2083338b123eSJens Wiklander static TEE_Result check_pub_rsa_key(struct bignum *e)
2084338b123eSJens Wiklander {
2085338b123eSJens Wiklander size_t n = crypto_bignum_num_bytes(e);
2086338b123eSJens Wiklander uint8_t bin_key[256 / 8] = { 0 };
2087338b123eSJens Wiklander
2088338b123eSJens Wiklander /*
2089338b123eSJens Wiklander * NIST SP800-56B requires public RSA key to be an odd integer in
209068ac62efSSami Tolvanen * the range 65537 <= e < 2^256. AOSP requires implementations to
209168ac62efSSami Tolvanen * support public exponents >= 3, which can be allowed by enabling
209268ac62efSSami Tolvanen * CFG_RSA_PUB_EXPONENT_3.
2093338b123eSJens Wiklander */
2094338b123eSJens Wiklander
209568ac62efSSami Tolvanen if (n > sizeof(bin_key) || n < 1)
2096338b123eSJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
2097338b123eSJens Wiklander
2098338b123eSJens Wiklander crypto_bignum_bn2bin(e, bin_key);
2099338b123eSJens Wiklander
2100c9366c1eSJens Wiklander if (!(bin_key[n - 1] & 1)) /* key must be odd */
2101338b123eSJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
2102338b123eSJens Wiklander
210368ac62efSSami Tolvanen if (n <= 3) {
210468ac62efSSami Tolvanen uint32_t min_key = 65537;
2105338b123eSJens Wiklander uint32_t key = 0;
210668ac62efSSami Tolvanen size_t m = 0;
2107338b123eSJens Wiklander
210868ac62efSSami Tolvanen if (IS_ENABLED(CFG_RSA_PUB_EXPONENT_3))
210968ac62efSSami Tolvanen min_key = 3;
211068ac62efSSami Tolvanen
211168ac62efSSami Tolvanen for (m = 0; m < n; m++) {
2112338b123eSJens Wiklander key <<= 8;
211368ac62efSSami Tolvanen key |= bin_key[m];
2114338b123eSJens Wiklander }
2115338b123eSJens Wiklander
211668ac62efSSami Tolvanen if (key < min_key)
2117338b123eSJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
2118338b123eSJens Wiklander }
2119338b123eSJens Wiklander
2120338b123eSJens Wiklander return TEE_SUCCESS;
2121338b123eSJens Wiklander }
2122338b123eSJens Wiklander
tee_svc_obj_generate_key_rsa(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)2123b0104773SPascal Brand static TEE_Result tee_svc_obj_generate_key_rsa(
2124b0104773SPascal Brand struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props,
2125c9b91489SPascal Brand uint32_t key_size,
2126c9b91489SPascal Brand const TEE_Attribute *params, uint32_t param_count)
2127b0104773SPascal Brand {
2128338b123eSJens Wiklander TEE_Result res = TEE_SUCCESS;
212940a4fd66SJens Wiklander struct rsa_keypair *key = o->attr;
213080439f38SPascal Brand uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537);
2131b0104773SPascal Brand
2132c9b91489SPascal Brand /* Copy the present attributes into the obj before starting */
2133c9b91489SPascal Brand res = tee_svc_cryp_obj_populate_type(o, type_props, params,
2134c9b91489SPascal Brand param_count);
2135c9b91489SPascal Brand if (res != TEE_SUCCESS)
2136c9b91489SPascal Brand return res;
2137338b123eSJens Wiklander if (get_attribute(o, type_props, TEE_ATTR_RSA_PUBLIC_EXPONENT)) {
2138338b123eSJens Wiklander res = check_pub_rsa_key(key->e);
2139338b123eSJens Wiklander if (res)
2140338b123eSJens Wiklander return res;
2141338b123eSJens Wiklander } else {
21422cc2a44cSClement Faure res = crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e),
21432cc2a44cSClement Faure key->e);
21442cc2a44cSClement Faure if (res)
21452cc2a44cSClement Faure return res;
2146338b123eSJens Wiklander }
2147291e5450SJens Wiklander res = crypto_acipher_gen_rsa_key(key, key_size);
2148b0104773SPascal Brand if (res != TEE_SUCCESS)
2149b0104773SPascal Brand return res;
2150b0104773SPascal Brand
2151b0104773SPascal Brand /* Set bits for all known attributes for this object type */
2152b0104773SPascal Brand o->have_attrs = (1 << type_props->num_type_attrs) - 1;
2153ffe04039SJerome Forissier
2154b0104773SPascal Brand return TEE_SUCCESS;
2155b0104773SPascal Brand }
2156b0104773SPascal Brand
tee_svc_obj_generate_key_dsa(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)2157b0104773SPascal Brand static TEE_Result tee_svc_obj_generate_key_dsa(
2158b0104773SPascal Brand struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props,
215982c30aaaSJerome Forissier uint32_t key_size, const TEE_Attribute *params, uint32_t param_count)
2160b0104773SPascal Brand {
2161b0104773SPascal Brand TEE_Result res;
2162b0104773SPascal Brand
216382c30aaaSJerome Forissier /* Copy the present attributes into the obj before starting */
216482c30aaaSJerome Forissier res = tee_svc_cryp_obj_populate_type(o, type_props, params,
216582c30aaaSJerome Forissier param_count);
216682c30aaaSJerome Forissier if (res != TEE_SUCCESS)
216782c30aaaSJerome Forissier return res;
216882c30aaaSJerome Forissier
2169291e5450SJens Wiklander res = crypto_acipher_gen_dsa_key(o->attr, key_size);
2170b0104773SPascal Brand if (res != TEE_SUCCESS)
2171b0104773SPascal Brand return res;
2172b0104773SPascal Brand
2173b0104773SPascal Brand /* Set bits for all known attributes for this object type */
2174b0104773SPascal Brand o->have_attrs = (1 << type_props->num_type_attrs) - 1;
2175ffe04039SJerome Forissier
2176b0104773SPascal Brand return TEE_SUCCESS;
2177b0104773SPascal Brand }
2178b0104773SPascal Brand
tee_svc_obj_generate_key_dh(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)2179b0104773SPascal Brand static TEE_Result tee_svc_obj_generate_key_dh(
2180b0104773SPascal Brand struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props,
21819f4dcefbSJerome Forissier uint32_t key_size, const TEE_Attribute *params, uint32_t param_count)
2182b0104773SPascal Brand {
2183b0104773SPascal Brand TEE_Result res;
2184ffe04039SJerome Forissier struct dh_keypair *tee_dh_key;
2185ffe04039SJerome Forissier struct bignum *dh_q = NULL;
2186b0104773SPascal Brand uint32_t dh_xbits = 0;
2187b0104773SPascal Brand
2188b0104773SPascal Brand /* Copy the present attributes into the obj before starting */
2189c2e1a053SJerome Forissier res = tee_svc_cryp_obj_populate_type(o, type_props, params,
2190c2e1a053SJerome Forissier param_count);
2191b0104773SPascal Brand if (res != TEE_SUCCESS)
2192b0104773SPascal Brand return res;
2193b0104773SPascal Brand
219440a4fd66SJens Wiklander tee_dh_key = (struct dh_keypair *)o->attr;
2195b0104773SPascal Brand
2196050ba678SJerome Forissier if (get_attribute(o, type_props, TEE_ATTR_DH_SUBPRIME))
2197ffe04039SJerome Forissier dh_q = tee_dh_key->q;
2198050ba678SJerome Forissier if (get_attribute(o, type_props, TEE_ATTR_DH_X_BITS))
2199b0104773SPascal Brand dh_xbits = tee_dh_key->xbits;
22009f4dcefbSJerome Forissier res = crypto_acipher_gen_dh_key(tee_dh_key, dh_q, dh_xbits, key_size);
2201b0104773SPascal Brand if (res != TEE_SUCCESS)
2202b0104773SPascal Brand return res;
2203b0104773SPascal Brand
2204b0104773SPascal Brand /* Set bits for the generated public and private key */
2205050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_DH_PUBLIC_VALUE);
2206050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_DH_PRIVATE_VALUE);
2207050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_DH_X_BITS);
2208b0104773SPascal Brand return TEE_SUCCESS;
2209b0104773SPascal Brand }
2210b0104773SPascal Brand
tee_svc_obj_generate_key_ecc(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)2211aeb0d927SCedric Chaumont static TEE_Result tee_svc_obj_generate_key_ecc(
2212aeb0d927SCedric Chaumont struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props,
221321282baeSJerome Forissier uint32_t key_size, const TEE_Attribute *params, uint32_t param_count)
2214aeb0d927SCedric Chaumont {
2215aeb0d927SCedric Chaumont TEE_Result res;
2216aeb0d927SCedric Chaumont struct ecc_keypair *tee_ecc_key;
2217aeb0d927SCedric Chaumont
2218aeb0d927SCedric Chaumont /* Copy the present attributes into the obj before starting */
2219aeb0d927SCedric Chaumont res = tee_svc_cryp_obj_populate_type(o, type_props, params,
2220aeb0d927SCedric Chaumont param_count);
2221aeb0d927SCedric Chaumont if (res != TEE_SUCCESS)
2222aeb0d927SCedric Chaumont return res;
2223aeb0d927SCedric Chaumont
222440a4fd66SJens Wiklander tee_ecc_key = (struct ecc_keypair *)o->attr;
2225aeb0d927SCedric Chaumont
222621282baeSJerome Forissier res = crypto_acipher_gen_ecc_key(tee_ecc_key, key_size);
2227aeb0d927SCedric Chaumont if (res != TEE_SUCCESS)
2228aeb0d927SCedric Chaumont return res;
2229aeb0d927SCedric Chaumont
2230aeb0d927SCedric Chaumont /* Set bits for the generated public and private key */
2231050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_ECC_PRIVATE_VALUE);
2232050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_X);
2233050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_Y);
2234050ba678SJerome Forissier set_attribute(o, type_props, TEE_ATTR_ECC_CURVE);
2235aeb0d927SCedric Chaumont return TEE_SUCCESS;
2236aeb0d927SCedric Chaumont }
2237aeb0d927SCedric Chaumont
223890040fa4SSohaib ul Hassan static TEE_Result
tee_svc_obj_generate_key_x25519(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)223990040fa4SSohaib ul Hassan tee_svc_obj_generate_key_x25519(struct tee_obj *o,
224090040fa4SSohaib ul Hassan const struct tee_cryp_obj_type_props
224190040fa4SSohaib ul Hassan *type_props,
224290040fa4SSohaib ul Hassan uint32_t key_size,
224390040fa4SSohaib ul Hassan const TEE_Attribute *params,
224490040fa4SSohaib ul Hassan uint32_t param_count)
224590040fa4SSohaib ul Hassan {
224690040fa4SSohaib ul Hassan TEE_Result res = TEE_ERROR_GENERIC;
224746e25a17Sloubaihui struct montgomery_keypair *tee_x25519_key = NULL;
224890040fa4SSohaib ul Hassan
224990040fa4SSohaib ul Hassan /* Copy the present attributes into the obj before starting */
225090040fa4SSohaib ul Hassan res = tee_svc_cryp_obj_populate_type(o, type_props, params,
225190040fa4SSohaib ul Hassan param_count);
225290040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
225390040fa4SSohaib ul Hassan return res;
225490040fa4SSohaib ul Hassan
225546e25a17Sloubaihui tee_x25519_key = (struct montgomery_keypair *)o->attr;
225690040fa4SSohaib ul Hassan
225790040fa4SSohaib ul Hassan res = crypto_acipher_gen_x25519_key(tee_x25519_key, key_size);
225890040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
225990040fa4SSohaib ul Hassan return res;
226090040fa4SSohaib ul Hassan
226190040fa4SSohaib ul Hassan /* Set bits for the generated public and private key */
226290040fa4SSohaib ul Hassan set_attribute(o, type_props, TEE_ATTR_X25519_PRIVATE_VALUE);
226390040fa4SSohaib ul Hassan set_attribute(o, type_props, TEE_ATTR_X25519_PUBLIC_VALUE);
226490040fa4SSohaib ul Hassan return TEE_SUCCESS;
226590040fa4SSohaib ul Hassan }
226690040fa4SSohaib ul Hassan
22670aaad418SValerii Chubar static TEE_Result
tee_svc_obj_generate_key_x448(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)226834ce35b1Sloubaihui tee_svc_obj_generate_key_x448(struct tee_obj *o,
226934ce35b1Sloubaihui const struct tee_cryp_obj_type_props *type_props,
227034ce35b1Sloubaihui uint32_t key_size, const TEE_Attribute *params,
227134ce35b1Sloubaihui uint32_t param_count)
227234ce35b1Sloubaihui {
227334ce35b1Sloubaihui TEE_Result res = TEE_ERROR_GENERIC;
227434ce35b1Sloubaihui struct montgomery_keypair *tee_x448_key = NULL;
227534ce35b1Sloubaihui
227634ce35b1Sloubaihui /* Copy the present attributes into the obj before starting */
227734ce35b1Sloubaihui res = tee_svc_cryp_obj_populate_type(o, type_props, params,
227834ce35b1Sloubaihui param_count);
227934ce35b1Sloubaihui if (res != TEE_SUCCESS)
228034ce35b1Sloubaihui return res;
228134ce35b1Sloubaihui
228234ce35b1Sloubaihui tee_x448_key = (struct montgomery_keypair *)o->attr;
228334ce35b1Sloubaihui res = crypto_acipher_gen_x448_key(tee_x448_key, key_size);
228434ce35b1Sloubaihui if (res != TEE_SUCCESS)
228534ce35b1Sloubaihui return res;
228634ce35b1Sloubaihui
228734ce35b1Sloubaihui set_attribute(o, type_props, TEE_ATTR_X448_PRIVATE_VALUE);
228834ce35b1Sloubaihui set_attribute(o, type_props, TEE_ATTR_X448_PUBLIC_VALUE);
228934ce35b1Sloubaihui
229034ce35b1Sloubaihui return TEE_SUCCESS;
229134ce35b1Sloubaihui }
229234ce35b1Sloubaihui
229334ce35b1Sloubaihui static TEE_Result
tee_svc_obj_generate_key_ed25519(struct tee_obj * o,const struct tee_cryp_obj_type_props * type_props,uint32_t key_size,const TEE_Attribute * params,uint32_t param_count)22940aaad418SValerii Chubar tee_svc_obj_generate_key_ed25519(struct tee_obj *o,
22950aaad418SValerii Chubar const struct tee_cryp_obj_type_props
22960aaad418SValerii Chubar *type_props,
22970aaad418SValerii Chubar uint32_t key_size,
22980aaad418SValerii Chubar const TEE_Attribute *params,
22990aaad418SValerii Chubar uint32_t param_count)
23000aaad418SValerii Chubar {
23010aaad418SValerii Chubar TEE_Result res = TEE_ERROR_GENERIC;
23020aaad418SValerii Chubar struct ed25519_keypair *key = NULL;
23030aaad418SValerii Chubar
23040aaad418SValerii Chubar /* Copy the present attributes into the obj before starting */
23050aaad418SValerii Chubar res = tee_svc_cryp_obj_populate_type(o, type_props, params,
23060aaad418SValerii Chubar param_count);
23070aaad418SValerii Chubar if (res != TEE_SUCCESS)
23080aaad418SValerii Chubar return res;
23090aaad418SValerii Chubar
23100aaad418SValerii Chubar key = o->attr;
23110aaad418SValerii Chubar
23120aaad418SValerii Chubar res = crypto_acipher_gen_ed25519_key(key, key_size);
23130aaad418SValerii Chubar if (res != TEE_SUCCESS)
23140aaad418SValerii Chubar return res;
23150aaad418SValerii Chubar
23160aaad418SValerii Chubar /* Set bits for the generated public and private key */
23170aaad418SValerii Chubar set_attribute(o, type_props, TEE_ATTR_ED25519_PRIVATE_VALUE);
23180aaad418SValerii Chubar set_attribute(o, type_props, TEE_ATTR_ED25519_PUBLIC_VALUE);
23190aaad418SValerii Chubar return TEE_SUCCESS;
23200aaad418SValerii Chubar }
23210aaad418SValerii Chubar
23220aaad418SValerii Chubar static TEE_Result
tee_svc_obj_ed25519_parse_params(const TEE_Attribute * params,size_t num_params,bool * ph_flag,const uint8_t ** ctx,size_t * ctx_len)23230aaad418SValerii Chubar tee_svc_obj_ed25519_parse_params(const TEE_Attribute *params, size_t num_params,
23240aaad418SValerii Chubar bool *ph_flag, const uint8_t **ctx,
23250aaad418SValerii Chubar size_t *ctx_len)
23260aaad418SValerii Chubar {
23270aaad418SValerii Chubar size_t n = 0;
23280aaad418SValerii Chubar
23290aaad418SValerii Chubar *ctx = NULL;
23300aaad418SValerii Chubar
23310aaad418SValerii Chubar for (n = 0; n < num_params; n++) {
23320aaad418SValerii Chubar switch (params[n].attributeID) {
23330aaad418SValerii Chubar case TEE_ATTR_EDDSA_PREHASH:
23343e8a6147SJens Wiklander if (params[n].content.value.b)
23353e8a6147SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
23363e8a6147SJens Wiklander if (!params[n].content.value.a)
23373e8a6147SJens Wiklander *ph_flag = false;
23383e8a6147SJens Wiklander else if (params[n].content.value.a == 1)
23390aaad418SValerii Chubar *ph_flag = true;
23403e8a6147SJens Wiklander else
23413e8a6147SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
23420aaad418SValerii Chubar break;
23430aaad418SValerii Chubar
23440aaad418SValerii Chubar case TEE_ATTR_EDDSA_CTX:
23450aaad418SValerii Chubar /* several provided contexts are treated as error */
23460aaad418SValerii Chubar if (*ctx)
23470aaad418SValerii Chubar return TEE_ERROR_BAD_PARAMETERS;
23480aaad418SValerii Chubar
23490aaad418SValerii Chubar *ctx_len = params[n].content.ref.length;
23500aaad418SValerii Chubar if (*ctx_len > TEE_ED25519_CTX_MAX_LENGTH)
23510aaad418SValerii Chubar return TEE_ERROR_BAD_PARAMETERS;
23520aaad418SValerii Chubar
23530aaad418SValerii Chubar if (!*ctx_len)
23540aaad418SValerii Chubar break;
23550aaad418SValerii Chubar
23560aaad418SValerii Chubar *ctx = params[n].content.ref.buffer;
23570aaad418SValerii Chubar if (!*ctx)
23580aaad418SValerii Chubar return TEE_ERROR_BAD_PARAMETERS;
23590aaad418SValerii Chubar break;
23600aaad418SValerii Chubar
23610aaad418SValerii Chubar default:
23620aaad418SValerii Chubar return TEE_ERROR_BAD_PARAMETERS;
23630aaad418SValerii Chubar }
23640aaad418SValerii Chubar }
23650aaad418SValerii Chubar
23660aaad418SValerii Chubar return TEE_SUCCESS;
23670aaad418SValerii Chubar }
23680aaad418SValerii Chubar
23690aaad418SValerii Chubar static TEE_Result
tee_svc_obj_ed25519_sign(struct ed25519_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len,const TEE_Attribute * params,size_t num_params)23700aaad418SValerii Chubar tee_svc_obj_ed25519_sign(struct ed25519_keypair *key,
23710aaad418SValerii Chubar const uint8_t *msg, size_t msg_len,
23720aaad418SValerii Chubar uint8_t *sig, size_t *sig_len,
23730aaad418SValerii Chubar const TEE_Attribute *params, size_t num_params)
23740aaad418SValerii Chubar {
23750aaad418SValerii Chubar TEE_Result err = TEE_ERROR_GENERIC;
23760aaad418SValerii Chubar size_t ctx_len = 0;
23770aaad418SValerii Chubar const uint8_t *ctx = NULL;
23780aaad418SValerii Chubar bool ph_flag = false;
23790aaad418SValerii Chubar
23800aaad418SValerii Chubar err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag,
23810aaad418SValerii Chubar &ctx, &ctx_len);
23820aaad418SValerii Chubar if (err != TEE_SUCCESS)
23830aaad418SValerii Chubar return err;
23840aaad418SValerii Chubar
23850aaad418SValerii Chubar if (ph_flag || ctx) {
23860aaad418SValerii Chubar return crypto_acipher_ed25519ctx_sign(key, msg, msg_len, sig,
23870aaad418SValerii Chubar sig_len, ph_flag,
23880aaad418SValerii Chubar ctx, ctx_len);
23890aaad418SValerii Chubar }
23900aaad418SValerii Chubar
23910aaad418SValerii Chubar return crypto_acipher_ed25519_sign(key, msg, msg_len, sig, sig_len);
23920aaad418SValerii Chubar }
23930aaad418SValerii Chubar
23940aaad418SValerii Chubar static TEE_Result
tee_svc_obj_ed25519_verify(struct ed25519_public_key * key,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len,const TEE_Attribute * params,size_t num_params)2395c4cab13eSClement Faure tee_svc_obj_ed25519_verify(struct ed25519_public_key *key,
23960aaad418SValerii Chubar const uint8_t *msg, size_t msg_len,
23970aaad418SValerii Chubar const uint8_t *sig, size_t sig_len,
23980aaad418SValerii Chubar const TEE_Attribute *params, size_t num_params)
23990aaad418SValerii Chubar {
24000aaad418SValerii Chubar TEE_Result err = TEE_ERROR_GENERIC;
24010aaad418SValerii Chubar size_t ctx_len = 0;
24020aaad418SValerii Chubar const uint8_t *ctx = NULL;
24030aaad418SValerii Chubar bool ph_flag = false;
24040aaad418SValerii Chubar
24050aaad418SValerii Chubar err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag,
24060aaad418SValerii Chubar &ctx, &ctx_len);
24070aaad418SValerii Chubar if (err)
24080aaad418SValerii Chubar return err;
24090aaad418SValerii Chubar
24100aaad418SValerii Chubar if (ph_flag || ctx) {
24110aaad418SValerii Chubar return crypto_acipher_ed25519ctx_verify(key, msg, msg_len, sig,
24120aaad418SValerii Chubar sig_len, ph_flag,
24130aaad418SValerii Chubar ctx, ctx_len);
24140aaad418SValerii Chubar }
24150aaad418SValerii Chubar
24160aaad418SValerii Chubar return crypto_acipher_ed25519_verify(key, msg, msg_len, sig, sig_len);
24170aaad418SValerii Chubar }
24180aaad418SValerii Chubar
syscall_obj_generate_key(unsigned long obj,unsigned long key_size,const struct utee_attribute * usr_params,unsigned long param_count)2419e86f1266SJens Wiklander TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size,
2420e86f1266SJens Wiklander const struct utee_attribute *usr_params,
2421e86f1266SJens Wiklander unsigned long param_count)
2422b0104773SPascal Brand {
242300b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
242400b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
242500b3b9a2SJens Wiklander const struct tee_cryp_obj_type_props *type_props = NULL;
242600b3b9a2SJens Wiklander struct tee_obj *o = NULL;
242700b3b9a2SJens Wiklander struct tee_cryp_obj_secret *key = NULL;
242800b3b9a2SJens Wiklander size_t byte_size = 0;
2429177603c7SJens Wiklander TEE_Attribute *params = NULL;
24309ff77e1eSJens Wiklander size_t alloc_size = 0;
2431b0104773SPascal Brand
2432c40a6505SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
2433b0104773SPascal Brand if (res != TEE_SUCCESS)
2434b0104773SPascal Brand return res;
2435b0104773SPascal Brand
2436b0104773SPascal Brand /* Must be a transient object */
2437b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
2438b0104773SPascal Brand return TEE_ERROR_BAD_STATE;
2439b0104773SPascal Brand
2440b0104773SPascal Brand /* Must not be initialized already */
2441b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
2442b0104773SPascal Brand return TEE_ERROR_BAD_STATE;
2443b0104773SPascal Brand
2444b0104773SPascal Brand /* Find description of object */
2445b0104773SPascal Brand type_props = tee_svc_find_type_props(o->info.objectType);
2446ffe04039SJerome Forissier if (!type_props)
2447b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED;
2448b0104773SPascal Brand
2449c56cc686SJens Wiklander /* Check that key_size follows restrictions */
2450c56cc686SJens Wiklander res = check_key_size(type_props, key_size);
2451c56cc686SJens Wiklander if (res)
2452c56cc686SJens Wiklander return res;
2453b0104773SPascal Brand
2454a6372432SJoakim Bech if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size))
2455a6372432SJoakim Bech return TEE_ERROR_OVERFLOW;
2456a6372432SJoakim Bech
2457a6372432SJoakim Bech params = malloc(alloc_size);
2458177603c7SJens Wiklander if (!params)
2459177603c7SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
24608684fde8SJens Wiklander res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_params, param_count,
24618684fde8SJens Wiklander params);
2462b0104773SPascal Brand if (res != TEE_SUCCESS)
2463177603c7SJens Wiklander goto out;
2464177603c7SJens Wiklander
2465177603c7SJens Wiklander res = tee_svc_cryp_check_attr(ATTR_USAGE_GENERATE_KEY, type_props,
2466177603c7SJens Wiklander params, param_count);
2467177603c7SJens Wiklander if (res != TEE_SUCCESS)
2468177603c7SJens Wiklander goto out;
2469b0104773SPascal Brand
2470b0104773SPascal Brand switch (o->info.objectType) {
2471b0104773SPascal Brand case TEE_TYPE_AES:
2472b0104773SPascal Brand case TEE_TYPE_DES:
2473b0104773SPascal Brand case TEE_TYPE_DES3:
2474ade6f848SJerome Forissier case TEE_TYPE_SM4:
2475b0104773SPascal Brand case TEE_TYPE_HMAC_MD5:
2476b0104773SPascal Brand case TEE_TYPE_HMAC_SHA1:
2477b0104773SPascal Brand case TEE_TYPE_HMAC_SHA224:
2478b0104773SPascal Brand case TEE_TYPE_HMAC_SHA256:
2479b0104773SPascal Brand case TEE_TYPE_HMAC_SHA384:
2480b0104773SPascal Brand case TEE_TYPE_HMAC_SHA512:
2481260b4028SJens Wiklander case TEE_TYPE_HMAC_SHA3_224:
2482260b4028SJens Wiklander case TEE_TYPE_HMAC_SHA3_256:
2483260b4028SJens Wiklander case TEE_TYPE_HMAC_SHA3_384:
2484260b4028SJens Wiklander case TEE_TYPE_HMAC_SHA3_512:
248547645577SJerome Forissier case TEE_TYPE_HMAC_SM3:
2486b0104773SPascal Brand case TEE_TYPE_GENERIC_SECRET:
2487b0104773SPascal Brand byte_size = key_size / 8;
2488b0104773SPascal Brand
2489b0104773SPascal Brand /*
2490c56cc686SJens Wiklander * In GP Internal API Specification 1.0 the partity bits
2491c56cc686SJens Wiklander * aren't counted when telling the size of the key in bits.
2492b0104773SPascal Brand */
2493c56cc686SJens Wiklander if (is_gp_legacy_des_key_size(o->info.objectType, key_size))
2494b0104773SPascal Brand byte_size = (key_size + key_size / 7) / 8;
2495b0104773SPascal Brand
249640a4fd66SJens Wiklander key = (struct tee_cryp_obj_secret *)o->attr;
249740a4fd66SJens Wiklander if (byte_size > key->alloc_size) {
2498177603c7SJens Wiklander res = TEE_ERROR_EXCESS_DATA;
2499177603c7SJens Wiklander goto out;
2500177603c7SJens Wiklander }
2501b0104773SPascal Brand
250236a063efSJens Wiklander res = crypto_rng_read((void *)(key + 1), byte_size);
2503b0104773SPascal Brand if (res != TEE_SUCCESS)
2504177603c7SJens Wiklander goto out;
2505b0104773SPascal Brand
2506b0104773SPascal Brand key->key_size = byte_size;
2507b0104773SPascal Brand
2508b0104773SPascal Brand /* Set bits for all known attributes for this object type */
2509b0104773SPascal Brand o->have_attrs = (1 << type_props->num_type_attrs) - 1;
2510b0104773SPascal Brand
2511b0104773SPascal Brand break;
2512b0104773SPascal Brand
2513b0104773SPascal Brand case TEE_TYPE_RSA_KEYPAIR:
2514c9b91489SPascal Brand res = tee_svc_obj_generate_key_rsa(o, type_props, key_size,
2515c9b91489SPascal Brand params, param_count);
2516b0104773SPascal Brand if (res != TEE_SUCCESS)
2517177603c7SJens Wiklander goto out;
2518b0104773SPascal Brand break;
2519b0104773SPascal Brand
2520b0104773SPascal Brand case TEE_TYPE_DSA_KEYPAIR:
252182c30aaaSJerome Forissier res = tee_svc_obj_generate_key_dsa(o, type_props, key_size,
252282c30aaaSJerome Forissier params, param_count);
2523b0104773SPascal Brand if (res != TEE_SUCCESS)
2524177603c7SJens Wiklander goto out;
2525b0104773SPascal Brand break;
2526b0104773SPascal Brand
2527b0104773SPascal Brand case TEE_TYPE_DH_KEYPAIR:
2528c2e1a053SJerome Forissier res = tee_svc_obj_generate_key_dh(o, type_props, key_size,
2529c2e1a053SJerome Forissier params, param_count);
2530b0104773SPascal Brand if (res != TEE_SUCCESS)
2531177603c7SJens Wiklander goto out;
2532b0104773SPascal Brand break;
2533b0104773SPascal Brand
2534aeb0d927SCedric Chaumont case TEE_TYPE_ECDSA_KEYPAIR:
2535aeb0d927SCedric Chaumont case TEE_TYPE_ECDH_KEYPAIR:
25363176f4d1SJerome Forissier case TEE_TYPE_SM2_DSA_KEYPAIR:
25373176f4d1SJerome Forissier case TEE_TYPE_SM2_KEP_KEYPAIR:
253891fc6bd8SJerome Forissier case TEE_TYPE_SM2_PKE_KEYPAIR:
2539aeb0d927SCedric Chaumont res = tee_svc_obj_generate_key_ecc(o, type_props, key_size,
2540aeb0d927SCedric Chaumont params, param_count);
2541aeb0d927SCedric Chaumont if (res != TEE_SUCCESS)
2542aeb0d927SCedric Chaumont goto out;
2543aeb0d927SCedric Chaumont break;
2544aeb0d927SCedric Chaumont
254590040fa4SSohaib ul Hassan case TEE_TYPE_X25519_KEYPAIR:
254690040fa4SSohaib ul Hassan res = tee_svc_obj_generate_key_x25519(o, type_props, key_size,
254790040fa4SSohaib ul Hassan params, param_count);
254890040fa4SSohaib ul Hassan if (res != TEE_SUCCESS)
254990040fa4SSohaib ul Hassan goto out;
255090040fa4SSohaib ul Hassan break;
255134ce35b1Sloubaihui case TEE_TYPE_X448_KEYPAIR:
255234ce35b1Sloubaihui res = tee_svc_obj_generate_key_x448(o, type_props, key_size,
255334ce35b1Sloubaihui params, param_count);
255434ce35b1Sloubaihui if (res != TEE_SUCCESS)
255534ce35b1Sloubaihui goto out;
255634ce35b1Sloubaihui break;
255790040fa4SSohaib ul Hassan
25580aaad418SValerii Chubar case TEE_TYPE_ED25519_KEYPAIR:
25590aaad418SValerii Chubar res = tee_svc_obj_generate_key_ed25519(o, type_props, key_size,
25600aaad418SValerii Chubar params, param_count);
25610aaad418SValerii Chubar if (res != TEE_SUCCESS)
25620aaad418SValerii Chubar goto out;
25630aaad418SValerii Chubar break;
25640aaad418SValerii Chubar
2565b0104773SPascal Brand default:
2566177603c7SJens Wiklander res = TEE_ERROR_BAD_FORMAT;
2567b0104773SPascal Brand }
2568b0104773SPascal Brand
2569177603c7SJens Wiklander out:
257070b61310SJerome Forissier free_wipe(params);
2571177603c7SJens Wiklander if (res == TEE_SUCCESS) {
2572181f0998SJens Wiklander o->info.objectSize = key_size;
2573b0104773SPascal Brand o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
2574177603c7SJens Wiklander }
2575177603c7SJens Wiklander return res;
2576b0104773SPascal Brand }
2577b0104773SPascal Brand
tee_svc_cryp_get_state(struct ts_session * sess,vaddr_t state_id,struct tee_cryp_state ** state)257800b3b9a2SJens Wiklander static TEE_Result tee_svc_cryp_get_state(struct ts_session *sess,
2579589a4941SJerome Forissier vaddr_t state_id,
2580b0104773SPascal Brand struct tee_cryp_state **state)
2581b0104773SPascal Brand {
2582b0104773SPascal Brand struct tee_cryp_state *s;
25838684fde8SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
2584b0104773SPascal Brand
25858684fde8SJens Wiklander TAILQ_FOREACH(s, &utc->cryp_states, link) {
258661ea19fdSJens Wiklander if (state_id == (vaddr_t)s) {
2587b0104773SPascal Brand *state = s;
2588b0104773SPascal Brand return TEE_SUCCESS;
2589b0104773SPascal Brand }
2590b0104773SPascal Brand }
2591b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2592b0104773SPascal Brand }
2593b0104773SPascal Brand
cryp_state_free(struct user_ta_ctx * utc,struct tee_cryp_state * cs)25948684fde8SJens Wiklander static void cryp_state_free(struct user_ta_ctx *utc, struct tee_cryp_state *cs)
2595b0104773SPascal Brand {
2596b0104773SPascal Brand struct tee_obj *o;
2597b0104773SPascal Brand
25988684fde8SJens Wiklander if (tee_obj_get(utc, cs->key1, &o) == TEE_SUCCESS)
25998684fde8SJens Wiklander tee_obj_close(utc, o);
26008684fde8SJens Wiklander if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS)
26018684fde8SJens Wiklander tee_obj_close(utc, o);
2602b0104773SPascal Brand
26038684fde8SJens Wiklander TAILQ_REMOVE(&utc->cryp_states, cs, link);
2604b0104773SPascal Brand if (cs->ctx_finalize != NULL)
260552ee414bSJens Wiklander cs->ctx_finalize(cs->ctx);
260682ef73bcSJens Wiklander
260782ef73bcSJens Wiklander switch (TEE_ALG_GET_CLASS(cs->algo)) {
260872a9b1a0SJens Wiklander case TEE_OPERATION_CIPHER:
2609cbda7091SJens Wiklander crypto_cipher_free_ctx(cs->ctx);
261072a9b1a0SJens Wiklander break;
2611d7ac7d0fSJens Wiklander case TEE_OPERATION_AE:
261252ee414bSJens Wiklander crypto_authenc_free_ctx(cs->ctx);
2613d7ac7d0fSJens Wiklander break;
261482ef73bcSJens Wiklander case TEE_OPERATION_DIGEST:
26156b3a371cSJens Wiklander crypto_hash_free_ctx(cs->ctx);
261682ef73bcSJens Wiklander break;
261782ef73bcSJens Wiklander case TEE_OPERATION_MAC:
2618c69bc615SJens Wiklander crypto_mac_free_ctx(cs->ctx);
261982ef73bcSJens Wiklander break;
262082ef73bcSJens Wiklander default:
2621795a089bSJens Wiklander assert(!cs->ctx);
262282ef73bcSJens Wiklander }
262382ef73bcSJens Wiklander
2624b0104773SPascal Brand free(cs);
2625b0104773SPascal Brand }
2626b0104773SPascal Brand
tee_svc_cryp_check_key_type(const struct tee_obj * o,uint32_t algo,TEE_OperationMode mode)2627b0104773SPascal Brand static TEE_Result tee_svc_cryp_check_key_type(const struct tee_obj *o,
2628b0104773SPascal Brand uint32_t algo,
2629b0104773SPascal Brand TEE_OperationMode mode)
2630b0104773SPascal Brand {
2631b0104773SPascal Brand uint32_t req_key_type;
263200d2e232SPascal Brand uint32_t req_key_type2 = 0;
2633b0104773SPascal Brand
2634b0104773SPascal Brand switch (TEE_ALG_GET_MAIN_ALG(algo)) {
2635b0104773SPascal Brand case TEE_MAIN_ALGO_MD5:
2636b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_MD5;
2637b0104773SPascal Brand break;
2638b0104773SPascal Brand case TEE_MAIN_ALGO_SHA1:
2639b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_SHA1;
2640b0104773SPascal Brand break;
2641b0104773SPascal Brand case TEE_MAIN_ALGO_SHA224:
2642b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_SHA224;
2643b0104773SPascal Brand break;
2644b0104773SPascal Brand case TEE_MAIN_ALGO_SHA256:
2645b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_SHA256;
2646b0104773SPascal Brand break;
2647b0104773SPascal Brand case TEE_MAIN_ALGO_SHA384:
2648b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_SHA384;
2649b0104773SPascal Brand break;
2650b0104773SPascal Brand case TEE_MAIN_ALGO_SHA512:
2651b0104773SPascal Brand req_key_type = TEE_TYPE_HMAC_SHA512;
2652b0104773SPascal Brand break;
2653260b4028SJens Wiklander case TEE_MAIN_ALGO_SHA3_224:
2654260b4028SJens Wiklander req_key_type = TEE_TYPE_HMAC_SHA3_224;
2655260b4028SJens Wiklander break;
2656260b4028SJens Wiklander case TEE_MAIN_ALGO_SHA3_256:
2657260b4028SJens Wiklander req_key_type = TEE_TYPE_HMAC_SHA3_256;
2658260b4028SJens Wiklander break;
2659260b4028SJens Wiklander case TEE_MAIN_ALGO_SHA3_384:
2660260b4028SJens Wiklander req_key_type = TEE_TYPE_HMAC_SHA3_384;
2661260b4028SJens Wiklander break;
2662260b4028SJens Wiklander case TEE_MAIN_ALGO_SHA3_512:
2663260b4028SJens Wiklander req_key_type = TEE_TYPE_HMAC_SHA3_512;
2664260b4028SJens Wiklander break;
266547645577SJerome Forissier case TEE_MAIN_ALGO_SM3:
266647645577SJerome Forissier req_key_type = TEE_TYPE_HMAC_SM3;
266747645577SJerome Forissier break;
2668b0104773SPascal Brand case TEE_MAIN_ALGO_AES:
2669b0104773SPascal Brand req_key_type = TEE_TYPE_AES;
2670b0104773SPascal Brand break;
2671b0104773SPascal Brand case TEE_MAIN_ALGO_DES:
2672b0104773SPascal Brand req_key_type = TEE_TYPE_DES;
2673b0104773SPascal Brand break;
2674b0104773SPascal Brand case TEE_MAIN_ALGO_DES3:
2675b0104773SPascal Brand req_key_type = TEE_TYPE_DES3;
2676b0104773SPascal Brand break;
2677ade6f848SJerome Forissier case TEE_MAIN_ALGO_SM4:
2678ade6f848SJerome Forissier req_key_type = TEE_TYPE_SM4;
2679ade6f848SJerome Forissier break;
2680b0104773SPascal Brand case TEE_MAIN_ALGO_RSA:
2681b0104773SPascal Brand req_key_type = TEE_TYPE_RSA_KEYPAIR;
268200d2e232SPascal Brand if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY)
268300d2e232SPascal Brand req_key_type2 = TEE_TYPE_RSA_PUBLIC_KEY;
2684b0104773SPascal Brand break;
2685b0104773SPascal Brand case TEE_MAIN_ALGO_DSA:
2686b0104773SPascal Brand req_key_type = TEE_TYPE_DSA_KEYPAIR;
268700d2e232SPascal Brand if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY)
268800d2e232SPascal Brand req_key_type2 = TEE_TYPE_DSA_PUBLIC_KEY;
2689b0104773SPascal Brand break;
2690b0104773SPascal Brand case TEE_MAIN_ALGO_DH:
2691b0104773SPascal Brand req_key_type = TEE_TYPE_DH_KEYPAIR;
2692b0104773SPascal Brand break;
2693c988227aSPascal Brand case TEE_MAIN_ALGO_ECDSA:
2694c988227aSPascal Brand req_key_type = TEE_TYPE_ECDSA_KEYPAIR;
269500d2e232SPascal Brand if (mode == TEE_MODE_VERIFY)
269600d2e232SPascal Brand req_key_type2 = TEE_TYPE_ECDSA_PUBLIC_KEY;
2697c988227aSPascal Brand break;
2698c988227aSPascal Brand case TEE_MAIN_ALGO_ECDH:
2699c988227aSPascal Brand req_key_type = TEE_TYPE_ECDH_KEYPAIR;
2700c988227aSPascal Brand break;
27010aaad418SValerii Chubar case TEE_MAIN_ALGO_ED25519:
27020aaad418SValerii Chubar req_key_type = TEE_TYPE_ED25519_KEYPAIR;
27030aaad418SValerii Chubar if (mode == TEE_MODE_VERIFY)
27040aaad418SValerii Chubar req_key_type2 = TEE_TYPE_ED25519_PUBLIC_KEY;
27050aaad418SValerii Chubar break;
270691fc6bd8SJerome Forissier case TEE_MAIN_ALGO_SM2_PKE:
270791fc6bd8SJerome Forissier if (mode == TEE_MODE_ENCRYPT)
270891fc6bd8SJerome Forissier req_key_type = TEE_TYPE_SM2_PKE_PUBLIC_KEY;
270991fc6bd8SJerome Forissier else
271091fc6bd8SJerome Forissier req_key_type = TEE_TYPE_SM2_PKE_KEYPAIR;
271191fc6bd8SJerome Forissier break;
27120f151943SJerome Forissier case TEE_MAIN_ALGO_SM2_DSA_SM3:
27130f151943SJerome Forissier if (mode == TEE_MODE_VERIFY)
27140f151943SJerome Forissier req_key_type = TEE_TYPE_SM2_DSA_PUBLIC_KEY;
27150f151943SJerome Forissier else
27160f151943SJerome Forissier req_key_type = TEE_TYPE_SM2_DSA_KEYPAIR;
27170f151943SJerome Forissier break;
27185b385b3fSJerome Forissier #if defined(CFG_CRYPTO_SM2_KEP)
27195b385b3fSJerome Forissier case TEE_MAIN_ALGO_SM2_KEP:
27205b385b3fSJerome Forissier req_key_type = TEE_TYPE_SM2_KEP_KEYPAIR;
27215b385b3fSJerome Forissier req_key_type2 = TEE_TYPE_SM2_KEP_PUBLIC_KEY;
27225b385b3fSJerome Forissier break;
27235b385b3fSJerome Forissier #endif
2724cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
2725cdb198a7SJerome Forissier case TEE_MAIN_ALGO_HKDF:
2726cdb198a7SJerome Forissier req_key_type = TEE_TYPE_HKDF_IKM;
2727cdb198a7SJerome Forissier break;
2728cdb198a7SJerome Forissier #endif
27298854d3c6SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
27308854d3c6SJerome Forissier case TEE_MAIN_ALGO_CONCAT_KDF:
27318854d3c6SJerome Forissier req_key_type = TEE_TYPE_CONCAT_KDF_Z;
27328854d3c6SJerome Forissier break;
27338854d3c6SJerome Forissier #endif
27340f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
27350f2293b7SJerome Forissier case TEE_MAIN_ALGO_PBKDF2:
27360f2293b7SJerome Forissier req_key_type = TEE_TYPE_PBKDF2_PASSWORD;
27370f2293b7SJerome Forissier break;
27380f2293b7SJerome Forissier #endif
273990040fa4SSohaib ul Hassan case TEE_MAIN_ALGO_X25519:
274090040fa4SSohaib ul Hassan req_key_type = TEE_TYPE_X25519_KEYPAIR;
274190040fa4SSohaib ul Hassan break;
274234ce35b1Sloubaihui case TEE_MAIN_ALGO_X448:
274334ce35b1Sloubaihui req_key_type = TEE_TYPE_X448_KEYPAIR;
274434ce35b1Sloubaihui break;
2745b0104773SPascal Brand default:
2746b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2747b0104773SPascal Brand }
2748b0104773SPascal Brand
274900d2e232SPascal Brand if (req_key_type != o->info.objectType &&
275000d2e232SPascal Brand req_key_type2 != o->info.objectType)
2751b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2752b0104773SPascal Brand return TEE_SUCCESS;
2753b0104773SPascal Brand }
2754b0104773SPascal Brand
translate_compat_algo(uint32_t algo)2755fe2fd3ffSJens Wiklander static uint32_t translate_compat_algo(uint32_t algo)
2756fe2fd3ffSJens Wiklander {
2757fe2fd3ffSJens Wiklander switch (algo) {
2758fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDSA_P192:
2759fe2fd3ffSJens Wiklander return TEE_ALG_ECDSA_SHA1;
2760fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDSA_P224:
2761fe2fd3ffSJens Wiklander return TEE_ALG_ECDSA_SHA224;
2762fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDSA_P256:
2763fe2fd3ffSJens Wiklander return TEE_ALG_ECDSA_SHA256;
2764fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDSA_P384:
2765fe2fd3ffSJens Wiklander return TEE_ALG_ECDSA_SHA384;
2766fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDSA_P521:
2767fe2fd3ffSJens Wiklander return TEE_ALG_ECDSA_SHA512;
2768fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDH_P192:
2769fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDH_P224:
2770fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDH_P256:
2771fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDH_P384:
2772fe2fd3ffSJens Wiklander case __OPTEE_ALG_ECDH_P521:
2773fe2fd3ffSJens Wiklander return TEE_ALG_ECDH_DERIVE_SHARED_SECRET;
2774fe2fd3ffSJens Wiklander default:
2775fe2fd3ffSJens Wiklander return algo;
2776fe2fd3ffSJens Wiklander }
2777fe2fd3ffSJens Wiklander }
2778fe2fd3ffSJens Wiklander
syscall_cryp_state_alloc(unsigned long algo,unsigned long mode,unsigned long key1,unsigned long key2,uint32_t * state)2779e86f1266SJens Wiklander TEE_Result syscall_cryp_state_alloc(unsigned long algo, unsigned long mode,
2780e86f1266SJens Wiklander unsigned long key1, unsigned long key2,
2781b0104773SPascal Brand uint32_t *state)
2782b0104773SPascal Brand {
278300b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
278400b3b9a2SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
278500b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
278600b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
2787b0104773SPascal Brand struct tee_obj *o1 = NULL;
2788b0104773SPascal Brand struct tee_obj *o2 = NULL;
2789b0104773SPascal Brand
2790fe2fd3ffSJens Wiklander algo = translate_compat_algo(algo);
2791fe2fd3ffSJens Wiklander
2792b0104773SPascal Brand if (key1 != 0) {
2793c40a6505SJens Wiklander res = tee_obj_get(utc, uref_to_vaddr(key1), &o1);
2794b0104773SPascal Brand if (res != TEE_SUCCESS)
2795b0104773SPascal Brand return res;
2796b0104773SPascal Brand if (o1->busy)
2797b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2798b0104773SPascal Brand res = tee_svc_cryp_check_key_type(o1, algo, mode);
2799b0104773SPascal Brand if (res != TEE_SUCCESS)
2800b0104773SPascal Brand return res;
2801b0104773SPascal Brand }
2802b0104773SPascal Brand if (key2 != 0) {
2803c40a6505SJens Wiklander res = tee_obj_get(utc, uref_to_vaddr(key2), &o2);
2804b0104773SPascal Brand if (res != TEE_SUCCESS)
2805b0104773SPascal Brand return res;
2806b0104773SPascal Brand if (o2->busy)
2807b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2808b0104773SPascal Brand res = tee_svc_cryp_check_key_type(o2, algo, mode);
2809b0104773SPascal Brand if (res != TEE_SUCCESS)
2810b0104773SPascal Brand return res;
2811b0104773SPascal Brand }
2812b0104773SPascal Brand
2813b0104773SPascal Brand cs = calloc(1, sizeof(struct tee_cryp_state));
2814ffe04039SJerome Forissier if (!cs)
2815b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY;
28168684fde8SJens Wiklander TAILQ_INSERT_TAIL(&utc->cryp_states, cs, link);
2817b0104773SPascal Brand cs->algo = algo;
2818b0104773SPascal Brand cs->mode = mode;
281934a08becSJoakim Bech cs->state = CRYP_STATE_UNINITIALIZED;
2820b0104773SPascal Brand
2821b0104773SPascal Brand switch (TEE_ALG_GET_CLASS(algo)) {
2822b0104773SPascal Brand case TEE_OPERATION_CIPHER:
2823696f56acSPingan Xie if ((TEE_ALG_GET_CHAIN_MODE(algo) == TEE_CHAIN_MODE_XTS &&
2824696f56acSPingan Xie (key1 == 0 || key2 == 0)) ||
2825696f56acSPingan Xie (TEE_ALG_GET_CHAIN_MODE(algo) != TEE_CHAIN_MODE_XTS &&
2826696f56acSPingan Xie (key1 == 0 || key2 != 0))) {
2827b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
2828b0104773SPascal Brand } else {
282972a9b1a0SJens Wiklander res = crypto_cipher_alloc_ctx(&cs->ctx, algo);
2830b0104773SPascal Brand if (res != TEE_SUCCESS)
2831b0104773SPascal Brand break;
2832b0104773SPascal Brand }
2833b0104773SPascal Brand break;
2834b0104773SPascal Brand case TEE_OPERATION_AE:
2835b0104773SPascal Brand if (key1 == 0 || key2 != 0) {
2836b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
2837b0104773SPascal Brand } else {
2838d7ac7d0fSJens Wiklander res = crypto_authenc_alloc_ctx(&cs->ctx, algo);
2839b0104773SPascal Brand if (res != TEE_SUCCESS)
2840b0104773SPascal Brand break;
2841b0104773SPascal Brand }
2842b0104773SPascal Brand break;
2843b0104773SPascal Brand case TEE_OPERATION_MAC:
2844b0104773SPascal Brand if (key1 == 0 || key2 != 0) {
2845b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
2846b0104773SPascal Brand } else {
284782ef73bcSJens Wiklander res = crypto_mac_alloc_ctx(&cs->ctx, algo);
2848b0104773SPascal Brand if (res != TEE_SUCCESS)
2849b0104773SPascal Brand break;
2850b0104773SPascal Brand }
2851b0104773SPascal Brand break;
2852b0104773SPascal Brand case TEE_OPERATION_DIGEST:
2853b0104773SPascal Brand if (key1 != 0 || key2 != 0) {
2854b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
2855b0104773SPascal Brand } else {
2856ecf2e014SJens Wiklander res = crypto_hash_alloc_ctx(&cs->ctx, algo);
2857b0104773SPascal Brand if (res != TEE_SUCCESS)
2858b0104773SPascal Brand break;
2859b0104773SPascal Brand }
2860b0104773SPascal Brand break;
2861b0104773SPascal Brand case TEE_OPERATION_ASYMMETRIC_CIPHER:
2862b0104773SPascal Brand case TEE_OPERATION_ASYMMETRIC_SIGNATURE:
2863688c335dSJerome Forissier if (algo == TEE_ALG_RSASSA_PKCS1_V1_5 &&
2864688c335dSJerome Forissier !IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) {
2865688c335dSJerome Forissier res = TEE_ERROR_NOT_SUPPORTED;
2866688c335dSJerome Forissier break;
2867688c335dSJerome Forissier }
2868b0104773SPascal Brand if (key1 == 0 || key2 != 0)
2869b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
2870b0104773SPascal Brand break;
2871b0104773SPascal Brand case TEE_OPERATION_KEY_DERIVATION:
28725b385b3fSJerome Forissier if (algo == TEE_ALG_SM2_KEP) {
28735b385b3fSJerome Forissier if (key1 == 0 || key2 == 0)
28745b385b3fSJerome Forissier res = TEE_ERROR_BAD_PARAMETERS;
28755b385b3fSJerome Forissier } else {
2876b0104773SPascal Brand if (key1 == 0 || key2 != 0)
2877b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
28785b385b3fSJerome Forissier }
2879b0104773SPascal Brand break;
2880b0104773SPascal Brand default:
2881b0104773SPascal Brand res = TEE_ERROR_NOT_SUPPORTED;
2882b0104773SPascal Brand break;
2883b0104773SPascal Brand }
2884b0104773SPascal Brand if (res != TEE_SUCCESS)
2885b0104773SPascal Brand goto out;
2886b0104773SPascal Brand
2887c40a6505SJens Wiklander res = copy_kaddr_to_uref(state, cs);
2888b0104773SPascal Brand if (res != TEE_SUCCESS)
2889b0104773SPascal Brand goto out;
2890b0104773SPascal Brand
2891b0104773SPascal Brand /* Register keys */
2892b0104773SPascal Brand if (o1 != NULL) {
2893b0104773SPascal Brand o1->busy = true;
2894e86f1266SJens Wiklander cs->key1 = (vaddr_t)o1;
2895b0104773SPascal Brand }
2896b0104773SPascal Brand if (o2 != NULL) {
2897b0104773SPascal Brand o2->busy = true;
2898e86f1266SJens Wiklander cs->key2 = (vaddr_t)o2;
2899b0104773SPascal Brand }
2900b0104773SPascal Brand
2901b0104773SPascal Brand out:
2902b0104773SPascal Brand if (res != TEE_SUCCESS)
29038684fde8SJens Wiklander cryp_state_free(utc, cs);
2904b0104773SPascal Brand return res;
2905b0104773SPascal Brand }
2906b0104773SPascal Brand
syscall_cryp_state_copy(unsigned long dst,unsigned long src)2907e86f1266SJens Wiklander TEE_Result syscall_cryp_state_copy(unsigned long dst, unsigned long src)
2908b0104773SPascal Brand {
290900b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
291000b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
291100b3b9a2SJens Wiklander struct tee_cryp_state *cs_dst = NULL;
291200b3b9a2SJens Wiklander struct tee_cryp_state *cs_src = NULL;
2913b0104773SPascal Brand
2914c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(dst), &cs_dst);
2915b0104773SPascal Brand if (res != TEE_SUCCESS)
2916b0104773SPascal Brand return res;
2917e86f1266SJens Wiklander
2918c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(src), &cs_src);
2919b0104773SPascal Brand if (res != TEE_SUCCESS)
2920b0104773SPascal Brand return res;
2921b0104773SPascal Brand if (cs_dst->algo != cs_src->algo || cs_dst->mode != cs_src->mode)
2922b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2923b0104773SPascal Brand
292482ef73bcSJens Wiklander switch (TEE_ALG_GET_CLASS(cs_src->algo)) {
292572a9b1a0SJens Wiklander case TEE_OPERATION_CIPHER:
2926cbda7091SJens Wiklander crypto_cipher_copy_state(cs_dst->ctx, cs_src->ctx);
292772a9b1a0SJens Wiklander break;
2928d7ac7d0fSJens Wiklander case TEE_OPERATION_AE:
292952ee414bSJens Wiklander crypto_authenc_copy_state(cs_dst->ctx, cs_src->ctx);
2930d7ac7d0fSJens Wiklander break;
293182ef73bcSJens Wiklander case TEE_OPERATION_DIGEST:
29326b3a371cSJens Wiklander crypto_hash_copy_state(cs_dst->ctx, cs_src->ctx);
293382ef73bcSJens Wiklander break;
293482ef73bcSJens Wiklander case TEE_OPERATION_MAC:
2935c69bc615SJens Wiklander crypto_mac_copy_state(cs_dst->ctx, cs_src->ctx);
293682ef73bcSJens Wiklander break;
293782ef73bcSJens Wiklander default:
2938795a089bSJens Wiklander return TEE_ERROR_BAD_STATE;
293982ef73bcSJens Wiklander }
2940ecf2e014SJens Wiklander
294134a08becSJoakim Bech cs_dst->state = cs_src->state;
29421defc238SJens Wiklander cs_dst->ctx_finalize = cs_src->ctx_finalize;
294334a08becSJoakim Bech
2944b0104773SPascal Brand return TEE_SUCCESS;
2945b0104773SPascal Brand }
2946b0104773SPascal Brand
tee_svc_cryp_free_states(struct user_ta_ctx * utc)29478684fde8SJens Wiklander void tee_svc_cryp_free_states(struct user_ta_ctx *utc)
2948b0104773SPascal Brand {
29498684fde8SJens Wiklander struct tee_cryp_state_head *states = &utc->cryp_states;
2950b0104773SPascal Brand
2951b0104773SPascal Brand while (!TAILQ_EMPTY(states))
29528684fde8SJens Wiklander cryp_state_free(utc, TAILQ_FIRST(states));
2953b0104773SPascal Brand }
2954b0104773SPascal Brand
syscall_cryp_state_free(unsigned long state)2955e86f1266SJens Wiklander TEE_Result syscall_cryp_state_free(unsigned long state)
2956b0104773SPascal Brand {
295700b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
295800b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
295900b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
2960b0104773SPascal Brand
2961c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
2962b0104773SPascal Brand if (res != TEE_SUCCESS)
2963b0104773SPascal Brand return res;
29648684fde8SJens Wiklander cryp_state_free(to_user_ta_ctx(sess->ctx), cs);
2965b0104773SPascal Brand return TEE_SUCCESS;
2966b0104773SPascal Brand }
2967b0104773SPascal Brand
syscall_hash_init(unsigned long state,const void * iv __maybe_unused,size_t iv_len __maybe_unused)29683276098dSJerome Forissier TEE_Result syscall_hash_init(unsigned long state,
29693276098dSJerome Forissier const void *iv __maybe_unused,
29703276098dSJerome Forissier size_t iv_len __maybe_unused)
2971b0104773SPascal Brand {
297200b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
297300b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
297400b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
2975b0104773SPascal Brand
2976c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
2977b0104773SPascal Brand if (res != TEE_SUCCESS)
2978b0104773SPascal Brand return res;
2979b0104773SPascal Brand
2980b0104773SPascal Brand switch (TEE_ALG_GET_CLASS(cs->algo)) {
2981b0104773SPascal Brand case TEE_OPERATION_DIGEST:
29826b3a371cSJens Wiklander res = crypto_hash_init(cs->ctx);
2983b0104773SPascal Brand if (res != TEE_SUCCESS)
2984b0104773SPascal Brand return res;
2985b0104773SPascal Brand break;
2986b0104773SPascal Brand case TEE_OPERATION_MAC:
2987b0104773SPascal Brand {
2988b0104773SPascal Brand struct tee_obj *o;
2989b0104773SPascal Brand struct tee_cryp_obj_secret *key;
2990b0104773SPascal Brand
29918684fde8SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx),
29928684fde8SJens Wiklander cs->key1, &o);
2993b0104773SPascal Brand if (res != TEE_SUCCESS)
2994b0104773SPascal Brand return res;
2995b0104773SPascal Brand if ((o->info.handleFlags &
2996b0104773SPascal Brand TEE_HANDLE_FLAG_INITIALIZED) == 0)
2997b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
2998b0104773SPascal Brand
299940a4fd66SJens Wiklander key = (struct tee_cryp_obj_secret *)o->attr;
3000c69bc615SJens Wiklander res = crypto_mac_init(cs->ctx, (void *)(key + 1),
3001c69bc615SJens Wiklander key->key_size);
3002b0104773SPascal Brand if (res != TEE_SUCCESS)
3003b0104773SPascal Brand return res;
3004b0104773SPascal Brand break;
3005b0104773SPascal Brand }
3006b0104773SPascal Brand default:
3007b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
3008b0104773SPascal Brand }
3009b0104773SPascal Brand
301034a08becSJoakim Bech cs->state = CRYP_STATE_INITIALIZED;
301134a08becSJoakim Bech
3012b0104773SPascal Brand return TEE_SUCCESS;
3013b0104773SPascal Brand }
3014b0104773SPascal Brand
syscall_hash_update(unsigned long state,const void * chunk,size_t chunk_size)3015e86f1266SJens Wiklander TEE_Result syscall_hash_update(unsigned long state, const void *chunk,
3016b0104773SPascal Brand size_t chunk_size)
3017b0104773SPascal Brand {
301800b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
30191936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
30201936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
3021b0104773SPascal Brand
302273d6c3baSJoakim Bech /* No data, but size provided isn't valid parameters. */
302373d6c3baSJoakim Bech if (!chunk && chunk_size)
302473d6c3baSJoakim Bech return TEE_ERROR_BAD_PARAMETERS;
302573d6c3baSJoakim Bech
302673d6c3baSJoakim Bech /* Zero length hash is valid, but nothing we need to do. */
302773d6c3baSJoakim Bech if (!chunk_size)
302873d6c3baSJoakim Bech return TEE_SUCCESS;
302973d6c3baSJoakim Bech
3030ef142203SJens Wiklander chunk = memtag_strip_tag_const(chunk);
3031ef142203SJens Wiklander
303289c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
3033b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
3034b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
30352ffdd194SJens Wiklander (uaddr_t)chunk, chunk_size);
3036b0104773SPascal Brand if (res != TEE_SUCCESS)
3037b0104773SPascal Brand return res;
3038b0104773SPascal Brand
3039c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
3040b0104773SPascal Brand if (res != TEE_SUCCESS)
3041b0104773SPascal Brand return res;
3042b0104773SPascal Brand
304334a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
304434a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
304534a08becSJoakim Bech
3046b0104773SPascal Brand switch (TEE_ALG_GET_CLASS(cs->algo)) {
3047b0104773SPascal Brand case TEE_OPERATION_DIGEST:
30484e154320SSeonghyun Park enter_user_access();
30496b3a371cSJens Wiklander res = crypto_hash_update(cs->ctx, chunk, chunk_size);
30504e154320SSeonghyun Park exit_user_access();
3051b0104773SPascal Brand if (res != TEE_SUCCESS)
3052b0104773SPascal Brand return res;
3053b0104773SPascal Brand break;
3054b0104773SPascal Brand case TEE_OPERATION_MAC:
30554e154320SSeonghyun Park enter_user_access();
3056c69bc615SJens Wiklander res = crypto_mac_update(cs->ctx, chunk, chunk_size);
30574e154320SSeonghyun Park exit_user_access();
3058b0104773SPascal Brand if (res != TEE_SUCCESS)
3059b0104773SPascal Brand return res;
3060b0104773SPascal Brand break;
3061b0104773SPascal Brand default:
3062b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
3063b0104773SPascal Brand }
3064b0104773SPascal Brand
3065b0104773SPascal Brand return TEE_SUCCESS;
3066b0104773SPascal Brand }
3067b0104773SPascal Brand
is_xof_algo(uint32_t algo)3068e81ed9d4SJens Wiklander static bool is_xof_algo(uint32_t algo)
3069e81ed9d4SJens Wiklander {
3070e81ed9d4SJens Wiklander return algo == TEE_ALG_SHAKE128 || algo == TEE_ALG_SHAKE256;
3071e81ed9d4SJens Wiklander }
3072e81ed9d4SJens Wiklander
syscall_hash_final(unsigned long state,const void * chunk,size_t chunk_size,void * hash,uint64_t * hash_len)3073e86f1266SJens Wiklander TEE_Result syscall_hash_final(unsigned long state, const void *chunk,
3074e86f1266SJens Wiklander size_t chunk_size, void *hash, uint64_t *hash_len)
3075b0104773SPascal Brand {
307600b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
30771936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
30781936dfc7SJens Wiklander TEE_Result res2 = TEE_SUCCESS;
30791936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
30801936dfc7SJens Wiklander size_t hash_size = 0;
308184e9c40bSJens Wiklander size_t hlen = 0;
3082b0104773SPascal Brand
308373d6c3baSJoakim Bech /* No data, but size provided isn't valid parameters. */
308473d6c3baSJoakim Bech if (!chunk && chunk_size)
308573d6c3baSJoakim Bech return TEE_ERROR_BAD_PARAMETERS;
308673d6c3baSJoakim Bech
3087ef142203SJens Wiklander chunk = memtag_strip_tag_const(chunk);
3088ef142203SJens Wiklander hash = memtag_strip_tag(hash);
3089ef142203SJens Wiklander
309089c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
3091b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
3092b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
30932ffdd194SJens Wiklander (uaddr_t)chunk, chunk_size);
3094b0104773SPascal Brand if (res != TEE_SUCCESS)
3095b0104773SPascal Brand return res;
3096b0104773SPascal Brand
309784e9c40bSJens Wiklander res = get_user_u64_as_size_t(&hlen, hash_len);
3098b0104773SPascal Brand if (res != TEE_SUCCESS)
3099b0104773SPascal Brand return res;
3100b0104773SPascal Brand
310189c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
3102b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
3103b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE |
3104b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
31052ffdd194SJens Wiklander (uaddr_t)hash, hlen);
3106b0104773SPascal Brand if (res != TEE_SUCCESS)
3107b0104773SPascal Brand return res;
3108b0104773SPascal Brand
3109c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
3110b0104773SPascal Brand if (res != TEE_SUCCESS)
3111b0104773SPascal Brand return res;
3112b0104773SPascal Brand
311334a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
311434a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
311534a08becSJoakim Bech
3116b0104773SPascal Brand switch (TEE_ALG_GET_CLASS(cs->algo)) {
3117b0104773SPascal Brand case TEE_OPERATION_DIGEST:
3118e81ed9d4SJens Wiklander if (is_xof_algo(cs->algo)) {
3119e81ed9d4SJens Wiklander if (chunk_size) {
31204e154320SSeonghyun Park enter_user_access();
3121e81ed9d4SJens Wiklander res = crypto_hash_update(cs->ctx, chunk,
3122e81ed9d4SJens Wiklander chunk_size);
31234e154320SSeonghyun Park exit_user_access();
3124e81ed9d4SJens Wiklander if (res)
3125e81ed9d4SJens Wiklander return res;
3126e81ed9d4SJens Wiklander }
3127e81ed9d4SJens Wiklander
3128e81ed9d4SJens Wiklander /*
3129e81ed9d4SJens Wiklander * hash_size is supposed to be unchanged for XOF
3130e81ed9d4SJens Wiklander * algorithms so return directly.
3131e81ed9d4SJens Wiklander */
31324e154320SSeonghyun Park enter_user_access();
31334e154320SSeonghyun Park res = crypto_hash_final(cs->ctx, hash, hlen);
31344e154320SSeonghyun Park exit_user_access();
31354e154320SSeonghyun Park return res;
3136e81ed9d4SJens Wiklander }
3137e81ed9d4SJens Wiklander
31387c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(cs->algo, &hash_size);
3139b0104773SPascal Brand if (res != TEE_SUCCESS)
3140b0104773SPascal Brand return res;
314154ebc3acSJoakim Bech if (hlen < hash_size) {
3142b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
3143b0104773SPascal Brand goto out;
3144b0104773SPascal Brand }
3145b0104773SPascal Brand
314673d6c3baSJoakim Bech if (chunk_size) {
31474e154320SSeonghyun Park enter_user_access();
31486b3a371cSJens Wiklander res = crypto_hash_update(cs->ctx, chunk, chunk_size);
31494e154320SSeonghyun Park exit_user_access();
3150b0104773SPascal Brand if (res != TEE_SUCCESS)
3151b0104773SPascal Brand return res;
315273d6c3baSJoakim Bech }
315373d6c3baSJoakim Bech
31544e154320SSeonghyun Park enter_user_access();
31556b3a371cSJens Wiklander res = crypto_hash_final(cs->ctx, hash, hash_size);
31564e154320SSeonghyun Park exit_user_access();
3157b0104773SPascal Brand if (res != TEE_SUCCESS)
3158b0104773SPascal Brand return res;
3159b0104773SPascal Brand break;
316073d6c3baSJoakim Bech
3161b0104773SPascal Brand case TEE_OPERATION_MAC:
31627c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(cs->algo, &hash_size);
3163b0104773SPascal Brand if (res != TEE_SUCCESS)
3164b0104773SPascal Brand return res;
316554ebc3acSJoakim Bech if (hlen < hash_size) {
3166b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
3167b0104773SPascal Brand goto out;
3168b0104773SPascal Brand }
3169b0104773SPascal Brand
3170d8e06e12SPascal Brand if (chunk_size) {
31714e154320SSeonghyun Park enter_user_access();
3172c69bc615SJens Wiklander res = crypto_mac_update(cs->ctx, chunk, chunk_size);
31734e154320SSeonghyun Park exit_user_access();
3174d8e06e12SPascal Brand if (res != TEE_SUCCESS)
3175d8e06e12SPascal Brand return res;
3176d8e06e12SPascal Brand }
3177d8e06e12SPascal Brand
31784e154320SSeonghyun Park enter_user_access();
3179c69bc615SJens Wiklander res = crypto_mac_final(cs->ctx, hash, hash_size);
31804e154320SSeonghyun Park exit_user_access();
3181b0104773SPascal Brand if (res != TEE_SUCCESS)
3182b0104773SPascal Brand return res;
3183b0104773SPascal Brand break;
318473d6c3baSJoakim Bech
3185b0104773SPascal Brand default:
3186b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
3187b0104773SPascal Brand }
3188b0104773SPascal Brand out:
318984e9c40bSJens Wiklander res2 = put_user_u64(hash_len, hash_size);
3190b0104773SPascal Brand if (res2 != TEE_SUCCESS)
3191b0104773SPascal Brand return res2;
3192b0104773SPascal Brand return res;
3193b0104773SPascal Brand }
3194b0104773SPascal Brand
syscall_cipher_init(unsigned long state,const void * iv,size_t iv_len)3195e86f1266SJens Wiklander TEE_Result syscall_cipher_init(unsigned long state, const void *iv,
3196e86f1266SJens Wiklander size_t iv_len)
3197b0104773SPascal Brand {
319800b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
319900b3b9a2SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
32001936dfc7SJens Wiklander struct tee_cryp_obj_secret *key1 = NULL;
32011936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
32021936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
32031936dfc7SJens Wiklander struct tee_obj *o = NULL;
3204a844a0b8SSeonghyun Park void *iv_bbuf = NULL;
3205b0104773SPascal Brand
3206c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
3207b0104773SPascal Brand if (res != TEE_SUCCESS)
3208b0104773SPascal Brand return res;
3209b0104773SPascal Brand
321028aa35f5SJoakim Bech if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_CIPHER)
321128aa35f5SJoakim Bech return TEE_ERROR_BAD_STATE;
321228aa35f5SJoakim Bech
32138684fde8SJens Wiklander res = tee_obj_get(utc, cs->key1, &o);
3214b0104773SPascal Brand if (res != TEE_SUCCESS)
3215b0104773SPascal Brand return res;
3216b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
3217b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
3218b0104773SPascal Brand
321940a4fd66SJens Wiklander key1 = o->attr;
3220b0104773SPascal Brand
3221a844a0b8SSeonghyun Park res = bb_memdup_user(iv, iv_len, &iv_bbuf);
3222a844a0b8SSeonghyun Park if (res)
3223a844a0b8SSeonghyun Park return res;
3224a844a0b8SSeonghyun Park
32258684fde8SJens Wiklander if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS) {
322640a4fd66SJens Wiklander struct tee_cryp_obj_secret *key2 = o->attr;
3227b0104773SPascal Brand
3228b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
3229b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
3230b0104773SPascal Brand
3231cbda7091SJens Wiklander res = crypto_cipher_init(cs->ctx, cs->mode,
323282d91db1SJens Wiklander (uint8_t *)(key1 + 1), key1->key_size,
323382d91db1SJens Wiklander (uint8_t *)(key2 + 1), key2->key_size,
3234a844a0b8SSeonghyun Park iv_bbuf, iv_len);
3235b0104773SPascal Brand } else {
3236cbda7091SJens Wiklander res = crypto_cipher_init(cs->ctx, cs->mode,
323782d91db1SJens Wiklander (uint8_t *)(key1 + 1), key1->key_size,
3238a844a0b8SSeonghyun Park NULL, 0, iv_bbuf, iv_len);
3239b0104773SPascal Brand }
3240b0104773SPascal Brand if (res != TEE_SUCCESS)
3241b0104773SPascal Brand return res;
3242b0104773SPascal Brand
324352ee414bSJens Wiklander cs->ctx_finalize = crypto_cipher_final;
324434a08becSJoakim Bech cs->state = CRYP_STATE_INITIALIZED;
324534a08becSJoakim Bech
3246b0104773SPascal Brand return TEE_SUCCESS;
3247b0104773SPascal Brand }
3248b0104773SPascal Brand
tee_svc_cipher_update_helper(unsigned long state,bool last_block,const void * src,size_t src_len,void * dst,uint64_t * dst_len)3249e86f1266SJens Wiklander static TEE_Result tee_svc_cipher_update_helper(unsigned long state,
3250e86f1266SJens Wiklander bool last_block, const void *src, size_t src_len,
3251e86f1266SJens Wiklander void *dst, uint64_t *dst_len)
3252b0104773SPascal Brand {
325300b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
32541936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
32551936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
325684e9c40bSJens Wiklander size_t dlen = 0;
3257b0104773SPascal Brand
3258c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
3259b0104773SPascal Brand if (res != TEE_SUCCESS)
3260b0104773SPascal Brand return res;
3261b0104773SPascal Brand
326234a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
326334a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
326434a08becSJoakim Bech
3265ef142203SJens Wiklander src = memtag_strip_tag_const(src);
3266ef142203SJens Wiklander dst = memtag_strip_tag(dst);
3267ef142203SJens Wiklander
326889c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
3269b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
3270b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
32712ffdd194SJens Wiklander (uaddr_t)src, src_len);
3272b0104773SPascal Brand if (res != TEE_SUCCESS)
3273b0104773SPascal Brand return res;
3274b0104773SPascal Brand
3275ffe04039SJerome Forissier if (!dst_len) {
3276b0104773SPascal Brand dlen = 0;
3277b0104773SPascal Brand } else {
32781936dfc7SJens Wiklander struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx;
32791936dfc7SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_READ |
32801936dfc7SJens Wiklander TEE_MEMORY_ACCESS_WRITE |
32811936dfc7SJens Wiklander TEE_MEMORY_ACCESS_ANY_OWNER;
32821936dfc7SJens Wiklander
328384e9c40bSJens Wiklander res = get_user_u64_as_size_t(&dlen, dst_len);
3284b0104773SPascal Brand if (res != TEE_SUCCESS)
3285b0104773SPascal Brand return res;
3286b0104773SPascal Brand
328789c9728dSJens Wiklander res = vm_check_access_rights(uctx, flags, (uaddr_t)dst, dlen);
3288b0104773SPascal Brand if (res != TEE_SUCCESS)
3289b0104773SPascal Brand return res;
3290b0104773SPascal Brand }
3291b0104773SPascal Brand
3292b0104773SPascal Brand if (dlen < src_len) {
3293b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
3294b0104773SPascal Brand goto out;
3295b0104773SPascal Brand }
3296b0104773SPascal Brand
3297b0104773SPascal Brand if (src_len > 0) {
3298b0104773SPascal Brand /* Permit src_len == 0 to finalize the operation */
32994e154320SSeonghyun Park enter_user_access();
3300ffe04039SJerome Forissier res = tee_do_cipher_update(cs->ctx, cs->algo, cs->mode,
3301ffe04039SJerome Forissier last_block, src, src_len, dst);
33024e154320SSeonghyun Park exit_user_access();
3303b0104773SPascal Brand }
3304b0104773SPascal Brand
3305b0104773SPascal Brand if (last_block && cs->ctx_finalize != NULL) {
330652ee414bSJens Wiklander cs->ctx_finalize(cs->ctx);
3307b0104773SPascal Brand cs->ctx_finalize = NULL;
3308b0104773SPascal Brand }
3309b0104773SPascal Brand
3310b0104773SPascal Brand out:
3311b0104773SPascal Brand if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) &&
3312b0104773SPascal Brand dst_len != NULL) {
3313177603c7SJens Wiklander TEE_Result res2;
3314177603c7SJens Wiklander
331584e9c40bSJens Wiklander res2 = put_user_u64(dst_len, src_len);
3316b0104773SPascal Brand if (res2 != TEE_SUCCESS)
3317b0104773SPascal Brand res = res2;
3318b0104773SPascal Brand }
3319b0104773SPascal Brand
3320b0104773SPascal Brand return res;
3321b0104773SPascal Brand }
3322b0104773SPascal Brand
syscall_cipher_update(unsigned long state,const void * src,size_t src_len,void * dst,uint64_t * dst_len)3323e86f1266SJens Wiklander TEE_Result syscall_cipher_update(unsigned long state, const void *src,
3324e86f1266SJens Wiklander size_t src_len, void *dst, uint64_t *dst_len)
3325b0104773SPascal Brand {
3326b0104773SPascal Brand return tee_svc_cipher_update_helper(state, false /* last_block */,
3327b0104773SPascal Brand src, src_len, dst, dst_len);
3328b0104773SPascal Brand }
3329b0104773SPascal Brand
syscall_cipher_final(unsigned long state,const void * src,size_t src_len,void * dst,uint64_t * dst_len)3330e86f1266SJens Wiklander TEE_Result syscall_cipher_final(unsigned long state, const void *src,
3331e86f1266SJens Wiklander size_t src_len, void *dst, uint64_t *dst_len)
3332b0104773SPascal Brand {
3333b0104773SPascal Brand return tee_svc_cipher_update_helper(state, true /* last_block */,
3334b0104773SPascal Brand src, src_len, dst, dst_len);
3335b0104773SPascal Brand }
3336b0104773SPascal Brand
3337cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
get_hkdf_params(uint32_t algo,const TEE_Attribute * params,uint32_t param_count,void ** salt,size_t * salt_len,void ** info,size_t * info_len,size_t * okm_len,uint32_t * hash_id)3338b93c7dffSJens Wiklander static TEE_Result get_hkdf_params(uint32_t algo, const TEE_Attribute *params,
3339cdb198a7SJerome Forissier uint32_t param_count,
3340cdb198a7SJerome Forissier void **salt, size_t *salt_len, void **info,
3341b93c7dffSJens Wiklander size_t *info_len, size_t *okm_len,
3342b93c7dffSJens Wiklander uint32_t *hash_id)
3343cdb198a7SJerome Forissier {
3344a844a0b8SSeonghyun Park TEE_Result res = TEE_SUCCESS;
3345cdb198a7SJerome Forissier size_t n;
3346b93c7dffSJens Wiklander enum { SALT = 0x1, LENGTH = 0x2, INFO = 0x4, HASH = 0x8 };
3347cdb198a7SJerome Forissier uint8_t found = 0;
3348cdb198a7SJerome Forissier
3349cdb198a7SJerome Forissier *salt = *info = NULL;
3350cdb198a7SJerome Forissier *salt_len = *info_len = *okm_len = 0;
3351cdb198a7SJerome Forissier
3352b93c7dffSJens Wiklander if (algo == TEE_ALG_HKDF) {
3353b93c7dffSJens Wiklander *hash_id = TEE_ALG_SHA256;
3354b93c7dffSJens Wiklander } else {
3355b93c7dffSJens Wiklander *hash_id = TEE_ALG_GET_DIGEST_HASH(algo);
3356b93c7dffSJens Wiklander found |= HASH;
3357b93c7dffSJens Wiklander }
3358b93c7dffSJens Wiklander
3359cdb198a7SJerome Forissier for (n = 0; n < param_count; n++) {
3360a844a0b8SSeonghyun Park const TEE_Attribute *p = ¶ms[n];
3361a844a0b8SSeonghyun Park
3362a844a0b8SSeonghyun Park switch (p->attributeID) {
3363b93c7dffSJens Wiklander case __OPTEE_TEE_ATTR_HKDF_SALT:
3364cdb198a7SJerome Forissier case TEE_ATTR_HKDF_SALT:
3365cdb198a7SJerome Forissier if (!(found & SALT)) {
3366a844a0b8SSeonghyun Park *salt_len = p->content.ref.length;
3367a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3368a844a0b8SSeonghyun Park *salt_len, salt);
3369a844a0b8SSeonghyun Park if (res)
3370a844a0b8SSeonghyun Park return res;
3371a844a0b8SSeonghyun Park
3372cdb198a7SJerome Forissier found |= SALT;
3373cdb198a7SJerome Forissier }
3374cdb198a7SJerome Forissier break;
3375b93c7dffSJens Wiklander case TEE_ATTR_KDF_KEY_SIZE:
3376cdb198a7SJerome Forissier case TEE_ATTR_HKDF_OKM_LENGTH:
3377cdb198a7SJerome Forissier if (!(found & LENGTH)) {
3378a844a0b8SSeonghyun Park *okm_len = p->content.value.a;
3379cdb198a7SJerome Forissier found |= LENGTH;
3380cdb198a7SJerome Forissier }
3381cdb198a7SJerome Forissier break;
3382b93c7dffSJens Wiklander case __OPTEE_ATTR_HKDF_INFO:
3383cdb198a7SJerome Forissier case TEE_ATTR_HKDF_INFO:
3384cdb198a7SJerome Forissier if (!(found & INFO)) {
3385a844a0b8SSeonghyun Park *info_len = p->content.ref.length;
3386a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3387a844a0b8SSeonghyun Park *info_len, info);
3388a844a0b8SSeonghyun Park if (res)
3389a844a0b8SSeonghyun Park return res;
3390a844a0b8SSeonghyun Park
3391cdb198a7SJerome Forissier found |= INFO;
3392cdb198a7SJerome Forissier }
3393cdb198a7SJerome Forissier break;
3394b93c7dffSJens Wiklander case TEE_ATTR_HKDF_HASH_ALGORITHM:
3395b93c7dffSJens Wiklander if (!(found & HASH)) {
3396a844a0b8SSeonghyun Park *hash_id = p->content.value.a;
3397b93c7dffSJens Wiklander found |= HASH;
3398b93c7dffSJens Wiklander }
3399b93c7dffSJens Wiklander break;
3400cdb198a7SJerome Forissier default:
3401cdb198a7SJerome Forissier /* Unexpected attribute */
3402cdb198a7SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
3403cdb198a7SJerome Forissier }
3404cdb198a7SJerome Forissier
3405cdb198a7SJerome Forissier }
3406cdb198a7SJerome Forissier
3407cdb198a7SJerome Forissier if (!(found & LENGTH))
3408cdb198a7SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
3409cdb198a7SJerome Forissier
3410cdb198a7SJerome Forissier return TEE_SUCCESS;
3411cdb198a7SJerome Forissier }
3412cdb198a7SJerome Forissier #endif
3413cdb198a7SJerome Forissier
34148854d3c6SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
get_concat_kdf_params(const TEE_Attribute * params,uint32_t param_count,void ** other_info,size_t * other_info_len,size_t * derived_key_len)34158854d3c6SJerome Forissier static TEE_Result get_concat_kdf_params(const TEE_Attribute *params,
34168854d3c6SJerome Forissier uint32_t param_count,
34178854d3c6SJerome Forissier void **other_info,
34188854d3c6SJerome Forissier size_t *other_info_len,
34198854d3c6SJerome Forissier size_t *derived_key_len)
34208854d3c6SJerome Forissier {
34218854d3c6SJerome Forissier size_t n;
34228854d3c6SJerome Forissier enum { LENGTH = 0x1, INFO = 0x2 };
34238854d3c6SJerome Forissier uint8_t found = 0;
34248854d3c6SJerome Forissier
34258854d3c6SJerome Forissier *other_info = NULL;
34268854d3c6SJerome Forissier *other_info_len = *derived_key_len = 0;
34278854d3c6SJerome Forissier
34288854d3c6SJerome Forissier for (n = 0; n < param_count; n++) {
3429a844a0b8SSeonghyun Park const TEE_Attribute *p = ¶ms[n];
3430a844a0b8SSeonghyun Park
3431a844a0b8SSeonghyun Park switch (p->attributeID) {
34328854d3c6SJerome Forissier case TEE_ATTR_CONCAT_KDF_OTHER_INFO:
34338854d3c6SJerome Forissier if (!(found & INFO)) {
3434a844a0b8SSeonghyun Park TEE_Result res = TEE_SUCCESS;
3435a844a0b8SSeonghyun Park
3436a844a0b8SSeonghyun Park *other_info_len = p->content.ref.length;
3437a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3438a844a0b8SSeonghyun Park *other_info_len,
3439a844a0b8SSeonghyun Park other_info);
3440a844a0b8SSeonghyun Park if (res)
3441a844a0b8SSeonghyun Park return res;
3442a844a0b8SSeonghyun Park
34438854d3c6SJerome Forissier found |= INFO;
34448854d3c6SJerome Forissier }
34458854d3c6SJerome Forissier break;
34468854d3c6SJerome Forissier case TEE_ATTR_CONCAT_KDF_DKM_LENGTH:
34478854d3c6SJerome Forissier if (!(found & LENGTH)) {
3448a844a0b8SSeonghyun Park *derived_key_len = p->content.value.a;
34498854d3c6SJerome Forissier found |= LENGTH;
34508854d3c6SJerome Forissier }
34518854d3c6SJerome Forissier break;
34528854d3c6SJerome Forissier default:
34538854d3c6SJerome Forissier /* Unexpected attribute */
34548854d3c6SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
34558854d3c6SJerome Forissier }
34568854d3c6SJerome Forissier }
34578854d3c6SJerome Forissier
34588854d3c6SJerome Forissier if (!(found & LENGTH))
34598854d3c6SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
34608854d3c6SJerome Forissier
34618854d3c6SJerome Forissier return TEE_SUCCESS;
34628854d3c6SJerome Forissier }
34638854d3c6SJerome Forissier #endif
34648854d3c6SJerome Forissier
34650f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
get_pbkdf2_params(const TEE_Attribute * params,uint32_t param_count,void ** salt,size_t * salt_len,size_t * derived_key_len,size_t * iteration_count)34660f2293b7SJerome Forissier static TEE_Result get_pbkdf2_params(const TEE_Attribute *params,
34670f2293b7SJerome Forissier uint32_t param_count, void **salt,
34680f2293b7SJerome Forissier size_t *salt_len, size_t *derived_key_len,
34690f2293b7SJerome Forissier size_t *iteration_count)
34700f2293b7SJerome Forissier {
34710f2293b7SJerome Forissier size_t n;
34720f2293b7SJerome Forissier enum { SALT = 0x1, LENGTH = 0x2, COUNT = 0x4 };
34730f2293b7SJerome Forissier uint8_t found = 0;
34740f2293b7SJerome Forissier
34750f2293b7SJerome Forissier *salt = NULL;
34760f2293b7SJerome Forissier *salt_len = *derived_key_len = *iteration_count = 0;
34770f2293b7SJerome Forissier
34780f2293b7SJerome Forissier for (n = 0; n < param_count; n++) {
3479a844a0b8SSeonghyun Park const TEE_Attribute *p = ¶ms[n];
3480a844a0b8SSeonghyun Park
3481a844a0b8SSeonghyun Park switch (p->attributeID) {
34820f2293b7SJerome Forissier case TEE_ATTR_PBKDF2_SALT:
34830f2293b7SJerome Forissier if (!(found & SALT)) {
3484a844a0b8SSeonghyun Park TEE_Result res = TEE_SUCCESS;
3485a844a0b8SSeonghyun Park
3486a844a0b8SSeonghyun Park *salt_len = p->content.ref.length;
3487a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3488a844a0b8SSeonghyun Park *salt_len, salt);
3489a844a0b8SSeonghyun Park if (res)
3490a844a0b8SSeonghyun Park return res;
3491a844a0b8SSeonghyun Park
34920f2293b7SJerome Forissier found |= SALT;
34930f2293b7SJerome Forissier }
34940f2293b7SJerome Forissier break;
34950f2293b7SJerome Forissier case TEE_ATTR_PBKDF2_DKM_LENGTH:
34960f2293b7SJerome Forissier if (!(found & LENGTH)) {
3497a844a0b8SSeonghyun Park *derived_key_len = p->content.value.a;
34980f2293b7SJerome Forissier found |= LENGTH;
34990f2293b7SJerome Forissier }
35000f2293b7SJerome Forissier break;
35010f2293b7SJerome Forissier case TEE_ATTR_PBKDF2_ITERATION_COUNT:
35020f2293b7SJerome Forissier if (!(found & COUNT)) {
3503a844a0b8SSeonghyun Park *iteration_count = p->content.value.a;
35040f2293b7SJerome Forissier found |= COUNT;
35050f2293b7SJerome Forissier }
35060f2293b7SJerome Forissier break;
35070f2293b7SJerome Forissier default:
35080f2293b7SJerome Forissier /* Unexpected attribute */
35090f2293b7SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
35100f2293b7SJerome Forissier }
35110f2293b7SJerome Forissier }
35120f2293b7SJerome Forissier
35130f2293b7SJerome Forissier if ((found & (LENGTH|COUNT)) != (LENGTH|COUNT))
35140f2293b7SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
35150f2293b7SJerome Forissier
35160f2293b7SJerome Forissier return TEE_SUCCESS;
35170f2293b7SJerome Forissier }
35180f2293b7SJerome Forissier #endif
35190f2293b7SJerome Forissier
35205b385b3fSJerome Forissier #if defined(CFG_CRYPTO_SM2_KEP)
get_sm2_kep_params(const TEE_Attribute * params,uint32_t param_count,struct ecc_public_key * peer_key,struct ecc_public_key * peer_eph_key,struct sm2_kep_parms * kep_parms)35215b385b3fSJerome Forissier static TEE_Result get_sm2_kep_params(const TEE_Attribute *params,
35225b385b3fSJerome Forissier uint32_t param_count,
35235b385b3fSJerome Forissier struct ecc_public_key *peer_key,
35245b385b3fSJerome Forissier struct ecc_public_key *peer_eph_key,
35255b385b3fSJerome Forissier struct sm2_kep_parms *kep_parms)
35265b385b3fSJerome Forissier {
35275b385b3fSJerome Forissier TEE_Result res = TEE_ERROR_GENERIC;
35285b385b3fSJerome Forissier size_t n;
35295b385b3fSJerome Forissier enum {
35305b385b3fSJerome Forissier IS_INITIATOR,
35315b385b3fSJerome Forissier PEER_KEY_X,
35325b385b3fSJerome Forissier PEER_KEY_Y,
35335b385b3fSJerome Forissier PEER_EPH_KEY_X,
35345b385b3fSJerome Forissier PEER_EPH_KEY_Y,
35355b385b3fSJerome Forissier INITIATOR_ID,
35365b385b3fSJerome Forissier RESPONDER_ID,
35375b385b3fSJerome Forissier };
35385b385b3fSJerome Forissier uint8_t mandatory = BIT(IS_INITIATOR) | BIT(PEER_KEY_X) |
35395b385b3fSJerome Forissier BIT(PEER_KEY_Y) | BIT(PEER_EPH_KEY_X) | BIT(PEER_EPH_KEY_Y) |
35405b385b3fSJerome Forissier BIT(INITIATOR_ID) | BIT(RESPONDER_ID);
35415b385b3fSJerome Forissier uint8_t found = 0;
35425b385b3fSJerome Forissier
3543df00cf59SCedric Neveux res = crypto_acipher_alloc_ecc_public_key(peer_key,
3544df00cf59SCedric Neveux TEE_TYPE_SM2_KEP_PUBLIC_KEY,
3545df00cf59SCedric Neveux 256);
35465b385b3fSJerome Forissier if (res)
35477e35937aSJerome Forissier return res;
35485b385b3fSJerome Forissier
3549df00cf59SCedric Neveux res = crypto_acipher_alloc_ecc_public_key(peer_eph_key,
3550df00cf59SCedric Neveux TEE_TYPE_SM2_KEP_PUBLIC_KEY,
3551df00cf59SCedric Neveux 256);
35525b385b3fSJerome Forissier if (res)
35537e35937aSJerome Forissier goto out_p;
35545b385b3fSJerome Forissier
35555b385b3fSJerome Forissier peer_key->curve = TEE_ECC_CURVE_SM2;
35565b385b3fSJerome Forissier peer_eph_key->curve = TEE_ECC_CURVE_SM2;
35575b385b3fSJerome Forissier
35585b385b3fSJerome Forissier for (n = 0; n < param_count; n++) {
35595b385b3fSJerome Forissier const TEE_Attribute *p = ¶ms[n];
3560a844a0b8SSeonghyun Park void *bbuf = NULL;
35615b385b3fSJerome Forissier
35625b385b3fSJerome Forissier switch (p->attributeID) {
35635b385b3fSJerome Forissier case TEE_ATTR_SM2_KEP_USER:
35645b385b3fSJerome Forissier kep_parms->is_initiator = !p->content.value.a;
35655b385b3fSJerome Forissier found |= BIT(IS_INITIATOR);
35665b385b3fSJerome Forissier break;
35675b385b3fSJerome Forissier case TEE_ATTR_ECC_PUBLIC_VALUE_X:
3568a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3569a844a0b8SSeonghyun Park p->content.ref.length,
3570a844a0b8SSeonghyun Park &bbuf);
3571a844a0b8SSeonghyun Park if (res)
3572a844a0b8SSeonghyun Park return res;
3573a844a0b8SSeonghyun Park
3574a844a0b8SSeonghyun Park crypto_bignum_bin2bn(bbuf,
35755b385b3fSJerome Forissier p->content.ref.length,
35765b385b3fSJerome Forissier peer_key->x);
35775b385b3fSJerome Forissier found |= BIT(PEER_KEY_X);
3578a844a0b8SSeonghyun Park bb_free(bbuf, p->content.ref.length);
35795b385b3fSJerome Forissier break;
35805b385b3fSJerome Forissier case TEE_ATTR_ECC_PUBLIC_VALUE_Y:
3581a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3582a844a0b8SSeonghyun Park p->content.ref.length,
3583a844a0b8SSeonghyun Park &bbuf);
3584a844a0b8SSeonghyun Park if (res)
3585a844a0b8SSeonghyun Park return res;
3586a844a0b8SSeonghyun Park
3587a844a0b8SSeonghyun Park crypto_bignum_bin2bn(bbuf,
35885b385b3fSJerome Forissier p->content.ref.length,
35895b385b3fSJerome Forissier peer_key->y);
35905b385b3fSJerome Forissier found |= BIT(PEER_KEY_Y);
3591a844a0b8SSeonghyun Park bb_free(bbuf, p->content.ref.length);
35925b385b3fSJerome Forissier break;
35931b865ed6SJens Wiklander case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X:
35945b385b3fSJerome Forissier case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X:
3595a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3596a844a0b8SSeonghyun Park p->content.ref.length,
3597a844a0b8SSeonghyun Park &bbuf);
3598a844a0b8SSeonghyun Park if (res)
3599a844a0b8SSeonghyun Park return res;
3600a844a0b8SSeonghyun Park
3601a844a0b8SSeonghyun Park crypto_bignum_bin2bn(bbuf,
36025b385b3fSJerome Forissier p->content.ref.length,
36035b385b3fSJerome Forissier peer_eph_key->x);
36045b385b3fSJerome Forissier found |= BIT(PEER_EPH_KEY_X);
3605a844a0b8SSeonghyun Park bb_free(bbuf, p->content.ref.length);
36065b385b3fSJerome Forissier break;
36071b865ed6SJens Wiklander case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y:
36085b385b3fSJerome Forissier case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y:
3609a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3610a844a0b8SSeonghyun Park p->content.ref.length,
3611a844a0b8SSeonghyun Park &bbuf);
3612a844a0b8SSeonghyun Park if (res)
3613a844a0b8SSeonghyun Park return res;
3614a844a0b8SSeonghyun Park
3615a844a0b8SSeonghyun Park crypto_bignum_bin2bn(bbuf,
36165b385b3fSJerome Forissier p->content.ref.length,
36175b385b3fSJerome Forissier peer_eph_key->y);
36185b385b3fSJerome Forissier found |= BIT(PEER_EPH_KEY_Y);
3619a844a0b8SSeonghyun Park bb_free(bbuf, p->content.ref.length);
36205b385b3fSJerome Forissier break;
36215b385b3fSJerome Forissier case TEE_ATTR_SM2_ID_INITIATOR:
3622a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3623a844a0b8SSeonghyun Park p->content.ref.length,
3624a844a0b8SSeonghyun Park &bbuf);
3625a844a0b8SSeonghyun Park if (res)
3626a844a0b8SSeonghyun Park return res;
3627a844a0b8SSeonghyun Park
3628a844a0b8SSeonghyun Park kep_parms->initiator_id = bbuf;
36295b385b3fSJerome Forissier kep_parms->initiator_id_len = p->content.ref.length;
36305b385b3fSJerome Forissier found |= BIT(INITIATOR_ID);
36315b385b3fSJerome Forissier break;
36325b385b3fSJerome Forissier case TEE_ATTR_SM2_ID_RESPONDER:
3633a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3634a844a0b8SSeonghyun Park p->content.ref.length,
3635a844a0b8SSeonghyun Park &bbuf);
3636a844a0b8SSeonghyun Park if (res)
3637a844a0b8SSeonghyun Park return res;
3638a844a0b8SSeonghyun Park
3639a844a0b8SSeonghyun Park kep_parms->responder_id = bbuf;
36405b385b3fSJerome Forissier kep_parms->responder_id_len = p->content.ref.length;
36415b385b3fSJerome Forissier found |= BIT(RESPONDER_ID);
36425b385b3fSJerome Forissier break;
36435b385b3fSJerome Forissier case TEE_ATTR_SM2_KEP_CONFIRMATION_IN:
3644a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3645a844a0b8SSeonghyun Park p->content.ref.length,
3646a844a0b8SSeonghyun Park &bbuf);
3647a844a0b8SSeonghyun Park if (res)
3648a844a0b8SSeonghyun Park return res;
3649a844a0b8SSeonghyun Park
3650a844a0b8SSeonghyun Park kep_parms->conf_in = bbuf;
36515b385b3fSJerome Forissier kep_parms->conf_in_len = p->content.ref.length;
36525b385b3fSJerome Forissier break;
36535b385b3fSJerome Forissier case TEE_ATTR_SM2_KEP_CONFIRMATION_OUT:
3654a844a0b8SSeonghyun Park res = bb_memdup_user(p->content.ref.buffer,
3655a844a0b8SSeonghyun Park p->content.ref.length,
3656a844a0b8SSeonghyun Park &bbuf);
3657a844a0b8SSeonghyun Park if (res)
3658a844a0b8SSeonghyun Park return res;
3659a844a0b8SSeonghyun Park
3660a844a0b8SSeonghyun Park kep_parms->conf_out = bbuf;
36615b385b3fSJerome Forissier kep_parms->conf_out_len = p->content.ref.length;
36625b385b3fSJerome Forissier break;
36635b385b3fSJerome Forissier default:
36645b385b3fSJerome Forissier /* Unexpected attribute */
36655b385b3fSJerome Forissier res = TEE_ERROR_BAD_PARAMETERS;
36665b385b3fSJerome Forissier goto out;
36675b385b3fSJerome Forissier }
36685b385b3fSJerome Forissier }
36695b385b3fSJerome Forissier
36705b385b3fSJerome Forissier if ((found & mandatory) != mandatory) {
36715b385b3fSJerome Forissier res = TEE_ERROR_BAD_PARAMETERS;
36725b385b3fSJerome Forissier goto out;
36735b385b3fSJerome Forissier }
36745b385b3fSJerome Forissier
36755b385b3fSJerome Forissier return TEE_SUCCESS;
36765b385b3fSJerome Forissier out:
36775b385b3fSJerome Forissier crypto_acipher_free_ecc_public_key(peer_eph_key);
36787e35937aSJerome Forissier out_p:
36797e35937aSJerome Forissier crypto_acipher_free_ecc_public_key(peer_key);
36805b385b3fSJerome Forissier return res;
36815b385b3fSJerome Forissier }
36825b385b3fSJerome Forissier #endif
36835b385b3fSJerome Forissier
syscall_cryp_derive_key(unsigned long state,const struct utee_attribute * usr_params,unsigned long param_count,unsigned long derived_key)3684e86f1266SJens Wiklander TEE_Result syscall_cryp_derive_key(unsigned long state,
3685e86f1266SJens Wiklander const struct utee_attribute *usr_params,
3686e86f1266SJens Wiklander unsigned long param_count, unsigned long derived_key)
3687b0104773SPascal Brand {
368800b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
368900b3b9a2SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
3690cdb198a7SJerome Forissier TEE_Result res = TEE_ERROR_NOT_SUPPORTED;
369100b3b9a2SJens Wiklander struct tee_obj *ko = NULL;
369200b3b9a2SJens Wiklander struct tee_obj *so = NULL;
369300b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
369400b3b9a2SJens Wiklander struct tee_cryp_obj_secret *sk = NULL;
369500b3b9a2SJens Wiklander const struct tee_cryp_obj_type_props *type_props = NULL;
3696177603c7SJens Wiklander TEE_Attribute *params = NULL;
369700b3b9a2SJens Wiklander size_t alloc_size = 0;
3698b0104773SPascal Brand
3699c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
3700b0104773SPascal Brand if (res != TEE_SUCCESS)
3701b0104773SPascal Brand return res;
3702b0104773SPascal Brand
3703a6372432SJoakim Bech if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size))
3704a6372432SJoakim Bech return TEE_ERROR_OVERFLOW;
3705a6372432SJoakim Bech
3706a6372432SJoakim Bech params = malloc(alloc_size);
3707177603c7SJens Wiklander if (!params)
3708177603c7SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
37098684fde8SJens Wiklander res = copy_in_attrs(utc, usr_params, param_count, params);
3710c2e1a053SJerome Forissier if (res != TEE_SUCCESS)
3711177603c7SJens Wiklander goto out;
3712c2e1a053SJerome Forissier
3713cdb198a7SJerome Forissier /* Get key set in operation */
37148684fde8SJens Wiklander res = tee_obj_get(utc, cs->key1, &ko);
3715b0104773SPascal Brand if (res != TEE_SUCCESS)
3716177603c7SJens Wiklander goto out;
3717b0104773SPascal Brand
3718c40a6505SJens Wiklander res = tee_obj_get(utc, uref_to_vaddr(derived_key), &so);
3719b0104773SPascal Brand if (res != TEE_SUCCESS)
3720177603c7SJens Wiklander goto out;
3721b0104773SPascal Brand
37228854d3c6SJerome Forissier /* Find information needed about the object to initialize */
372340a4fd66SJens Wiklander sk = so->attr;
3724b0104773SPascal Brand
3725b0104773SPascal Brand /* Find description of object */
3726b0104773SPascal Brand type_props = tee_svc_find_type_props(so->info.objectType);
3727177603c7SJens Wiklander if (!type_props) {
3728177603c7SJens Wiklander res = TEE_ERROR_NOT_SUPPORTED;
3729177603c7SJens Wiklander goto out;
3730177603c7SJens Wiklander }
3731b0104773SPascal Brand
37328854d3c6SJerome Forissier if (cs->algo == TEE_ALG_DH_DERIVE_SHARED_SECRET) {
37339ff77e1eSJens Wiklander struct bignum *pub = NULL;
37349ff77e1eSJens Wiklander struct bignum *ss = NULL;
37359ff77e1eSJens Wiklander size_t bin_size = 0;
3736a844a0b8SSeonghyun Park void *bbuf = NULL;
37378854d3c6SJerome Forissier
37388854d3c6SJerome Forissier if (param_count != 1 ||
3739177603c7SJens Wiklander params[0].attributeID != TEE_ATTR_DH_PUBLIC_VALUE) {
3740177603c7SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
3741177603c7SJens Wiklander goto out;
3742177603c7SJens Wiklander }
37435e5a1011SJerome Forissier
37449ff77e1eSJens Wiklander bin_size = params[0].content.ref.length;
3745ea8357c1SJoakim Bech
3746ea8357c1SJoakim Bech if (MUL_OVERFLOW(bin_size, 8, &alloc_size)) {
3747ea8357c1SJoakim Bech res = TEE_ERROR_OVERFLOW;
3748ea8357c1SJoakim Bech goto out;
3749ea8357c1SJoakim Bech }
3750ea8357c1SJoakim Bech
3751a844a0b8SSeonghyun Park res = bb_memdup_user(params[0].content.ref.buffer, bin_size,
3752a844a0b8SSeonghyun Park &bbuf);
3753a844a0b8SSeonghyun Park if (res)
3754a844a0b8SSeonghyun Park goto out;
3755a844a0b8SSeonghyun Park
375633790cc1SJens Wiklander pub = crypto_bignum_allocate(alloc_size);
375733790cc1SJens Wiklander ss = crypto_bignum_allocate(alloc_size);
37588854d3c6SJerome Forissier if (pub && ss) {
3759a844a0b8SSeonghyun Park crypto_bignum_bin2bn(bbuf, bin_size, pub);
3760291e5450SJens Wiklander res = crypto_acipher_dh_shared_secret(ko->attr,
37618854d3c6SJerome Forissier pub, ss);
3762b0104773SPascal Brand if (res == TEE_SUCCESS) {
376333790cc1SJens Wiklander sk->key_size = crypto_bignum_num_bytes(ss);
376433790cc1SJens Wiklander crypto_bignum_bn2bin(ss, (uint8_t *)(sk + 1));
37658854d3c6SJerome Forissier so->info.handleFlags |=
37668854d3c6SJerome Forissier TEE_HANDLE_FLAG_INITIALIZED;
3767050ba678SJerome Forissier set_attribute(so, type_props,
37688854d3c6SJerome Forissier TEE_ATTR_SECRET_VALUE);
37698854d3c6SJerome Forissier }
37708854d3c6SJerome Forissier } else {
37718854d3c6SJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY;
37728854d3c6SJerome Forissier }
3773e2ec831cSJihwan Park crypto_bignum_free(&pub);
3774e2ec831cSJihwan Park crypto_bignum_free(&ss);
3775fe2fd3ffSJens Wiklander } else if (cs->algo == TEE_ALG_ECDH_DERIVE_SHARED_SECRET) {
3776fe2fd3ffSJens Wiklander uint32_t curve = ((struct ecc_keypair *)ko->attr)->curve;
3777fe2fd3ffSJens Wiklander struct ecc_public_key key_public = { };
3778fe2fd3ffSJens Wiklander uint8_t *pt_secret = NULL;
3779fe2fd3ffSJens Wiklander unsigned long pt_secret_len = 0;
3780df00cf59SCedric Neveux uint32_t key_type = TEE_TYPE_ECDH_PUBLIC_KEY;
3781a844a0b8SSeonghyun Park void *x_bbuf = NULL;
3782a844a0b8SSeonghyun Park void *y_bbuf = NULL;
3783543d7e74SPascal Brand
3784543d7e74SPascal Brand if (param_count != 2 ||
3785543d7e74SPascal Brand params[0].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_X ||
3786543d7e74SPascal Brand params[1].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_Y) {
3787543d7e74SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
3788543d7e74SPascal Brand goto out;
3789543d7e74SPascal Brand }
3790543d7e74SPascal Brand
3791fe2fd3ffSJens Wiklander switch (curve) {
3792fe2fd3ffSJens Wiklander case TEE_ECC_CURVE_NIST_P192:
3793543d7e74SPascal Brand alloc_size = 192;
3794543d7e74SPascal Brand break;
3795fe2fd3ffSJens Wiklander case TEE_ECC_CURVE_NIST_P224:
3796543d7e74SPascal Brand alloc_size = 224;
3797543d7e74SPascal Brand break;
3798fe2fd3ffSJens Wiklander case TEE_ECC_CURVE_NIST_P256:
3799543d7e74SPascal Brand alloc_size = 256;
3800543d7e74SPascal Brand break;
3801fe2fd3ffSJens Wiklander case TEE_ECC_CURVE_NIST_P384:
3802543d7e74SPascal Brand alloc_size = 384;
3803543d7e74SPascal Brand break;
3804fe2fd3ffSJens Wiklander case TEE_ECC_CURVE_NIST_P521:
3805543d7e74SPascal Brand alloc_size = 521;
3806543d7e74SPascal Brand break;
3807543d7e74SPascal Brand default:
3808543d7e74SPascal Brand res = TEE_ERROR_NOT_IMPLEMENTED;
3809543d7e74SPascal Brand goto out;
3810543d7e74SPascal Brand }
3811543d7e74SPascal Brand
3812a844a0b8SSeonghyun Park res = bb_memdup_user(params[0].content.ref.buffer,
3813a844a0b8SSeonghyun Park params[0].content.ref.length,
3814a844a0b8SSeonghyun Park &x_bbuf);
3815a844a0b8SSeonghyun Park if (res)
3816a844a0b8SSeonghyun Park goto out;
3817a844a0b8SSeonghyun Park
3818a844a0b8SSeonghyun Park res = bb_memdup_user(params[1].content.ref.buffer,
3819a844a0b8SSeonghyun Park params[1].content.ref.length,
3820a844a0b8SSeonghyun Park &y_bbuf);
3821a844a0b8SSeonghyun Park if (res)
3822a844a0b8SSeonghyun Park goto out;
3823a844a0b8SSeonghyun Park
3824543d7e74SPascal Brand /* Create the public key */
3825df00cf59SCedric Neveux res = crypto_acipher_alloc_ecc_public_key(&key_public, key_type,
3826543d7e74SPascal Brand alloc_size);
3827543d7e74SPascal Brand if (res != TEE_SUCCESS)
3828543d7e74SPascal Brand goto out;
3829fe2fd3ffSJens Wiklander key_public.curve = curve;
3830a844a0b8SSeonghyun Park crypto_bignum_bin2bn(x_bbuf, params[0].content.ref.length,
3831543d7e74SPascal Brand key_public.x);
3832a844a0b8SSeonghyun Park crypto_bignum_bin2bn(y_bbuf, params[1].content.ref.length,
3833543d7e74SPascal Brand key_public.y);
3834543d7e74SPascal Brand
3835543d7e74SPascal Brand pt_secret = (uint8_t *)(sk + 1);
383640a4fd66SJens Wiklander pt_secret_len = sk->alloc_size;
3837291e5450SJens Wiklander res = crypto_acipher_ecc_shared_secret(ko->attr, &key_public,
3838291e5450SJens Wiklander pt_secret,
3839291e5450SJens Wiklander &pt_secret_len);
3840543d7e74SPascal Brand
3841543d7e74SPascal Brand if (res == TEE_SUCCESS) {
3842543d7e74SPascal Brand sk->key_size = pt_secret_len;
3843543d7e74SPascal Brand so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
3844050ba678SJerome Forissier set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
3845543d7e74SPascal Brand }
3846543d7e74SPascal Brand
3847543d7e74SPascal Brand /* free the public key */
3848291e5450SJens Wiklander crypto_acipher_free_ecc_public_key(&key_public);
38498854d3c6SJerome Forissier }
3850cdb198a7SJerome Forissier #if defined(CFG_CRYPTO_HKDF)
3851cdb198a7SJerome Forissier else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_HKDF) {
3852cdb198a7SJerome Forissier void *salt, *info;
3853cdb198a7SJerome Forissier size_t salt_len, info_len, okm_len;
3854b93c7dffSJens Wiklander uint32_t hash_id = 0;
385540a4fd66SJens Wiklander struct tee_cryp_obj_secret *ik = ko->attr;
3856cdb198a7SJerome Forissier const uint8_t *ikm = (const uint8_t *)(ik + 1);
3857cdb198a7SJerome Forissier
3858b93c7dffSJens Wiklander res = get_hkdf_params(cs->algo, params, param_count, &salt,
3859b93c7dffSJens Wiklander &salt_len, &info, &info_len, &okm_len,
3860b93c7dffSJens Wiklander &hash_id);
3861cdb198a7SJerome Forissier if (res != TEE_SUCCESS)
3862177603c7SJens Wiklander goto out;
3863cdb198a7SJerome Forissier
3864cdb198a7SJerome Forissier /* Requested size must fit into the output object's buffer */
386540a4fd66SJens Wiklander if (okm_len > ik->alloc_size) {
3866177603c7SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
3867177603c7SJens Wiklander goto out;
3868177603c7SJens Wiklander }
3869cdb198a7SJerome Forissier
3870cdb198a7SJerome Forissier res = tee_cryp_hkdf(hash_id, ikm, ik->key_size, salt, salt_len,
3871cdb198a7SJerome Forissier info, info_len, (uint8_t *)(sk + 1),
3872cdb198a7SJerome Forissier okm_len);
3873cdb198a7SJerome Forissier if (res == TEE_SUCCESS) {
3874cdb198a7SJerome Forissier sk->key_size = okm_len;
3875cdb198a7SJerome Forissier so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
3876050ba678SJerome Forissier set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
3877cdb198a7SJerome Forissier }
3878cdb198a7SJerome Forissier }
3879cdb198a7SJerome Forissier #endif
38808854d3c6SJerome Forissier #if defined(CFG_CRYPTO_CONCAT_KDF)
38818854d3c6SJerome Forissier else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_CONCAT_KDF) {
38828854d3c6SJerome Forissier void *info;
38838854d3c6SJerome Forissier size_t info_len, derived_key_len;
38848854d3c6SJerome Forissier uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo);
388540a4fd66SJens Wiklander struct tee_cryp_obj_secret *ss = ko->attr;
38868854d3c6SJerome Forissier const uint8_t *shared_secret = (const uint8_t *)(ss + 1);
38878854d3c6SJerome Forissier
38888854d3c6SJerome Forissier res = get_concat_kdf_params(params, param_count, &info,
38898854d3c6SJerome Forissier &info_len, &derived_key_len);
38908854d3c6SJerome Forissier if (res != TEE_SUCCESS)
3891177603c7SJens Wiklander goto out;
38928854d3c6SJerome Forissier
38938854d3c6SJerome Forissier /* Requested size must fit into the output object's buffer */
389440a4fd66SJens Wiklander if (derived_key_len > ss->alloc_size) {
3895177603c7SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
3896177603c7SJens Wiklander goto out;
3897177603c7SJens Wiklander }
38988854d3c6SJerome Forissier
38998854d3c6SJerome Forissier res = tee_cryp_concat_kdf(hash_id, shared_secret, ss->key_size,
39008854d3c6SJerome Forissier info, info_len, (uint8_t *)(sk + 1),
39018854d3c6SJerome Forissier derived_key_len);
39028854d3c6SJerome Forissier if (res == TEE_SUCCESS) {
39038854d3c6SJerome Forissier sk->key_size = derived_key_len;
3904b0104773SPascal Brand so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
3905050ba678SJerome Forissier set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
3906b0104773SPascal Brand }
39078854d3c6SJerome Forissier }
39088854d3c6SJerome Forissier #endif
39090f2293b7SJerome Forissier #if defined(CFG_CRYPTO_PBKDF2)
39100f2293b7SJerome Forissier else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_PBKDF2) {
39110f2293b7SJerome Forissier void *salt;
39120f2293b7SJerome Forissier size_t salt_len, iteration_count, derived_key_len;
39130f2293b7SJerome Forissier uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo);
391440a4fd66SJens Wiklander struct tee_cryp_obj_secret *ss = ko->attr;
39150f2293b7SJerome Forissier const uint8_t *password = (const uint8_t *)(ss + 1);
39160f2293b7SJerome Forissier
39170f2293b7SJerome Forissier res = get_pbkdf2_params(params, param_count, &salt, &salt_len,
39180f2293b7SJerome Forissier &derived_key_len, &iteration_count);
39190f2293b7SJerome Forissier if (res != TEE_SUCCESS)
3920177603c7SJens Wiklander goto out;
39210f2293b7SJerome Forissier
39220f2293b7SJerome Forissier /* Requested size must fit into the output object's buffer */
392340a4fd66SJens Wiklander if (derived_key_len > ss->alloc_size) {
3924177603c7SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
3925177603c7SJens Wiklander goto out;
3926177603c7SJens Wiklander }
39270f2293b7SJerome Forissier
39280f2293b7SJerome Forissier res = tee_cryp_pbkdf2(hash_id, password, ss->key_size, salt,
39290f2293b7SJerome Forissier salt_len, iteration_count,
39300f2293b7SJerome Forissier (uint8_t *)(sk + 1), derived_key_len);
39310f2293b7SJerome Forissier if (res == TEE_SUCCESS) {
39320f2293b7SJerome Forissier sk->key_size = derived_key_len;
39330f2293b7SJerome Forissier so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
3934050ba678SJerome Forissier set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
39350f2293b7SJerome Forissier }
39360f2293b7SJerome Forissier }
39370f2293b7SJerome Forissier #endif
39385b385b3fSJerome Forissier #if defined(CFG_CRYPTO_SM2_KEP)
39395b385b3fSJerome Forissier else if (cs->algo == TEE_ALG_SM2_KEP) {
39405b385b3fSJerome Forissier struct ecc_public_key peer_eph_key = { };
39415b385b3fSJerome Forissier struct ecc_public_key peer_key = { };
39425b385b3fSJerome Forissier struct sm2_kep_parms kep_parms = {
39435b385b3fSJerome Forissier .out = (uint8_t *)(sk + 1),
3944181f0998SJens Wiklander .out_len = so->info.maxObjectSize,
39455b385b3fSJerome Forissier };
39465b385b3fSJerome Forissier struct tee_obj *ko2 = NULL;
39475b385b3fSJerome Forissier
39485b385b3fSJerome Forissier res = tee_obj_get(utc, cs->key2, &ko2);
39495b385b3fSJerome Forissier if (res != TEE_SUCCESS)
39505b385b3fSJerome Forissier goto out;
39515b385b3fSJerome Forissier
39525b385b3fSJerome Forissier res = get_sm2_kep_params(params, param_count, &peer_key,
39535b385b3fSJerome Forissier &peer_eph_key, &kep_parms);
39545b385b3fSJerome Forissier if (res != TEE_SUCCESS)
39555b385b3fSJerome Forissier goto out;
39565b385b3fSJerome Forissier
39575b385b3fSJerome Forissier /*
39585b385b3fSJerome Forissier * key1 is our private keypair, key2 is our ephemeral public key
39595b385b3fSJerome Forissier */
39605b385b3fSJerome Forissier res = crypto_acipher_sm2_kep_derive(ko->attr, /* key1 */
39615b385b3fSJerome Forissier ko2->attr, /* key2 */
39625b385b3fSJerome Forissier &peer_key, &peer_eph_key,
39635b385b3fSJerome Forissier &kep_parms);
39645b385b3fSJerome Forissier
39655b385b3fSJerome Forissier if (res == TEE_SUCCESS) {
39665b385b3fSJerome Forissier sk->key_size = kep_parms.out_len;
39675b385b3fSJerome Forissier so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
39685b385b3fSJerome Forissier set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
39695b385b3fSJerome Forissier }
39705b385b3fSJerome Forissier crypto_acipher_free_ecc_public_key(&peer_key);
39715b385b3fSJerome Forissier crypto_acipher_free_ecc_public_key(&peer_eph_key);
39725b385b3fSJerome Forissier }
39735b385b3fSJerome Forissier #endif
397490040fa4SSohaib ul Hassan #if defined(CFG_CRYPTO_X25519)
397590040fa4SSohaib ul Hassan else if (cs->algo == TEE_ALG_X25519) {
397690040fa4SSohaib ul Hassan uint8_t *x25519_pub_key = NULL;
397790040fa4SSohaib ul Hassan uint8_t *pt_secret = NULL;
397890040fa4SSohaib ul Hassan unsigned long pt_secret_len = 0;
3979a844a0b8SSeonghyun Park void *bbuf = NULL;
398090040fa4SSohaib ul Hassan
398190040fa4SSohaib ul Hassan if (param_count != 1 ||
398290040fa4SSohaib ul Hassan params[0].attributeID != TEE_ATTR_X25519_PUBLIC_VALUE) {
398390040fa4SSohaib ul Hassan res = TEE_ERROR_BAD_PARAMETERS;
398490040fa4SSohaib ul Hassan goto out;
398590040fa4SSohaib ul Hassan }
398690040fa4SSohaib ul Hassan
398790040fa4SSohaib ul Hassan /* X25519 public key size is 32 bytes */
398890040fa4SSohaib ul Hassan if (params[0].content.ref.length != KEY_SIZE_BYTES_25519) {
398990040fa4SSohaib ul Hassan res = TEE_ERROR_BAD_PARAMETERS;
399090040fa4SSohaib ul Hassan goto out;
399190040fa4SSohaib ul Hassan }
399290040fa4SSohaib ul Hassan
3993a844a0b8SSeonghyun Park res = bb_memdup_user(params[0].content.ref.buffer,
3994a844a0b8SSeonghyun Park params[0].content.ref.length,
3995a844a0b8SSeonghyun Park &bbuf);
3996a844a0b8SSeonghyun Park if (res)
3997a844a0b8SSeonghyun Park goto out;
3998a844a0b8SSeonghyun Park
399990040fa4SSohaib ul Hassan /* Set the public key */
4000a844a0b8SSeonghyun Park x25519_pub_key = bbuf;
400190040fa4SSohaib ul Hassan
400290040fa4SSohaib ul Hassan pt_secret = (uint8_t *)(sk + 1);
400390040fa4SSohaib ul Hassan pt_secret_len = sk->alloc_size;
400490040fa4SSohaib ul Hassan res = crypto_acipher_x25519_shared_secret(ko->attr,
400590040fa4SSohaib ul Hassan x25519_pub_key,
400690040fa4SSohaib ul Hassan pt_secret,
400790040fa4SSohaib ul Hassan &pt_secret_len);
400890040fa4SSohaib ul Hassan
400990040fa4SSohaib ul Hassan if (res == TEE_SUCCESS) {
401090040fa4SSohaib ul Hassan sk->key_size = pt_secret_len;
401190040fa4SSohaib ul Hassan so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
401290040fa4SSohaib ul Hassan set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
401390040fa4SSohaib ul Hassan }
401490040fa4SSohaib ul Hassan }
401590040fa4SSohaib ul Hassan #endif
401634ce35b1Sloubaihui #if defined(CFG_CRYPTO_X448)
401734ce35b1Sloubaihui else if (cs->algo == TEE_ALG_X448) {
401834ce35b1Sloubaihui uint8_t *x448_pub_key = NULL;
401934ce35b1Sloubaihui uint8_t *pt_secret = NULL;
402034ce35b1Sloubaihui unsigned long pt_secret_len = 0;
402134ce35b1Sloubaihui void *bbuf = NULL;
402234ce35b1Sloubaihui
402334ce35b1Sloubaihui if (param_count != 1 ||
402434ce35b1Sloubaihui params[0].attributeID != TEE_ATTR_X448_PUBLIC_VALUE) {
402534ce35b1Sloubaihui res = TEE_ERROR_BAD_PARAMETERS;
402634ce35b1Sloubaihui goto out;
402734ce35b1Sloubaihui }
402834ce35b1Sloubaihui
402934ce35b1Sloubaihui /* X448 public key size is 56 bytes */
403034ce35b1Sloubaihui if (params[0].content.ref.length != KEY_SIZE_BYTES_448) {
403134ce35b1Sloubaihui res = TEE_ERROR_BAD_PARAMETERS;
403234ce35b1Sloubaihui goto out;
403334ce35b1Sloubaihui }
403434ce35b1Sloubaihui
403534ce35b1Sloubaihui res = bb_memdup_user(params[0].content.ref.buffer,
403634ce35b1Sloubaihui params[0].content.ref.length,
403734ce35b1Sloubaihui &bbuf);
403834ce35b1Sloubaihui if (res)
403934ce35b1Sloubaihui goto out;
404034ce35b1Sloubaihui
404134ce35b1Sloubaihui /* Set the public key */
404234ce35b1Sloubaihui x448_pub_key = bbuf;
404334ce35b1Sloubaihui
404434ce35b1Sloubaihui pt_secret = (uint8_t *)(sk + 1);
404534ce35b1Sloubaihui pt_secret_len = sk->alloc_size;
404634ce35b1Sloubaihui res = crypto_acipher_x448_shared_secret(ko->attr,
404734ce35b1Sloubaihui x448_pub_key,
404834ce35b1Sloubaihui pt_secret,
404934ce35b1Sloubaihui &pt_secret_len);
405034ce35b1Sloubaihui
405134ce35b1Sloubaihui if (res == TEE_SUCCESS) {
405234ce35b1Sloubaihui sk->key_size = pt_secret_len;
405334ce35b1Sloubaihui so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
405434ce35b1Sloubaihui set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE);
405534ce35b1Sloubaihui }
405634ce35b1Sloubaihui }
405734ce35b1Sloubaihui #endif
40588854d3c6SJerome Forissier else
40590f2293b7SJerome Forissier res = TEE_ERROR_NOT_SUPPORTED;
40608854d3c6SJerome Forissier
4061177603c7SJens Wiklander out:
406270b61310SJerome Forissier free_wipe(params);
4063b0104773SPascal Brand return res;
4064b0104773SPascal Brand }
4065b0104773SPascal Brand
syscall_cryp_random_number_generate(void * buf,size_t blen)4066453a5030SJerome Forissier TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen)
4067b0104773SPascal Brand {
40681936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
4069a844a0b8SSeonghyun Park void *bbuf = NULL;
4070b0104773SPascal Brand
4071a844a0b8SSeonghyun Park bbuf = bb_alloc(blen);
4072a844a0b8SSeonghyun Park if (!bbuf)
4073a844a0b8SSeonghyun Park return TEE_ERROR_OUT_OF_MEMORY;
4074ef142203SJens Wiklander
4075a844a0b8SSeonghyun Park res = crypto_rng_read(bbuf, blen);
4076b0104773SPascal Brand if (res != TEE_SUCCESS)
4077b0104773SPascal Brand return res;
4078b0104773SPascal Brand
4079a844a0b8SSeonghyun Park res = copy_to_user(buf, bbuf, blen);
4080b0104773SPascal Brand return res;
4081b0104773SPascal Brand }
4082b0104773SPascal Brand
syscall_authenc_init(unsigned long state,const void * nonce,size_t nonce_len,size_t tag_len,size_t aad_len,size_t payload_len)4083e86f1266SJens Wiklander TEE_Result syscall_authenc_init(unsigned long state, const void *nonce,
4084b0104773SPascal Brand size_t nonce_len, size_t tag_len,
4085b0104773SPascal Brand size_t aad_len, size_t payload_len)
4086b0104773SPascal Brand {
408700b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
40881936dfc7SJens Wiklander struct tee_cryp_obj_secret *key = NULL;
40891936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
40901936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
40911936dfc7SJens Wiklander struct tee_obj *o = NULL;
4092a844a0b8SSeonghyun Park void *nonce_bbuf = NULL;
409306aa9a9bSJerome Forissier
4094c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4095b0104773SPascal Brand if (res != TEE_SUCCESS)
4096b0104773SPascal Brand return res;
4097b0104773SPascal Brand
40988684fde8SJens Wiklander res = tee_obj_get(to_user_ta_ctx(sess->ctx), cs->key1, &o);
4099b0104773SPascal Brand if (res != TEE_SUCCESS)
4100b0104773SPascal Brand return res;
4101b0104773SPascal Brand if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
4102b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
4103b0104773SPascal Brand
410440a4fd66SJens Wiklander key = o->attr;
4105a844a0b8SSeonghyun Park
4106a844a0b8SSeonghyun Park res = bb_memdup_user(nonce, nonce_len, &nonce_bbuf);
4107a844a0b8SSeonghyun Park if (res)
4108a844a0b8SSeonghyun Park return res;
4109a844a0b8SSeonghyun Park
411052ee414bSJens Wiklander res = crypto_authenc_init(cs->ctx, cs->mode, (uint8_t *)(key + 1),
4111a844a0b8SSeonghyun Park key->key_size, nonce_bbuf, nonce_len, tag_len,
411252ee414bSJens Wiklander aad_len, payload_len);
4113b0104773SPascal Brand if (res != TEE_SUCCESS)
4114b0104773SPascal Brand return res;
4115b0104773SPascal Brand
411652ee414bSJens Wiklander cs->ctx_finalize = crypto_authenc_final;
411734a08becSJoakim Bech cs->state = CRYP_STATE_INITIALIZED;
411834a08becSJoakim Bech
4119b0104773SPascal Brand return TEE_SUCCESS;
4120b0104773SPascal Brand }
4121b0104773SPascal Brand
syscall_authenc_update_aad(unsigned long state,const void * aad_data,size_t aad_data_len)4122e86f1266SJens Wiklander TEE_Result syscall_authenc_update_aad(unsigned long state,
4123e86f1266SJens Wiklander const void *aad_data, size_t aad_data_len)
4124b0104773SPascal Brand {
412500b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
41261936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
412700b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
4128b0104773SPascal Brand
4129ef142203SJens Wiklander aad_data = memtag_strip_tag_const(aad_data);
4130ef142203SJens Wiklander
413189c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
4132b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4133b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
413489c9728dSJens Wiklander (uaddr_t)aad_data, aad_data_len);
4135b0104773SPascal Brand if (res != TEE_SUCCESS)
4136b0104773SPascal Brand return res;
4137b0104773SPascal Brand
4138c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4139b0104773SPascal Brand if (res != TEE_SUCCESS)
4140b0104773SPascal Brand return res;
4141b0104773SPascal Brand
414234a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
414334a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
414434a08becSJoakim Bech
414545a367d8SJoakim Bech if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE)
414645a367d8SJoakim Bech return TEE_ERROR_BAD_STATE;
414745a367d8SJoakim Bech
41484e154320SSeonghyun Park enter_user_access();
414952ee414bSJens Wiklander res = crypto_authenc_update_aad(cs->ctx, cs->mode, aad_data,
415052ee414bSJens Wiklander aad_data_len);
41514e154320SSeonghyun Park exit_user_access();
4152b0104773SPascal Brand if (res != TEE_SUCCESS)
4153b0104773SPascal Brand return res;
4154b0104773SPascal Brand
4155b0104773SPascal Brand return TEE_SUCCESS;
4156b0104773SPascal Brand }
4157b0104773SPascal Brand
syscall_authenc_update_payload(unsigned long state,const void * src_data,size_t src_len,void * dst_data,uint64_t * dst_len)4158e86f1266SJens Wiklander TEE_Result syscall_authenc_update_payload(unsigned long state,
41591936dfc7SJens Wiklander const void *src_data,
41601936dfc7SJens Wiklander size_t src_len, void *dst_data,
4161e86f1266SJens Wiklander uint64_t *dst_len)
4162b0104773SPascal Brand {
416300b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
41641936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
41651936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
416684e9c40bSJens Wiklander size_t dlen = 0;
4167b0104773SPascal Brand
4168c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4169b0104773SPascal Brand if (res != TEE_SUCCESS)
4170b0104773SPascal Brand return res;
4171b0104773SPascal Brand
417234a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
417334a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
417434a08becSJoakim Bech
417545a367d8SJoakim Bech if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE)
417645a367d8SJoakim Bech return TEE_ERROR_BAD_STATE;
417745a367d8SJoakim Bech
4178ef142203SJens Wiklander src_data = memtag_strip_tag_const(src_data);
4179ef142203SJens Wiklander dst_data = memtag_strip_tag(dst_data);
4180ef142203SJens Wiklander
418189c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
4182b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4183b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
41842ffdd194SJens Wiklander (uaddr_t)src_data, src_len);
4185b0104773SPascal Brand if (res != TEE_SUCCESS)
4186b0104773SPascal Brand return res;
4187b0104773SPascal Brand
418884e9c40bSJens Wiklander res = get_user_u64_as_size_t(&dlen, dst_len);
4189b0104773SPascal Brand if (res != TEE_SUCCESS)
4190b0104773SPascal Brand return res;
4191b0104773SPascal Brand
419289c9728dSJens Wiklander res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx,
4193b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4194b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE |
4195b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
41962ffdd194SJens Wiklander (uaddr_t)dst_data, dlen);
4197b0104773SPascal Brand if (res != TEE_SUCCESS)
4198b0104773SPascal Brand return res;
4199b0104773SPascal Brand
4200b0104773SPascal Brand if (dlen < src_len) {
4201b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
4202b0104773SPascal Brand goto out;
4203b0104773SPascal Brand }
4204b0104773SPascal Brand
42054e154320SSeonghyun Park enter_user_access();
420652ee414bSJens Wiklander res = crypto_authenc_update_payload(cs->ctx, cs->mode, src_data,
420752ee414bSJens Wiklander src_len, dst_data, &dlen);
42084e154320SSeonghyun Park exit_user_access();
4209b0104773SPascal Brand out:
4210b0104773SPascal Brand if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
421184e9c40bSJens Wiklander TEE_Result res2 = put_user_u64(dst_len, dlen);
421284e9c40bSJens Wiklander
4213b0104773SPascal Brand if (res2 != TEE_SUCCESS)
4214b0104773SPascal Brand res = res2;
4215b0104773SPascal Brand }
4216b0104773SPascal Brand
4217b0104773SPascal Brand return res;
4218b0104773SPascal Brand }
4219b0104773SPascal Brand
syscall_authenc_enc_final(unsigned long state,const void * src_data,size_t src_len,void * dst_data,uint64_t * dst_len,void * tag,uint64_t * tag_len)42201936dfc7SJens Wiklander TEE_Result syscall_authenc_enc_final(unsigned long state, const void *src_data,
42211936dfc7SJens Wiklander size_t src_len, void *dst_data,
42221936dfc7SJens Wiklander uint64_t *dst_len, void *tag,
42231936dfc7SJens Wiklander uint64_t *tag_len)
4224b0104773SPascal Brand {
422500b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
422600b3b9a2SJens Wiklander struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx;
42271936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
42281936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
422984e9c40bSJens Wiklander size_t dlen = 0;
423084e9c40bSJens Wiklander size_t tlen = 0;
4231b0104773SPascal Brand
4232c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4233b0104773SPascal Brand if (res != TEE_SUCCESS)
4234b0104773SPascal Brand return res;
4235b0104773SPascal Brand
423634a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
423734a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
423834a08becSJoakim Bech
4239b0104773SPascal Brand if (cs->mode != TEE_MODE_ENCRYPT)
4240b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
4241b0104773SPascal Brand
424245a367d8SJoakim Bech if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE)
424345a367d8SJoakim Bech return TEE_ERROR_BAD_STATE;
424445a367d8SJoakim Bech
4245ef142203SJens Wiklander src_data = memtag_strip_tag_const(src_data);
4246ef142203SJens Wiklander dst_data = memtag_strip_tag(dst_data);
4247ef142203SJens Wiklander tag = memtag_strip_tag(tag);
4248ef142203SJens Wiklander
424989c9728dSJens Wiklander res = vm_check_access_rights(uctx,
4250b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4251b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
42522ffdd194SJens Wiklander (uaddr_t)src_data, src_len);
4253b0104773SPascal Brand if (res != TEE_SUCCESS)
4254b0104773SPascal Brand return res;
4255b0104773SPascal Brand
4256ffe04039SJerome Forissier if (!dst_len) {
4257b0104773SPascal Brand dlen = 0;
4258b0104773SPascal Brand } else {
425984e9c40bSJens Wiklander res = get_user_u64_as_size_t(&dlen, dst_len);
4260b0104773SPascal Brand if (res != TEE_SUCCESS)
4261b0104773SPascal Brand return res;
4262b0104773SPascal Brand
426389c9728dSJens Wiklander res = vm_check_access_rights(uctx,
4264b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4265b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE |
4266b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
42672ffdd194SJens Wiklander (uaddr_t)dst_data, dlen);
4268b0104773SPascal Brand if (res != TEE_SUCCESS)
4269b0104773SPascal Brand return res;
4270b0104773SPascal Brand }
4271b0104773SPascal Brand
4272b0104773SPascal Brand if (dlen < src_len) {
4273b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
4274b0104773SPascal Brand goto out;
4275b0104773SPascal Brand }
4276b0104773SPascal Brand
427784e9c40bSJens Wiklander res = get_user_u64_as_size_t(&tlen, tag_len);
4278b0104773SPascal Brand if (res != TEE_SUCCESS)
4279b0104773SPascal Brand return res;
4280b0104773SPascal Brand
428189c9728dSJens Wiklander res = vm_check_access_rights(uctx,
4282b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4283b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE |
4284b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
42852ffdd194SJens Wiklander (uaddr_t)tag, tlen);
4286b0104773SPascal Brand if (res != TEE_SUCCESS)
4287b0104773SPascal Brand return res;
4288b0104773SPascal Brand
42894e154320SSeonghyun Park enter_user_access();
429052ee414bSJens Wiklander res = crypto_authenc_enc_final(cs->ctx, src_data, src_len, dst_data,
429152ee414bSJens Wiklander &dlen, tag, &tlen);
42924e154320SSeonghyun Park exit_user_access();
4293b0104773SPascal Brand
4294b0104773SPascal Brand out:
4295b0104773SPascal Brand if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
42961936dfc7SJens Wiklander TEE_Result res2 = TEE_SUCCESS;
4297b0104773SPascal Brand
4298b0104773SPascal Brand if (dst_len != NULL) {
429984e9c40bSJens Wiklander res2 = put_user_u64(dst_len, dlen);
4300b0104773SPascal Brand if (res2 != TEE_SUCCESS)
4301b0104773SPascal Brand return res2;
4302b0104773SPascal Brand }
4303b0104773SPascal Brand
430484e9c40bSJens Wiklander res2 = put_user_u64(tag_len, tlen);
4305b0104773SPascal Brand if (res2 != TEE_SUCCESS)
4306b0104773SPascal Brand return res2;
4307b0104773SPascal Brand }
4308b0104773SPascal Brand
4309b0104773SPascal Brand return res;
4310b0104773SPascal Brand }
4311b0104773SPascal Brand
syscall_authenc_dec_final(unsigned long state,const void * src_data,size_t src_len,void * dst_data,uint64_t * dst_len,const void * tag,size_t tag_len)4312e86f1266SJens Wiklander TEE_Result syscall_authenc_dec_final(unsigned long state,
4313e86f1266SJens Wiklander const void *src_data, size_t src_len, void *dst_data,
4314e86f1266SJens Wiklander uint64_t *dst_len, const void *tag, size_t tag_len)
4315b0104773SPascal Brand {
431600b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
431700b3b9a2SJens Wiklander struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx;
43181936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
43191936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
432084e9c40bSJens Wiklander size_t dlen = 0;
4321b0104773SPascal Brand
4322c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4323b0104773SPascal Brand if (res != TEE_SUCCESS)
4324b0104773SPascal Brand return res;
4325b0104773SPascal Brand
432634a08becSJoakim Bech if (cs->state != CRYP_STATE_INITIALIZED)
432734a08becSJoakim Bech return TEE_ERROR_BAD_STATE;
432834a08becSJoakim Bech
4329b0104773SPascal Brand if (cs->mode != TEE_MODE_DECRYPT)
4330b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
4331b0104773SPascal Brand
433245a367d8SJoakim Bech if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE)
433345a367d8SJoakim Bech return TEE_ERROR_BAD_STATE;
433445a367d8SJoakim Bech
4335ef142203SJens Wiklander src_data = memtag_strip_tag_const(src_data);
4336ef142203SJens Wiklander dst_data = memtag_strip_tag(dst_data);
4337ef142203SJens Wiklander tag = memtag_strip_tag_const(tag);
4338ef142203SJens Wiklander
433989c9728dSJens Wiklander res = vm_check_access_rights(uctx,
4340b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4341b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
43422ffdd194SJens Wiklander (uaddr_t)src_data, src_len);
4343b0104773SPascal Brand if (res != TEE_SUCCESS)
4344b0104773SPascal Brand return res;
4345b0104773SPascal Brand
4346ffe04039SJerome Forissier if (!dst_len) {
4347b0104773SPascal Brand dlen = 0;
4348b0104773SPascal Brand } else {
434984e9c40bSJens Wiklander res = get_user_u64_as_size_t(&dlen, dst_len);
4350b0104773SPascal Brand if (res != TEE_SUCCESS)
4351b0104773SPascal Brand return res;
4352b0104773SPascal Brand
435389c9728dSJens Wiklander res = vm_check_access_rights(uctx,
4354b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4355b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE |
4356b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
43572ffdd194SJens Wiklander (uaddr_t)dst_data, dlen);
4358b0104773SPascal Brand if (res != TEE_SUCCESS)
4359b0104773SPascal Brand return res;
4360b0104773SPascal Brand }
4361b0104773SPascal Brand
4362b0104773SPascal Brand if (dlen < src_len) {
4363b0104773SPascal Brand res = TEE_ERROR_SHORT_BUFFER;
4364b0104773SPascal Brand goto out;
4365b0104773SPascal Brand }
4366b0104773SPascal Brand
4367a0be044cSlei zhou /* Despite TEE Internal Core API up to v1.3, tag is [inbuf], not [in] */
4368a0be044cSlei zhou res = vm_check_access_rights(uctx,
4369a0be044cSlei zhou TEE_MEMORY_ACCESS_READ |
4370a0be044cSlei zhou TEE_MEMORY_ACCESS_ANY_OWNER,
43712ffdd194SJens Wiklander (uaddr_t)tag, tag_len);
4372b0104773SPascal Brand if (res != TEE_SUCCESS)
4373b0104773SPascal Brand return res;
4374b0104773SPascal Brand
43754e154320SSeonghyun Park enter_user_access();
437652ee414bSJens Wiklander res = crypto_authenc_dec_final(cs->ctx, src_data, src_len, dst_data,
437752ee414bSJens Wiklander &dlen, tag, tag_len);
43784e154320SSeonghyun Park exit_user_access();
4379b0104773SPascal Brand
4380b0104773SPascal Brand out:
4381b0104773SPascal Brand if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) &&
4382b0104773SPascal Brand dst_len != NULL) {
438384e9c40bSJens Wiklander TEE_Result res2 = put_user_u64(dst_len, dlen);
4384b0104773SPascal Brand
4385b0104773SPascal Brand if (res2 != TEE_SUCCESS)
4386b0104773SPascal Brand return res2;
4387b0104773SPascal Brand }
4388b0104773SPascal Brand
4389b0104773SPascal Brand return res;
4390b0104773SPascal Brand }
4391b0104773SPascal Brand
pkcs1_get_salt_len(const TEE_Attribute * params,uint32_t num_params,size_t default_len)43926bfd8c14SJens Wiklander static int pkcs1_get_salt_len(const TEE_Attribute *params, uint32_t num_params,
43936bfd8c14SJens Wiklander size_t default_len)
4394b0104773SPascal Brand {
4395b0104773SPascal Brand size_t n;
4396b0104773SPascal Brand
43976bfd8c14SJens Wiklander assert(default_len < INT_MAX);
43986bfd8c14SJens Wiklander
4399b0104773SPascal Brand for (n = 0; n < num_params; n++) {
4400b0104773SPascal Brand if (params[n].attributeID == TEE_ATTR_RSA_PSS_SALT_LENGTH) {
44016bfd8c14SJens Wiklander if (params[n].content.value.a < INT_MAX)
44026bfd8c14SJens Wiklander return params[n].content.value.a;
44036bfd8c14SJens Wiklander break;
4404b0104773SPascal Brand }
4405b0104773SPascal Brand }
44066bfd8c14SJens Wiklander /*
44076bfd8c14SJens Wiklander * If salt length isn't provided use the default value which is
44086bfd8c14SJens Wiklander * the length of the digest.
44096bfd8c14SJens Wiklander */
44106bfd8c14SJens Wiklander return default_len;
4411b0104773SPascal Brand }
4412b0104773SPascal Brand
syscall_asymm_operate(unsigned long state,const struct utee_attribute * usr_params,size_t num_params,const void * src_data,size_t src_len,void * dst_data,uint64_t * dst_len)4413e86f1266SJens Wiklander TEE_Result syscall_asymm_operate(unsigned long state,
4414e86f1266SJens Wiklander const struct utee_attribute *usr_params,
4415e86f1266SJens Wiklander size_t num_params, const void *src_data, size_t src_len,
4416e86f1266SJens Wiklander void *dst_data, uint64_t *dst_len)
4417b0104773SPascal Brand {
441800b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
441900b3b9a2SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
442000b3b9a2SJens Wiklander TEE_Result res = TEE_SUCCESS;
442100b3b9a2SJens Wiklander struct tee_cryp_state *cs = NULL;
442200b3b9a2SJens Wiklander size_t dlen = 0;
442300b3b9a2SJens Wiklander struct tee_obj *o = NULL;
4424b0104773SPascal Brand void *label = NULL;
4425b0104773SPascal Brand size_t label_len = 0;
442600b3b9a2SJens Wiklander size_t n = 0;
442700b3b9a2SJens Wiklander int salt_len = 0;
4428177603c7SJens Wiklander TEE_Attribute *params = NULL;
44299ff77e1eSJens Wiklander size_t alloc_size = 0;
4430*86ee543bSSami Tolvanen uint32_t mgf_algo = 0;
4431b0104773SPascal Brand
4432c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4433b0104773SPascal Brand if (res != TEE_SUCCESS)
4434b0104773SPascal Brand return res;
4435b0104773SPascal Brand
4436ef142203SJens Wiklander src_data = memtag_strip_tag_const(src_data);
4437ef142203SJens Wiklander dst_data = memtag_strip_tag(dst_data);
4438ef142203SJens Wiklander
443989c9728dSJens Wiklander res = vm_check_access_rights(&utc->uctx,
44401936dfc7SJens Wiklander TEE_MEMORY_ACCESS_READ |
44411936dfc7SJens Wiklander TEE_MEMORY_ACCESS_ANY_OWNER,
44422ffdd194SJens Wiklander (uaddr_t)src_data, src_len);
4443b0104773SPascal Brand if (res != TEE_SUCCESS)
4444b0104773SPascal Brand return res;
4445b0104773SPascal Brand
444684e9c40bSJens Wiklander res = get_user_u64_as_size_t(&dlen, dst_len);
4447b0104773SPascal Brand if (res != TEE_SUCCESS)
4448b0104773SPascal Brand return res;
4449b0104773SPascal Brand
445089c9728dSJens Wiklander res = vm_check_access_rights(&utc->uctx,
44511936dfc7SJens Wiklander TEE_MEMORY_ACCESS_READ |
44521936dfc7SJens Wiklander TEE_MEMORY_ACCESS_WRITE |
4453b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
44542ffdd194SJens Wiklander (uaddr_t)dst_data, dlen);
4455b0104773SPascal Brand if (res != TEE_SUCCESS)
4456b0104773SPascal Brand return res;
4457b0104773SPascal Brand
445870697bf3SJoakim Bech if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size))
445970697bf3SJoakim Bech return TEE_ERROR_OVERFLOW;
446070697bf3SJoakim Bech
446170697bf3SJoakim Bech params = malloc(alloc_size);
4462177603c7SJens Wiklander if (!params)
4463177603c7SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
44648684fde8SJens Wiklander res = copy_in_attrs(utc, usr_params, num_params, params);
4465c2e1a053SJerome Forissier if (res != TEE_SUCCESS)
4466177603c7SJens Wiklander goto out;
4467c2e1a053SJerome Forissier
44688684fde8SJens Wiklander res = tee_obj_get(utc, cs->key1, &o);
4469b0104773SPascal Brand if (res != TEE_SUCCESS)
4470177603c7SJens Wiklander goto out;
4471177603c7SJens Wiklander if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
4472177603c7SJens Wiklander res = TEE_ERROR_GENERIC;
4473177603c7SJens Wiklander goto out;
4474177603c7SJens Wiklander }
4475b0104773SPascal Brand
4476b0104773SPascal Brand switch (cs->algo) {
4477b0104773SPascal Brand case TEE_ALG_RSA_NOPAD:
4478b0104773SPascal Brand if (cs->mode == TEE_MODE_ENCRYPT) {
44794e154320SSeonghyun Park enter_user_access();
4480291e5450SJens Wiklander res = crypto_acipher_rsanopad_encrypt(o->attr, src_data,
4481291e5450SJens Wiklander src_len, dst_data,
4482ffe04039SJerome Forissier &dlen);
44834e154320SSeonghyun Park exit_user_access();
4484291e5450SJens Wiklander } else if (cs->mode == TEE_MODE_DECRYPT) {
44854e154320SSeonghyun Park enter_user_access();
4486291e5450SJens Wiklander res = crypto_acipher_rsanopad_decrypt(o->attr, src_data,
4487291e5450SJens Wiklander src_len, dst_data,
4488291e5450SJens Wiklander &dlen);
44894e154320SSeonghyun Park exit_user_access();
4490b0104773SPascal Brand } else {
44918844ebfcSPascal Brand /*
44928844ebfcSPascal Brand * We will panic because "the mode is not compatible
44938844ebfcSPascal Brand * with the function"
44948844ebfcSPascal Brand */
4495177603c7SJens Wiklander res = TEE_ERROR_GENERIC;
4496b0104773SPascal Brand }
4497b0104773SPascal Brand break;
4498b0104773SPascal Brand
449991fc6bd8SJerome Forissier case TEE_ALG_SM2_PKE:
450091fc6bd8SJerome Forissier if (cs->mode == TEE_MODE_ENCRYPT) {
45014e154320SSeonghyun Park enter_user_access();
450291fc6bd8SJerome Forissier res = crypto_acipher_sm2_pke_encrypt(o->attr, src_data,
450391fc6bd8SJerome Forissier src_len, dst_data,
450491fc6bd8SJerome Forissier &dlen);
45054e154320SSeonghyun Park exit_user_access();
450691fc6bd8SJerome Forissier } else if (cs->mode == TEE_MODE_DECRYPT) {
45074e154320SSeonghyun Park enter_user_access();
450891fc6bd8SJerome Forissier res = crypto_acipher_sm2_pke_decrypt(o->attr, src_data,
450991fc6bd8SJerome Forissier src_len, dst_data,
451091fc6bd8SJerome Forissier &dlen);
45114e154320SSeonghyun Park exit_user_access();
451291fc6bd8SJerome Forissier } else {
451391fc6bd8SJerome Forissier res = TEE_ERROR_GENERIC;
451491fc6bd8SJerome Forissier }
451591fc6bd8SJerome Forissier break;
451691fc6bd8SJerome Forissier
4517b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_V1_5:
4518f5c3d85aSJulien Masson case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5:
4519b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
4520b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
4521b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
4522b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
4523b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
4524b0104773SPascal Brand for (n = 0; n < num_params; n++) {
4525b0104773SPascal Brand if (params[n].attributeID == TEE_ATTR_RSA_OAEP_LABEL) {
4526b0104773SPascal Brand label = params[n].content.ref.buffer;
4527b0104773SPascal Brand label_len = params[n].content.ref.length;
4528b0104773SPascal Brand break;
4529b0104773SPascal Brand }
4530*86ee543bSSami Tolvanen
4531999b69d0SJens Wiklander if (cs->algo != TEE_ALG_RSAES_PKCS1_V1_5 &&
4532999b69d0SJens Wiklander params[n].attributeID ==
4533999b69d0SJens Wiklander TEE_ATTR_RSA_OAEP_MGF_HASH) {
4534a844a0b8SSeonghyun Park void *buf = params[n].content.ref.buffer;
4535999b69d0SJens Wiklander
4536999b69d0SJens Wiklander if (params[n].content.ref.length !=
4537*86ee543bSSami Tolvanen sizeof(mgf_algo)) {
4538999b69d0SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
45399ab92dedSEtienne Carriere goto out;
4540999b69d0SJens Wiklander }
4541a844a0b8SSeonghyun Park
4542*86ee543bSSami Tolvanen res = copy_from_user(&mgf_algo, buf,
4543*86ee543bSSami Tolvanen sizeof(mgf_algo));
4544a844a0b8SSeonghyun Park if (res)
4545a844a0b8SSeonghyun Park goto out;
4546*86ee543bSSami Tolvanen }
4547*86ee543bSSami Tolvanen }
4548a844a0b8SSeonghyun Park
4549*86ee543bSSami Tolvanen if (!mgf_algo)
4550*86ee543bSSami Tolvanen mgf_algo = TEE_INTERNAL_HASH_TO_ALGO(cs->algo);
4551b0104773SPascal Brand
4552b0104773SPascal Brand if (cs->mode == TEE_MODE_ENCRYPT) {
45534e154320SSeonghyun Park enter_user_access();
4554291e5450SJens Wiklander res = crypto_acipher_rsaes_encrypt(cs->algo, o->attr,
4555291e5450SJens Wiklander label, label_len,
4556*86ee543bSSami Tolvanen mgf_algo,
4557291e5450SJens Wiklander src_data, src_len,
4558291e5450SJens Wiklander dst_data, &dlen);
45594e154320SSeonghyun Park exit_user_access();
4560291e5450SJens Wiklander } else if (cs->mode == TEE_MODE_DECRYPT) {
45614e154320SSeonghyun Park enter_user_access();
4562291e5450SJens Wiklander res = crypto_acipher_rsaes_decrypt(
456340a4fd66SJens Wiklander cs->algo, o->attr, label, label_len,
4564*86ee543bSSami Tolvanen mgf_algo,
4565b0104773SPascal Brand src_data, src_len, dst_data, &dlen);
45664e154320SSeonghyun Park exit_user_access();
4567b0104773SPascal Brand } else {
4568b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
4569b0104773SPascal Brand }
4570b0104773SPascal Brand break;
4571b0104773SPascal Brand
457256859c53SGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1)
457356859c53SGabor Szekely case TEE_ALG_RSASSA_PKCS1_V1_5:
457456859c53SGabor Szekely #endif
4575b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
4576b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
4577b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
4578b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
4579b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
4580b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
4581f5c3d85aSJulien Masson case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
4582b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
4583b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
4584b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
4585b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
4586b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
4587b0104773SPascal Brand if (cs->mode != TEE_MODE_SIGN) {
4588b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
4589b0104773SPascal Brand break;
4590b0104773SPascal Brand }
45916bfd8c14SJens Wiklander salt_len = pkcs1_get_salt_len(params, num_params, src_len);
45924e154320SSeonghyun Park enter_user_access();
4593291e5450SJens Wiklander res = crypto_acipher_rsassa_sign(cs->algo, o->attr, salt_len,
4594291e5450SJens Wiklander src_data, src_len, dst_data,
4595291e5450SJens Wiklander &dlen);
45964e154320SSeonghyun Park exit_user_access();
4597b0104773SPascal Brand break;
4598b0104773SPascal Brand
4599b0104773SPascal Brand case TEE_ALG_DSA_SHA1:
460007a169c5SCedric Chaumont case TEE_ALG_DSA_SHA224:
460107a169c5SCedric Chaumont case TEE_ALG_DSA_SHA256:
46024e154320SSeonghyun Park enter_user_access();
4603291e5450SJens Wiklander res = crypto_acipher_dsa_sign(cs->algo, o->attr, src_data,
4604ffe04039SJerome Forissier src_len, dst_data, &dlen);
46054e154320SSeonghyun Park exit_user_access();
4606b0104773SPascal Brand break;
46070aaad418SValerii Chubar
46080aaad418SValerii Chubar case TEE_ALG_ED25519:
46094e154320SSeonghyun Park enter_user_access();
46100aaad418SValerii Chubar res = tee_svc_obj_ed25519_sign(o->attr, src_data, src_len,
46110aaad418SValerii Chubar dst_data, &dlen, params,
46120aaad418SValerii Chubar num_params);
46134e154320SSeonghyun Park exit_user_access();
46140aaad418SValerii Chubar break;
46150aaad418SValerii Chubar
4616fe2fd3ffSJens Wiklander case TEE_ALG_ECDSA_SHA1:
4617fe2fd3ffSJens Wiklander case TEE_ALG_ECDSA_SHA224:
4618fe2fd3ffSJens Wiklander case TEE_ALG_ECDSA_SHA256:
4619fe2fd3ffSJens Wiklander case TEE_ALG_ECDSA_SHA384:
4620fe2fd3ffSJens Wiklander case TEE_ALG_ECDSA_SHA512:
462108e47d6bSCedric Neveux case TEE_ALG_SM2_DSA_SM3:
46224e154320SSeonghyun Park enter_user_access();
4623291e5450SJens Wiklander res = crypto_acipher_ecc_sign(cs->algo, o->attr, src_data,
4624c988227aSPascal Brand src_len, dst_data, &dlen);
46254e154320SSeonghyun Park exit_user_access();
4626c988227aSPascal Brand break;
4627b0104773SPascal Brand default:
4628b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS;
4629b0104773SPascal Brand break;
4630b0104773SPascal Brand }
4631b0104773SPascal Brand
4632177603c7SJens Wiklander out:
463370b61310SJerome Forissier free_wipe(params);
4634177603c7SJens Wiklander
4635b0104773SPascal Brand if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
463684e9c40bSJens Wiklander TEE_Result res2 = put_user_u64(dst_len, dlen);
4637b0104773SPascal Brand
4638b0104773SPascal Brand if (res2 != TEE_SUCCESS)
4639b0104773SPascal Brand return res2;
4640b0104773SPascal Brand }
4641b0104773SPascal Brand
4642b0104773SPascal Brand return res;
4643b0104773SPascal Brand }
4644b0104773SPascal Brand
syscall_asymm_verify(unsigned long state,const struct utee_attribute * usr_params,size_t num_params,const void * data,size_t data_len,const void * sig,size_t sig_len)4645e86f1266SJens Wiklander TEE_Result syscall_asymm_verify(unsigned long state,
4646e86f1266SJens Wiklander const struct utee_attribute *usr_params,
4647e86f1266SJens Wiklander size_t num_params, const void *data, size_t data_len,
4648e86f1266SJens Wiklander const void *sig, size_t sig_len)
4649b0104773SPascal Brand {
465000b3b9a2SJens Wiklander struct ts_session *sess = ts_get_current_session();
465100b3b9a2SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
46521936dfc7SJens Wiklander struct tee_cryp_state *cs = NULL;
46531936dfc7SJens Wiklander TEE_Result res = TEE_SUCCESS;
4654177603c7SJens Wiklander TEE_Attribute *params = NULL;
46551936dfc7SJens Wiklander struct tee_obj *o = NULL;
46561936dfc7SJens Wiklander size_t hash_size = 0;
46571936dfc7SJens Wiklander uint32_t hash_algo = 0;
46581936dfc7SJens Wiklander int salt_len = 0;
46599ff77e1eSJens Wiklander size_t alloc_size = 0;
4660b0104773SPascal Brand
4661c40a6505SJens Wiklander res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
4662b0104773SPascal Brand if (res != TEE_SUCCESS)
4663b0104773SPascal Brand return res;
4664b0104773SPascal Brand
4665b0104773SPascal Brand if (cs->mode != TEE_MODE_VERIFY)
4666b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
4667b0104773SPascal Brand
4668ef142203SJens Wiklander data = memtag_strip_tag_const(data);
4669ef142203SJens Wiklander sig = memtag_strip_tag_const(sig);
4670ef142203SJens Wiklander
467189c9728dSJens Wiklander res = vm_check_access_rights(&utc->uctx,
4672b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4673b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
46742ffdd194SJens Wiklander (uaddr_t)data, data_len);
4675b0104773SPascal Brand if (res != TEE_SUCCESS)
4676b0104773SPascal Brand return res;
4677b0104773SPascal Brand
467889c9728dSJens Wiklander res = vm_check_access_rights(&utc->uctx,
4679b0104773SPascal Brand TEE_MEMORY_ACCESS_READ |
4680b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER,
46812ffdd194SJens Wiklander (uaddr_t)sig, sig_len);
4682b0104773SPascal Brand if (res != TEE_SUCCESS)
4683b0104773SPascal Brand return res;
4684b0104773SPascal Brand
468570697bf3SJoakim Bech if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size))
468670697bf3SJoakim Bech return TEE_ERROR_OVERFLOW;
468770697bf3SJoakim Bech
468870697bf3SJoakim Bech params = malloc(alloc_size);
4689177603c7SJens Wiklander if (!params)
4690177603c7SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY;
46918684fde8SJens Wiklander res = copy_in_attrs(utc, usr_params, num_params, params);
4692c2e1a053SJerome Forissier if (res != TEE_SUCCESS)
4693177603c7SJens Wiklander goto out;
4694c2e1a053SJerome Forissier
46958684fde8SJens Wiklander res = tee_obj_get(utc, cs->key1, &o);
4696b0104773SPascal Brand if (res != TEE_SUCCESS)
4697177603c7SJens Wiklander goto out;
4698177603c7SJens Wiklander if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
4699177603c7SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS;
4700177603c7SJens Wiklander goto out;
4701177603c7SJens Wiklander }
4702b0104773SPascal Brand
4703b0104773SPascal Brand switch (TEE_ALG_GET_MAIN_ALG(cs->algo)) {
4704b0104773SPascal Brand case TEE_MAIN_ALGO_RSA:
470556859c53SGabor Szekely if (cs->algo != TEE_ALG_RSASSA_PKCS1_V1_5) {
4706dc9c6ddaSJerome Forissier hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo);
47077c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(hash_algo, &hash_size);
4708dc9c6ddaSJerome Forissier if (res != TEE_SUCCESS)
4709dc9c6ddaSJerome Forissier break;
4710dc9c6ddaSJerome Forissier if (data_len != hash_size) {
4711dc9c6ddaSJerome Forissier res = TEE_ERROR_BAD_PARAMETERS;
4712dc9c6ddaSJerome Forissier break;
4713dc9c6ddaSJerome Forissier }
471456859c53SGabor Szekely salt_len = pkcs1_get_salt_len(params, num_params,
471556859c53SGabor Szekely hash_size);
471656859c53SGabor Szekely }
47174e154320SSeonghyun Park enter_user_access();
4718291e5450SJens Wiklander res = crypto_acipher_rsassa_verify(cs->algo, o->attr, salt_len,
4719291e5450SJens Wiklander data, data_len, sig,
4720291e5450SJens Wiklander sig_len);
47214e154320SSeonghyun Park exit_user_access();
4722b0104773SPascal Brand break;
4723b0104773SPascal Brand
4724b0104773SPascal Brand case TEE_MAIN_ALGO_DSA:
4725dc9c6ddaSJerome Forissier hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo);
47267c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(hash_algo, &hash_size);
4727dc9c6ddaSJerome Forissier if (res != TEE_SUCCESS)
4728dc9c6ddaSJerome Forissier break;
472968c68bceSJens Wiklander
473068c68bceSJens Wiklander if (data_len != hash_size) {
473168c68bceSJens Wiklander struct dsa_public_key *key = o->attr;
473268c68bceSJens Wiklander
4733dc9c6ddaSJerome Forissier /*
473468c68bceSJens Wiklander * Depending on the DSA algorithm (NIST), the
473568c68bceSJens Wiklander * digital signature output size may be truncated
473668c68bceSJens Wiklander * to the size of a key pair (Q prime size). Q
473768c68bceSJens Wiklander * prime size must be less or equal than the hash
473868c68bceSJens Wiklander * output length of the hash algorithm involved.
473968c68bceSJens Wiklander *
474068c68bceSJens Wiklander * We're checking here in order to be able to
474168c68bceSJens Wiklander * return this particular error code, which will
474268c68bceSJens Wiklander * cause TEE_AsymmetricVerifyDigest() to panic as
474368c68bceSJens Wiklander * required by GP. crypto_acipher_dsa_verify() is
474468c68bceSJens Wiklander * implemented in the glue layer of the crypto
474568c68bceSJens Wiklander * library and it might be a bit harder to catch
474668c68bceSJens Wiklander * this particular case there or lead to duplicated
474768c68bceSJens Wiklander * code in different crypto glue layers.
474868c68bceSJens Wiklander *
474968c68bceSJens Wiklander * The GP spec says that we SHOULD panic if
475068c68bceSJens Wiklander * data_len != hash_size, but that would break a
475168c68bceSJens Wiklander * few of the DSA tests in xtest where the
475268c68bceSJens Wiklander * hash_size is larger than possible data_len. So
475368c68bceSJens Wiklander * the compromise is in case data_len != hash_size
475468c68bceSJens Wiklander * check that it's not smaller than what makes
475568c68bceSJens Wiklander * sense.
4756dc9c6ddaSJerome Forissier */
475768c68bceSJens Wiklander if (data_len != crypto_bignum_num_bytes(key->q)) {
4758dc9c6ddaSJerome Forissier res = TEE_ERROR_BAD_PARAMETERS;
4759dc9c6ddaSJerome Forissier break;
4760dc9c6ddaSJerome Forissier }
476168c68bceSJens Wiklander }
47624e154320SSeonghyun Park enter_user_access();
4763291e5450SJens Wiklander res = crypto_acipher_dsa_verify(cs->algo, o->attr, data,
4764ffe04039SJerome Forissier data_len, sig, sig_len);
47654e154320SSeonghyun Park exit_user_access();
4766b0104773SPascal Brand break;
4767b0104773SPascal Brand
47680aaad418SValerii Chubar case TEE_MAIN_ALGO_ED25519:
47694e154320SSeonghyun Park enter_user_access();
47700aaad418SValerii Chubar res = tee_svc_obj_ed25519_verify(o->attr, data,
47710aaad418SValerii Chubar data_len, sig, sig_len,
47720aaad418SValerii Chubar params, num_params);
47734e154320SSeonghyun Park exit_user_access();
47740aaad418SValerii Chubar break;
47750aaad418SValerii Chubar
4776c988227aSPascal Brand case TEE_MAIN_ALGO_ECDSA:
47770f151943SJerome Forissier case TEE_MAIN_ALGO_SM2_DSA_SM3:
47784e154320SSeonghyun Park enter_user_access();
477908e47d6bSCedric Neveux res = crypto_acipher_ecc_verify(cs->algo, o->attr, data,
47800f151943SJerome Forissier data_len, sig, sig_len);
47814e154320SSeonghyun Park exit_user_access();
47820f151943SJerome Forissier break;
47830f151943SJerome Forissier
4784b0104773SPascal Brand default:
4785b0104773SPascal Brand res = TEE_ERROR_NOT_SUPPORTED;
4786b0104773SPascal Brand }
4787b0104773SPascal Brand
4788177603c7SJens Wiklander out:
478970b61310SJerome Forissier free_wipe(params);
4790b0104773SPascal Brand return res;
4791b0104773SPascal Brand }
4792