xref: /optee_os/core/lib/libtomcrypt/ecc.c (revision e7971844f76d4380d4f510ed0a02257d9df3f1bf)
16644e2f0SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
26644e2f0SJens Wiklander /*
36644e2f0SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
46644e2f0SJens Wiklander  */
56644e2f0SJens Wiklander 
61fa655fcSCedric Neveux #include <config.h>
7b56ad90eSCedric Neveux #include <crypto/crypto_impl.h>
86644e2f0SJens Wiklander #include <stdlib.h>
96644e2f0SJens Wiklander #include <string.h>
106644e2f0SJens Wiklander #include <tee_api_types.h>
116644e2f0SJens Wiklander #include <trace.h>
126644e2f0SJens Wiklander #include <utee_defines.h>
136644e2f0SJens Wiklander 
146644e2f0SJens Wiklander #include "acipher_helpers.h"
156644e2f0SJens Wiklander 
16b56ad90eSCedric Neveux static void _ltc_ecc_free_public_key(struct ecc_public_key *s)
176644e2f0SJens Wiklander {
186644e2f0SJens Wiklander 	if (!s)
196644e2f0SJens Wiklander 		return;
206644e2f0SJens Wiklander 
216644e2f0SJens Wiklander 	crypto_bignum_free(s->x);
226644e2f0SJens Wiklander 	crypto_bignum_free(s->y);
236644e2f0SJens Wiklander }
246644e2f0SJens Wiklander 
256644e2f0SJens Wiklander /*
265a913ee7SJerome Forissier  * For a given TEE @curve, return key size and LTC curve name. Also check that
275a913ee7SJerome Forissier  * @algo is compatible with this curve.
285a913ee7SJerome Forissier  * @curve: TEE_ECC_CURVE_NIST_P192, ...
295a913ee7SJerome Forissier  * @algo: TEE_ALG_ECDSA_P192, ...
306644e2f0SJens Wiklander  */
315a913ee7SJerome Forissier static TEE_Result ecc_get_curve_info(uint32_t curve, uint32_t algo,
325a913ee7SJerome Forissier 				     size_t *key_size_bytes,
335a913ee7SJerome Forissier 				     size_t *key_size_bits,
345a913ee7SJerome Forissier 				     const char **curve_name)
356644e2f0SJens Wiklander {
365a913ee7SJerome Forissier 	size_t size_bytes = 0;
375a913ee7SJerome Forissier 	size_t size_bits = 0;
385a913ee7SJerome Forissier 	const char *name = NULL;
395a913ee7SJerome Forissier 
406644e2f0SJens Wiklander 	/*
416644e2f0SJens Wiklander 	 * Excerpt of libtomcrypt documentation:
426644e2f0SJens Wiklander 	 * ecc_make_key(... key_size ...): The keysize is the size of the
436644e2f0SJens Wiklander 	 * modulus in bytes desired. Currently directly supported values
446644e2f0SJens Wiklander 	 * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond
456644e2f0SJens Wiklander 	 * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits
466644e2f0SJens Wiklander 	 * respectively.
476644e2f0SJens Wiklander 	 */
486644e2f0SJens Wiklander 
496644e2f0SJens Wiklander 	/*
506644e2f0SJens Wiklander 	 * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET
516644e2f0SJens Wiklander 	 * but defines TEE_ALG_ECDH_P192
526644e2f0SJens Wiklander 	 */
536644e2f0SJens Wiklander 
546644e2f0SJens Wiklander 	switch (curve) {
556644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P192:
565a913ee7SJerome Forissier 		size_bits = 192;
575a913ee7SJerome Forissier 		size_bytes = 24;
585a913ee7SJerome Forissier 		name = "NISTP192";
596644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P192) &&
606644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P192))
616644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
626644e2f0SJens Wiklander 		break;
636644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P224:
645a913ee7SJerome Forissier 		size_bits = 224;
655a913ee7SJerome Forissier 		size_bytes = 28;
665a913ee7SJerome Forissier 		name = "NISTP224";
676644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P224) &&
686644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P224))
696644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
706644e2f0SJens Wiklander 		break;
716644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P256:
725a913ee7SJerome Forissier 		size_bits = 256;
735a913ee7SJerome Forissier 		size_bytes = 32;
745a913ee7SJerome Forissier 		name = "NISTP256";
756644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P256) &&
766644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P256))
776644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
786644e2f0SJens Wiklander 		break;
796644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P384:
805a913ee7SJerome Forissier 		size_bits = 384;
815a913ee7SJerome Forissier 		size_bytes = 48;
825a913ee7SJerome Forissier 		name = "NISTP384";
836644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P384) &&
846644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P384))
856644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
866644e2f0SJens Wiklander 		break;
876644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P521:
885a913ee7SJerome Forissier 		size_bits = 521;
895a913ee7SJerome Forissier 		size_bytes = 66;
905a913ee7SJerome Forissier 		name = "NISTP521";
916644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P521) &&
926644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P521))
936644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
946644e2f0SJens Wiklander 		break;
9591fc6bd8SJerome Forissier 	case TEE_ECC_CURVE_SM2:
9691fc6bd8SJerome Forissier 		size_bits = 256;
9791fc6bd8SJerome Forissier 		size_bytes = 32;
9891fc6bd8SJerome Forissier 		name = "SM2";
990f151943SJerome Forissier 		if ((algo != 0) && (algo != TEE_ALG_SM2_PKE) &&
1005b385b3fSJerome Forissier 		    (algo != TEE_ALG_SM2_DSA_SM3) &&
1015b385b3fSJerome Forissier 		    (algo != TEE_ALG_SM2_KEP))
10291fc6bd8SJerome Forissier 			return TEE_ERROR_BAD_PARAMETERS;
10391fc6bd8SJerome Forissier 		break;
1046644e2f0SJens Wiklander 	default:
1056644e2f0SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
1066644e2f0SJens Wiklander 	}
1076644e2f0SJens Wiklander 
1085a913ee7SJerome Forissier 	if (key_size_bytes)
1095a913ee7SJerome Forissier 		*key_size_bytes = size_bytes;
1105a913ee7SJerome Forissier 	if (key_size_bits)
1115a913ee7SJerome Forissier 		*key_size_bits = size_bits;
1125a913ee7SJerome Forissier 	if (curve_name)
1135a913ee7SJerome Forissier 		*curve_name = name;
1146644e2f0SJens Wiklander 	return TEE_SUCCESS;
1156644e2f0SJens Wiklander }
1166644e2f0SJens Wiklander 
117ecf9194dSJerome Forissier /* Note: this function clears the key before setting the curve */
118ecf9194dSJerome Forissier static TEE_Result ecc_set_curve_from_name(ecc_key *ltc_key,
119ecf9194dSJerome Forissier 					  const char *curve_name)
120ecf9194dSJerome Forissier {
121ecf9194dSJerome Forissier 	const ltc_ecc_curve *curve = NULL;
122ecf9194dSJerome Forissier 	int ltc_res = 0;
123ecf9194dSJerome Forissier 
124ecf9194dSJerome Forissier 	ltc_res = ecc_find_curve(curve_name, &curve);
125ecf9194dSJerome Forissier 	if (ltc_res != CRYPT_OK)
126ecf9194dSJerome Forissier 		return TEE_ERROR_NOT_SUPPORTED;
127ecf9194dSJerome Forissier 
128ecf9194dSJerome Forissier 	ltc_res = ecc_set_curve(curve, ltc_key);
129ecf9194dSJerome Forissier 	if (ltc_res != CRYPT_OK)
130ecf9194dSJerome Forissier 		return TEE_ERROR_GENERIC;
131ecf9194dSJerome Forissier 
132ecf9194dSJerome Forissier 	return TEE_SUCCESS;
133ecf9194dSJerome Forissier }
134ecf9194dSJerome Forissier 
135b56ad90eSCedric Neveux static TEE_Result _ltc_ecc_generate_keypair(struct ecc_keypair *key,
136b56ad90eSCedric Neveux 					    size_t key_size)
1376644e2f0SJens Wiklander {
1386644e2f0SJens Wiklander 	TEE_Result res;
1396644e2f0SJens Wiklander 	ecc_key ltc_tmp_key;
1406644e2f0SJens Wiklander 	int ltc_res;
1416644e2f0SJens Wiklander 	size_t key_size_bytes = 0;
1426644e2f0SJens Wiklander 	size_t key_size_bits = 0;
143ecf9194dSJerome Forissier 	const char *name = NULL;
1446644e2f0SJens Wiklander 
1455a913ee7SJerome Forissier 	res = ecc_get_curve_info(key->curve, 0, &key_size_bytes, &key_size_bits,
146ecf9194dSJerome Forissier 				 &name);
1476644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
1486644e2f0SJens Wiklander 		return res;
1496644e2f0SJens Wiklander 
15021282baeSJerome Forissier 	if (key_size != key_size_bits)
15121282baeSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
15221282baeSJerome Forissier 
153ecf9194dSJerome Forissier 	res = ecc_set_curve_from_name(&ltc_tmp_key, name);
154ecf9194dSJerome Forissier 	if (res)
155ecf9194dSJerome Forissier 		return res;
156ecf9194dSJerome Forissier 
1576644e2f0SJens Wiklander 	/* Generate the ECC key */
158ecf9194dSJerome Forissier 	ltc_res = ecc_generate_key(NULL, find_prng("prng_crypto"),
159ecf9194dSJerome Forissier 				   &ltc_tmp_key);
1606644e2f0SJens Wiklander 	if (ltc_res != CRYPT_OK)
1616644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
1626644e2f0SJens Wiklander 
1636644e2f0SJens Wiklander 	/* check the size of the keys */
1646644e2f0SJens Wiklander 	if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) ||
1656644e2f0SJens Wiklander 	    ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) ||
1666644e2f0SJens Wiklander 	    ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) {
1676644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1686644e2f0SJens Wiklander 		goto exit;
1696644e2f0SJens Wiklander 	}
1706644e2f0SJens Wiklander 
1716644e2f0SJens Wiklander 	/* check LTC is returning z==1 */
1726644e2f0SJens Wiklander 	if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) {
1736644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1746644e2f0SJens Wiklander 		goto exit;
1756644e2f0SJens Wiklander 	}
1766644e2f0SJens Wiklander 
1776644e2f0SJens Wiklander 	/* Copy the key */
1786644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.k, key->d);
1796644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x);
1806644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y);
1816644e2f0SJens Wiklander 
1826644e2f0SJens Wiklander 	res = TEE_SUCCESS;
1836644e2f0SJens Wiklander 
1846644e2f0SJens Wiklander exit:
1856644e2f0SJens Wiklander 	ecc_free(&ltc_tmp_key);		/* Free the temporary key */
1866644e2f0SJens Wiklander 	return res;
1876644e2f0SJens Wiklander }
1886644e2f0SJens Wiklander 
1896644e2f0SJens Wiklander /*
1906644e2f0SJens Wiklander  * Given a keypair "key", populate the Libtomcrypt private key "ltc_key"
1916644e2f0SJens Wiklander  * It also returns the key size, in bytes
1926644e2f0SJens Wiklander  */
193c0691130SJerome Forissier TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key,
1946644e2f0SJens Wiklander 					struct ecc_keypair *key,
195c0691130SJerome Forissier 					uint32_t algo, size_t *key_size_bytes)
1966644e2f0SJens Wiklander {
1975a913ee7SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
1985a913ee7SJerome Forissier 	const char *name = NULL;
1996644e2f0SJens Wiklander 
2005a913ee7SJerome Forissier 	res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name);
2015a913ee7SJerome Forissier 	if (res)
2026644e2f0SJens Wiklander 		return res;
2036644e2f0SJens Wiklander 
2045a913ee7SJerome Forissier 	memset(ltc_key, 0, sizeof(*ltc_key));
2055a913ee7SJerome Forissier 
2065a913ee7SJerome Forissier 	res = ecc_set_curve_from_name(ltc_key, name);
2075a913ee7SJerome Forissier 	if (res)
2085a913ee7SJerome Forissier 		return res;
2095a913ee7SJerome Forissier 
2105a913ee7SJerome Forissier 	ltc_key->type = PK_PRIVATE;
2115a913ee7SJerome Forissier 	mp_copy(key->d, ltc_key->k);
2127ecec894SJerome Forissier 	mp_copy(key->x, ltc_key->pubkey.x);
2137ecec894SJerome Forissier 	mp_copy(key->y, ltc_key->pubkey.y);
2147ecec894SJerome Forissier 	mp_set_int(ltc_key->pubkey.z, 1);
2155a913ee7SJerome Forissier 
2165a913ee7SJerome Forissier 	return TEE_SUCCESS;
2176644e2f0SJens Wiklander }
2186644e2f0SJens Wiklander 
2196644e2f0SJens Wiklander /*
2206644e2f0SJens Wiklander  * Given a public "key", populate the Libtomcrypt public key "ltc_key"
2216644e2f0SJens Wiklander  * It also returns the key size, in bytes
2226644e2f0SJens Wiklander  */
223c0691130SJerome Forissier TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key,
2246644e2f0SJens Wiklander 				       struct ecc_public_key *key,
225c0691130SJerome Forissier 				       uint32_t algo, size_t *key_size_bytes)
2266644e2f0SJens Wiklander {
2275a913ee7SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
2285a913ee7SJerome Forissier 	const char *name = NULL;
2296644e2f0SJens Wiklander 	uint8_t one[1] = { 1 };
2306644e2f0SJens Wiklander 
2315a913ee7SJerome Forissier 	res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name);
2325a913ee7SJerome Forissier 	if (res)
2336644e2f0SJens Wiklander 		return res;
2346644e2f0SJens Wiklander 
2355a913ee7SJerome Forissier 	memset(ltc_key, 0, sizeof(*ltc_key));
2365a913ee7SJerome Forissier 
2375a913ee7SJerome Forissier 	res = ecc_set_curve_from_name(ltc_key, name);
2385a913ee7SJerome Forissier 	if (res)
2395a913ee7SJerome Forissier 		return res;
2405a913ee7SJerome Forissier 
2415a913ee7SJerome Forissier 	ltc_key->type = PK_PUBLIC;
2425a913ee7SJerome Forissier 
2435a913ee7SJerome Forissier 	mp_copy(key->x, ltc_key->pubkey.x);
2445a913ee7SJerome Forissier 	mp_copy(key->y, ltc_key->pubkey.y);
2455a913ee7SJerome Forissier 	mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one));
2465a913ee7SJerome Forissier 
2475a913ee7SJerome Forissier 	return TEE_SUCCESS;
2486644e2f0SJens Wiklander }
2496644e2f0SJens Wiklander 
250b56ad90eSCedric Neveux static TEE_Result _ltc_ecc_sign(uint32_t algo, struct ecc_keypair *key,
2516644e2f0SJens Wiklander 				const uint8_t *msg, size_t msg_len,
2526644e2f0SJens Wiklander 				uint8_t *sig, size_t *sig_len)
2536644e2f0SJens Wiklander {
2545a913ee7SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
2555a913ee7SJerome Forissier 	int ltc_res = 0;
2565a913ee7SJerome Forissier 	size_t key_size_bytes = 0;
2575a913ee7SJerome Forissier 	ecc_key ltc_key = { };
2585a913ee7SJerome Forissier 	unsigned long ltc_sig_len = 0;
2596644e2f0SJens Wiklander 
2605a913ee7SJerome Forissier 	if (algo == 0)
2615a913ee7SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2626644e2f0SJens Wiklander 
2636644e2f0SJens Wiklander 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo,
2646644e2f0SJens Wiklander 					   &key_size_bytes);
2656644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
2665a913ee7SJerome Forissier 		return res;
2676644e2f0SJens Wiklander 
2686644e2f0SJens Wiklander 	if (*sig_len < 2 * key_size_bytes) {
2696644e2f0SJens Wiklander 		*sig_len = 2 * key_size_bytes;
2706644e2f0SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
2715a913ee7SJerome Forissier 		goto out;
2726644e2f0SJens Wiklander 	}
2736644e2f0SJens Wiklander 
2745a913ee7SJerome Forissier 	ltc_sig_len = *sig_len;
2755a913ee7SJerome Forissier 	ltc_res = ecc_sign_hash_rfc7518(msg, msg_len, sig, &ltc_sig_len,
2761f3b1115SJens Wiklander 				    NULL, find_prng("prng_crypto"), &ltc_key);
2776644e2f0SJens Wiklander 	if (ltc_res == CRYPT_OK) {
2786644e2f0SJens Wiklander 		res = TEE_SUCCESS;
2796644e2f0SJens Wiklander 	} else {
2806644e2f0SJens Wiklander 		res = TEE_ERROR_GENERIC;
2816644e2f0SJens Wiklander 	}
2825a913ee7SJerome Forissier 	*sig_len = ltc_sig_len;
2836644e2f0SJens Wiklander 
2845a913ee7SJerome Forissier out:
2855a913ee7SJerome Forissier 	ecc_free(&ltc_key);
2866644e2f0SJens Wiklander 	return res;
2876644e2f0SJens Wiklander }
2886644e2f0SJens Wiklander 
289b56ad90eSCedric Neveux static TEE_Result _ltc_ecc_verify(uint32_t algo, struct ecc_public_key *key,
2906644e2f0SJens Wiklander 				  const uint8_t *msg, size_t msg_len,
2916644e2f0SJens Wiklander 				  const uint8_t *sig, size_t sig_len)
2926644e2f0SJens Wiklander {
2935a913ee7SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
2945a913ee7SJerome Forissier 	int ltc_stat = 0;
2955a913ee7SJerome Forissier 	int ltc_res = 0;
2965a913ee7SJerome Forissier 	size_t key_size_bytes = 0;
2975a913ee7SJerome Forissier 	ecc_key ltc_key = { };
2986644e2f0SJens Wiklander 
2996644e2f0SJens Wiklander 	if (algo == 0)
3006644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
3016644e2f0SJens Wiklander 
3025a913ee7SJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_key, key, algo, &key_size_bytes);
3036644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3046644e2f0SJens Wiklander 		goto out;
3056644e2f0SJens Wiklander 
3066644e2f0SJens Wiklander 	/* check keysize vs sig_len */
3076644e2f0SJens Wiklander 	if ((key_size_bytes * 2) != sig_len) {
3086644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
3096644e2f0SJens Wiklander 		goto out;
3106644e2f0SJens Wiklander 	}
3116644e2f0SJens Wiklander 
3125a913ee7SJerome Forissier 	ltc_res = ecc_verify_hash_rfc7518(sig, sig_len, msg, msg_len, &ltc_stat,
3135a913ee7SJerome Forissier 					  &ltc_key);
3146644e2f0SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
3156644e2f0SJens Wiklander out:
3165a913ee7SJerome Forissier 	ecc_free(&ltc_key);
3176644e2f0SJens Wiklander 	return res;
3186644e2f0SJens Wiklander }
3196644e2f0SJens Wiklander 
320b56ad90eSCedric Neveux static TEE_Result _ltc_ecc_shared_secret(struct ecc_keypair *private_key,
3216644e2f0SJens Wiklander 					 struct ecc_public_key *public_key,
3226644e2f0SJens Wiklander 					 void *secret,
3236644e2f0SJens Wiklander 					 unsigned long *secret_len)
3246644e2f0SJens Wiklander {
3255a913ee7SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
3265a913ee7SJerome Forissier 	int ltc_res = 0;
3275a913ee7SJerome Forissier 	ecc_key ltc_private_key = { };
3285a913ee7SJerome Forissier 	ecc_key ltc_public_key = { };
3295a913ee7SJerome Forissier 	size_t key_size_bytes = 0;
3306644e2f0SJens Wiklander 
3316644e2f0SJens Wiklander 	/* Check the curves are the same */
3326644e2f0SJens Wiklander 	if (private_key->curve != public_key->curve)
3336644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
3346644e2f0SJens Wiklander 
3356644e2f0SJens Wiklander 	res = ecc_populate_ltc_private_key(&ltc_private_key, private_key,
3366644e2f0SJens Wiklander 					   0, &key_size_bytes);
3376644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3386644e2f0SJens Wiklander 		goto out;
3395a913ee7SJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_public_key, public_key,
3406644e2f0SJens Wiklander 					  0, &key_size_bytes);
3416644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3426644e2f0SJens Wiklander 		goto out;
3436644e2f0SJens Wiklander 
3446644e2f0SJens Wiklander 	ltc_res = ecc_shared_secret(&ltc_private_key, &ltc_public_key,
3456644e2f0SJens Wiklander 				    secret, secret_len);
3466644e2f0SJens Wiklander 	if (ltc_res == CRYPT_OK)
3476644e2f0SJens Wiklander 		res = TEE_SUCCESS;
3486644e2f0SJens Wiklander 	else
3496644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
3506644e2f0SJens Wiklander 
3516644e2f0SJens Wiklander out:
3525a913ee7SJerome Forissier 	ecc_free(&ltc_private_key);
3535a913ee7SJerome Forissier 	ecc_free(&ltc_public_key);
3546644e2f0SJens Wiklander 	return res;
3556644e2f0SJens Wiklander }
356b56ad90eSCedric Neveux 
357b56ad90eSCedric Neveux static const struct crypto_ecc_keypair_ops ecc_keypair_ops = {
35855b5758dSJerome Forissier 	.generate = _ltc_ecc_generate_keypair,
35955b5758dSJerome Forissier 	.sign = _ltc_ecc_sign,
36055b5758dSJerome Forissier 	.shared_secret = _ltc_ecc_shared_secret,
361b56ad90eSCedric Neveux };
362b56ad90eSCedric Neveux 
363b56ad90eSCedric Neveux static const struct crypto_ecc_public_ops ecc_public_key_ops = {
36455b5758dSJerome Forissier 	.free = _ltc_ecc_free_public_key,
36555b5758dSJerome Forissier 	.verify = _ltc_ecc_verify,
366b56ad90eSCedric Neveux };
367b56ad90eSCedric Neveux 
3681fa655fcSCedric Neveux static const struct crypto_ecc_keypair_ops sm2_dsa_keypair_ops = {
36955b5758dSJerome Forissier 	.generate = _ltc_ecc_generate_keypair,
37055b5758dSJerome Forissier 	.sign = sm2_ltc_dsa_sign,
3711fa655fcSCedric Neveux };
3721fa655fcSCedric Neveux 
3731fa655fcSCedric Neveux static const struct crypto_ecc_public_ops sm2_dsa_public_key_ops = {
37455b5758dSJerome Forissier 	.free = _ltc_ecc_free_public_key,
37555b5758dSJerome Forissier 	.verify = sm2_ltc_dsa_verify,
3761fa655fcSCedric Neveux };
3771fa655fcSCedric Neveux 
3781fa655fcSCedric Neveux static const struct crypto_ecc_keypair_ops sm2_pke_keypair_ops = {
37955b5758dSJerome Forissier 	.generate = _ltc_ecc_generate_keypair,
38055b5758dSJerome Forissier 	.decrypt = sm2_ltc_pke_decrypt,
3811fa655fcSCedric Neveux };
3821fa655fcSCedric Neveux 
3831fa655fcSCedric Neveux static const struct crypto_ecc_public_ops sm2_pke_public_key_ops = {
38455b5758dSJerome Forissier 	.free = _ltc_ecc_free_public_key,
38555b5758dSJerome Forissier 	.encrypt = sm2_ltc_pke_encrypt,
3861fa655fcSCedric Neveux };
3871fa655fcSCedric Neveux 
3881fa655fcSCedric Neveux static const struct crypto_ecc_keypair_ops sm2_kep_keypair_ops = {
38955b5758dSJerome Forissier 	.generate = _ltc_ecc_generate_keypair,
3901fa655fcSCedric Neveux };
3911fa655fcSCedric Neveux 
3921fa655fcSCedric Neveux static const struct crypto_ecc_public_ops sm2_kep_public_key_ops = {
39355b5758dSJerome Forissier 	.free = _ltc_ecc_free_public_key,
3941fa655fcSCedric Neveux };
3951fa655fcSCedric Neveux 
396*e7971844SJorge Ramirez-Ortiz const struct crypto_ecc_keypair_ops *
397*e7971844SJorge Ramirez-Ortiz crypto_asym_get_ecc_keypair_ops( uint32_t key_type)
398*e7971844SJorge Ramirez-Ortiz {
399*e7971844SJorge Ramirez-Ortiz 	switch (key_type) {
400*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_ECDSA_KEYPAIR:
401*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_ECDH_KEYPAIR:
402*e7971844SJorge Ramirez-Ortiz 		return &ecc_keypair_ops;
403*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_DSA_KEYPAIR:
404*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA))
405*e7971844SJorge Ramirez-Ortiz 			return NULL;
406*e7971844SJorge Ramirez-Ortiz 		return &sm2_dsa_keypair_ops;
407*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_PKE_KEYPAIR:
408*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE))
409*e7971844SJorge Ramirez-Ortiz 			return NULL;
410*e7971844SJorge Ramirez-Ortiz 		return &sm2_pke_keypair_ops;
411*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_KEP_KEYPAIR:
412*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP))
413*e7971844SJorge Ramirez-Ortiz 			return NULL;
414*e7971844SJorge Ramirez-Ortiz 		return &sm2_kep_keypair_ops;
415*e7971844SJorge Ramirez-Ortiz 	default:
416*e7971844SJorge Ramirez-Ortiz 		return NULL;
417*e7971844SJorge Ramirez-Ortiz 	}
418*e7971844SJorge Ramirez-Ortiz }
419*e7971844SJorge Ramirez-Ortiz 
420b56ad90eSCedric Neveux TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s,
4211fa655fcSCedric Neveux 					 uint32_t key_type,
422b56ad90eSCedric Neveux 					 size_t key_size_bits __unused)
423b56ad90eSCedric Neveux {
424b56ad90eSCedric Neveux 	memset(s, 0, sizeof(*s));
4251fa655fcSCedric Neveux 
4261fa655fcSCedric Neveux 	switch (key_type) {
4271fa655fcSCedric Neveux 	case TEE_TYPE_ECDSA_KEYPAIR:
4281fa655fcSCedric Neveux 	case TEE_TYPE_ECDH_KEYPAIR:
4291fa655fcSCedric Neveux 		s->ops = &ecc_keypair_ops;
4301fa655fcSCedric Neveux 		break;
4311fa655fcSCedric Neveux 	case TEE_TYPE_SM2_DSA_KEYPAIR:
4321fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA))
4331fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
4341fa655fcSCedric Neveux 
4353002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
4361fa655fcSCedric Neveux 		s->ops = &sm2_dsa_keypair_ops;
4371fa655fcSCedric Neveux 		break;
4381fa655fcSCedric Neveux 	case TEE_TYPE_SM2_PKE_KEYPAIR:
4391fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE))
4401fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
4411fa655fcSCedric Neveux 
4423002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
4431fa655fcSCedric Neveux 		s->ops = &sm2_pke_keypair_ops;
4441fa655fcSCedric Neveux 		break;
4451fa655fcSCedric Neveux 	case TEE_TYPE_SM2_KEP_KEYPAIR:
4461fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP))
4471fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
4481fa655fcSCedric Neveux 
4493002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
4501fa655fcSCedric Neveux 		s->ops = &sm2_kep_keypair_ops;
4511fa655fcSCedric Neveux 		break;
4521fa655fcSCedric Neveux 	default:
4531fa655fcSCedric Neveux 		return TEE_ERROR_NOT_IMPLEMENTED;
4541fa655fcSCedric Neveux 	}
4551fa655fcSCedric Neveux 
456b56ad90eSCedric Neveux 	if (!bn_alloc_max(&s->d))
457b56ad90eSCedric Neveux 		goto err;
458b56ad90eSCedric Neveux 	if (!bn_alloc_max(&s->x))
459b56ad90eSCedric Neveux 		goto err;
460b56ad90eSCedric Neveux 	if (!bn_alloc_max(&s->y))
461b56ad90eSCedric Neveux 		goto err;
462b56ad90eSCedric Neveux 
463b56ad90eSCedric Neveux 	return TEE_SUCCESS;
4641fa655fcSCedric Neveux 
465b56ad90eSCedric Neveux err:
4661fa655fcSCedric Neveux 	s->ops = NULL;
4671fa655fcSCedric Neveux 
468b56ad90eSCedric Neveux 	crypto_bignum_free(s->d);
469b56ad90eSCedric Neveux 	crypto_bignum_free(s->x);
4701fa655fcSCedric Neveux 
471b56ad90eSCedric Neveux 	return TEE_ERROR_OUT_OF_MEMORY;
472b56ad90eSCedric Neveux }
473b56ad90eSCedric Neveux 
474*e7971844SJorge Ramirez-Ortiz const struct crypto_ecc_public_ops*
475*e7971844SJorge Ramirez-Ortiz crypto_asym_get_ecc_public_ops(uint32_t key_type)
476*e7971844SJorge Ramirez-Ortiz {
477*e7971844SJorge Ramirez-Ortiz 	switch (key_type) {
478*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_ECDSA_PUBLIC_KEY:
479*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_ECDH_PUBLIC_KEY:
480*e7971844SJorge Ramirez-Ortiz 		return &ecc_public_key_ops;
481*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
482*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA))
483*e7971844SJorge Ramirez-Ortiz 			return NULL;
484*e7971844SJorge Ramirez-Ortiz 		return &sm2_dsa_public_key_ops;
485*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
486*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE))
487*e7971844SJorge Ramirez-Ortiz 			return NULL;
488*e7971844SJorge Ramirez-Ortiz 		return &sm2_pke_public_key_ops;
489*e7971844SJorge Ramirez-Ortiz 	case TEE_TYPE_SM2_KEP_PUBLIC_KEY:
490*e7971844SJorge Ramirez-Ortiz 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP))
491*e7971844SJorge Ramirez-Ortiz 			return NULL;
492*e7971844SJorge Ramirez-Ortiz 		return &sm2_kep_public_key_ops;
493*e7971844SJorge Ramirez-Ortiz 	default:
494*e7971844SJorge Ramirez-Ortiz 		return NULL;
495*e7971844SJorge Ramirez-Ortiz 	}
496*e7971844SJorge Ramirez-Ortiz }
497*e7971844SJorge Ramirez-Ortiz 
498b56ad90eSCedric Neveux TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s,
4991fa655fcSCedric Neveux 					    uint32_t key_type,
500b56ad90eSCedric Neveux 					    size_t key_size_bits __unused)
501b56ad90eSCedric Neveux {
502b56ad90eSCedric Neveux 	memset(s, 0, sizeof(*s));
5031fa655fcSCedric Neveux 
5041fa655fcSCedric Neveux 	switch (key_type) {
5051fa655fcSCedric Neveux 	case TEE_TYPE_ECDSA_PUBLIC_KEY:
5061fa655fcSCedric Neveux 	case TEE_TYPE_ECDH_PUBLIC_KEY:
5071fa655fcSCedric Neveux 		s->ops = &ecc_public_key_ops;
5081fa655fcSCedric Neveux 		break;
5091fa655fcSCedric Neveux 	case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
5101fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA))
5111fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
5121fa655fcSCedric Neveux 
5133002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
5141fa655fcSCedric Neveux 		s->ops = &sm2_dsa_public_key_ops;
5151fa655fcSCedric Neveux 		break;
5161fa655fcSCedric Neveux 	case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
5171fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE))
5181fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
5191fa655fcSCedric Neveux 
5203002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
5211fa655fcSCedric Neveux 		s->ops = &sm2_pke_public_key_ops;
5221fa655fcSCedric Neveux 		break;
5231fa655fcSCedric Neveux 	case TEE_TYPE_SM2_KEP_PUBLIC_KEY:
5241fa655fcSCedric Neveux 		if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP))
5251fa655fcSCedric Neveux 			return TEE_ERROR_NOT_IMPLEMENTED;
5261fa655fcSCedric Neveux 
5273002cbb0SJerome Forissier 		s->curve = TEE_ECC_CURVE_SM2;
5281fa655fcSCedric Neveux 		s->ops = &sm2_kep_public_key_ops;
5291fa655fcSCedric Neveux 		break;
5301fa655fcSCedric Neveux 	default:
5311fa655fcSCedric Neveux 		return TEE_ERROR_NOT_IMPLEMENTED;
5321fa655fcSCedric Neveux 	}
5331fa655fcSCedric Neveux 
534b56ad90eSCedric Neveux 	if (!bn_alloc_max(&s->x))
535b56ad90eSCedric Neveux 		goto err;
536b56ad90eSCedric Neveux 	if (!bn_alloc_max(&s->y))
537b56ad90eSCedric Neveux 		goto err;
538b56ad90eSCedric Neveux 
539b56ad90eSCedric Neveux 	return TEE_SUCCESS;
5401fa655fcSCedric Neveux 
541b56ad90eSCedric Neveux err:
5421fa655fcSCedric Neveux 	s->ops = NULL;
5431fa655fcSCedric Neveux 
544b56ad90eSCedric Neveux 	crypto_bignum_free(s->x);
5451fa655fcSCedric Neveux 
546b56ad90eSCedric Neveux 	return TEE_ERROR_OUT_OF_MEMORY;
547b56ad90eSCedric Neveux }
548