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