xref: /optee_os/core/lib/libtomcrypt/ecc.c (revision 1f3b11151257f0984bf32070f56b542e58b788a0)
16644e2f0SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
26644e2f0SJens Wiklander /*
36644e2f0SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
46644e2f0SJens Wiklander  */
56644e2f0SJens Wiklander 
66644e2f0SJens Wiklander #include <crypto/crypto.h>
76644e2f0SJens Wiklander #include <stdlib.h>
86644e2f0SJens Wiklander #include <string.h>
96644e2f0SJens Wiklander #include <tee_api_types.h>
106644e2f0SJens Wiklander #include <tomcrypt.h>
116644e2f0SJens Wiklander #include <trace.h>
126644e2f0SJens Wiklander #include <utee_defines.h>
136644e2f0SJens Wiklander 
146644e2f0SJens Wiklander #include "acipher_helpers.h"
156644e2f0SJens Wiklander 
166644e2f0SJens Wiklander TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s,
176644e2f0SJens Wiklander 					    size_t key_size_bits __unused)
186644e2f0SJens Wiklander {
196644e2f0SJens Wiklander 	memset(s, 0, sizeof(*s));
206644e2f0SJens Wiklander 	if (!bn_alloc_max(&s->d))
216644e2f0SJens Wiklander 		goto err;
226644e2f0SJens Wiklander 	if (!bn_alloc_max(&s->x))
236644e2f0SJens Wiklander 		goto err;
246644e2f0SJens Wiklander 	if (!bn_alloc_max(&s->y))
256644e2f0SJens Wiklander 		goto err;
266644e2f0SJens Wiklander 	return TEE_SUCCESS;
276644e2f0SJens Wiklander err:
286644e2f0SJens Wiklander 	crypto_bignum_free(s->d);
296644e2f0SJens Wiklander 	crypto_bignum_free(s->x);
306644e2f0SJens Wiklander 	crypto_bignum_free(s->y);
316644e2f0SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
326644e2f0SJens Wiklander }
336644e2f0SJens Wiklander 
346644e2f0SJens Wiklander TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s,
356644e2f0SJens Wiklander 					       size_t key_size_bits __unused)
366644e2f0SJens Wiklander {
376644e2f0SJens Wiklander 	memset(s, 0, sizeof(*s));
386644e2f0SJens Wiklander 	if (!bn_alloc_max(&s->x))
396644e2f0SJens Wiklander 		goto err;
406644e2f0SJens Wiklander 	if (!bn_alloc_max(&s->y))
416644e2f0SJens Wiklander 		goto err;
426644e2f0SJens Wiklander 	return TEE_SUCCESS;
436644e2f0SJens Wiklander err:
446644e2f0SJens Wiklander 	crypto_bignum_free(s->x);
456644e2f0SJens Wiklander 	crypto_bignum_free(s->y);
466644e2f0SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
476644e2f0SJens Wiklander }
486644e2f0SJens Wiklander 
496644e2f0SJens Wiklander void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s)
506644e2f0SJens Wiklander {
516644e2f0SJens Wiklander 	if (!s)
526644e2f0SJens Wiklander 		return;
536644e2f0SJens Wiklander 
546644e2f0SJens Wiklander 	crypto_bignum_free(s->x);
556644e2f0SJens Wiklander 	crypto_bignum_free(s->y);
566644e2f0SJens Wiklander }
576644e2f0SJens Wiklander 
586644e2f0SJens Wiklander /*
596644e2f0SJens Wiklander  * curve is part of TEE_ECC_CURVE_NIST_P192,...
606644e2f0SJens Wiklander  * algo is part of TEE_ALG_ECDSA_P192,..., and 0 if we do not have it
616644e2f0SJens Wiklander  */
626644e2f0SJens Wiklander static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo,
636644e2f0SJens Wiklander 				  size_t *key_size_bytes, size_t *key_size_bits)
646644e2f0SJens Wiklander {
656644e2f0SJens Wiklander 	/*
666644e2f0SJens Wiklander 	 * Excerpt of libtomcrypt documentation:
676644e2f0SJens Wiklander 	 * ecc_make_key(... key_size ...): The keysize is the size of the
686644e2f0SJens Wiklander 	 * modulus in bytes desired. Currently directly supported values
696644e2f0SJens Wiklander 	 * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond
706644e2f0SJens Wiklander 	 * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits
716644e2f0SJens Wiklander 	 * respectively.
726644e2f0SJens Wiklander 	 */
736644e2f0SJens Wiklander 
746644e2f0SJens Wiklander 	/*
756644e2f0SJens Wiklander 	 * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET
766644e2f0SJens Wiklander 	 * but defines TEE_ALG_ECDH_P192
776644e2f0SJens Wiklander 	 */
786644e2f0SJens Wiklander 
796644e2f0SJens Wiklander 	switch (curve) {
806644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P192:
816644e2f0SJens Wiklander 		*key_size_bits = 192;
826644e2f0SJens Wiklander 		*key_size_bytes = 24;
836644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P192) &&
846644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P192))
856644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
866644e2f0SJens Wiklander 		break;
876644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P224:
886644e2f0SJens Wiklander 		*key_size_bits = 224;
896644e2f0SJens Wiklander 		*key_size_bytes = 28;
906644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P224) &&
916644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P224))
926644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
936644e2f0SJens Wiklander 		break;
946644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P256:
956644e2f0SJens Wiklander 		*key_size_bits = 256;
966644e2f0SJens Wiklander 		*key_size_bytes = 32;
976644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P256) &&
986644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P256))
996644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
1006644e2f0SJens Wiklander 		break;
1016644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P384:
1026644e2f0SJens Wiklander 		*key_size_bits = 384;
1036644e2f0SJens Wiklander 		*key_size_bytes = 48;
1046644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P384) &&
1056644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P384))
1066644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
1076644e2f0SJens Wiklander 		break;
1086644e2f0SJens Wiklander 	case TEE_ECC_CURVE_NIST_P521:
1096644e2f0SJens Wiklander 		*key_size_bits = 521;
1106644e2f0SJens Wiklander 		/*
1116644e2f0SJens Wiklander 		 * set 66 instead of 65 wrt to Libtomcrypt documentation as
1126644e2f0SJens Wiklander 		 * if it the real key size
1136644e2f0SJens Wiklander 		 */
1146644e2f0SJens Wiklander 		*key_size_bytes = 66;
1156644e2f0SJens Wiklander 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P521) &&
1166644e2f0SJens Wiklander 		    (algo != TEE_ALG_ECDH_P521))
1176644e2f0SJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
1186644e2f0SJens Wiklander 		break;
1196644e2f0SJens Wiklander 	default:
1206644e2f0SJens Wiklander 		*key_size_bits = 0;
1216644e2f0SJens Wiklander 		*key_size_bytes = 0;
1226644e2f0SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
1236644e2f0SJens Wiklander 	}
1246644e2f0SJens Wiklander 
1256644e2f0SJens Wiklander 	return TEE_SUCCESS;
1266644e2f0SJens Wiklander }
1276644e2f0SJens Wiklander 
1286644e2f0SJens Wiklander TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key)
1296644e2f0SJens Wiklander {
1306644e2f0SJens Wiklander 	TEE_Result res;
1316644e2f0SJens Wiklander 	ecc_key ltc_tmp_key;
1326644e2f0SJens Wiklander 	int ltc_res;
1336644e2f0SJens Wiklander 	size_t key_size_bytes = 0;
1346644e2f0SJens Wiklander 	size_t key_size_bits = 0;
1356644e2f0SJens Wiklander 
1366644e2f0SJens Wiklander 	res = ecc_get_keysize(key->curve, 0, &key_size_bytes, &key_size_bits);
1376644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
1386644e2f0SJens Wiklander 		return res;
1396644e2f0SJens Wiklander 
1406644e2f0SJens Wiklander 	/* Generate the ECC key */
141*1f3b1115SJens Wiklander 	ltc_res = ecc_make_key(NULL, find_prng("prng_crypto"),
1426644e2f0SJens Wiklander 			       key_size_bytes, &ltc_tmp_key);
1436644e2f0SJens Wiklander 	if (ltc_res != CRYPT_OK)
1446644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
1456644e2f0SJens Wiklander 
1466644e2f0SJens Wiklander 	/* check the size of the keys */
1476644e2f0SJens Wiklander 	if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) ||
1486644e2f0SJens Wiklander 	    ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) ||
1496644e2f0SJens Wiklander 	    ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) {
1506644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1516644e2f0SJens Wiklander 		goto exit;
1526644e2f0SJens Wiklander 	}
1536644e2f0SJens Wiklander 
1546644e2f0SJens Wiklander 	/* check LTC is returning z==1 */
1556644e2f0SJens Wiklander 	if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) {
1566644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1576644e2f0SJens Wiklander 		goto exit;
1586644e2f0SJens Wiklander 	}
1596644e2f0SJens Wiklander 
1606644e2f0SJens Wiklander 	/* Copy the key */
1616644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.k, key->d);
1626644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x);
1636644e2f0SJens Wiklander 	ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y);
1646644e2f0SJens Wiklander 
1656644e2f0SJens Wiklander 	res = TEE_SUCCESS;
1666644e2f0SJens Wiklander 
1676644e2f0SJens Wiklander exit:
1686644e2f0SJens Wiklander 	ecc_free(&ltc_tmp_key);		/* Free the temporary key */
1696644e2f0SJens Wiklander 	return res;
1706644e2f0SJens Wiklander }
1716644e2f0SJens Wiklander 
1726644e2f0SJens Wiklander static TEE_Result ecc_compute_key_idx(ecc_key *ltc_key, size_t keysize)
1736644e2f0SJens Wiklander {
1746644e2f0SJens Wiklander 	size_t x;
1756644e2f0SJens Wiklander 
1766644e2f0SJens Wiklander 	for (x = 0; ((int)keysize > ltc_ecc_sets[x].size) &&
1776644e2f0SJens Wiklander 		    (ltc_ecc_sets[x].size != 0);
1786644e2f0SJens Wiklander 	     x++)
1796644e2f0SJens Wiklander 		;
1806644e2f0SJens Wiklander 	keysize = (size_t)ltc_ecc_sets[x].size;
1816644e2f0SJens Wiklander 
1826644e2f0SJens Wiklander 	if ((keysize > ECC_MAXSIZE) || (ltc_ecc_sets[x].size == 0))
1836644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
1846644e2f0SJens Wiklander 
1856644e2f0SJens Wiklander 	ltc_key->idx = -1;
1866644e2f0SJens Wiklander 	ltc_key->dp  = &ltc_ecc_sets[x];
1876644e2f0SJens Wiklander 
1886644e2f0SJens Wiklander 	return TEE_SUCCESS;
1896644e2f0SJens Wiklander }
1906644e2f0SJens Wiklander 
1916644e2f0SJens Wiklander /*
1926644e2f0SJens Wiklander  * Given a keypair "key", populate the Libtomcrypt private key "ltc_key"
1936644e2f0SJens Wiklander  * It also returns the key size, in bytes
1946644e2f0SJens Wiklander  */
1956644e2f0SJens Wiklander static TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key,
1966644e2f0SJens Wiklander 					       struct ecc_keypair *key,
1976644e2f0SJens Wiklander 					       uint32_t algo,
1986644e2f0SJens Wiklander 					       size_t *key_size_bytes)
1996644e2f0SJens Wiklander {
2006644e2f0SJens Wiklander 	TEE_Result res;
2016644e2f0SJens Wiklander 	size_t key_size_bits;
2026644e2f0SJens Wiklander 
2036644e2f0SJens Wiklander 	memset(ltc_key, 0, sizeof(*ltc_key));
2046644e2f0SJens Wiklander 	ltc_key->type = PK_PRIVATE;
2056644e2f0SJens Wiklander 	ltc_key->k = key->d;
2066644e2f0SJens Wiklander 
2076644e2f0SJens Wiklander 	/* compute the index of the ecc curve */
2086644e2f0SJens Wiklander 	res = ecc_get_keysize(key->curve, algo,
2096644e2f0SJens Wiklander 			      key_size_bytes, &key_size_bits);
2106644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
2116644e2f0SJens Wiklander 		return res;
2126644e2f0SJens Wiklander 
2136644e2f0SJens Wiklander 	return ecc_compute_key_idx(ltc_key, *key_size_bytes);
2146644e2f0SJens Wiklander }
2156644e2f0SJens Wiklander 
2166644e2f0SJens Wiklander /*
2176644e2f0SJens Wiklander  * Given a public "key", populate the Libtomcrypt public key "ltc_key"
2186644e2f0SJens Wiklander  * It also returns the key size, in bytes
2196644e2f0SJens Wiklander  */
2206644e2f0SJens Wiklander static TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key,
2216644e2f0SJens Wiklander 					      struct ecc_public_key *key,
2226644e2f0SJens Wiklander 					      void *key_z,
2236644e2f0SJens Wiklander 					      uint32_t algo,
2246644e2f0SJens Wiklander 					      size_t *key_size_bytes)
2256644e2f0SJens Wiklander {
2266644e2f0SJens Wiklander 	TEE_Result res;
2276644e2f0SJens Wiklander 	size_t key_size_bits;
2286644e2f0SJens Wiklander 	uint8_t one[1] = { 1 };
2296644e2f0SJens Wiklander 
2306644e2f0SJens Wiklander 
2316644e2f0SJens Wiklander 	memset(ltc_key, 0, sizeof(*ltc_key));
2326644e2f0SJens Wiklander 	ltc_key->type = PK_PUBLIC;
2336644e2f0SJens Wiklander 	ltc_key->pubkey.x = key->x;
2346644e2f0SJens Wiklander 	ltc_key->pubkey.y = key->y;
2356644e2f0SJens Wiklander 	ltc_key->pubkey.z = key_z;
2366644e2f0SJens Wiklander 	mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one));
2376644e2f0SJens Wiklander 
2386644e2f0SJens Wiklander 	/* compute the index of the ecc curve */
2396644e2f0SJens Wiklander 	res = ecc_get_keysize(key->curve, algo,
2406644e2f0SJens Wiklander 			      key_size_bytes, &key_size_bits);
2416644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
2426644e2f0SJens Wiklander 		return res;
2436644e2f0SJens Wiklander 
2446644e2f0SJens Wiklander 	return ecc_compute_key_idx(ltc_key, *key_size_bytes);
2456644e2f0SJens Wiklander }
2466644e2f0SJens Wiklander 
2476644e2f0SJens Wiklander TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key,
2486644e2f0SJens Wiklander 				   const uint8_t *msg, size_t msg_len,
2496644e2f0SJens Wiklander 				   uint8_t *sig, size_t *sig_len)
2506644e2f0SJens Wiklander {
2516644e2f0SJens Wiklander 	TEE_Result res;
2526644e2f0SJens Wiklander 	int ltc_res;
2536644e2f0SJens Wiklander 	void *r, *s;
2546644e2f0SJens Wiklander 	size_t key_size_bytes;
2556644e2f0SJens Wiklander 	ecc_key ltc_key;
2566644e2f0SJens Wiklander 
2576644e2f0SJens Wiklander 	if (algo == 0) {
2586644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
2596644e2f0SJens Wiklander 		goto err;
2606644e2f0SJens Wiklander 	}
2616644e2f0SJens Wiklander 
2626644e2f0SJens Wiklander 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo,
2636644e2f0SJens Wiklander 					   &key_size_bytes);
2646644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
2656644e2f0SJens Wiklander 		goto err;
2666644e2f0SJens Wiklander 
2676644e2f0SJens Wiklander 	if (*sig_len < 2 * key_size_bytes) {
2686644e2f0SJens Wiklander 		*sig_len = 2 * key_size_bytes;
2696644e2f0SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
2706644e2f0SJens Wiklander 		goto err;
2716644e2f0SJens Wiklander 	}
2726644e2f0SJens Wiklander 
2736644e2f0SJens Wiklander 	ltc_res = mp_init_multi(&r, &s, NULL);
2746644e2f0SJens Wiklander 	if (ltc_res != CRYPT_OK) {
2756644e2f0SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
2766644e2f0SJens Wiklander 		goto err;
2776644e2f0SJens Wiklander 	}
2786644e2f0SJens Wiklander 
2796644e2f0SJens Wiklander 	ltc_res = ecc_sign_hash_raw(msg, msg_len, r, s,
280*1f3b1115SJens Wiklander 				    NULL, find_prng("prng_crypto"), &ltc_key);
2816644e2f0SJens Wiklander 
2826644e2f0SJens Wiklander 	if (ltc_res == CRYPT_OK) {
2836644e2f0SJens Wiklander 		*sig_len = 2 * key_size_bytes;
2846644e2f0SJens Wiklander 		memset(sig, 0, *sig_len);
2856644e2f0SJens Wiklander 		mp_to_unsigned_bin(r, (uint8_t *)sig + *sig_len/2 -
2866644e2f0SJens Wiklander 				   mp_unsigned_bin_size(r));
2876644e2f0SJens Wiklander 		mp_to_unsigned_bin(s, (uint8_t *)sig + *sig_len -
2886644e2f0SJens Wiklander 				   mp_unsigned_bin_size(s));
2896644e2f0SJens Wiklander 		res = TEE_SUCCESS;
2906644e2f0SJens Wiklander 	} else {
2916644e2f0SJens Wiklander 		res = TEE_ERROR_GENERIC;
2926644e2f0SJens Wiklander 	}
2936644e2f0SJens Wiklander 
2946644e2f0SJens Wiklander 	mp_clear_multi(r, s, NULL);
2956644e2f0SJens Wiklander 
2966644e2f0SJens Wiklander err:
2976644e2f0SJens Wiklander 	return res;
2986644e2f0SJens Wiklander }
2996644e2f0SJens Wiklander 
3006644e2f0SJens Wiklander TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key,
3016644e2f0SJens Wiklander 				     const uint8_t *msg, size_t msg_len,
3026644e2f0SJens Wiklander 				     const uint8_t *sig, size_t sig_len)
3036644e2f0SJens Wiklander {
3046644e2f0SJens Wiklander 	TEE_Result res;
3056644e2f0SJens Wiklander 	int ltc_stat;
3066644e2f0SJens Wiklander 	int ltc_res;
3076644e2f0SJens Wiklander 	void *r;
3086644e2f0SJens Wiklander 	void *s;
3096644e2f0SJens Wiklander 	void *key_z;
3106644e2f0SJens Wiklander 	size_t key_size_bytes;
3116644e2f0SJens Wiklander 	ecc_key ltc_key;
3126644e2f0SJens Wiklander 
3136644e2f0SJens Wiklander 	if (algo == 0)
3146644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
3156644e2f0SJens Wiklander 
3166644e2f0SJens Wiklander 	ltc_res = mp_init_multi(&key_z, &r, &s, NULL);
3176644e2f0SJens Wiklander 	if (ltc_res != CRYPT_OK)
3186644e2f0SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
3196644e2f0SJens Wiklander 
3206644e2f0SJens Wiklander 	res = ecc_populate_ltc_public_key(&ltc_key, key, key_z, algo,
3216644e2f0SJens Wiklander 					  &key_size_bytes);
3226644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3236644e2f0SJens Wiklander 		goto out;
3246644e2f0SJens Wiklander 
3256644e2f0SJens Wiklander 	/* check keysize vs sig_len */
3266644e2f0SJens Wiklander 	if ((key_size_bytes * 2) != sig_len) {
3276644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
3286644e2f0SJens Wiklander 		goto out;
3296644e2f0SJens Wiklander 	}
3306644e2f0SJens Wiklander 
3316644e2f0SJens Wiklander 	mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2);
3326644e2f0SJens Wiklander 	mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2);
3336644e2f0SJens Wiklander 
3346644e2f0SJens Wiklander 	ltc_res = ecc_verify_hash_raw(r, s, msg, msg_len, &ltc_stat, &ltc_key);
3356644e2f0SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
3366644e2f0SJens Wiklander out:
3376644e2f0SJens Wiklander 	mp_clear_multi(key_z, r, s, NULL);
3386644e2f0SJens Wiklander 	return res;
3396644e2f0SJens Wiklander }
3406644e2f0SJens Wiklander 
3416644e2f0SJens Wiklander TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key,
3426644e2f0SJens Wiklander 					    struct ecc_public_key *public_key,
3436644e2f0SJens Wiklander 					    void *secret,
3446644e2f0SJens Wiklander 					    unsigned long *secret_len)
3456644e2f0SJens Wiklander {
3466644e2f0SJens Wiklander 	TEE_Result res;
3476644e2f0SJens Wiklander 	int ltc_res;
3486644e2f0SJens Wiklander 	ecc_key ltc_private_key;
3496644e2f0SJens Wiklander 	ecc_key ltc_public_key;
3506644e2f0SJens Wiklander 	size_t key_size_bytes;
3516644e2f0SJens Wiklander 	void *key_z;
3526644e2f0SJens Wiklander 
3536644e2f0SJens Wiklander 	/* Check the curves are the same */
3546644e2f0SJens Wiklander 	if (private_key->curve != public_key->curve)
3556644e2f0SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
3566644e2f0SJens Wiklander 
3576644e2f0SJens Wiklander 	ltc_res = mp_init_multi(&key_z, NULL);
3586644e2f0SJens Wiklander 	if (ltc_res != CRYPT_OK)
3596644e2f0SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
3606644e2f0SJens Wiklander 
3616644e2f0SJens Wiklander 	res = ecc_populate_ltc_private_key(&ltc_private_key, private_key,
3626644e2f0SJens Wiklander 					   0, &key_size_bytes);
3636644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3646644e2f0SJens Wiklander 		goto out;
3656644e2f0SJens Wiklander 	res = ecc_populate_ltc_public_key(&ltc_public_key, public_key, key_z,
3666644e2f0SJens Wiklander 					  0, &key_size_bytes);
3676644e2f0SJens Wiklander 	if (res != TEE_SUCCESS)
3686644e2f0SJens Wiklander 		goto out;
3696644e2f0SJens Wiklander 
3706644e2f0SJens Wiklander 	ltc_res = ecc_shared_secret(&ltc_private_key, &ltc_public_key,
3716644e2f0SJens Wiklander 				    secret, secret_len);
3726644e2f0SJens Wiklander 	if (ltc_res == CRYPT_OK)
3736644e2f0SJens Wiklander 		res = TEE_SUCCESS;
3746644e2f0SJens Wiklander 	else
3756644e2f0SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
3766644e2f0SJens Wiklander 
3776644e2f0SJens Wiklander out:
3786644e2f0SJens Wiklander 	mp_clear_multi(key_z, NULL);
3796644e2f0SJens Wiklander 	return res;
3806644e2f0SJens Wiklander }
381