att_db_util: added security requirement arguments to creator functions

This commit is contained in:
Matthias Ringwald 2018-04-05 12:36:48 +02:00
parent 2c37f7fbb7
commit ff04bac77c
7 changed files with 117 additions and 70 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- SM: support pairing using Out-of-Band (OOB) data with LE Secure Connections
### Changed
- att_db_util: added security requirement arguments to characteristic creators
### Fixed

View File

@ -127,7 +127,8 @@ static void att_db_util_add_attribute_uuid16(uint16_t uuid16, uint16_t flags, ui
att_db_util_set_end_tag();
}
static void att_db_util_add_attribute_uuid128(uint8_t * uuid128, uint16_t flags, uint8_t * data, uint16_t data_len){
static void att_db_util_add_attribute_uuid128(const uint8_t * uuid128, uint16_t flags, uint8_t * data, uint16_t data_len){
printf("add flags %04x\n", flags);
int size = 2 + 2 + 2 + 16 + data_len;
if (!att_db_util_assert_space(size)) return;
flags |= ATT_PROPERTY_UUID128;
@ -153,7 +154,7 @@ uint16_t att_db_util_add_service_uuid16(uint16_t uuid16){
return service_handle;
}
uint16_t att_db_util_add_service_uuid128(uint8_t * uuid128){
uint16_t att_db_util_add_service_uuid128(const uint8_t * uuid128){
uint8_t buffer[16];
reverse_128(uuid128, buffer);
uint16_t service_handle = att_db_next_handle;
@ -161,55 +162,78 @@ uint16_t att_db_util_add_service_uuid128(uint8_t * uuid128){
return service_handle;
}
static void att_db_util_add_client_characteristic_configuration(uint16_t properties){
static void att_db_util_add_client_characteristic_configuration(uint16_t flags){
uint8_t buffer[2];
// drop permission for read (0xc00), keep write permissions (0x0011)
uint16_t flags = (properties & 0x1f311) | ATT_PROPERTY_READ | ATT_PROPERTY_WRITE | ATT_PROPERTY_READ_ANYBODY | ATT_PROPERTY_DYNAMIC;
flags = (flags & 0x1f311) | ATT_PROPERTY_READ | ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC;
little_endian_store_16(buffer, 0, 0);
att_db_util_add_attribute_uuid16(GATT_CLIENT_CHARACTERISTICS_CONFIGURATION, flags, buffer, 2);
}
uint16_t att_db_util_add_characteristic_uuid16(uint16_t uuid16, uint16_t properties, uint8_t * data, uint16_t data_len){
static uint16_t att_db_util_encode_permissions(uint16_t properties, uint8_t read_permission, uint8_t write_permission){
// drop Broadcast (0x01), Notify (0x10), Indicate (0x20) - not used for flags
uint16_t flags = properties & 0xfffce;
// if encryption requested, set encryption key size to 16
if ((read_permission > ATT_SECURITY_NONE) || (write_permission > ATT_SECURITY_NONE)){
flags |= 0xf000;
}
// encode read/write security levels
if (read_permission & 1){
flags |= ATT_PROPERTY_READ_PERMISSION_BIT_0;
}
if (read_permission & 1){
flags |= ATT_PROPERTY_READ_PERMISSION_BIT_1;
}
if (write_permission & 1){
flags |= ATT_PROPERTY_WRITE_PERMISSION_BIT_0;
}
if (write_permission & 1){
flags |= ATT_PROPERTY_WRITE_PERMISSION_BIT_1;
}
return flags;
}
uint16_t att_db_util_add_characteristic_uuid16(uint16_t uuid16, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len){
uint8_t buffer[5];
buffer[0] = properties;
little_endian_store_16(buffer, 1, att_db_next_handle + 1);
little_endian_store_16(buffer, 3, uuid16);
att_db_util_add_attribute_uuid16(GATT_CHARACTERISTICS_UUID, ATT_PROPERTY_READ, buffer, sizeof(buffer));
// drop Broadcast, Notify, Indicate - not used for flags
uint16_t value_flags = properties & 0x1ffce;
uint16_t flags = att_db_util_encode_permissions(properties, read_permission, write_permission);
uint16_t value_handle = att_db_next_handle;
att_db_util_add_attribute_uuid16(uuid16, value_flags, data, data_len);
att_db_util_add_attribute_uuid16(uuid16, flags, data, data_len);
if (properties & (ATT_PROPERTY_NOTIFY | ATT_PROPERTY_INDICATE)){
att_db_util_add_client_characteristic_configuration(properties);
att_db_util_add_client_characteristic_configuration(flags);
}
return value_handle;
}
uint16_t att_db_util_add_characteristic_uuid128(uint8_t * uuid128, uint16_t properties, uint8_t * data, uint16_t data_len){
uint16_t att_db_util_add_characteristic_uuid128(const uint8_t * uuid128, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len){
uint8_t buffer[19];
buffer[0] = properties;
little_endian_store_16(buffer, 1, att_db_next_handle + 1);
reverse_128(uuid128, &buffer[3]);
att_db_util_add_attribute_uuid16(GATT_CHARACTERISTICS_UUID, ATT_PROPERTY_READ, buffer, sizeof(buffer));
// drop Broadcast, Notify, Indicate - not used for flags
uint16_t value_flags = properties & 0x1ffce;
uint16_t flags = att_db_util_encode_permissions(properties, read_permission, write_permission);
uint16_t value_handle = att_db_next_handle;
att_db_util_add_attribute_uuid128(uuid128, value_flags, data, data_len);
att_db_util_add_attribute_uuid128(uuid128, flags, data, data_len);
if (properties & (ATT_PROPERTY_NOTIFY | ATT_PROPERTY_INDICATE)){
att_db_util_add_client_characteristic_configuration(properties);
att_db_util_add_client_characteristic_configuration(flags);
}
return value_handle;
}
uint16_t att_db_util_add_descriptor_uuid16(uint16_t uuid16, uint16_t properties, uint8_t * data, uint16_t data_len){
uint16_t att_db_util_add_descriptor_uuid16(uint16_t uuid16, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len){
uint16_t descriptor_handler = att_db_next_handle;
att_db_util_add_attribute_uuid16(uuid16, properties, data, data_len);
uint16_t flags = att_db_util_encode_permissions(properties, read_permission, write_permission);
att_db_util_add_attribute_uuid16(uuid16, flags, data, data_len);
return descriptor_handler;
}
uint16_t att_db_util_add_descriptor_uuid128(uint8_t * uuid128, uint16_t properties, uint8_t * data, uint16_t data_len){
uint16_t att_db_util_add_descriptor_uuid128(const uint8_t * uuid128, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len){
uint16_t descriptor_handler = att_db_next_handle;
att_db_util_add_attribute_uuid128(uuid128, properties, data, data_len);
uint16_t flags = att_db_util_encode_permissions(properties, read_permission, write_permission);
att_db_util_add_attribute_uuid128(uuid128, flags, data, data_len);
return descriptor_handler;
}

View File

@ -64,47 +64,69 @@ void att_db_util_init(void);
/**
* @brief Add primary service for 16-bit UUID
* @param uuid16
* @returns attribute handle for the new service definition
*/
uint16_t att_db_util_add_service_uuid16(uint16_t udid16);
uint16_t att_db_util_add_service_uuid16(uint16_t uuid16);
/**
* @brief Add primary service for 128-bit UUID
* @param uuid1286
* @returns attribute handle for the new service definition
*/
uint16_t att_db_util_add_service_uuid128(uint8_t * udid128);
uint16_t att_db_util_add_service_uuid128(const uint8_t * uuid128);
/**
* @brief Add Characteristic with 16-bit UUID, properties, and data
* @param uuid16
* @param properties - see ATT_PROPERTY_* in src/bluetooth.h
* @param read_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param write_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param data returned in read operations if ATT_PROPERTY_DYNAMIC is not specified
* @param data_len
* @returns attribute handle of the new characteristic value declaration
* @note If properties contains ATT_PROPERTY_NOTIFY or ATT_PROPERTY_INDICATE flags, a Client Configuration Characteristic Descriptor (CCCD)
* is created as well. The attribute value handle of the CCCD is the attribute value handle plus 1
* @see ATT_PROPERTY_* in ble/att_db.h
*/
uint16_t att_db_util_add_characteristic_uuid16(uint16_t udid16, uint16_t properties, uint8_t * data, uint16_t data_len);
uint16_t att_db_util_add_characteristic_uuid16(uint16_t uuid16, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len);
/**
* @brief Add Characteristic with 128-bit UUID, properties, and data
* @param uuid128
* @param properties - see ATT_PROPERTY_* in src/bluetooth.h
* @param read_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param write_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param data returned in read operations if ATT_PROPERTY_DYNAMIC is not specified
* @param data_len
* @returns attribute handle of the new characteristic value declaration
* @note If properties contains ATT_PROPERTY_NOTIFY or ATT_PROPERTY_INDICATE flags, a Client Configuration Characteristic Descriptor (CCCD)
* is created as well. The attribute value handle of the CCCD is the attribute value handle plus 1
* @see ATT_PROPERTY_* in ble/att_db.h
*/
uint16_t att_db_util_add_characteristic_uuid128(uint8_t * udid128, uint16_t properties, uint8_t * data, uint16_t data_len);
/**
* @brief Add descriptor with 16-bit UUID, properties, and data
* @returns attribute handle of the new descriptor
* @see ATT_PROPERTY_* in ble/att_db.h
*/
uint16_t att_db_util_add_descriptor_uuid16(uint16_t uuid16, uint16_t properties, uint8_t * data, uint16_t data_len);
uint16_t att_db_util_add_characteristic_uuid128(const uint8_t * uuid128, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len);
/**
* @brief Add descriptor with 128-bit UUID, properties, and data
* @param uuid16
* @param properties - see ATT_PROPERTY_* in src/bluetooth.h
* @param read_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param write_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param data returned in read operations if ATT_PROPERTY_DYNAMIC is not specified
* @param data_len
* @returns attribute handle of the new characteristic descriptor declaration
* @see ATT_PROPERTY_* in ble/att_db.h
*/
uint16_t att_db_util_add_descriptor_uuid128(uint8_t * udid128, uint16_t properties, uint8_t * data, uint16_t data_len);
uint16_t att_db_util_add_descriptor_uuid16(uint16_t uuid16, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len);
/**
* @brief Add descriptor with 128-bit UUID, properties, and data
* @param uuid16
* @param properties - see ATT_PROPERTY_* in src/bluetooth.h
* @param read_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param write_permissions - see ATT_SECURITY_* in src/bluetooth.h
* @param data returned in read operations if ATT_PROPERTY_DYNAMIC is not specified
* @param data_len
* @returns attribute handle of the new characteristic descriptor declaration
*/
uint16_t att_db_util_add_descriptor_uuid128(const uint8_t * uuid128, uint16_t properties, uint8_t read_permission, uint8_t write_permission, uint8_t * data, uint16_t data_len);
/**
* @brief Get address of constructed ATT DB

View File

@ -1100,6 +1100,14 @@ typedef enum {
// MARK: Attribute Property Flag, BTstack extension
// value is asked from client
#define ATT_PROPERTY_DYNAMIC 0x100
// Security levels
#define ATT_SECURITY_NONE 0
#define ATT_SECURITY_ENCRYPTED 1
#define ATT_SECURITY_AUTHENTICATED 2
#define ATT_SECURITY_AUTHORIZED 3
// internal additions
// 128 bit UUID used
#define ATT_PROPERTY_UUID128 0x200
// Read/Write Permission bits
@ -1107,22 +1115,7 @@ typedef enum {
#define ATT_PROPERTY_READ_PERMISSION_BIT_1 0x0800
#define ATT_PROPERTY_WRITE_PERMISSION_BIT_0 0x0001
#define ATT_PROPERTY_WRITE_PERMISSION_BIT_1 0x0010
// Security levels
#define ATT_SECURITY_NONE 0
#define ATT_SECURITY_ENCRYPTED 1
#define ATT_SECURITY_AUTHENTICATED 2
#define ATT_SECURITY_AUTHORIZED 3
// Masks for use with att_db_util function
#define ATT_PROPERTY_READ_ANYBODY (0)
#define ATT_PROPERTY_READ_ENCRYPTED (ATT_PROPERTY_READ_PERMISSION_BIT_0)
#define ATT_PROPERTY_READ_AUTHENTICATED (ATT_PROPERTY_READ_PERMISSION_BIT_1)
#define ATT_PROPERTY_READ_AUTHORIZED (ATT_PROPERTY_READ_PERMISSION_BIT_0|ATT_PROPERTY_READ_PERMISSION_BIT_1)
#define ATT_PROPERTY_WRITE_ANYBODY (0)
#define ATT_PROPERTY_WRITE_ENCRYPTED (ATT_PROPERTY_WRITE_PERMISSION_BIT_0)
#define ATT_PROPERTY_WRITE_AUTHENTICATED (ATT_PROPERTY_WRITE_PERMISSION_BIT_1)
#define ATT_PROPERTY_WRITE_AUTHORIZED (ATT_PROPERTY_WRITE_PERMISSION_BIT_0|ATT_PROPERTY_WRITE_PERMISSION_BIT_1)
// Encryption key size stored in upper 4 bits, 0 == no encryption, encryption key size - 1 otherwise
// ATT Transaction Timeout of 30 seconds for Command/Response or Indication/Confirmation
#define ATT_TRANSACTION_TIMEOUT_MS 30000

View File

@ -55,20 +55,7 @@
#include "btstack_util.h"
#include "bluetooth.h"
#include "le_counter.h"
#if 0
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SPP+LE Counter"
PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
// Counter Service
PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
// Counter Characteristic, with read and notify
CHARACTERISTIC, 0000FF11-0000-1000-8000-00805F9B34FB, READ | NOTIFY | DYNAMIC,
#endif
#include "att_db_util_test.h"
// 0000FF10-0000-1000-8000-00805F9B34FB
uint8_t counter_service_uuid[] = { 0x00, 0x00, 0xFF, 0x10, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
@ -77,7 +64,7 @@ uint8_t counter_characteristic_uuid[] = { 0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x
void CHECK_EQUAL_ARRAY(const uint8_t * expected, uint8_t * actual, int size){
for (int i=0; i<size; i++){
// printf("%03u: %02x - %02x\n", i, expected[i], actual[i]);
printf("%03u: %02x - %02x\n", i, expected[i], actual[i]);
BYTES_EQUAL(expected[i], actual[i]);
}
}
@ -96,17 +83,19 @@ TEST_GROUP(AttDbUtil){
TEST(AttDbUtil, LeCounterDb){
att_db_util_add_service_uuid16(GAP_SERVICE_UUID);
att_db_util_add_characteristic_uuid16(GAP_DEVICE_NAME_UUID, ATT_PROPERTY_READ, (uint8_t*)"SPP+LE Counter", 14);
att_db_util_add_characteristic_uuid16(GAP_DEVICE_NAME_UUID, ATT_PROPERTY_READ, ATT_SECURITY_NONE, ATT_SECURITY_NONE, (uint8_t*)"SPP+LE Counter", 14);
att_db_util_add_service_uuid16(0x1801);
att_db_util_add_characteristic_uuid16(0x2a05, ATT_PROPERTY_READ, NULL, 0);
att_db_util_add_characteristic_uuid16(0x2a05, ATT_PROPERTY_READ, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
att_db_util_add_service_uuid128(counter_service_uuid);
att_db_util_add_characteristic_uuid128(counter_characteristic_uuid, ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY | ATT_PROPERTY_DYNAMIC, NULL, 0);
att_db_util_add_characteristic_uuid128(counter_characteristic_uuid, ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
uint8_t * addr = att_db_util_get_address();
uint16_t size = att_db_util_get_size();
printf_hexdump(addr, size);
CHECK_EQUAL(size, (uint16_t)sizeof(profile_data));
CHECK_EQUAL_ARRAY(profile_data, addr, size);
}

View File

@ -0,0 +1,10 @@
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SPP+LE Counter"
PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
// Counter Service
PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
// Counter Characteristic, with read and notify
CHARACTERISTIC, 0000FF11-0000-1000-8000-00805F9B34FB, READ | NOTIFY | DYNAMIC,

View File

@ -1,18 +1,23 @@
// le_counter.h generated from le_counter.gatt for BTstack
// att_db_util_test.h generated from att_db_util_test.gatt for BTstack
// att db format version 1
// binary representation
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
// binary attribute representation:
// - size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#include <stdint.h>
const uint8_t profile_data[] =
{
// ATT DB Version
1,
// 0x0001 PRIMARY_SERVICE-GAP_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,
// 0x0002 CHARACTERISTIC-GAP_DEVICE_NAME-READ
0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a,
// 0x0003 VALUE-GAP_DEVICE_NAME-READ-'SPP+LE Counter'
// READ_ANYBODY
0x16, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x2a, 0x53, 0x50, 0x50, 0x2b, 0x4c, 0x45, 0x20, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
// 0x0004 PRIMARY_SERVICE-GATT_SERVICE
@ -20,6 +25,7 @@ const uint8_t profile_data[] =
// 0x0005 CHARACTERISTIC-GATT_SERVICE_CHANGED-READ
0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x02, 0x06, 0x00, 0x05, 0x2a,
// 0x0006 VALUE-GATT_SERVICE_CHANGED-READ-''
// READ_ANYBODY
0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x05, 0x2a,
// Counter Service
@ -29,9 +35,11 @@ const uint8_t profile_data[] =
// 0x0008 CHARACTERISTIC-0000FF11-0000-1000-8000-00805F9B34FB-READ | NOTIFY | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x03, 0x28, 0x12, 0x09, 0x00, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x11, 0xff, 0x00, 0x00,
// 0x0009 VALUE-0000FF11-0000-1000-8000-00805F9B34FB-READ | NOTIFY | DYNAMIC-''
// READ_ANYBODY
0x16, 0x00, 0x02, 0x03, 0x09, 0x00, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x11, 0xff, 0x00, 0x00,
// 0x000a CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0b, 0x01, 0x0a, 0x00, 0x02, 0x29, 0x00, 0x00,
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0a, 0x01, 0x0a, 0x00, 0x02, 0x29, 0x00, 0x00,
// END
0x00, 0x00,