xref: /optee_os/core/drivers/crypto/versal/ecc.c (revision e2ec831cb07ed0099535c7c140cb6338aa62816a)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) Foundries Ltd. 2022.
4  * Author: Jorge Ramirez <jorge@foundries.io>
5  */
6 
7 #include <drvcrypt.h>
8 #include <drvcrypt_acipher.h>
9 #include <crypto/crypto_impl.h>
10 #include <initcall.h>
11 #include <ipi.h>
12 #include <kernel/panic.h>
13 #include <mm/core_memprot.h>
14 #include <string.h>
15 #include <tee/cache.h>
16 #include <tee/tee_cryp_utl.h>
17 #include <util.h>
18 
19 /* AMD/Xilinx Versal's Known Answer Tests */
20 #define XSECURE_ECDSA_KAT_NIST_P384	0
21 #define XSECURE_ECDSA_KAT_NIST_P521	2
22 
23 /* Software based ECDSA operations */
24 static const struct crypto_ecc_keypair_ops *pair_ops;
25 static const struct crypto_ecc_public_ops *pub_ops;
26 
27 enum versal_ecc_err {
28 	KAT_KEY_NOTVALID_ERROR = 0xC0,
29 	KAT_FAILED_ERROR,
30 	NON_SUPPORTED_CURVE,
31 	KEY_ZERO,
32 	KEY_WRONG_ORDER,
33 	KEY_NOT_ON_CURVE,
34 	BAD_SIGN,
35 	GEN_SIGN_INCORRECT_HASH_LEN,
36 	VER_SIGN_INCORRECT_HASH_LEN,
37 	GEN_SIGN_BAD_RAND_NUM,
38 	GEN_KEY_ERR,
39 	INVALID_PARAM,
40 	VER_SIGN_R_ZERO,
41 	VER_SIGN_S_ZERO,
42 	VER_SIGN_R_ORDER_ERROR,
43 	VER_SIGN_S_ORDER_ERROR,
44 	KAT_INVLD_CRV_ERROR,
45 };
46 
47 #define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) }
48 
versal_ecc_error(uint8_t err)49 static const char *versal_ecc_error(uint8_t err)
50 {
51 	struct {
52 		enum versal_ecc_err error;
53 		const char *name;
54 	} elist[] = {
55 		VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR),
56 		VERSAL_ECC_ERROR(KAT_FAILED_ERROR),
57 		VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE),
58 		VERSAL_ECC_ERROR(KEY_ZERO),
59 		VERSAL_ECC_ERROR(KEY_WRONG_ORDER),
60 		VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE),
61 		VERSAL_ECC_ERROR(BAD_SIGN),
62 		VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN),
63 		VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN),
64 		VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM),
65 		VERSAL_ECC_ERROR(GEN_KEY_ERR),
66 		VERSAL_ECC_ERROR(INVALID_PARAM),
67 		VERSAL_ECC_ERROR(VER_SIGN_R_ZERO),
68 		VERSAL_ECC_ERROR(VER_SIGN_S_ZERO),
69 		VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR),
70 		VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR),
71 		VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR),
72 	};
73 
74 	if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) {
75 		if (elist[err - KAT_KEY_NOTVALID_ERROR].name)
76 			return elist[err - KAT_KEY_NOTVALID_ERROR].name;
77 
78 		return "Invalid";
79 	}
80 
81 	return "Unknown";
82 }
83 
ecc_get_key_size(uint32_t curve,size_t * bytes,size_t * bits)84 static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits)
85 {
86 	switch (curve) {
87 	case TEE_ECC_CURVE_NIST_P384:
88 		*bits = 384;
89 		*bytes = 48;
90 		break;
91 	case TEE_ECC_CURVE_NIST_P521:
92 		*bits = 521;
93 		*bytes = 66;
94 		break;
95 	default:
96 		return TEE_ERROR_NOT_SUPPORTED;
97 	}
98 
99 	return TEE_SUCCESS;
100 }
101 
memcpy_swp(uint8_t * to,const uint8_t * from,size_t len)102 static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len)
103 {
104 	size_t i = 0;
105 
106 	for (i = 0; i < len; i++)
107 		to[i] = from[len - 1 - i];
108 }
109 
crypto_bignum_bn2bin_eswap(uint32_t curve,struct bignum * from,uint8_t * to)110 static void crypto_bignum_bn2bin_eswap(uint32_t curve,
111 				       struct bignum *from, uint8_t *to)
112 {
113 	uint8_t pad[66] = { 0 };
114 	size_t len = crypto_bignum_num_bytes(from);
115 	size_t bytes = 0;
116 	size_t bits = 0;
117 
118 	if (ecc_get_key_size(curve, &bytes, &bits))
119 		panic();
120 
121 	crypto_bignum_bn2bin(from, pad + bytes - len);
122 	memcpy_swp(to, pad, bytes);
123 }
124 
ecc_prepare_msg(uint32_t algo,const uint8_t * msg,size_t msg_len,struct versal_mbox_mem * p)125 static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg,
126 				  size_t msg_len, struct versal_mbox_mem *p)
127 {
128 	uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 };
129 	size_t len = 0;
130 
131 	if (msg_len > TEE_SHA512_HASH_SIZE + 2)
132 		return TEE_ERROR_BAD_PARAMETERS;
133 
134 	if (algo == TEE_ALG_ECDSA_SHA384)
135 		len = TEE_SHA384_HASH_SIZE;
136 	else if (algo == TEE_ALG_ECDSA_SHA512)
137 		len = TEE_SHA512_HASH_SIZE + 2;
138 	else
139 		return TEE_ERROR_NOT_SUPPORTED;
140 
141 	/* Swap the hash/message and pad if necessary */
142 	memcpy_swp(swp, msg, msg_len);
143 	return versal_mbox_alloc(len, swp, p);
144 }
145 
verify(uint32_t algo,struct ecc_public_key * key,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len)146 static TEE_Result verify(uint32_t algo, struct ecc_public_key *key,
147 			 const uint8_t *msg, size_t msg_len,
148 			 const uint8_t *sig, size_t sig_len)
149 {
150 	TEE_Result ret = TEE_SUCCESS;
151 	struct versal_ecc_verify_param *cmd = NULL;
152 	struct versal_cmd_args arg = { };
153 	struct versal_mbox_mem x = { };
154 	struct versal_mbox_mem s = { };
155 	struct versal_mbox_mem p = { };
156 	struct versal_mbox_mem cmd_buf = { };
157 	uint32_t err = 0;
158 	size_t bytes = 0;
159 	size_t bits = 0;
160 
161 	if (sig_len % 2)
162 		return TEE_ERROR_SIGNATURE_INVALID;
163 
164 	ret = ecc_get_key_size(key->curve, &bytes, &bits);
165 	if (ret != TEE_SUCCESS) {
166 		if (ret != TEE_ERROR_NOT_SUPPORTED)
167 			return ret;
168 
169 		/* Fallback to software */
170 		return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len);
171 	}
172 
173 	ret = ecc_prepare_msg(algo, msg, msg_len, &p);
174 	if (ret)
175 		return ret;
176 
177 	versal_mbox_alloc(bytes * 2, NULL, &x);
178 	crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf);
179 	crypto_bignum_bn2bin_eswap(key->curve, key->y,
180 				   (uint8_t *)x.buf + bytes);
181 	/* Validate the public key for the curve */
182 	arg.data[0] = key->curve;
183 	arg.dlen = 1;
184 	arg.ibuf[0].mem = x;
185 	if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY,
186 				  &arg, &err)) {
187 		EMSG("Versal ECC: %s", versal_ecc_error(err));
188 		ret = TEE_ERROR_GENERIC;
189 		goto out;
190 	}
191 	memset(&arg, 0, sizeof(arg));
192 
193 	versal_mbox_alloc(sig_len, NULL, &s);
194 	/* Swap the {R,S} components */
195 	memcpy_swp(s.buf, sig, sig_len / 2);
196 	memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2,
197 		   sig_len / 2);
198 	versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf);
199 
200 	cmd = cmd_buf.buf;
201 	cmd->signature_addr = virt_to_phys(s.buf);
202 	cmd->pub_key_addr = virt_to_phys(x.buf);
203 	cmd->hash_addr = virt_to_phys(p.buf);
204 	cmd->hash_len = p.len;
205 	cmd->curve = key->curve;
206 
207 	arg.ibuf[0].mem = cmd_buf;
208 	arg.ibuf[1].mem = p;
209 	arg.ibuf[1].only_cache = true;
210 	arg.ibuf[2].mem = x;
211 	arg.ibuf[3].mem = s;
212 
213 	if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) {
214 		EMSG("Versal ECC: %s", versal_ecc_error(err));
215 		ret = TEE_ERROR_GENERIC;
216 	}
217 out:
218 	free(p.buf);
219 	free(x.buf);
220 	free(s.buf);
221 	free(cmd);
222 
223 	return ret;
224 }
225 
sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)226 static TEE_Result sign(uint32_t algo, struct ecc_keypair *key,
227 		       const uint8_t *msg, size_t msg_len,
228 		       uint8_t *sig, size_t *sig_len)
229 {
230 	struct versal_ecc_sign_param *cmd = NULL;
231 	struct versal_mbox_mem cmd_buf = { };
232 	struct ecc_keypair ephemeral = { };
233 	struct versal_cmd_args arg = { };
234 	struct versal_mbox_mem p = { };
235 	struct versal_mbox_mem k = { };
236 	struct versal_mbox_mem d = { };
237 	struct versal_mbox_mem s = { };
238 	TEE_Result ret = TEE_SUCCESS;
239 	uint32_t err = 0;
240 	size_t bytes = 0;
241 	size_t bits = 0;
242 
243 	ret = ecc_get_key_size(key->curve, &bytes, &bits);
244 	if (ret != TEE_SUCCESS) {
245 		if (ret != TEE_ERROR_NOT_SUPPORTED)
246 			return ret;
247 
248 		/* Fallback to software */
249 		return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len);
250 	}
251 
252 	/* Hash and update the length */
253 	ret = ecc_prepare_msg(algo, msg, msg_len, &p);
254 	if (ret)
255 		return ret;
256 
257 	/* Ephemeral private key */
258 	ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral,
259 					      TEE_TYPE_ECDSA_KEYPAIR, bits);
260 	if (ret) {
261 		EMSG("Versal, can't allocate the ephemeral key");
262 		return ret;
263 	}
264 
265 	ephemeral.curve = key->curve;
266 	ret = crypto_acipher_gen_ecc_key(&ephemeral, bits);
267 	if (ret) {
268 		EMSG("Versal, can't generate the ephemeral key");
269 		return ret;
270 	}
271 
272 	versal_mbox_alloc(bytes, NULL, &k);
273 	crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf);
274 	crypto_bignum_free(&ephemeral.d);
275 	crypto_bignum_free(&ephemeral.x);
276 	crypto_bignum_free(&ephemeral.y);
277 
278 	/* Private key*/
279 	versal_mbox_alloc(bytes, NULL, &d);
280 	crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf);
281 
282 	/* Signature */
283 	versal_mbox_alloc(*sig_len, NULL, &s);
284 
285 	/* IPI command */
286 	versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf);
287 
288 	cmd = cmd_buf.buf;
289 	cmd->priv_key_addr = virt_to_phys(d.buf);
290 	cmd->epriv_key_addr = virt_to_phys(k.buf);
291 	cmd->hash_addr = virt_to_phys(p.buf);
292 	cmd->hash_len = p.len;
293 	cmd->curve = key->curve;
294 
295 	arg.ibuf[0].mem = cmd_buf;
296 	arg.ibuf[1].mem = s;
297 	arg.ibuf[2].mem = k;
298 	arg.ibuf[3].mem = d;
299 	arg.ibuf[4].mem = p;
300 
301 	if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) {
302 		EMSG("Versal ECC: %s", versal_ecc_error(err));
303 		ret = TEE_ERROR_GENERIC;
304 		goto out;
305 	}
306 
307 	*sig_len = 2 * bytes;
308 
309 	/* Swap the {R,S} components */
310 	memcpy_swp(sig, s.buf, *sig_len / 2);
311 	memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2,
312 		   *sig_len / 2);
313 out:
314 	free(cmd);
315 	free(k.buf);
316 	free(p.buf);
317 	free(s.buf);
318 	free(d.buf);
319 
320 	return ret;
321 }
322 
shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,size_t * secret_len)323 static TEE_Result shared_secret(struct ecc_keypair *private_key,
324 				struct ecc_public_key *public_key,
325 				void *secret, size_t *secret_len)
326 {
327 	return pair_ops->shared_secret(private_key, public_key,
328 					  secret, secret_len);
329 }
330 
do_shared_secret(struct drvcrypt_secret_data * sdata)331 static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
332 {
333 	return shared_secret(sdata->key_priv,
334 			     sdata->key_pub,
335 			     sdata->secret.data,
336 			     &sdata->secret.length);
337 }
338 
do_sign(struct drvcrypt_sign_data * sdata)339 static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
340 {
341 	return sign(sdata->algo,
342 		    sdata->key,
343 		    sdata->message.data,
344 		    sdata->message.length,
345 		    sdata->signature.data,
346 		    &sdata->signature.length);
347 }
348 
do_verify(struct drvcrypt_sign_data * sdata)349 static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
350 {
351 	return verify(sdata->algo,
352 		      sdata->key,
353 		      sdata->message.data,
354 		      sdata->message.length,
355 		      sdata->signature.data,
356 		      sdata->signature.length);
357 }
358 
do_gen_keypair(struct ecc_keypair * s,size_t size_bits)359 static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits)
360 {
361 	/*
362 	 * Versal requires little endian so need to memcpy_swp on Versal IP ops.
363 	 * We chose not to do it here because some tests might be using
364 	 * their own keys
365 	 */
366 	return pair_ops->generate(s, size_bits);
367 }
368 
do_alloc_keypair(struct ecc_keypair * s,uint32_t type,size_t size_bits)369 static TEE_Result do_alloc_keypair(struct ecc_keypair *s,
370 				   uint32_t type, size_t size_bits)
371 {
372 	TEE_Result ret = TEE_SUCCESS;
373 
374 	/* This driver only supports ECDH/ECDSA */
375 	if (type != TEE_TYPE_ECDSA_KEYPAIR &&
376 	    type != TEE_TYPE_ECDH_KEYPAIR)
377 		return TEE_ERROR_NOT_IMPLEMENTED;
378 
379 	ret = crypto_asym_alloc_ecc_keypair(s, TEE_TYPE_ECDSA_KEYPAIR,
380 					    size_bits);
381 	if (ret)
382 		return TEE_ERROR_NOT_IMPLEMENTED;
383 
384 	/*
385 	 * Ignore the software operations, the crypto API will populate
386 	 * this interface.
387 	 */
388 	s->ops = NULL;
389 
390 	return TEE_SUCCESS;
391 }
392 
do_alloc_publickey(struct ecc_public_key * s,uint32_t type,size_t size_bits)393 static TEE_Result do_alloc_publickey(struct ecc_public_key *s,
394 				     uint32_t type, size_t size_bits)
395 {
396 	TEE_Result ret = TEE_SUCCESS;
397 
398 	/* This driver only supports ECDH/ECDSA */
399 	if (type != TEE_TYPE_ECDSA_PUBLIC_KEY &&
400 	    type != TEE_TYPE_ECDH_PUBLIC_KEY)
401 		return TEE_ERROR_NOT_IMPLEMENTED;
402 
403 	ret = crypto_asym_alloc_ecc_public_key(s, TEE_TYPE_ECDSA_PUBLIC_KEY,
404 					       size_bits);
405 	if (ret)
406 		return TEE_ERROR_NOT_IMPLEMENTED;
407 
408 	/*
409 	 * Ignore the software operations, the crypto API will populate
410 	 * this interface.
411 	 */
412 	s->ops = NULL;
413 
414 	return TEE_SUCCESS;
415 }
416 
do_free_publickey(struct ecc_public_key * s)417 static void do_free_publickey(struct ecc_public_key *s)
418 {
419 	return pub_ops->free(s);
420 }
421 
422 static struct drvcrypt_ecc driver_ecc = {
423 	.shared_secret = do_shared_secret,
424 	.alloc_publickey = do_alloc_publickey,
425 	.free_publickey = do_free_publickey,
426 	.alloc_keypair = do_alloc_keypair,
427 	.gen_keypair = do_gen_keypair,
428 	.verify = do_verify,
429 	.sign = do_sign,
430 };
431 
ecc_init(void)432 static TEE_Result ecc_init(void)
433 {
434 	struct versal_cmd_args arg = { };
435 	uint32_t err = 0;
436 
437 	arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384;
438 	if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) {
439 		EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err));
440 		return TEE_ERROR_GENERIC;
441 	}
442 
443 	/* Clean previous request */
444 	arg.dlen = 0;
445 
446 	arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P521;
447 	if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) {
448 		EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err));
449 		return TEE_ERROR_GENERIC;
450 	}
451 
452 	pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR);
453 	if (!pair_ops)
454 		return TEE_ERROR_GENERIC;
455 
456 	pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY);
457 	if (!pub_ops)
458 		return TEE_ERROR_GENERIC;
459 
460 	/* This driver supports both ECDH and ECDSA */
461 	assert((pub_ops ==
462 		crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) &&
463 	       (pair_ops ==
464 		crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR)));
465 
466 	return drvcrypt_register_ecc(&driver_ecc);
467 }
468 
469 driver_init(ecc_init);
470