This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How does SoftDevice set up permissions on characteristics? Example makes no sense.

Here is the code snippet initializing the Heart Rate Measurement Characteristic in the BleHeartRateMonitor example:

static uint32_t characteristic_init()
{
  uint32_t error_code;
  ble_gatts_char_md_t char_md;
  ble_gatts_attr_md_t cccd_md;
  ble_gatts_attr_t attr_char_value;
  ble_uuid_t ble_uuid;
  ble_gatts_attr_md_t attr_md;
  uint8_t encoded_initial_hrm[MAX_HRM_LEN];
  uint16_t attr_char_value_init_len;

  memset(&cccd_md, 0, sizeof(cccd_md));

  cccd_md.rd_auth = 1;
  cccd_md.wr_auth = 1;
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
  //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.read_perm);
  //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.write_perm);
  cccd_md.vloc = BLE_GATTS_VLOC_STACK;

  memset(&char_md, 0, sizeof(char_md));

  char_md.char_props.notify = 1;
  char_md.p_char_user_desc = NULL;
  char_md.p_char_pf = NULL;
  char_md.p_user_desc_md = NULL;
  char_md.p_cccd_md = &cccd_md;
  char_md.p_sccd_md = NULL;

  BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_HEART_RATE_MEASUREMENT_CHAR);

  memset(&attr_md, 0, sizeof(attr_md));

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
  //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
  //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm);

  attr_md.vloc = BLE_GATTS_VLOC_STACK;
  attr_md.rd_auth = 0;
  attr_md.wr_auth = 0;
  attr_md.vlen = 1;

  memset(&attr_char_value, 0, sizeof(attr_char_value));

  attr_char_value_init_len = heart_rate_measurement_encode(encoded_initial_hrm, 0);

  attr_char_value.p_uuid = &ble_uuid;
  attr_char_value.p_attr_md = &attr_md;
  attr_char_value.init_len = attr_char_value_init_len;
  attr_char_value.init_offs = 0;
  attr_char_value.max_len = MAX_HRM_LEN;
  attr_char_value.p_value = encoded_initial_hrm;

  error_code = sd_ble_gatts_characteristic_add(m_adapter, m_heart_rate_service_handle,
    &char_md,
    &attr_char_value,
    &m_heart_rate_measurement_handle);

  if (error_code != NRF_SUCCESS)
  {
    printf("Failed to initialize characteristics. Error code: 0x%02X\n", error_code);
    fflush(stdout);
    return error_code;
  }

  printf("Characteristics initiated\n");
  fflush(stdout);
  return NRF_SUCCESS;
}

My attempt here is to require pairing before the client central can enable notifications. The HR spec also states that the HR measurement characteristic is not readable or writable.

The example in the pc-ble-drive is as shown above (without my four commented rows), I am able to get measurements from my Android client app. It successfully enables the HR descriptor. 

However, the HR measurement characteristic is given read/write permissions. That should NOT be allowed according to the spec, so I commented them out. However, when I run the app and go through the spin up procedure, trying to write the CCCD for notifications fails! Why is that? The CCCDs clearly have write and read permissions.

Now what I want to do is make sure that the HR measurement is NOT readable or writable (but only 'notifyable') and to require encryption before writing the CCCD. So I would EXPECT to replace the existing CCCD permissions with

  BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.write_perm);

and give no permissions on the attribute. But in that case all I get is a failure writing the descriptor - no insufficient authentication

None of this makes sense.

How do I configure JUST the CCCD for secured write?

How do I make sure the the HR measurement itself is NOT readable or writable?

Why does commenting out the attribute read/write permissions prevent me from writing to the CCCD when the CCCD has read/write permissions?

Parents
  • Hi,

    How do I configure JUST the CCCD for secured write?

    You set the value of the cccd_write_access accordingly.

    How do I make sure the the HR measurement itself is NOT readable or writable?

    This is at least partially answered here. Essentially this is defined by the char_props, and since char_md in this code is memset to 0, anything you do not explicitly enable by setting it to 1 is disabled. Writing or reading is not allowed with this code, as you want. 

Reply
  • Hi,

    How do I configure JUST the CCCD for secured write?

    You set the value of the cccd_write_access accordingly.

    How do I make sure the the HR measurement itself is NOT readable or writable?

    This is at least partially answered here. Essentially this is defined by the char_props, and since char_md in this code is memset to 0, anything you do not explicitly enable by setting it to 1 is disabled. Writing or reading is not allowed with this code, as you want. 

Children
No Data
Related