Bluetooth: Host: SMP: Verify public key before usage

Add a separate test for public key validity. This needs to be done
synchronously so that we can respond with an early failure message to the
peer device.

Fixes #80218

Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
This commit is contained in:
Johan Hedberg 2024-12-09 16:08:36 +02:00 committed by Benjamin Cabé
commit 880384a20e
3 changed files with 45 additions and 0 deletions

View file

@ -7,9 +7,12 @@
#include <stdint.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/check.h>
#include <zephyr/bluetooth/hci.h>
#include <psa/crypto.h>
#include "ecc.h"
#include "hci_core.h"
@ -39,6 +42,35 @@ bool bt_pub_key_is_debug(uint8_t *cmp_pub_key)
return memcmp(cmp_pub_key, debug_public_key, BT_PUB_KEY_LEN) == 0;
}
bool bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN])
{
uint8_t key_be[BT_PUB_KEY_LEN + 1];
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t ret;
psa_key_id_t handle;
psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attr, 256);
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
/* PSA expects secp256r1 public key to start with a predefined 0x04 byte */
key_be[0] = 0x04;
sys_memcpy_swap(&key_be[1], key, BT_PUB_KEY_COORD_LEN);
sys_memcpy_swap(&key_be[1 + BT_PUB_KEY_COORD_LEN], &key[BT_PUB_KEY_COORD_LEN],
BT_PUB_KEY_COORD_LEN);
ret = psa_import_key(&attr, key_be, sizeof(key_be), &handle);
psa_reset_key_attributes(&attr);
if (ret == PSA_SUCCESS) {
psa_destroy_key(handle);
return true;
}
return false;
}
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
{
struct bt_pub_key_cb *cb;

View file

@ -44,6 +44,16 @@ struct bt_pub_key_cb {
*/
bool bt_pub_key_is_debug(uint8_t *cmp_pub_key);
/* @brief Check if public key is valid.
*
* Verify that the public key is valid, e.g. that its coordinates lie on the eliptic curve.
*
* @param key The public key to validate.
*
* @return True if the public key is valid.
*/
bool bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN]);
/* @brief Generate a new Public Key.
*
* Generate a new ECC Public Key. Provided cb must persists until callback

View file

@ -4311,6 +4311,9 @@ static uint8_t smp_public_key(struct bt_smp *smp, struct net_buf *buf)
if (!update_debug_keys_check(smp)) {
return BT_SMP_ERR_AUTH_REQUIREMENTS;
}
} else if (!bt_pub_key_is_valid(smp->pkey)) {
LOG_WRN("Received invalid public key");
return BT_SMP_ERR_INVALID_PARAMS;
}
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&