xref: /optee_os/core/tee/tee_svc_cryp.c (revision 86ee543b2786068e4d192111ab5e582d065c2a8d)
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 = &params[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 = &params[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 = &params[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 = &params[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