diff options
author | Edison Ai <edison.ai@arm.com> | 2017-09-11 14:16:52 +0800 |
---|---|---|
committer | Jérôme Forissier <jerome.forissier@linaro.org> | 2019-04-01 09:34:25 +0200 |
commit | ad6cfae7c06cc85282d75cb7345942b0ca29c489 (patch) | |
tree | c566f38e4822223982d3b0e5f7325f86bb84ba12 /lib/libmbedtls | |
parent | 34789f62982fd82b82b1147bd101dc9065fb5420 (diff) |
libmbedtls: support mbedtls ECC function
Support mbedtls ECC: ecdh and ecdsa.
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Edison Ai <edison.ai@arm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'lib/libmbedtls')
-rw-r--r-- | lib/libmbedtls/core/ecc.c | 378 | ||||
-rw-r--r-- | lib/libmbedtls/core/stubbed.c | 53 | ||||
-rw-r--r-- | lib/libmbedtls/core/sub.mk | 1 | ||||
-rw-r--r-- | lib/libmbedtls/include/mbedtls_config_kernel.h | 20 |
4 files changed, 398 insertions, 54 deletions
diff --git a/lib/libmbedtls/core/ecc.c b/lib/libmbedtls/core/ecc.c new file mode 100644 index 00000000..3c042586 --- /dev/null +++ b/lib/libmbedtls/core/ecc.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include <assert.h> +#include <compiler.h> +#include <crypto/crypto.h> +#include <mbedtls/ctr_drbg.h> +#include <mbedtls/ecdh.h> +#include <mbedtls/ecdsa.h> +#include <mbedtls/ecp.h> +#include <mbedtls/entropy.h> +#include <mbedtls/pk.h> +#include <stdlib.h> +#include <string.h> + +#include "mbd_rand.h" + +/* Translate mbedtls result to TEE result */ +static TEE_Result get_tee_result(int lmd_res) +{ + switch (lmd_res) { + case 0: + return TEE_SUCCESS; + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return TEE_ERROR_SIGNATURE_INVALID; + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return TEE_ERROR_SHORT_BUFFER; + default: + return TEE_ERROR_BAD_STATE; + } +} + +TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + s->d = crypto_bignum_allocate(key_size_bits); + if (!s->d) + goto err; + s->x = crypto_bignum_allocate(key_size_bits); + if (!s->x) + goto err; + s->y = crypto_bignum_allocate(key_size_bits); + if (!s->y) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->d); + crypto_bignum_free(s->x); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + s->x = crypto_bignum_allocate(key_size_bits); + if (!s->x) + goto err; + s->y = crypto_bignum_allocate(key_size_bits); + if (!s->y) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->x); + return TEE_ERROR_OUT_OF_MEMORY; +} + +void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s) +{ + if (!s) + return; + + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); +} + +/* + * curve is part of TEE_ECC_CURVE_NIST_P192,... + * algo is part of TEE_ALG_ECDSA_P192,..., and 0 if we do not have it + */ +static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo, + size_t *key_size_bytes, size_t *key_size_bits) +{ + /* + * Note GPv1.1 indicates TEE_ALG_ECDH_NIST_P192_DERIVE_SHARED_SECRET + * but defines TEE_ALG_ECDH_P192 + */ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + *key_size_bits = 192; + *key_size_bytes = 24; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_P192) && + (algo != TEE_ALG_ECDH_P192)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P224: + *key_size_bits = 224; + *key_size_bytes = 28; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_P224) && + (algo != TEE_ALG_ECDH_P224)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P256: + *key_size_bits = 256; + *key_size_bytes = 32; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_P256) && + (algo != TEE_ALG_ECDH_P256)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P384: + *key_size_bits = 384; + *key_size_bytes = 48; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_P384) && + (algo != TEE_ALG_ECDH_P384)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P521: + *key_size_bits = 521; + *key_size_bytes = 66; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_P521) && + (algo != TEE_ALG_ECDH_P521)) + return TEE_ERROR_BAD_PARAMETERS; + break; + default: + *key_size_bits = 0; + *key_size_bytes = 0; + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +/* + * Clear some memory that was used to prepare the context + */ +static void ecc_clear_precomputed(mbedtls_ecp_group *grp) +{ + size_t i = 0; + + if (grp->T) { + for (i = 0; i < grp->T_size; i++) + mbedtls_ecp_point_free(&grp->T[i]); + free(grp->T); + } + grp->T = NULL; + grp->T_size = 0; +} + +TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_ecdsa_context ecdsa; + size_t key_size_bytes = 0; + size_t key_size_bits = 0; + + memset(&ecdsa, 0, sizeof(ecdsa)); + + res = ecc_get_keysize(key->curve, 0, &key_size_bytes, &key_size_bits); + if (res != TEE_SUCCESS) + return res; + + mbedtls_ecdsa_init(&ecdsa); + + /* Generate the ECC key */ + lmd_res = mbedtls_ecdsa_genkey(&ecdsa, key->curve, mbd_rand, NULL); + if (lmd_res != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("mbedtls_ecdsa_genkey failed."); + goto exit; + } + ecc_clear_precomputed(&ecdsa.grp); + + /* check the size of the keys */ + if ((mbedtls_mpi_bitlen(&ecdsa.Q.X) > key_size_bits) || + (mbedtls_mpi_bitlen(&ecdsa.Q.Y) > key_size_bits) || + (mbedtls_mpi_bitlen(&ecdsa.d) > key_size_bits)) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("Check the size of the keys failed."); + goto exit; + } + + /* check LMD is returning z==1 */ + if (mbedtls_mpi_bitlen(&ecdsa.Q.Z) != 1) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("Check LMD failed."); + goto exit; + } + + /* Copy the key */ + crypto_bignum_copy(key->d, (void *)&ecdsa.d); + crypto_bignum_copy(key->x, (void *)&ecdsa.Q.X); + crypto_bignum_copy(key->y, (void *)&ecdsa.Q.Y); + + res = TEE_SUCCESS; +exit: + mbedtls_ecdsa_free(&ecdsa); /* Free the temporary key */ + return res; +} + +TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + const mbedtls_pk_info_t *pk_info = NULL; + mbedtls_ecdsa_context ecdsa; + size_t key_size_bytes = 0; + size_t key_size_bits = 0; + mbedtls_mpi r; + mbedtls_mpi s; + + memset(&ecdsa, 0, sizeof(ecdsa)); + memset(&r, 0, sizeof(r)); + memset(&s, 0, sizeof(s)); + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_init(&ecdsa); + lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, key->curve); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdsa.d = *(mbedtls_mpi *)key->d; + + res = ecc_get_keysize(key->curve, algo, &key_size_bytes, + &key_size_bits); + if (res != TEE_SUCCESS) + goto out; + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); + if (pk_info == NULL) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + lmd_res = mbedtls_ecdsa_sign(&ecdsa.grp, &r, &s, &ecdsa.d, msg, + msg_len, mbd_rand, NULL); + if (lmd_res == 0) { + *sig_len = 2 * key_size_bytes; + memset(sig, 0, *sig_len); + mbedtls_mpi_write_binary(&r, sig + *sig_len / 2 - + mbedtls_mpi_size(&r), + mbedtls_mpi_size(&r)); + + mbedtls_mpi_write_binary(&s, sig + *sig_len - + mbedtls_mpi_size(&s), + mbedtls_mpi_size(&s)); + res = TEE_SUCCESS; + } else { + FMSG("mbedtls_ecdsa_sign failed, returned 0x%x\n", -lmd_res); + res = TEE_ERROR_GENERIC; + } +out: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdsa.d); + mbedtls_ecdsa_free(&ecdsa); + return res; +} + +TEE_Result crypto_acipher_ecc_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) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_ecdsa_context ecdsa; + size_t key_size_bytes, key_size_bits = 0; + uint8_t one[1] = { 1 }; + mbedtls_mpi r; + mbedtls_mpi s; + + memset(&ecdsa, 0, sizeof(ecdsa)); + memset(&r, 0, sizeof(r)); + memset(&s, 0, sizeof(s)); + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_init(&ecdsa); + + lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, key->curve); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdsa.Q.X = *(mbedtls_mpi *)key->x; + ecdsa.Q.Y = *(mbedtls_mpi *)key->y; + mbedtls_mpi_read_binary(&ecdsa.Q.Z, one, sizeof(one)); + + res = ecc_get_keysize(key->curve, algo, + &key_size_bytes, &key_size_bits); + if (res != TEE_SUCCESS) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* check keysize vs sig_len */ + if ((key_size_bytes * 2) != sig_len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + mbedtls_mpi_read_binary(&r, sig, sig_len / 2); + mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); + + lmd_res = mbedtls_ecdsa_verify(&ecdsa.grp, msg, msg_len, &ecdsa.Q, + &r, &s); + if (lmd_res != 0) { + FMSG("mbedtls_ecdsa_verify failed, returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + } +out: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdsa.Q.X); + mbedtls_mpi_init(&ecdsa.Q.Y); + mbedtls_ecdsa_free(&ecdsa); + return res; +} + +TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, + unsigned long *secret_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + uint8_t one[1] = { 1 }; + mbedtls_ecdh_context ecdh; + size_t out_len = 0; + + memset(&ecdh, 0, sizeof(ecdh)); + mbedtls_ecdh_init(&ecdh); + lmd_res = mbedtls_ecp_group_load(&ecdh.grp, private_key->curve); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdh.d = *(mbedtls_mpi *)private_key->d; + ecdh.Qp.X = *(mbedtls_mpi *)public_key->x; + ecdh.Qp.Y = *(mbedtls_mpi *)public_key->y; + mbedtls_mpi_read_binary(&ecdh.Qp.Z, one, sizeof(one)); + + lmd_res = mbedtls_ecdh_calc_secret(&ecdh, &out_len, secret, + *secret_len, mbd_rand, NULL); + if (lmd_res != 0) { + res = get_tee_result(lmd_res); + goto out; + } + *secret_len = out_len; +out: + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdh.d); + mbedtls_mpi_init(&ecdh.Qp.X); + mbedtls_mpi_init(&ecdh.Qp.Y); + mbedtls_ecdh_free(&ecdh); + return res; +} diff --git a/lib/libmbedtls/core/stubbed.c b/lib/libmbedtls/core/stubbed.c index b8f6b895..359d6551 100644 --- a/lib/libmbedtls/core/stubbed.c +++ b/lib/libmbedtls/core/stubbed.c @@ -57,59 +57,6 @@ TEE_Result crypto_acipher_dsa_verify(uint32_t algo __unused, } #endif /* CFG_CRYPTO_DSA */ -#if defined(CFG_CRYPTO_ECC) -TEE_Result -crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s __unused, - size_t key_size_bits __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} - -TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s __unused, - size_t key_size_bits __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} - -void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s __unused) -{ -} - -TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} - -TEE_Result crypto_acipher_ecc_sign(uint32_t algo __unused, - struct ecc_keypair *key __unused, - const uint8_t *msg __unused, - size_t msg_len __unused, - uint8_t *sig __unused, - size_t *sig_len __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} - -TEE_Result crypto_acipher_ecc_verify(uint32_t algo __unused, - struct ecc_public_key *key __unused, - const uint8_t *msg __unused, - size_t msg_len __unused, - const uint8_t *sig __unused, - size_t sig_len __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} - -TEE_Result -crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key __unused, - struct ecc_public_key *public_key __unused, - void *secret __unused, - unsigned long *secret_len __unused) -{ - return TEE_ERROR_NOT_IMPLEMENTED; -} -#endif /* CFG_CRYPTO_ECC */ - /* Stubs for the crypto alloc ctx functions matching crypto_impl.h */ #undef CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED diff --git a/lib/libmbedtls/core/sub.mk b/lib/libmbedtls/core/sub.mk index ff67e18f..dc26286c 100644 --- a/lib/libmbedtls/core/sub.mk +++ b/lib/libmbedtls/core/sub.mk @@ -26,3 +26,4 @@ srcs-$(call cfg-one-enabled, CFG_CRYPTO_RSA CFG_CRYPTO_DSA \ CFG_CRYPTO_DH CFG_CRYPTO_ECC) += bignum.c srcs-$(CFG_CRYPTO_RSA) += rsa.c srcs-$(CFG_CRYPTO_DH) += dh.c +srcs-$(CFG_CRYPTO_ECC) += ecc.c diff --git a/lib/libmbedtls/include/mbedtls_config_kernel.h b/lib/libmbedtls/include/mbedtls_config_kernel.h index b3d71cdd..d8ade1d3 100644 --- a/lib/libmbedtls/include/mbedtls_config_kernel.h +++ b/lib/libmbedtls/include/mbedtls_config_kernel.h @@ -79,7 +79,7 @@ #define MBEDTLS_RSA_NO_CRT #endif -#if defined(CFG_CRYPTO_RSA) +#if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_ECC) #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif @@ -88,6 +88,24 @@ #define MBEDTLS_DHM_C #endif +#if defined(CFG_CRYPTO_ECC) +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECDH_C +#endif + #endif /*CFG_CRYPTOLIB_NAME_mbedtls*/ #include <mbedtls/check_config.h> |