mirror of https://github.com/ARMmbed/mbed-os.git
Nordic BLE: Update GATT server security management
This patch refines permission applied to characteristic and descriptors; instead of a single level of permission , each characteristic receives a permission for the read operation, one for the write operation and another one for the update operation. As a consequence, updates are not sent if the link does not cover the update permission requirement. Descriptors also benefits individually from read and write permission.pull/6932/head
parent
4f1e574eff
commit
0a59e00b23
|
@ -30,6 +30,34 @@ typedef struct {
|
|||
static unsigned uuidTableEntries = 0; /* current usage of the table */
|
||||
converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
|
||||
|
||||
namespace {
|
||||
|
||||
static void set_perm(ble_gap_conn_sec_mode_t& dest, GattAttribute::Security_t src) {
|
||||
switch (src.value()) {
|
||||
case GattAttribute::Security_t::NONE:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dest);
|
||||
break;
|
||||
|
||||
case GattAttribute::Security_t::UNAUTHENTICATED:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dest);
|
||||
break;
|
||||
|
||||
case GattAttribute::Security_t::AUTHENTICATED:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&dest);
|
||||
break;
|
||||
|
||||
case GattAttribute::Security_t::SC_AUTHENTICATED:
|
||||
BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dest);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void custom_reset_128bits_uuid_table() {
|
||||
uuidTableEntries = 0;
|
||||
}
|
||||
|
@ -203,7 +231,9 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
|
|||
error_t custom_add_in_characteristic(uint16_t service_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t properties,
|
||||
SecurityManager::SecurityMode_t requiredSecurity,
|
||||
GattAttribute::Security_t read_security,
|
||||
GattAttribute::Security_t write_security,
|
||||
GattAttribute::Security_t update_security,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
|
@ -226,8 +256,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
|
|||
/* Notification requires cccd */
|
||||
memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t));
|
||||
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
|
||||
set_perm(cccd_md.read_perm, GattAttribute::Security_t::NONE);
|
||||
set_perm(cccd_md.write_perm, update_security);
|
||||
}
|
||||
|
||||
ble_gatts_char_md_t char_md = {0};
|
||||
|
@ -256,49 +286,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
|
|||
/* Always set variable size */
|
||||
attr_md.vlen = has_variable_len;
|
||||
|
||||
if (char_props.read || char_props.notify || char_props.indicate) {
|
||||
switch (requiredSecurity) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if (char_props.write || char_props.write_wo_resp) {
|
||||
switch (requiredSecurity) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
set_perm(attr_md.read_perm, read_security);
|
||||
set_perm(attr_md.write_perm, write_security);
|
||||
|
||||
ble_gatts_attr_t attr_char_value = {0};
|
||||
|
||||
|
@ -342,7 +331,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle,
|
|||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
uint16_t *p_desc_handle)
|
||||
uint16_t *p_desc_handle,
|
||||
GattAttribute::Security_t read_security,
|
||||
GattAttribute::Security_t write_security)
|
||||
{
|
||||
/* Descriptor metadata */
|
||||
ble_gatts_attr_md_t desc_md = {0};
|
||||
|
@ -352,8 +343,8 @@ error_t custom_add_in_descriptor(uint16_t char_handle,
|
|||
desc_md.vlen = has_variable_len;
|
||||
|
||||
/* Make it readable and writable */
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm);
|
||||
set_perm(desc_md.read_perm, read_security);
|
||||
set_perm(desc_md.write_perm, write_security);
|
||||
|
||||
ble_gatts_attr_t attr_desc = {0};
|
||||
|
||||
|
|
|
@ -45,7 +45,9 @@ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid);
|
|||
error_t custom_add_in_characteristic(uint16_t service_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t properties,
|
||||
SecurityManager::SecurityMode_t requiredSecurity,
|
||||
GattAttribute::Security_t read_security,
|
||||
GattAttribute::Security_t write_security,
|
||||
GattAttribute::Security_t update_security,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
|
@ -64,7 +66,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle,
|
|||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
uint16_t *p_desc_handle);
|
||||
uint16_t *p_desc_handle,
|
||||
GattAttribute::Security_t read_security,
|
||||
GattAttribute::Security_t write_security);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "btle/custom/custom_helper.h"
|
||||
|
||||
#include "nRF5xn.h"
|
||||
#include "nrf_ble_gap.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -164,21 +165,25 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
}
|
||||
|
||||
ASSERT_TRUE ( ERROR_NONE ==
|
||||
custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID,
|
||||
&nordicUUID,
|
||||
p_char->getProperties(),
|
||||
p_char->getRequiredSecurity(),
|
||||
p_char->getValueAttribute().getValuePtr(),
|
||||
p_char->getValueAttribute().getLength(),
|
||||
p_char->getValueAttribute().getMaxLength(),
|
||||
p_char->getValueAttribute().hasVariableLength(),
|
||||
userDescriptionDescriptorValuePtr,
|
||||
userDescriptionDescriptorValueLen,
|
||||
presentationFormatDescriptorValuePtr,
|
||||
presentationFormatDescriptorValueLen,
|
||||
p_char->isReadAuthorizationEnabled(),
|
||||
p_char->isWriteAuthorizationEnabled(),
|
||||
&nrfCharacteristicHandles[characteristicCount]),
|
||||
custom_add_in_characteristic(
|
||||
BLE_GATT_HANDLE_INVALID,
|
||||
&nordicUUID,
|
||||
p_char->getProperties(),
|
||||
p_char->getReadSecurityRequirement(),
|
||||
p_char->getWriteSecurityRequirement(),
|
||||
p_char->getUpdateSecurityRequirement(),
|
||||
p_char->getValueAttribute().getValuePtr(),
|
||||
p_char->getValueAttribute().getLength(),
|
||||
p_char->getValueAttribute().getMaxLength(),
|
||||
p_char->getValueAttribute().hasVariableLength(),
|
||||
userDescriptionDescriptorValuePtr,
|
||||
userDescriptionDescriptorValueLen,
|
||||
presentationFormatDescriptorValuePtr,
|
||||
presentationFormatDescriptorValueLen,
|
||||
p_char->isReadAuthorizationEnabled(),
|
||||
p_char->isWriteAuthorizationEnabled(),
|
||||
&nrfCharacteristicHandles[characteristicCount]
|
||||
),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
|
||||
/* Update the characteristic handle */
|
||||
|
@ -218,7 +223,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
p_desc->getLength(),
|
||||
p_desc->getMaxLength(),
|
||||
p_desc->hasVariableLength(),
|
||||
&nrfDescriptorHandles[descriptorCount]),
|
||||
&nrfDescriptorHandles[descriptorCount],
|
||||
p_desc->getReadSecurityRequirement(),
|
||||
p_desc->getWriteSecurityRequirement()),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
|
||||
p_descriptors[descriptorCount] = p_desc;
|
||||
|
@ -345,7 +352,16 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute
|
|||
}
|
||||
}
|
||||
|
||||
if (updatesEnabled) {
|
||||
bool updates_permitted = false;
|
||||
ble_gap_conn_sec_t connection_security;
|
||||
uint32_t err = sd_ble_gap_conn_sec_get(connectionHandle, &connection_security);
|
||||
if (!err &&
|
||||
(connection_security.sec_mode.sm == 1) &&
|
||||
(connection_security.sec_mode.lv >= p_characteristics[characteristicIndex]->getUpdateSecurityRequirement().value())) {
|
||||
updates_permitted = true;
|
||||
}
|
||||
|
||||
if (updatesEnabled && updates_permitted) {
|
||||
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
||||
if (error != ERROR_NONE) {
|
||||
switch (error) {
|
||||
|
|
Loading…
Reference in New Issue