xref: /optee_os/core/lib/libtomcrypt/ecc.c (revision 12484fc76d224d174b691b211fff84265077ff1b)
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.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  * curve is part of TEE_ECC_CURVE_NIST_P192,...
60  * algo is part of TEE_ALG_ECDSA_P192,..., and 0 if we do not have it
61  */
62 static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo,
63 				  size_t *key_size_bytes, size_t *key_size_bits)
64 {
65 	/*
66 	 * Excerpt of libtomcrypt documentation:
67 	 * ecc_make_key(... key_size ...): The keysize is the size of the
68 	 * modulus in bytes desired. Currently directly supported values
69 	 * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond
70 	 * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits
71 	 * respectively.
72 	 */
73 
74 	/*
75 	 * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET
76 	 * but defines TEE_ALG_ECDH_P192
77 	 */
78 
79 	switch (curve) {
80 	case TEE_ECC_CURVE_NIST_P192:
81 		*key_size_bits = 192;
82 		*key_size_bytes = 24;
83 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P192) &&
84 		    (algo != TEE_ALG_ECDH_P192))
85 			return TEE_ERROR_BAD_PARAMETERS;
86 		break;
87 	case TEE_ECC_CURVE_NIST_P224:
88 		*key_size_bits = 224;
89 		*key_size_bytes = 28;
90 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P224) &&
91 		    (algo != TEE_ALG_ECDH_P224))
92 			return TEE_ERROR_BAD_PARAMETERS;
93 		break;
94 	case TEE_ECC_CURVE_NIST_P256:
95 		*key_size_bits = 256;
96 		*key_size_bytes = 32;
97 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P256) &&
98 		    (algo != TEE_ALG_ECDH_P256))
99 			return TEE_ERROR_BAD_PARAMETERS;
100 		break;
101 	case TEE_ECC_CURVE_NIST_P384:
102 		*key_size_bits = 384;
103 		*key_size_bytes = 48;
104 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P384) &&
105 		    (algo != TEE_ALG_ECDH_P384))
106 			return TEE_ERROR_BAD_PARAMETERS;
107 		break;
108 	case TEE_ECC_CURVE_NIST_P521:
109 		*key_size_bits = 521;
110 		/*
111 		 * set 66 instead of 65 wrt to Libtomcrypt documentation as
112 		 * if it the real key size
113 		 */
114 		*key_size_bytes = 66;
115 		if ((algo != 0) && (algo != TEE_ALG_ECDSA_P521) &&
116 		    (algo != TEE_ALG_ECDH_P521))
117 			return TEE_ERROR_BAD_PARAMETERS;
118 		break;
119 	default:
120 		*key_size_bits = 0;
121 		*key_size_bytes = 0;
122 		return TEE_ERROR_NOT_SUPPORTED;
123 	}
124 
125 	return TEE_SUCCESS;
126 }
127 
128 TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key)
129 {
130 	TEE_Result res;
131 	ecc_key ltc_tmp_key;
132 	int ltc_res;
133 	size_t key_size_bytes = 0;
134 	size_t key_size_bits = 0;
135 
136 	res = ecc_get_keysize(key->curve, 0, &key_size_bytes, &key_size_bits);
137 	if (res != TEE_SUCCESS)
138 		return res;
139 
140 	/* Generate the ECC key */
141 	ltc_res = ecc_make_key(NULL, find_prng("prng_crypto"),
142 			       key_size_bytes, &ltc_tmp_key);
143 	if (ltc_res != CRYPT_OK)
144 		return TEE_ERROR_BAD_PARAMETERS;
145 
146 	/* check the size of the keys */
147 	if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) ||
148 	    ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) ||
149 	    ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) {
150 		res = TEE_ERROR_BAD_PARAMETERS;
151 		goto exit;
152 	}
153 
154 	/* check LTC is returning z==1 */
155 	if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) {
156 		res = TEE_ERROR_BAD_PARAMETERS;
157 		goto exit;
158 	}
159 
160 	/* Copy the key */
161 	ltc_mp.copy(ltc_tmp_key.k, key->d);
162 	ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x);
163 	ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y);
164 
165 	res = TEE_SUCCESS;
166 
167 exit:
168 	ecc_free(&ltc_tmp_key);		/* Free the temporary key */
169 	return res;
170 }
171 
172 static TEE_Result ecc_compute_key_idx(ecc_key *ltc_key, size_t keysize)
173 {
174 	size_t x;
175 
176 	for (x = 0; ((int)keysize > ltc_ecc_sets[x].size) &&
177 		    (ltc_ecc_sets[x].size != 0);
178 	     x++)
179 		;
180 	keysize = (size_t)ltc_ecc_sets[x].size;
181 
182 	if ((keysize > ECC_MAXSIZE) || (ltc_ecc_sets[x].size == 0))
183 		return TEE_ERROR_BAD_PARAMETERS;
184 
185 	ltc_key->idx = -1;
186 	ltc_key->dp  = &ltc_ecc_sets[x];
187 
188 	return TEE_SUCCESS;
189 }
190 
191 /*
192  * Given a keypair "key", populate the Libtomcrypt private key "ltc_key"
193  * It also returns the key size, in bytes
194  */
195 static TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key,
196 					       struct ecc_keypair *key,
197 					       uint32_t algo,
198 					       size_t *key_size_bytes)
199 {
200 	TEE_Result res;
201 	size_t key_size_bits;
202 
203 	memset(ltc_key, 0, sizeof(*ltc_key));
204 	ltc_key->type = PK_PRIVATE;
205 	ltc_key->k = key->d;
206 
207 	/* compute the index of the ecc curve */
208 	res = ecc_get_keysize(key->curve, algo,
209 			      key_size_bytes, &key_size_bits);
210 	if (res != TEE_SUCCESS)
211 		return res;
212 
213 	return ecc_compute_key_idx(ltc_key, *key_size_bytes);
214 }
215 
216 /*
217  * Given a public "key", populate the Libtomcrypt public key "ltc_key"
218  * It also returns the key size, in bytes
219  */
220 static TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key,
221 					      struct ecc_public_key *key,
222 					      void *key_z,
223 					      uint32_t algo,
224 					      size_t *key_size_bytes)
225 {
226 	TEE_Result res;
227 	size_t key_size_bits;
228 	uint8_t one[1] = { 1 };
229 
230 
231 	memset(ltc_key, 0, sizeof(*ltc_key));
232 	ltc_key->type = PK_PUBLIC;
233 	ltc_key->pubkey.x = key->x;
234 	ltc_key->pubkey.y = key->y;
235 	ltc_key->pubkey.z = key_z;
236 	mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one));
237 
238 	/* compute the index of the ecc curve */
239 	res = ecc_get_keysize(key->curve, algo,
240 			      key_size_bytes, &key_size_bits);
241 	if (res != TEE_SUCCESS)
242 		return res;
243 
244 	return ecc_compute_key_idx(ltc_key, *key_size_bytes);
245 }
246 
247 TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key,
248 				   const uint8_t *msg, size_t msg_len,
249 				   uint8_t *sig, size_t *sig_len)
250 {
251 	TEE_Result res;
252 	int ltc_res;
253 	void *r, *s;
254 	size_t key_size_bytes;
255 	ecc_key ltc_key;
256 
257 	if (algo == 0) {
258 		res = TEE_ERROR_BAD_PARAMETERS;
259 		goto err;
260 	}
261 
262 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo,
263 					   &key_size_bytes);
264 	if (res != TEE_SUCCESS)
265 		goto err;
266 
267 	if (*sig_len < 2 * key_size_bytes) {
268 		*sig_len = 2 * key_size_bytes;
269 		res = TEE_ERROR_SHORT_BUFFER;
270 		goto err;
271 	}
272 
273 	ltc_res = mp_init_multi(&r, &s, NULL);
274 	if (ltc_res != CRYPT_OK) {
275 		res = TEE_ERROR_OUT_OF_MEMORY;
276 		goto err;
277 	}
278 
279 	ltc_res = ecc_sign_hash_raw(msg, msg_len, r, s,
280 				    NULL, find_prng("prng_crypto"), &ltc_key);
281 
282 	if (ltc_res == CRYPT_OK) {
283 		*sig_len = 2 * key_size_bytes;
284 		memset(sig, 0, *sig_len);
285 		mp_to_unsigned_bin(r, (uint8_t *)sig + *sig_len/2 -
286 				   mp_unsigned_bin_size(r));
287 		mp_to_unsigned_bin(s, (uint8_t *)sig + *sig_len -
288 				   mp_unsigned_bin_size(s));
289 		res = TEE_SUCCESS;
290 	} else {
291 		res = TEE_ERROR_GENERIC;
292 	}
293 
294 	mp_clear_multi(r, s, NULL);
295 
296 err:
297 	return res;
298 }
299 
300 TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key,
301 				     const uint8_t *msg, size_t msg_len,
302 				     const uint8_t *sig, size_t sig_len)
303 {
304 	TEE_Result res;
305 	int ltc_stat;
306 	int ltc_res;
307 	void *r;
308 	void *s;
309 	void *key_z;
310 	size_t key_size_bytes;
311 	ecc_key ltc_key;
312 
313 	if (algo == 0)
314 		return TEE_ERROR_BAD_PARAMETERS;
315 
316 	ltc_res = mp_init_multi(&key_z, &r, &s, NULL);
317 	if (ltc_res != CRYPT_OK)
318 		return TEE_ERROR_OUT_OF_MEMORY;
319 
320 	res = ecc_populate_ltc_public_key(&ltc_key, key, key_z, algo,
321 					  &key_size_bytes);
322 	if (res != TEE_SUCCESS)
323 		goto out;
324 
325 	/* check keysize vs sig_len */
326 	if ((key_size_bytes * 2) != sig_len) {
327 		res = TEE_ERROR_BAD_PARAMETERS;
328 		goto out;
329 	}
330 
331 	mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2);
332 	mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2);
333 
334 	ltc_res = ecc_verify_hash_raw(r, s, msg, msg_len, &ltc_stat, &ltc_key);
335 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
336 out:
337 	mp_clear_multi(key_z, r, s, NULL);
338 	return res;
339 }
340 
341 TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key,
342 					    struct ecc_public_key *public_key,
343 					    void *secret,
344 					    unsigned long *secret_len)
345 {
346 	TEE_Result res;
347 	int ltc_res;
348 	ecc_key ltc_private_key;
349 	ecc_key ltc_public_key;
350 	size_t key_size_bytes;
351 	void *key_z;
352 
353 	/* Check the curves are the same */
354 	if (private_key->curve != public_key->curve)
355 		return TEE_ERROR_BAD_PARAMETERS;
356 
357 	ltc_res = mp_init_multi(&key_z, NULL);
358 	if (ltc_res != CRYPT_OK)
359 		return TEE_ERROR_OUT_OF_MEMORY;
360 
361 	res = ecc_populate_ltc_private_key(&ltc_private_key, private_key,
362 					   0, &key_size_bytes);
363 	if (res != TEE_SUCCESS)
364 		goto out;
365 	res = ecc_populate_ltc_public_key(&ltc_public_key, public_key, key_z,
366 					  0, &key_size_bytes);
367 	if (res != TEE_SUCCESS)
368 		goto out;
369 
370 	ltc_res = ecc_shared_secret(&ltc_private_key, &ltc_public_key,
371 				    secret, secret_len);
372 	if (ltc_res == CRYPT_OK)
373 		res = TEE_SUCCESS;
374 	else
375 		res = TEE_ERROR_BAD_PARAMETERS;
376 
377 out:
378 	mp_clear_multi(key_z, NULL);
379 	return res;
380 }
381