xref: /optee_os/core/lib/libtomcrypt/ecc.c (revision 5a913ee74d3c71af2a2860ce8a4e7aeab2916f9b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014-2019, Linaro Limited
4  */
5 
6 #include <crypto/crypto.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <tee_api_types.h>
10 #include <tomcrypt_private.h>
11 #include <trace.h>
12 #include <utee_defines.h>
13 
14 #include "acipher_helpers.h"
15 
16 TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s,
17 					    size_t key_size_bits __unused)
18 {
19 	memset(s, 0, sizeof(*s));
20 	if (!bn_alloc_max(&s->d))
21 		goto err;
22 	if (!bn_alloc_max(&s->x))
23 		goto err;
24 	if (!bn_alloc_max(&s->y))
25 		goto err;
26 	return TEE_SUCCESS;
27 err:
28 	crypto_bignum_free(s->d);
29 	crypto_bignum_free(s->x);
30 	crypto_bignum_free(s->y);
31 	return TEE_ERROR_OUT_OF_MEMORY;
32 }
33 
34 TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s,
35 					       size_t key_size_bits __unused)
36 {
37 	memset(s, 0, sizeof(*s));
38 	if (!bn_alloc_max(&s->x))
39 		goto err;
40 	if (!bn_alloc_max(&s->y))
41 		goto err;
42 	return TEE_SUCCESS;
43 err:
44 	crypto_bignum_free(s->x);
45 	crypto_bignum_free(s->y);
46 	return TEE_ERROR_OUT_OF_MEMORY;
47 }
48 
49 void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s)
50 {
51 	if (!s)
52 		return;
53 
54 	crypto_bignum_free(s->x);
55 	crypto_bignum_free(s->y);
56 }
57 
58 /*
59  * For a given TEE @curve, return key size and LTC curve name. Also check that
60  * @algo is compatible with this curve.
61  * @curve: TEE_ECC_CURVE_NIST_P192, ...
62  * @algo: TEE_ALG_ECDSA_P192, ...
63  */
64 static TEE_Result ecc_get_curve_info(uint32_t curve, uint32_t algo,
65 				     size_t *key_size_bytes,
66 				     size_t *key_size_bits,
67 				     const char **curve_name)
68 {
69 	size_t size_bytes = 0;
70 	size_t size_bits = 0;
71 	const char *name = NULL;
72 
73 	/*
74 	 * Excerpt of libtomcrypt documentation:
75 	 * ecc_make_key(... key_size ...): The keysize is the size of the
76 	 * modulus in bytes desired. Currently directly supported values
77 	 * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond
78 	 * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits
79 	 * respectively.
80 	 */
81 
82 	/*
83 	 * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET
84 	 * but defines TEE_ALG_ECDH_P192
85 	 */
86 
87 	switch (curve) {
88 	case TEE_ECC_CURVE_NIST_P192:
89 		size_bits = 192;
90 		size_bytes = 24;
91 		name = "NISTP192";
92 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P192) &&
93 		    (algo != TEE_ALG_ECDH_P192))
94 			return TEE_ERROR_BAD_PARAMETERS;
95 		break;
96 	case TEE_ECC_CURVE_NIST_P224:
97 		size_bits = 224;
98 		size_bytes = 28;
99 		name = "NISTP224";
100 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P224) &&
101 		    (algo != TEE_ALG_ECDH_P224))
102 			return TEE_ERROR_BAD_PARAMETERS;
103 		break;
104 	case TEE_ECC_CURVE_NIST_P256:
105 		size_bits = 256;
106 		size_bytes = 32;
107 		name = "NISTP256";
108 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P256) &&
109 		    (algo != TEE_ALG_ECDH_P256))
110 			return TEE_ERROR_BAD_PARAMETERS;
111 		break;
112 	case TEE_ECC_CURVE_NIST_P384:
113 		size_bits = 384;
114 		size_bytes = 48;
115 		name = "NISTP384";
116 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P384) &&
117 		    (algo != TEE_ALG_ECDH_P384))
118 			return TEE_ERROR_BAD_PARAMETERS;
119 		break;
120 	case TEE_ECC_CURVE_NIST_P521:
121 		size_bits = 521;
122 		size_bytes = 66;
123 		name = "NISTP521";
124 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P521) &&
125 		    (algo != TEE_ALG_ECDH_P521))
126 			return TEE_ERROR_BAD_PARAMETERS;
127 		break;
128 	default:
129 		return TEE_ERROR_NOT_SUPPORTED;
130 	}
131 
132 	if (key_size_bytes)
133 		*key_size_bytes = size_bytes;
134 	if (key_size_bits)
135 		*key_size_bits = size_bits;
136 	if (curve_name)
137 		*curve_name = name;
138 	return TEE_SUCCESS;
139 }
140 
141 TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key)
142 {
143 	TEE_Result res;
144 	ecc_key ltc_tmp_key;
145 	int ltc_res;
146 	size_t key_size_bytes = 0;
147 	size_t key_size_bits = 0;
148 
149 	res = ecc_get_curve_info(key->curve, 0, &key_size_bytes, &key_size_bits,
150 				 NULL);
151 	if (res != TEE_SUCCESS)
152 		return res;
153 
154 	/* Generate the ECC key */
155 	ltc_res = ecc_make_key(NULL, find_prng("prng_crypto"),
156 			       key_size_bytes, &ltc_tmp_key);
157 	if (ltc_res != CRYPT_OK)
158 		return TEE_ERROR_BAD_PARAMETERS;
159 
160 	/* check the size of the keys */
161 	if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) ||
162 	    ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) ||
163 	    ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) {
164 		res = TEE_ERROR_BAD_PARAMETERS;
165 		goto exit;
166 	}
167 
168 	/* check LTC is returning z==1 */
169 	if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) {
170 		res = TEE_ERROR_BAD_PARAMETERS;
171 		goto exit;
172 	}
173 
174 	/* Copy the key */
175 	ltc_mp.copy(ltc_tmp_key.k, key->d);
176 	ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x);
177 	ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y);
178 
179 	res = TEE_SUCCESS;
180 
181 exit:
182 	ecc_free(&ltc_tmp_key);		/* Free the temporary key */
183 	return res;
184 }
185 
186 /* Note: this function clears the key before setting the curve */
187 static TEE_Result ecc_set_curve_from_name(ecc_key *ltc_key,
188 					  const char *curve_name)
189 {
190 	const ltc_ecc_curve *curve = NULL;
191 	int ltc_res = 0;
192 
193 	ltc_res = ecc_find_curve(curve_name, &curve);
194 	if (ltc_res != CRYPT_OK)
195 		return TEE_ERROR_NOT_SUPPORTED;
196 
197 	ltc_res = ecc_set_curve(curve, ltc_key);
198 	if (ltc_res != CRYPT_OK)
199 		return TEE_ERROR_GENERIC;
200 
201 	return TEE_SUCCESS;
202 }
203 
204 /*
205  * Given a keypair "key", populate the Libtomcrypt private key "ltc_key"
206  * It also returns the key size, in bytes
207  */
208 static TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key,
209 					       struct ecc_keypair *key,
210 					       uint32_t algo,
211 					       size_t *key_size_bytes)
212 {
213 	TEE_Result res = TEE_ERROR_GENERIC;
214 	const char *name = NULL;
215 
216 	res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name);
217 	if (res)
218 		return res;
219 
220 	memset(ltc_key, 0, sizeof(*ltc_key));
221 
222 	res = ecc_set_curve_from_name(ltc_key, name);
223 	if (res)
224 		return res;
225 
226 	ltc_key->type = PK_PRIVATE;
227 	mp_copy(key->d, ltc_key->k);
228 
229 	return TEE_SUCCESS;
230 }
231 
232 /*
233  * Given a public "key", populate the Libtomcrypt public key "ltc_key"
234  * It also returns the key size, in bytes
235  */
236 static TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key,
237 					      struct ecc_public_key *key,
238 					      uint32_t algo,
239 					      size_t *key_size_bytes)
240 {
241 	TEE_Result res = TEE_ERROR_GENERIC;
242 	const char *name = NULL;
243 	uint8_t one[1] = { 1 };
244 
245 	res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name);
246 	if (res)
247 		return res;
248 
249 	memset(ltc_key, 0, sizeof(*ltc_key));
250 
251 	res = ecc_set_curve_from_name(ltc_key, name);
252 	if (res)
253 		return res;
254 
255 	ltc_key->type = PK_PUBLIC;
256 
257 	mp_copy(key->x, ltc_key->pubkey.x);
258 	mp_copy(key->y, ltc_key->pubkey.y);
259 	mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one));
260 
261 	return TEE_SUCCESS;
262 }
263 
264 TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key,
265 				   const uint8_t *msg, size_t msg_len,
266 				   uint8_t *sig, size_t *sig_len)
267 {
268 	TEE_Result res = TEE_ERROR_GENERIC;
269 	int ltc_res = 0;
270 	size_t key_size_bytes = 0;
271 	ecc_key ltc_key = { };
272 	unsigned long ltc_sig_len = 0;
273 
274 	if (algo == 0)
275 		return TEE_ERROR_BAD_PARAMETERS;
276 
277 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo,
278 					   &key_size_bytes);
279 	if (res != TEE_SUCCESS)
280 		return res;
281 
282 	if (*sig_len < 2 * key_size_bytes) {
283 		*sig_len = 2 * key_size_bytes;
284 		res = TEE_ERROR_SHORT_BUFFER;
285 		goto out;
286 	}
287 
288 	ltc_sig_len = *sig_len;
289 	ltc_res = ecc_sign_hash_rfc7518(msg, msg_len, sig, &ltc_sig_len,
290 				    NULL, find_prng("prng_crypto"), &ltc_key);
291 	if (ltc_res == CRYPT_OK) {
292 		res = TEE_SUCCESS;
293 	} else {
294 		res = TEE_ERROR_GENERIC;
295 	}
296 	*sig_len = ltc_sig_len;
297 
298 out:
299 	ecc_free(&ltc_key);
300 	return res;
301 }
302 
303 TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key,
304 				     const uint8_t *msg, size_t msg_len,
305 				     const uint8_t *sig, size_t sig_len)
306 {
307 	TEE_Result res = TEE_ERROR_GENERIC;
308 	int ltc_stat = 0;
309 	int ltc_res = 0;
310 	size_t key_size_bytes = 0;
311 	ecc_key ltc_key = { };
312 
313 	if (algo == 0)
314 		return TEE_ERROR_BAD_PARAMETERS;
315 
316 	res = ecc_populate_ltc_public_key(&ltc_key, key, algo, &key_size_bytes);
317 	if (res != TEE_SUCCESS)
318 		goto out;
319 
320 	/* check keysize vs sig_len */
321 	if ((key_size_bytes * 2) != sig_len) {
322 		res = TEE_ERROR_BAD_PARAMETERS;
323 		goto out;
324 	}
325 
326 	ltc_res = ecc_verify_hash_rfc7518(sig, sig_len, msg, msg_len, &ltc_stat,
327 					  &ltc_key);
328 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
329 out:
330 	ecc_free(&ltc_key);
331 	return res;
332 }
333 
334 TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key,
335 					    struct ecc_public_key *public_key,
336 					    void *secret,
337 					    unsigned long *secret_len)
338 {
339 	TEE_Result res = TEE_ERROR_GENERIC;
340 	int ltc_res = 0;
341 	ecc_key ltc_private_key = { };
342 	ecc_key ltc_public_key = { };
343 	size_t key_size_bytes = 0;
344 
345 	/* Check the curves are the same */
346 	if (private_key->curve != public_key->curve)
347 		return TEE_ERROR_BAD_PARAMETERS;
348 
349 	res = ecc_populate_ltc_private_key(&ltc_private_key, private_key,
350 					   0, &key_size_bytes);
351 	if (res != TEE_SUCCESS)
352 		goto out;
353 	res = ecc_populate_ltc_public_key(&ltc_public_key, public_key,
354 					  0, &key_size_bytes);
355 	if (res != TEE_SUCCESS)
356 		goto out;
357 
358 	ltc_res = ecc_shared_secret(&ltc_private_key, &ltc_public_key,
359 				    secret, secret_len);
360 	if (ltc_res == CRYPT_OK)
361 		res = TEE_SUCCESS;
362 	else
363 		res = TEE_ERROR_BAD_PARAMETERS;
364 
365 out:
366 	ecc_free(&ltc_private_key);
367 	ecc_free(&ltc_public_key);
368 	return res;
369 }
370