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

not able to set system attributes using sd_ble_gatts_sys_attr_set

Hello

I'm trying to reenable notifications on a characteristic from GATTS side

The device is 52810 running a custom service and this is the piece of code where i use

 err_code = sd_ble_gatts_sys_attr_get(m_service.conn_handle, 0, &attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
 err_code = sd_ble_gatts_sys_attr_get(m_service.conn_handle, sys_attr_data, &attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
      
      for(uint8_t i = 0; i < attr_len; i+= 6)
        {
        if(sys_attr_data[i] == iterator->value_handles.cccd_handle && sys_attr_data[i + 4] == 0)
          {
          sys_attr_data[i + 4] = 1;
          crc = crc16_compute(sys_attr_data, attr_len - 2, NULL);
          sys_attr_data[attr_len - 2] = crc & 0xff;
          sys_attr_data[attr_len - 1] = crc >> 8;
          err_code = sd_ble_gatts_sys_attr_set(m_service.conn_handle, sys_attr_data, attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);    // initialize cccd attribute
          NRF_LOG_INFO("sys attr set: %2x / %2x %2x %2x", err_code, sys_attr_data[0], sys_attr_data[2], sys_attr_data[4]);
          memset(sys_attr_data, 0, 32);
          err_code = sd_ble_gatts_sys_attr_get(m_service.conn_handle, sys_attr_data, &attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
          NRF_LOG_INFO("sys attr get: %2x / %2x %2x %2x", err_code, sys_attr_data[0], sys_attr_data[2], sys_attr_data[4]);
          break;
          }
        }

log output is like this

[00:00:49.204,101] <info> app: sys attr set: 0 / E 2 1
[00:00:49.204,162] <info> app: sys attr get: 0 / E 2 0

The value set is 1 and the value get is 0, return value for both calls ...set() and ...get() is NRF_SUCCESS

can someone suggest how to set the value?

Parents
  • Hi Sigurd

    If PM is able to restore this value i would expect the application could update it also.
    But i don't understand your comment "Only the first call to sd_ble_gatts_sys_attr_set() will have an effect. The second call does nothing and returns SUCCESS."
    Can you give more details here?

    Let me give some more background for this need maybe you can give other suggestions.
    The peripheral as embedded device falls in the category NoInputNoOutput so not much of security can be implemented. Only "it just works unauthenticated".
    This makes the peripheral easy to hack with MITM
    To reduce the damage i can encrypt any data transfer so the malicious device cannot use it, but i cannot encrypt the requests.
    I cannot prevent the malicious device to enable/disable notifications, which might be critical especially in the case of disabling notifications.
    This is the reason I need to validate such request with a prior encrypted message.
    If the authorized device wants to disable notifications, first send the message and second the request.
    When the gatt server on the peripheral receive a disable notification request which is not enabled by previous message, then the application on the peripheral will reenable notifications again using sd_ble_gatts_sys_attr_set.

    Do you think this is a reasonable approach?

  • Hi,

    ves said:
    But i don't understand your comment "Only the first call to sd_ble_gatts_sys_attr_set() will have an effect. The second call does nothing and returns SUCCESS."
    Can you give more details here?

    Bonded devices need to retain the CCCDs values, and restore it on re-connection. Peer Manager handles this for you(saves the values to flash, and restores them when a bonded device connects again). The sd_ble_gatts_sys_attr_set() is implemented for this use-case. 

    ves said:
    Do you think this is a reasonable approach?

    The way to handle this is by configuring the CCCD for the characteristics. Set the CCCD write access to SEC_JUST_WORKS, so that only a link with 'Just Works' security at least is allowed to write to the CCCD. Then, if you want the application to decide if the write request for the CCCD should succeed or not(even if the link is encrypted with Just Works), then you need to configure the CCCD for authorization (cccd_md.wr_auth = 1). The application will then get the event BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST for all write requests, and it needs to reply to it by using the function sd_ble_gatts_rw_authorize_reply(). Let me know if you want's some code snippets on how to do this. Message Sequence Chart: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s112.api.v7.0.1%2Fgroup___b_l_e___g_a_t_t_s___w_r_i_t_e___r_e_q___a_u_t_h___m_s_c.html

  • Hi Sigurd

    Thx for the very good hint!
    Much better the way you suggested. In your way i don't need any more to check cccd status each time i have to send a notification. I just need to allow notification state change only if validated in step 1.

    ... but even my problem is solved now, i cannot mark this ticket as answered
    The ticket headline is "not able to set system attributes using sd_ble_gatts_sys_attr_set"
    I did some investigations and got the behavior you pointed to: only the first call of sd_ble_gatts_sys_attr_set has effect next calls looks to be ignored.
    I checked this by completely disabling peer manager in my application and i can see the first call can change the value form 0 to 1.
    But as soon as i enable/disable notifications from client side further calls to sd_ble_gatts_sys_attr_set() have no effect. I mean regarding cccd (did not test for other system attributes).
    Can you give us some background for this behavior?

  • ves said:
    Can you give us some background for this behavior?

     The intention is that it should not be possible to change the CCCDs locally/ on the GATT server. (other than the very first time on re-reconnect when you need to restore the values). It is the GATT client that enables and disables the CCCDs, the GATT server should not change these values locally, and get in a situation were there is a mismatch between what the value actually is, and what the GATT client believes the value is. The documentation is a big lacking on this point, so I will see if we can improve the documentation on this.

  • Thx Sigurd.

    OK it make sense. An update of the documentation will be highly appreciated

Reply Children
No Data
Related