New function mbedtls_ecp_set_public_key

Set the public key in a key pair. This complements mbedtls_ecp_read_key and
the functions can be used in either order.

Document the need to call check functions separately.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2023-06-21 19:52:11 +02:00
parent 091a85a762
commit 28240323d3
4 changed files with 196 additions and 0 deletions

View file

@ -1259,6 +1259,38 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng); void *p_rng);
/** \brief Set the public key in a key pair object.
*
* \note This function does not check that the point actually
* belongs to the given group. Call mbedtls_ecp_check_pubkey()
* on \p Q before calling this function to check that.
*
* \note This function does not check that the public key matches
* the private key that is already in \p key, if any.
* To check the consistency of the resulting key pair object,
* call mbedtls_ecp_check_pub_priv() after setting both
* the public key and the private key.
*
* \param grp_id The ECP group identifier.
* \param key The key pair object. It must be initialized.
* If its group has already been set, it must match \p grp_id.
* If its group has not been set, it will be set to \p grp_id.
* If the public key has already been set, it is overwritten.
* \param Q The public key to copy. This must be a point on the
* curve indicated by \p grp_id.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p key does not
* match \p grp_id.
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
* the group is not implemented.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
* \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,
mbedtls_ecp_keypair *key,
const mbedtls_ecp_point *Q);
/** /**
* \brief This function reads an elliptic curve private key. * \brief This function reads an elliptic curve private key.
* *

View file

@ -3198,6 +3198,25 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
} }
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,
mbedtls_ecp_keypair *key,
const mbedtls_ecp_point *Q)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (key->grp.id == MBEDTLS_ECP_DP_NONE) {
/* Group not set yet */
if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {
return ret;
}
} else if (key->grp.id != grp_id) {
/* Group mismatch */
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
return mbedtls_ecp_copy(&key->Q, Q);
}
#define ECP_CURVE25519_KEY_SIZE 32 #define ECP_CURVE25519_KEY_SIZE 32
#define ECP_CURVE448_KEY_SIZE 56 #define ECP_CURVE448_KEY_SIZE 56
/* /*

View file

@ -581,6 +581,48 @@ genkey_mx_known_answer:447:"ffffffffffffffffffffffffffffffffffffffffffffffffffff
ECP generate Montgomery key: Curve448, not enough entropy ECP generate Montgomery key: Curve448, not enough entropy
genkey_mx_known_answer:447:"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536":"" genkey_mx_known_answer:447:"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536":""
ECP set public key: invalid group (0)
ecp_set_public_key_group_check:MBEDTLS_ECP_DP_NONE:MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
ECP set public key: valid group (secp256r1)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_set_public_key_group_check:MBEDTLS_ECP_DP_SECP256R1:0
ECP set public key: group not supported (secp256r1)
depends_on:!MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_set_public_key_group_check:MBEDTLS_ECP_DP_SECP256R1:MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
ECP set public key: bad group (not in enum)
ecp_set_public_key_group_check:MBEDTLS_ECP_DP_MAX:MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
ECP set public key: good, secp256r1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_set_public_key_good:MBEDTLS_ECP_DP_SECP256R1:"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579"
ECP set public key: good, Curve25519
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_set_public_key_good:MBEDTLS_ECP_DP_CURVE25519:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
ECP set public key after private: good, secp256r1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_set_public_key_after_private:MBEDTLS_ECP_DP_SECP256R1:"70726976617465206b6579":MBEDTLS_ECP_DP_SECP256R1:"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579"
ECP set public key after private: good, Curve25519
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_set_public_key_after_private:MBEDTLS_ECP_DP_CURVE25519:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":MBEDTLS_ECP_DP_CURVE25519:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
ECP set public key after private: secp256r1 then secp256k1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP256K1_ENABLED
ecp_set_public_key_after_private:MBEDTLS_ECP_DP_SECP256R1:"70726976617465206b6579":MBEDTLS_ECP_DP_SECP256K1:"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579"
ECP set public key after private: secp256r1 then secp384r1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_set_public_key_after_private:MBEDTLS_ECP_DP_SECP256R1:"70726976617465206b6579":MBEDTLS_ECP_DP_SECP384R1:"04aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaae1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
ECP set public key after private: secp384r1 then secp256r1
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_set_public_key_after_private:MBEDTLS_ECP_DP_SECP384R1:"70726976617465206b6579":MBEDTLS_ECP_DP_SECP256R1:"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579"
ECP read key #1 (short weierstrass, too small) ECP read key #1 (short weierstrass, too small)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
mbedtls_ecp_read_key:MBEDTLS_ECP_DP_SECP192R1:"00":MBEDTLS_ERR_ECP_INVALID_KEY:0 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_SECP192R1:"00":MBEDTLS_ERR_ECP_INVALID_KEY:0

View file

@ -1039,6 +1039,109 @@ exit:
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void ecp_set_public_key_group_check(int grp_id, int expected_ret)
{
mbedtls_ecp_keypair key;
mbedtls_ecp_keypair_init(&key);
mbedtls_ecp_point Q;
mbedtls_ecp_point_init(&Q);
TEST_EQUAL(mbedtls_ecp_set_public_key(grp_id, &key, &Q),
expected_ret);
exit:
mbedtls_ecp_keypair_free(&key);
mbedtls_ecp_point_free(&Q);
}
/* END_CASE */
/* BEGIN_CASE */
void ecp_set_public_key_good(int grp_id, data_t *public_data)
{
mbedtls_ecp_keypair key;
mbedtls_ecp_keypair_init(&key);
mbedtls_ecp_group grp;
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point Q;
mbedtls_ecp_point_init(&Q);
TEST_EQUAL(mbedtls_ecp_group_load(&grp, grp_id), 0);
TEST_EQUAL(mbedtls_ecp_point_read_binary(&grp, &Q,
public_data->x, public_data->len),
0);
/* Freshly initialized key */
TEST_EQUAL(mbedtls_ecp_set_public_key(grp_id, &key, &Q), 0);
TEST_EQUAL(key.grp.id, grp_id);
TEST_EQUAL(mbedtls_ecp_point_cmp(&key.Q, &Q), 0);
#if defined(MBEDTLS_BIGNUM_C)
/* Key with a public key already set to a different value */
TEST_EQUAL(mbedtls_mpi_add_int(&key.Q.X, &key.Q.X, 1), 0);
TEST_EQUAL(mbedtls_mpi_add_int(&key.Q.Y, &key.Q.Y, 1), 0);
TEST_EQUAL(mbedtls_mpi_add_int(&key.Q.Z, &key.Q.Z, 1), 0);
TEST_EQUAL(mbedtls_ecp_set_public_key(grp_id, &key, &Q), 0);
TEST_EQUAL(key.grp.id, grp_id);
TEST_EQUAL(mbedtls_ecp_point_cmp(&key.Q, &Q), 0);
#endif
exit:
mbedtls_ecp_keypair_free(&key);
mbedtls_ecp_group_free(&grp);
mbedtls_ecp_point_free(&Q);
}
/* END_CASE */
/* BEGIN_CASE */
void ecp_set_public_key_after_private(int private_grp_id, data_t *private_data,
int public_grp_id, data_t *public_data)
{
mbedtls_ecp_keypair key;
mbedtls_ecp_keypair_init(&key);
mbedtls_ecp_group grp;
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point Q;
mbedtls_ecp_point_init(&Q);
#if defined(MBEDTLS_BIGNUM_C)
mbedtls_mpi d;
mbedtls_mpi_init(&d);
#endif
TEST_EQUAL(mbedtls_ecp_group_load(&grp, public_grp_id), 0);
TEST_EQUAL(mbedtls_ecp_point_read_binary(&grp, &Q,
public_data->x, public_data->len),
0);
TEST_EQUAL(mbedtls_ecp_read_key(private_grp_id, &key,
private_data->x, private_data->len),
0);
#if defined(MBEDTLS_BIGNUM_C)
TEST_EQUAL(mbedtls_mpi_copy(&d, &key.d), 0);
#endif
int ret = mbedtls_ecp_set_public_key(public_grp_id, &key, &Q);
if (private_grp_id == public_grp_id) {
TEST_EQUAL(ret, 0);
TEST_EQUAL(key.grp.id, public_grp_id);
TEST_EQUAL(mbedtls_ecp_point_cmp(&key.Q, &Q), 0);
#if defined(MBEDTLS_BIGNUM_C)
TEST_EQUAL(mbedtls_mpi_cmp_mpi(&d, &key.d), 0);
#endif
} else {
TEST_EQUAL(ret, MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
}
exit:
mbedtls_ecp_keypair_free(&key);
mbedtls_ecp_group_free(&grp);
mbedtls_ecp_point_free(&Q);
#if defined(MBEDTLS_BIGNUM_C)
mbedtls_mpi_free(&d);
#endif
}
/* END_CASE */
/* BEGIN_CASE */ /* BEGIN_CASE */
void mbedtls_ecp_read_key(int grp_id, data_t *in_key, int expected, int canonical) void mbedtls_ecp_read_key(int grp_id, data_t *in_key, int expected, int canonical)
{ {