149b0febcSJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
249b0febcSJorge Ramirez-Ortiz /*
349b0febcSJorge Ramirez-Ortiz * Copyright (C) Foundries Ltd. 2022.
449b0febcSJorge Ramirez-Ortiz * Author: Jorge Ramirez <jorge@foundries.io>
549b0febcSJorge Ramirez-Ortiz */
649b0febcSJorge Ramirez-Ortiz
749b0febcSJorge Ramirez-Ortiz #include <drvcrypt.h>
849b0febcSJorge Ramirez-Ortiz #include <drvcrypt_acipher.h>
949b0febcSJorge Ramirez-Ortiz #include <crypto/crypto_impl.h>
1049b0febcSJorge Ramirez-Ortiz #include <initcall.h>
1149b0febcSJorge Ramirez-Ortiz #include <ipi.h>
1249b0febcSJorge Ramirez-Ortiz #include <kernel/panic.h>
1349b0febcSJorge Ramirez-Ortiz #include <mm/core_memprot.h>
1449b0febcSJorge Ramirez-Ortiz #include <string.h>
1549b0febcSJorge Ramirez-Ortiz #include <tee/cache.h>
1649b0febcSJorge Ramirez-Ortiz #include <tee/tee_cryp_utl.h>
1749b0febcSJorge Ramirez-Ortiz #include <util.h>
1849b0febcSJorge Ramirez-Ortiz
1949b0febcSJorge Ramirez-Ortiz /* AMD/Xilinx Versal's Known Answer Tests */
2049b0febcSJorge Ramirez-Ortiz #define XSECURE_ECDSA_KAT_NIST_P384 0
2149b0febcSJorge Ramirez-Ortiz #define XSECURE_ECDSA_KAT_NIST_P521 2
2249b0febcSJorge Ramirez-Ortiz
2349b0febcSJorge Ramirez-Ortiz /* Software based ECDSA operations */
241220a68bSJorge Ramirez-Ortiz static const struct crypto_ecc_keypair_ops *pair_ops;
2549b0febcSJorge Ramirez-Ortiz static const struct crypto_ecc_public_ops *pub_ops;
2649b0febcSJorge Ramirez-Ortiz
2749b0febcSJorge Ramirez-Ortiz enum versal_ecc_err {
2849b0febcSJorge Ramirez-Ortiz KAT_KEY_NOTVALID_ERROR = 0xC0,
2949b0febcSJorge Ramirez-Ortiz KAT_FAILED_ERROR,
3049b0febcSJorge Ramirez-Ortiz NON_SUPPORTED_CURVE,
3149b0febcSJorge Ramirez-Ortiz KEY_ZERO,
3249b0febcSJorge Ramirez-Ortiz KEY_WRONG_ORDER,
3349b0febcSJorge Ramirez-Ortiz KEY_NOT_ON_CURVE,
3449b0febcSJorge Ramirez-Ortiz BAD_SIGN,
3549b0febcSJorge Ramirez-Ortiz GEN_SIGN_INCORRECT_HASH_LEN,
3649b0febcSJorge Ramirez-Ortiz VER_SIGN_INCORRECT_HASH_LEN,
3749b0febcSJorge Ramirez-Ortiz GEN_SIGN_BAD_RAND_NUM,
3849b0febcSJorge Ramirez-Ortiz GEN_KEY_ERR,
3949b0febcSJorge Ramirez-Ortiz INVALID_PARAM,
4049b0febcSJorge Ramirez-Ortiz VER_SIGN_R_ZERO,
4149b0febcSJorge Ramirez-Ortiz VER_SIGN_S_ZERO,
4249b0febcSJorge Ramirez-Ortiz VER_SIGN_R_ORDER_ERROR,
4349b0febcSJorge Ramirez-Ortiz VER_SIGN_S_ORDER_ERROR,
4449b0febcSJorge Ramirez-Ortiz KAT_INVLD_CRV_ERROR,
4549b0febcSJorge Ramirez-Ortiz };
4649b0febcSJorge Ramirez-Ortiz
4749b0febcSJorge Ramirez-Ortiz #define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) }
4849b0febcSJorge Ramirez-Ortiz
versal_ecc_error(uint8_t err)4949b0febcSJorge Ramirez-Ortiz static const char *versal_ecc_error(uint8_t err)
5049b0febcSJorge Ramirez-Ortiz {
5149b0febcSJorge Ramirez-Ortiz struct {
5249b0febcSJorge Ramirez-Ortiz enum versal_ecc_err error;
5349b0febcSJorge Ramirez-Ortiz const char *name;
5449b0febcSJorge Ramirez-Ortiz } elist[] = {
5549b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR),
5649b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KAT_FAILED_ERROR),
5749b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE),
5849b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KEY_ZERO),
5949b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KEY_WRONG_ORDER),
6049b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE),
6149b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(BAD_SIGN),
6249b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN),
6349b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN),
6449b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM),
6549b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(GEN_KEY_ERR),
6649b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(INVALID_PARAM),
6749b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(VER_SIGN_R_ZERO),
6849b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(VER_SIGN_S_ZERO),
6949b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR),
7049b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR),
7149b0febcSJorge Ramirez-Ortiz VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR),
7249b0febcSJorge Ramirez-Ortiz };
7349b0febcSJorge Ramirez-Ortiz
7449b0febcSJorge Ramirez-Ortiz if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) {
7549b0febcSJorge Ramirez-Ortiz if (elist[err - KAT_KEY_NOTVALID_ERROR].name)
7649b0febcSJorge Ramirez-Ortiz return elist[err - KAT_KEY_NOTVALID_ERROR].name;
7749b0febcSJorge Ramirez-Ortiz
7849b0febcSJorge Ramirez-Ortiz return "Invalid";
7949b0febcSJorge Ramirez-Ortiz }
8049b0febcSJorge Ramirez-Ortiz
8149b0febcSJorge Ramirez-Ortiz return "Unknown";
8249b0febcSJorge Ramirez-Ortiz }
8349b0febcSJorge Ramirez-Ortiz
ecc_get_key_size(uint32_t curve,size_t * bytes,size_t * bits)8449b0febcSJorge Ramirez-Ortiz static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits)
8549b0febcSJorge Ramirez-Ortiz {
8649b0febcSJorge Ramirez-Ortiz switch (curve) {
8749b0febcSJorge Ramirez-Ortiz case TEE_ECC_CURVE_NIST_P384:
8849b0febcSJorge Ramirez-Ortiz *bits = 384;
8949b0febcSJorge Ramirez-Ortiz *bytes = 48;
9049b0febcSJorge Ramirez-Ortiz break;
9149b0febcSJorge Ramirez-Ortiz case TEE_ECC_CURVE_NIST_P521:
9249b0febcSJorge Ramirez-Ortiz *bits = 521;
9349b0febcSJorge Ramirez-Ortiz *bytes = 66;
9449b0febcSJorge Ramirez-Ortiz break;
9549b0febcSJorge Ramirez-Ortiz default:
9649b0febcSJorge Ramirez-Ortiz return TEE_ERROR_NOT_SUPPORTED;
9749b0febcSJorge Ramirez-Ortiz }
9849b0febcSJorge Ramirez-Ortiz
9949b0febcSJorge Ramirez-Ortiz return TEE_SUCCESS;
10049b0febcSJorge Ramirez-Ortiz }
10149b0febcSJorge Ramirez-Ortiz
memcpy_swp(uint8_t * to,const uint8_t * from,size_t len)102e8bbd0e0SJorge Ramirez-Ortiz static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len)
103e8bbd0e0SJorge Ramirez-Ortiz {
104e8bbd0e0SJorge Ramirez-Ortiz size_t i = 0;
105e8bbd0e0SJorge Ramirez-Ortiz
106e8bbd0e0SJorge Ramirez-Ortiz for (i = 0; i < len; i++)
107e8bbd0e0SJorge Ramirez-Ortiz to[i] = from[len - 1 - i];
108e8bbd0e0SJorge Ramirez-Ortiz }
109e8bbd0e0SJorge Ramirez-Ortiz
crypto_bignum_bn2bin_eswap(uint32_t curve,struct bignum * from,uint8_t * to)11049b0febcSJorge Ramirez-Ortiz static void crypto_bignum_bn2bin_eswap(uint32_t curve,
11149b0febcSJorge Ramirez-Ortiz struct bignum *from, uint8_t *to)
11249b0febcSJorge Ramirez-Ortiz {
11349b0febcSJorge Ramirez-Ortiz uint8_t pad[66] = { 0 };
11449b0febcSJorge Ramirez-Ortiz size_t len = crypto_bignum_num_bytes(from);
11549b0febcSJorge Ramirez-Ortiz size_t bytes = 0;
11649b0febcSJorge Ramirez-Ortiz size_t bits = 0;
11749b0febcSJorge Ramirez-Ortiz
11849b0febcSJorge Ramirez-Ortiz if (ecc_get_key_size(curve, &bytes, &bits))
11949b0febcSJorge Ramirez-Ortiz panic();
12049b0febcSJorge Ramirez-Ortiz
12149b0febcSJorge Ramirez-Ortiz crypto_bignum_bn2bin(from, pad + bytes - len);
122e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp(to, pad, bytes);
12349b0febcSJorge Ramirez-Ortiz }
12449b0febcSJorge Ramirez-Ortiz
ecc_prepare_msg(uint32_t algo,const uint8_t * msg,size_t msg_len,struct versal_mbox_mem * p)12549b0febcSJorge Ramirez-Ortiz static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg,
12649b0febcSJorge Ramirez-Ortiz size_t msg_len, struct versal_mbox_mem *p)
12749b0febcSJorge Ramirez-Ortiz {
128e8bbd0e0SJorge Ramirez-Ortiz uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 };
12949b0febcSJorge Ramirez-Ortiz size_t len = 0;
13049b0febcSJorge Ramirez-Ortiz
131e8bbd0e0SJorge Ramirez-Ortiz if (msg_len > TEE_SHA512_HASH_SIZE + 2)
132e8bbd0e0SJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS;
133e8bbd0e0SJorge Ramirez-Ortiz
1349cf576a9SJerome Forissier if (algo == TEE_ALG_ECDSA_SHA384)
13549b0febcSJorge Ramirez-Ortiz len = TEE_SHA384_HASH_SIZE;
1369cf576a9SJerome Forissier else if (algo == TEE_ALG_ECDSA_SHA512)
13749b0febcSJorge Ramirez-Ortiz len = TEE_SHA512_HASH_SIZE + 2;
138e8bbd0e0SJorge Ramirez-Ortiz else
139e8bbd0e0SJorge Ramirez-Ortiz return TEE_ERROR_NOT_SUPPORTED;
14049b0febcSJorge Ramirez-Ortiz
141e8bbd0e0SJorge Ramirez-Ortiz /* Swap the hash/message and pad if necessary */
142e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp(swp, msg, msg_len);
143e8bbd0e0SJorge Ramirez-Ortiz return versal_mbox_alloc(len, swp, p);
14449b0febcSJorge Ramirez-Ortiz }
14549b0febcSJorge Ramirez-Ortiz
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)14649b0febcSJorge Ramirez-Ortiz static TEE_Result verify(uint32_t algo, struct ecc_public_key *key,
14749b0febcSJorge Ramirez-Ortiz const uint8_t *msg, size_t msg_len,
14849b0febcSJorge Ramirez-Ortiz const uint8_t *sig, size_t sig_len)
14949b0febcSJorge Ramirez-Ortiz {
15049b0febcSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS;
15149b0febcSJorge Ramirez-Ortiz struct versal_ecc_verify_param *cmd = NULL;
15249b0febcSJorge Ramirez-Ortiz struct versal_cmd_args arg = { };
15349b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem x = { };
15449b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem s = { };
15549b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem p = { };
15649b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem cmd_buf = { };
15749b0febcSJorge Ramirez-Ortiz uint32_t err = 0;
15849b0febcSJorge Ramirez-Ortiz size_t bytes = 0;
15949b0febcSJorge Ramirez-Ortiz size_t bits = 0;
16049b0febcSJorge Ramirez-Ortiz
161e8bbd0e0SJorge Ramirez-Ortiz if (sig_len % 2)
162e8bbd0e0SJorge Ramirez-Ortiz return TEE_ERROR_SIGNATURE_INVALID;
163e8bbd0e0SJorge Ramirez-Ortiz
16449b0febcSJorge Ramirez-Ortiz ret = ecc_get_key_size(key->curve, &bytes, &bits);
16549b0febcSJorge Ramirez-Ortiz if (ret != TEE_SUCCESS) {
16649b0febcSJorge Ramirez-Ortiz if (ret != TEE_ERROR_NOT_SUPPORTED)
16749b0febcSJorge Ramirez-Ortiz return ret;
16849b0febcSJorge Ramirez-Ortiz
16949b0febcSJorge Ramirez-Ortiz /* Fallback to software */
17049b0febcSJorge Ramirez-Ortiz return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len);
17149b0febcSJorge Ramirez-Ortiz }
17249b0febcSJorge Ramirez-Ortiz
17349b0febcSJorge Ramirez-Ortiz ret = ecc_prepare_msg(algo, msg, msg_len, &p);
17449b0febcSJorge Ramirez-Ortiz if (ret)
17549b0febcSJorge Ramirez-Ortiz return ret;
17649b0febcSJorge Ramirez-Ortiz
17749b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(bytes * 2, NULL, &x);
17849b0febcSJorge Ramirez-Ortiz crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf);
17949b0febcSJorge Ramirez-Ortiz crypto_bignum_bn2bin_eswap(key->curve, key->y,
18049b0febcSJorge Ramirez-Ortiz (uint8_t *)x.buf + bytes);
18149b0febcSJorge Ramirez-Ortiz /* Validate the public key for the curve */
18249b0febcSJorge Ramirez-Ortiz arg.data[0] = key->curve;
18349b0febcSJorge Ramirez-Ortiz arg.dlen = 1;
18449b0febcSJorge Ramirez-Ortiz arg.ibuf[0].mem = x;
18549b0febcSJorge Ramirez-Ortiz if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY,
18649b0febcSJorge Ramirez-Ortiz &arg, &err)) {
18749b0febcSJorge Ramirez-Ortiz EMSG("Versal ECC: %s", versal_ecc_error(err));
18849b0febcSJorge Ramirez-Ortiz ret = TEE_ERROR_GENERIC;
18949b0febcSJorge Ramirez-Ortiz goto out;
19049b0febcSJorge Ramirez-Ortiz }
19149b0febcSJorge Ramirez-Ortiz memset(&arg, 0, sizeof(arg));
19249b0febcSJorge Ramirez-Ortiz
193e8bbd0e0SJorge Ramirez-Ortiz versal_mbox_alloc(sig_len, NULL, &s);
194e8bbd0e0SJorge Ramirez-Ortiz /* Swap the {R,S} components */
195e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp(s.buf, sig, sig_len / 2);
196e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2,
197e8bbd0e0SJorge Ramirez-Ortiz sig_len / 2);
19849b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf);
19949b0febcSJorge Ramirez-Ortiz
20049b0febcSJorge Ramirez-Ortiz cmd = cmd_buf.buf;
20149b0febcSJorge Ramirez-Ortiz cmd->signature_addr = virt_to_phys(s.buf);
20249b0febcSJorge Ramirez-Ortiz cmd->pub_key_addr = virt_to_phys(x.buf);
20349b0febcSJorge Ramirez-Ortiz cmd->hash_addr = virt_to_phys(p.buf);
20449b0febcSJorge Ramirez-Ortiz cmd->hash_len = p.len;
20549b0febcSJorge Ramirez-Ortiz cmd->curve = key->curve;
20649b0febcSJorge Ramirez-Ortiz
20749b0febcSJorge Ramirez-Ortiz arg.ibuf[0].mem = cmd_buf;
20849b0febcSJorge Ramirez-Ortiz arg.ibuf[1].mem = p;
20949b0febcSJorge Ramirez-Ortiz arg.ibuf[1].only_cache = true;
21049b0febcSJorge Ramirez-Ortiz arg.ibuf[2].mem = x;
21149b0febcSJorge Ramirez-Ortiz arg.ibuf[3].mem = s;
21249b0febcSJorge Ramirez-Ortiz
21349b0febcSJorge Ramirez-Ortiz if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) {
21449b0febcSJorge Ramirez-Ortiz EMSG("Versal ECC: %s", versal_ecc_error(err));
21549b0febcSJorge Ramirez-Ortiz ret = TEE_ERROR_GENERIC;
21649b0febcSJorge Ramirez-Ortiz }
21749b0febcSJorge Ramirez-Ortiz out:
21849b0febcSJorge Ramirez-Ortiz free(p.buf);
21949b0febcSJorge Ramirez-Ortiz free(x.buf);
22049b0febcSJorge Ramirez-Ortiz free(s.buf);
22149b0febcSJorge Ramirez-Ortiz free(cmd);
22249b0febcSJorge Ramirez-Ortiz
22349b0febcSJorge Ramirez-Ortiz return ret;
22449b0febcSJorge Ramirez-Ortiz }
22549b0febcSJorge Ramirez-Ortiz
sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)22649b0febcSJorge Ramirez-Ortiz static TEE_Result sign(uint32_t algo, struct ecc_keypair *key,
22749b0febcSJorge Ramirez-Ortiz const uint8_t *msg, size_t msg_len,
22849b0febcSJorge Ramirez-Ortiz uint8_t *sig, size_t *sig_len)
22949b0febcSJorge Ramirez-Ortiz {
23049b0febcSJorge Ramirez-Ortiz struct versal_ecc_sign_param *cmd = NULL;
23149b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem cmd_buf = { };
23249b0febcSJorge Ramirez-Ortiz struct ecc_keypair ephemeral = { };
23349b0febcSJorge Ramirez-Ortiz struct versal_cmd_args arg = { };
23449b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem p = { };
23549b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem k = { };
23649b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem d = { };
23749b0febcSJorge Ramirez-Ortiz struct versal_mbox_mem s = { };
23849b0febcSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS;
23949b0febcSJorge Ramirez-Ortiz uint32_t err = 0;
24049b0febcSJorge Ramirez-Ortiz size_t bytes = 0;
24149b0febcSJorge Ramirez-Ortiz size_t bits = 0;
24249b0febcSJorge Ramirez-Ortiz
24349b0febcSJorge Ramirez-Ortiz ret = ecc_get_key_size(key->curve, &bytes, &bits);
24449b0febcSJorge Ramirez-Ortiz if (ret != TEE_SUCCESS) {
24549b0febcSJorge Ramirez-Ortiz if (ret != TEE_ERROR_NOT_SUPPORTED)
24649b0febcSJorge Ramirez-Ortiz return ret;
24749b0febcSJorge Ramirez-Ortiz
24849b0febcSJorge Ramirez-Ortiz /* Fallback to software */
2491220a68bSJorge Ramirez-Ortiz return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len);
25049b0febcSJorge Ramirez-Ortiz }
25149b0febcSJorge Ramirez-Ortiz
25249b0febcSJorge Ramirez-Ortiz /* Hash and update the length */
25349b0febcSJorge Ramirez-Ortiz ret = ecc_prepare_msg(algo, msg, msg_len, &p);
25449b0febcSJorge Ramirez-Ortiz if (ret)
25549b0febcSJorge Ramirez-Ortiz return ret;
25649b0febcSJorge Ramirez-Ortiz
25749b0febcSJorge Ramirez-Ortiz /* Ephemeral private key */
25849b0febcSJorge Ramirez-Ortiz ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral,
25949b0febcSJorge Ramirez-Ortiz TEE_TYPE_ECDSA_KEYPAIR, bits);
26049b0febcSJorge Ramirez-Ortiz if (ret) {
26149b0febcSJorge Ramirez-Ortiz EMSG("Versal, can't allocate the ephemeral key");
26249b0febcSJorge Ramirez-Ortiz return ret;
26349b0febcSJorge Ramirez-Ortiz }
26449b0febcSJorge Ramirez-Ortiz
26549b0febcSJorge Ramirez-Ortiz ephemeral.curve = key->curve;
26649b0febcSJorge Ramirez-Ortiz ret = crypto_acipher_gen_ecc_key(&ephemeral, bits);
26749b0febcSJorge Ramirez-Ortiz if (ret) {
26849b0febcSJorge Ramirez-Ortiz EMSG("Versal, can't generate the ephemeral key");
26949b0febcSJorge Ramirez-Ortiz return ret;
27049b0febcSJorge Ramirez-Ortiz }
27149b0febcSJorge Ramirez-Ortiz
27249b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(bytes, NULL, &k);
27349b0febcSJorge Ramirez-Ortiz crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf);
274*e2ec831cSJihwan Park crypto_bignum_free(&ephemeral.d);
275*e2ec831cSJihwan Park crypto_bignum_free(&ephemeral.x);
276*e2ec831cSJihwan Park crypto_bignum_free(&ephemeral.y);
27749b0febcSJorge Ramirez-Ortiz
27849b0febcSJorge Ramirez-Ortiz /* Private key*/
27949b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(bytes, NULL, &d);
28049b0febcSJorge Ramirez-Ortiz crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf);
28149b0febcSJorge Ramirez-Ortiz
28249b0febcSJorge Ramirez-Ortiz /* Signature */
28349b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(*sig_len, NULL, &s);
28449b0febcSJorge Ramirez-Ortiz
28549b0febcSJorge Ramirez-Ortiz /* IPI command */
28649b0febcSJorge Ramirez-Ortiz versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf);
28749b0febcSJorge Ramirez-Ortiz
28849b0febcSJorge Ramirez-Ortiz cmd = cmd_buf.buf;
28949b0febcSJorge Ramirez-Ortiz cmd->priv_key_addr = virt_to_phys(d.buf);
29049b0febcSJorge Ramirez-Ortiz cmd->epriv_key_addr = virt_to_phys(k.buf);
29149b0febcSJorge Ramirez-Ortiz cmd->hash_addr = virt_to_phys(p.buf);
29249b0febcSJorge Ramirez-Ortiz cmd->hash_len = p.len;
29349b0febcSJorge Ramirez-Ortiz cmd->curve = key->curve;
29449b0febcSJorge Ramirez-Ortiz
29549b0febcSJorge Ramirez-Ortiz arg.ibuf[0].mem = cmd_buf;
29649b0febcSJorge Ramirez-Ortiz arg.ibuf[1].mem = s;
29749b0febcSJorge Ramirez-Ortiz arg.ibuf[2].mem = k;
29849b0febcSJorge Ramirez-Ortiz arg.ibuf[3].mem = d;
29949b0febcSJorge Ramirez-Ortiz arg.ibuf[4].mem = p;
30049b0febcSJorge Ramirez-Ortiz
30149b0febcSJorge Ramirez-Ortiz if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) {
30249b0febcSJorge Ramirez-Ortiz EMSG("Versal ECC: %s", versal_ecc_error(err));
30349b0febcSJorge Ramirez-Ortiz ret = TEE_ERROR_GENERIC;
30449b0febcSJorge Ramirez-Ortiz goto out;
30549b0febcSJorge Ramirez-Ortiz }
30649b0febcSJorge Ramirez-Ortiz
30749b0febcSJorge Ramirez-Ortiz *sig_len = 2 * bytes;
308e8bbd0e0SJorge Ramirez-Ortiz
309e8bbd0e0SJorge Ramirez-Ortiz /* Swap the {R,S} components */
310e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp(sig, s.buf, *sig_len / 2);
311e8bbd0e0SJorge Ramirez-Ortiz memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2,
312e8bbd0e0SJorge Ramirez-Ortiz *sig_len / 2);
31349b0febcSJorge Ramirez-Ortiz out:
31449b0febcSJorge Ramirez-Ortiz free(cmd);
31549b0febcSJorge Ramirez-Ortiz free(k.buf);
31649b0febcSJorge Ramirez-Ortiz free(p.buf);
31749b0febcSJorge Ramirez-Ortiz free(s.buf);
31849b0febcSJorge Ramirez-Ortiz free(d.buf);
31949b0febcSJorge Ramirez-Ortiz
32049b0febcSJorge Ramirez-Ortiz return ret;
32149b0febcSJorge Ramirez-Ortiz }
32249b0febcSJorge Ramirez-Ortiz
shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,size_t * secret_len)32349b0febcSJorge Ramirez-Ortiz static TEE_Result shared_secret(struct ecc_keypair *private_key,
32449b0febcSJorge Ramirez-Ortiz struct ecc_public_key *public_key,
32549b0febcSJorge Ramirez-Ortiz void *secret, size_t *secret_len)
32649b0febcSJorge Ramirez-Ortiz {
3271220a68bSJorge Ramirez-Ortiz return pair_ops->shared_secret(private_key, public_key,
32849b0febcSJorge Ramirez-Ortiz secret, secret_len);
32949b0febcSJorge Ramirez-Ortiz }
33049b0febcSJorge Ramirez-Ortiz
do_shared_secret(struct drvcrypt_secret_data * sdata)33149b0febcSJorge Ramirez-Ortiz static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
33249b0febcSJorge Ramirez-Ortiz {
33349b0febcSJorge Ramirez-Ortiz return shared_secret(sdata->key_priv,
33449b0febcSJorge Ramirez-Ortiz sdata->key_pub,
33549b0febcSJorge Ramirez-Ortiz sdata->secret.data,
33649b0febcSJorge Ramirez-Ortiz &sdata->secret.length);
33749b0febcSJorge Ramirez-Ortiz }
33849b0febcSJorge Ramirez-Ortiz
do_sign(struct drvcrypt_sign_data * sdata)33949b0febcSJorge Ramirez-Ortiz static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
34049b0febcSJorge Ramirez-Ortiz {
34149b0febcSJorge Ramirez-Ortiz return sign(sdata->algo,
34249b0febcSJorge Ramirez-Ortiz sdata->key,
34349b0febcSJorge Ramirez-Ortiz sdata->message.data,
34449b0febcSJorge Ramirez-Ortiz sdata->message.length,
34549b0febcSJorge Ramirez-Ortiz sdata->signature.data,
34649b0febcSJorge Ramirez-Ortiz &sdata->signature.length);
34749b0febcSJorge Ramirez-Ortiz }
34849b0febcSJorge Ramirez-Ortiz
do_verify(struct drvcrypt_sign_data * sdata)34949b0febcSJorge Ramirez-Ortiz static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
35049b0febcSJorge Ramirez-Ortiz {
35149b0febcSJorge Ramirez-Ortiz return verify(sdata->algo,
35249b0febcSJorge Ramirez-Ortiz sdata->key,
35349b0febcSJorge Ramirez-Ortiz sdata->message.data,
35449b0febcSJorge Ramirez-Ortiz sdata->message.length,
35549b0febcSJorge Ramirez-Ortiz sdata->signature.data,
35649b0febcSJorge Ramirez-Ortiz sdata->signature.length);
35749b0febcSJorge Ramirez-Ortiz }
35849b0febcSJorge Ramirez-Ortiz
do_gen_keypair(struct ecc_keypair * s,size_t size_bits)35949b0febcSJorge Ramirez-Ortiz static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits)
36049b0febcSJorge Ramirez-Ortiz {
36149b0febcSJorge Ramirez-Ortiz /*
362e8bbd0e0SJorge Ramirez-Ortiz * Versal requires little endian so need to memcpy_swp on Versal IP ops.
36349b0febcSJorge Ramirez-Ortiz * We chose not to do it here because some tests might be using
36449b0febcSJorge Ramirez-Ortiz * their own keys
36549b0febcSJorge Ramirez-Ortiz */
3661220a68bSJorge Ramirez-Ortiz return pair_ops->generate(s, size_bits);
36749b0febcSJorge Ramirez-Ortiz }
36849b0febcSJorge Ramirez-Ortiz
do_alloc_keypair(struct ecc_keypair * s,uint32_t type,size_t size_bits)36992d75aefSJorge Ramirez-Ortiz static TEE_Result do_alloc_keypair(struct ecc_keypair *s,
3701220a68bSJorge Ramirez-Ortiz uint32_t type, size_t size_bits)
37149b0febcSJorge Ramirez-Ortiz {
37249b0febcSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS;
37349b0febcSJorge Ramirez-Ortiz
3741220a68bSJorge Ramirez-Ortiz /* This driver only supports ECDH/ECDSA */
3751220a68bSJorge Ramirez-Ortiz if (type != TEE_TYPE_ECDSA_KEYPAIR &&
3761220a68bSJorge Ramirez-Ortiz type != TEE_TYPE_ECDH_KEYPAIR)
3771220a68bSJorge Ramirez-Ortiz return TEE_ERROR_NOT_IMPLEMENTED;
3781220a68bSJorge Ramirez-Ortiz
37949b0febcSJorge Ramirez-Ortiz ret = crypto_asym_alloc_ecc_keypair(s, TEE_TYPE_ECDSA_KEYPAIR,
38049b0febcSJorge Ramirez-Ortiz size_bits);
38149b0febcSJorge Ramirez-Ortiz if (ret)
38249b0febcSJorge Ramirez-Ortiz return TEE_ERROR_NOT_IMPLEMENTED;
38349b0febcSJorge Ramirez-Ortiz
3841220a68bSJorge Ramirez-Ortiz /*
3851220a68bSJorge Ramirez-Ortiz * Ignore the software operations, the crypto API will populate
3861220a68bSJorge Ramirez-Ortiz * this interface.
3871220a68bSJorge Ramirez-Ortiz */
38849b0febcSJorge Ramirez-Ortiz s->ops = NULL;
38949b0febcSJorge Ramirez-Ortiz
39049b0febcSJorge Ramirez-Ortiz return TEE_SUCCESS;
39149b0febcSJorge Ramirez-Ortiz }
39249b0febcSJorge Ramirez-Ortiz
do_alloc_publickey(struct ecc_public_key * s,uint32_t type,size_t size_bits)39392d75aefSJorge Ramirez-Ortiz static TEE_Result do_alloc_publickey(struct ecc_public_key *s,
3941220a68bSJorge Ramirez-Ortiz uint32_t type, size_t size_bits)
39549b0febcSJorge Ramirez-Ortiz {
39649b0febcSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS;
39749b0febcSJorge Ramirez-Ortiz
3981220a68bSJorge Ramirez-Ortiz /* This driver only supports ECDH/ECDSA */
3991220a68bSJorge Ramirez-Ortiz if (type != TEE_TYPE_ECDSA_PUBLIC_KEY &&
4001220a68bSJorge Ramirez-Ortiz type != TEE_TYPE_ECDH_PUBLIC_KEY)
4011220a68bSJorge Ramirez-Ortiz return TEE_ERROR_NOT_IMPLEMENTED;
4021220a68bSJorge Ramirez-Ortiz
40349b0febcSJorge Ramirez-Ortiz ret = crypto_asym_alloc_ecc_public_key(s, TEE_TYPE_ECDSA_PUBLIC_KEY,
40449b0febcSJorge Ramirez-Ortiz size_bits);
40549b0febcSJorge Ramirez-Ortiz if (ret)
40649b0febcSJorge Ramirez-Ortiz return TEE_ERROR_NOT_IMPLEMENTED;
40749b0febcSJorge Ramirez-Ortiz
4081220a68bSJorge Ramirez-Ortiz /*
4091220a68bSJorge Ramirez-Ortiz * Ignore the software operations, the crypto API will populate
4101220a68bSJorge Ramirez-Ortiz * this interface.
4111220a68bSJorge Ramirez-Ortiz */
41249b0febcSJorge Ramirez-Ortiz s->ops = NULL;
41349b0febcSJorge Ramirez-Ortiz
41449b0febcSJorge Ramirez-Ortiz return TEE_SUCCESS;
41549b0febcSJorge Ramirez-Ortiz }
41649b0febcSJorge Ramirez-Ortiz
do_free_publickey(struct ecc_public_key * s)41749b0febcSJorge Ramirez-Ortiz static void do_free_publickey(struct ecc_public_key *s)
41849b0febcSJorge Ramirez-Ortiz {
41949b0febcSJorge Ramirez-Ortiz return pub_ops->free(s);
42049b0febcSJorge Ramirez-Ortiz }
42149b0febcSJorge Ramirez-Ortiz
42249b0febcSJorge Ramirez-Ortiz static struct drvcrypt_ecc driver_ecc = {
42349b0febcSJorge Ramirez-Ortiz .shared_secret = do_shared_secret,
42449b0febcSJorge Ramirez-Ortiz .alloc_publickey = do_alloc_publickey,
42549b0febcSJorge Ramirez-Ortiz .free_publickey = do_free_publickey,
42649b0febcSJorge Ramirez-Ortiz .alloc_keypair = do_alloc_keypair,
42749b0febcSJorge Ramirez-Ortiz .gen_keypair = do_gen_keypair,
42849b0febcSJorge Ramirez-Ortiz .verify = do_verify,
42949b0febcSJorge Ramirez-Ortiz .sign = do_sign,
43049b0febcSJorge Ramirez-Ortiz };
43149b0febcSJorge Ramirez-Ortiz
ecc_init(void)43249b0febcSJorge Ramirez-Ortiz static TEE_Result ecc_init(void)
43349b0febcSJorge Ramirez-Ortiz {
43449b0febcSJorge Ramirez-Ortiz struct versal_cmd_args arg = { };
43549b0febcSJorge Ramirez-Ortiz uint32_t err = 0;
43649b0febcSJorge Ramirez-Ortiz
43749b0febcSJorge Ramirez-Ortiz arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384;
43849b0febcSJorge Ramirez-Ortiz if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) {
43949b0febcSJorge Ramirez-Ortiz EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err));
44049b0febcSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC;
44149b0febcSJorge Ramirez-Ortiz }
44249b0febcSJorge Ramirez-Ortiz
44349b0febcSJorge Ramirez-Ortiz /* Clean previous request */
44449b0febcSJorge Ramirez-Ortiz arg.dlen = 0;
44549b0febcSJorge Ramirez-Ortiz
44649b0febcSJorge Ramirez-Ortiz arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P521;
44749b0febcSJorge Ramirez-Ortiz if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) {
44849b0febcSJorge Ramirez-Ortiz EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err));
44949b0febcSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC;
45049b0febcSJorge Ramirez-Ortiz }
45149b0febcSJorge Ramirez-Ortiz
4521220a68bSJorge Ramirez-Ortiz pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR);
4531220a68bSJorge Ramirez-Ortiz if (!pair_ops)
45449b0febcSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC;
45549b0febcSJorge Ramirez-Ortiz
45649b0febcSJorge Ramirez-Ortiz pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY);
45749b0febcSJorge Ramirez-Ortiz if (!pub_ops)
45849b0febcSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC;
45949b0febcSJorge Ramirez-Ortiz
4601220a68bSJorge Ramirez-Ortiz /* This driver supports both ECDH and ECDSA */
4611220a68bSJorge Ramirez-Ortiz assert((pub_ops ==
4621220a68bSJorge Ramirez-Ortiz crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) &&
4631220a68bSJorge Ramirez-Ortiz (pair_ops ==
4641220a68bSJorge Ramirez-Ortiz crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR)));
4651220a68bSJorge Ramirez-Ortiz
46649b0febcSJorge Ramirez-Ortiz return drvcrypt_register_ecc(&driver_ecc);
46749b0febcSJorge Ramirez-Ortiz }
46849b0febcSJorge Ramirez-Ortiz
46949b0febcSJorge Ramirez-Ortiz driver_init(ecc_init);
470