From 7ea72026cde2d9c9e0cc6141f0d8f34493163189 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 21 Jun 2023 20:39:08 +0200 Subject: [PATCH] New function mbedtls_ecp_keypair_calc_public For when you calculate or import a private key, and then need to calculate the public key. Signed-off-by: Gilles Peskine --- include/mbedtls/ecp.h | 17 ++++++++++++++ library/ecp.c | 8 +++++++ tests/suites/test_suite_ecp.data | 18 +++++++++++++++ tests/suites/test_suite_ecp.function | 34 ++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 96f030d1f2..1847f2cb2c 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -1365,6 +1365,23 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +/** \brief Calculate the public key from a private key in a key pair. + * + * \param key A keypair structure. It must have a private key set. + * If the public key is set, it will be overwritten. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. + * + * \return \c 0 on success. The key pair object can be used for + * operations that require the public key. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_keypair_calc_public( + mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + /** \brief Query the group that a key pair belongs to. * * \param key The key pair to query. diff --git a/library/ecp.c b/library/ecp.c index bb0cf6905c..43f7d6930a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -3374,6 +3374,14 @@ cleanup: return ret; } + +int mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, + f_rng, p_rng); +} #endif /* MBEDTLS_ECP_C */ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 8bf288b79e..01fdc477f7 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -529,6 +529,24 @@ ECP check public-private #7 (wrong Qy) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED mbedtls_ecp_check_pub_priv:MBEDTLS_ECP_DP_SECP256R1:"37cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f76822596292":"4ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edfe":MBEDTLS_ECP_DP_SECP256R1:"00f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":"37cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f76822596292":"4ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edfe":MBEDTLS_ERR_ECP_BAD_INPUT_DATA +ECP calculate public: secp256r1, good +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_calc_public:MBEDTLS_ECP_DP_SECP256R1:"00f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":0:"0437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edff" + +ECP calculate public: secp256r1, private value out of range +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_calc_public:MBEDTLS_ECP_DP_SECP256R1:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":MBEDTLS_ERR_ECP_INVALID_KEY:"" + +# Alice's private key from rfc 7748, masked and adjusted for endianness +# because the test function wants the little-endian representation. +ECP calculate public: Curve25519, good +depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED +ecp_calc_public:MBEDTLS_ECP_DP_CURVE25519:"6a2cb91da5fb77b12a99c0eb872f4cdf4566b25172c1163c7da518730a6d0770":0:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" + +ECP calculate public: Curve25519, private value not masked +depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED +ecp_calc_public:MBEDTLS_ECP_DP_CURVE25519:"2a2cb91da5fb77b12a99c0eb872f4cdf4566b25172c1163c7da518730a6d0770":MBEDTLS_ERR_ECP_INVALID_KEY:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" + ECP gen keypair [#1] depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED mbedtls_ecp_gen_keypair:MBEDTLS_ECP_DP_SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 53b78d9009..8c8d32699d 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -988,6 +988,40 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_C */ +void ecp_calc_public(int grp_id, data_t *private, + int expected_ret, data_t *expected_public) +{ + mbedtls_ecp_keypair key; + mbedtls_ecp_keypair_init(&key); + mbedtls_test_rnd_pseudo_info rnd_info; + memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); + + TEST_EQUAL(mbedtls_ecp_group_load(&key.grp, grp_id), 0); + TEST_EQUAL(mbedtls_mpi_read_binary(&key.d, private->x, private->len), 0); + + TEST_EQUAL(mbedtls_ecp_keypair_calc_public(&key, + &mbedtls_test_rnd_pseudo_rand, &rnd_info), + expected_ret); + + if (expected_ret == 0) { + TEST_EQUAL(mbedtls_ecp_check_pub_priv(&key, &key, + &mbedtls_test_rnd_pseudo_rand, &rnd_info), + 0); + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + size_t length; + TEST_EQUAL(mbedtls_ecp_point_write_binary(&key.grp, &key.Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &length, buf, sizeof(buf)), + 0); + ASSERT_COMPARE(expected_public->x, expected_public->len, buf, length); + } + +exit: + mbedtls_ecp_keypair_free(&key); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_ECP_C */ void mbedtls_ecp_gen_keypair(int id) {