8 Replies Latest reply on Apr 14, 2020 1:28 AM by MiBi_4539931

    Encrypt connection without pairing




      We have developed application on nrf chip that is in production now. We want now port it to Cypress CYW20819 chip. I want to make as least changes as possible in application logic to make this porting smooth process.


      For nrf chip it was possible to encrypt connection without executing pairing process - instead of initiating pairing central was starting encrypting connection with a hardcoded key. It make sense to do that because we want only connect to our own devices, skipping pairing is faster and we don't have to care about flash used for many different devices.


      So far I was trying modify Heart Rate client example to do that but no success so far. I created a custom key record and used hrc_save_link_keys to to save it in flash on application startup. I also tried to replace hrc_read_link_keys to always respond with my hardcoded key. In both cases I then tried to call wiced_bt_dev_set_encryption on connection start instead of wiced_bt_dev_sec_bond. That doesn't seem to work as I am getting an error.


      I would assume that key thing is to fill p_event_data->paired_device_link_keys_request with proper data after BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT is generated. I should then be able to just call wiced_bt_dev_set_encryption  but I was wondering if there is maybe more into this?


      Is what I am doing even possible for Cypress CYW20819 chip? If so can you guide me a bit?



        • 1. Re: Encrypt connection without pairing

          Hi MiBi_4539931 ,


          Please note there is no fixed passkey option available for 20819 chip.

          If the peer device is any third party device which can have a fixed passkey , in that case we can use IO capability of 20819 as keyboard and instead of entering the passkey manually , you can use API wiced_bt_dev_pass_key_req_reply and send the known passkey as reply. This will work.


          Otherwise , only one way I can think about is to use Just works security model.

          Thus you need not have to enter passkey for pairing, but the link will be secured.



          Please refer to WBT101-04B-BLE-Ntfy-Sec.pdf for explanation of various security options & how to use it for 20819 : CypressAcademy_WBT101_Files/Labmanual at master · cypresssemiconductorco/CypressAcademy_WBT101_Files · GitHub




          1 of 1 people found this helpful
          • 2. Re: Encrypt connection without pairing



            Maybe it was a bit unclear, but I meant a long term key not the passkey. And I meant bonding, I guess that is correct name.


            Thanks for links, I will have a look if I can find anything useful.



            • 3. Re: Encrypt connection without pairing

              Hi MiBi_4539931 ,


              Long term key setting is done by the internal BT stack. It cannot be set in the application. Its handled internally as per the BT spec.

              For your application requirement , for any encrypted link, I would suggest you to choose Just works pairing method.

              You may go through the labmaual and other examples available in WICED Academy for setting the required pairing method.



              1 of 2 people found this helpful
              • 4. Re: Encrypt connection without pairing



                I see that ltk is stored in application by hrc_save_link_keys . It is called on BTM_PAIRED_DEVICE_LINK_KEYS_UPDATE_EVT event. So it is bt stack to control saving/updating keys but it is actually application that stores and read key on request from bt stack. That makes me think that I should be able to skip process of pairing and just save hardcoded keys which I can later send to bt stack on request. Can you please relate to this ?



                • 5. Re: Encrypt connection without pairing

                  Hi Michał,


                  The regular steps to encrypt a link are:

                    1/ Authenticate the connection (verify that both devices have the same LinkKey).

                         1a/ If there is no LinkKey (in NVRAM), a new LinkKey must be create via the Pairing process

                         1b/ If there is already a LinkKey (in NVRAM), it I used to Authenticate the connection.

                    2/ Once a connection is Authenticated, the Connection can be Encrypted.


                  If the peer device is a ‘regular’ device (e.g. Phone, computer, etc.), then you have to follow this mechanism.


                  But, if you implement the two devices, you may ‘hack’ the steps and bypass the Pairing step (and use an hardcoded LinkKey).

                  Note that this connection will not be secured (a hacker will probably be able to hack your system).


                  The Wiced SDK exposes two APIs:

                    - wiced_bt_dev_sec_bond: This API will initiate the Pairing (aka Bonding).

                    - wiced_bt_dev_set_encryption: This API, which supposes that a LinkKey exists, will initiate the Pairing.


                  So, if you do not call wiced_bt_dev_sec_bond  but call wiced_bt_dev_set_encryption (as soon an a BLE device is connected), the BT stack will ask for the LinkKey (BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT event).

                  Upon reception of this event, your application will have to fill the p_data-> paired_device_link_keys_request.key_data field/structure with your hardcoded data.


                    - The same values must be used of both devices.

                    - The key_data field/structure is a bit complex (many fields, bitfields, etc.). I recommend to use the regular Pairing and

                       dump the key_data field/structure received in the BTM_PAIRED_DEVICE_LINK_KEYS_UPDATE_EVT to understand how it works.




                  2 of 2 people found this helpful
                  • 6. Re: Encrypt connection without pairing

                    Hi Patrick,


                    Thank you very much for stepping in and clarifying this. I tried to do what you suggested. But it still doesn't work as intedent.


                    I have replaced code for getting keys with my implementation where I simply assign all needed values. Here is the code:

                    wiced_bool_t hrc_read_link_keys(wiced_bt_device_link_keys_t *p_keys)
                        uint8_t         bytes_read;
                        wiced_result_t  result;
                        bytes_read = wiced_hal_read_nvram(HRC_PAIRED_KEYS_VS_ID, sizeof(wiced_bt_device_link_keys_t), (uint8_t *)p_keys, &result);
                        for (uint8_t i = 0; i < 16; i++)
                          p_keys->key_data.le_keys.irk[i] = i;
                          p_keys->key_data.le_keys.pltk[i] = i;
                          p_keys->key_data.le_keys.pcsrk[i] = i;
                          p_keys->key_data.le_keys.lltk[i] = i;
                          p_keys->key_data.le_keys.lcsrk[i] = i;
                        p_keys->key_data.le_keys_available_mask = 119;
                        p_keys->key_data.ble_addr_type = 1;
                        p_keys->key_data.static_addr_type = 0;
                        p_keys->key_data.static_addr[0] = 0x20;
                        p_keys->key_data.static_addr[1] = 0x81;
                        p_keys->key_data.static_addr[2] = 0x9a;
                        p_keys->key_data.static_addr[3] = 0x09;
                        p_keys->key_data.static_addr[4] = 0x3e;
                        p_keys->key_data.static_addr[5] = 0x41;
                        p_keys->key_data.le_keys.ediv = 0;
                        p_keys->key_data.le_keys.div = 0;
                        p_keys->key_data.le_keys.sec_level = 1;
                        p_keys->key_data.le_keys.key_size = 16;
                        p_keys->key_data.le_keys.srk_sec_level = 0;
                        p_keys->key_data.le_keys.local_csrk_sec_level = 0;
                        p_keys->key_data.le_keys.counter = 0;
                        p_keys->key_data.le_keys.local_counter = 0;
                        WICED_BT_TRACE("read %d bytes at id:%d\n", bytes_read, HRC_PAIRED_KEYS_VS_ID);
                        return WICED_TRUE;//(bytes_read == sizeof (wiced_bt_device_link_keys_t));//

                    I wonder how I should handle irk and csrk, does bt stack care about it at all? Also when dumping static_addr it was the same for both central and peripheral (0x20819a093r41) does it make sense?


                    I am also wondering if I should care about address resolution database? I see keys are loaded there and I guess it is done for a reason?


                    • 7. Re: Encrypt connection without pairing

                      Hi Michał,


                      All these fields are usually filled by the embedded BT Stack (I don't know how to use them).

                      Did you try to use the regular pairing (using wiced_bt_dev_sec_bond API) and dump the structure as I recommended in my previous email?


                      You can, also, try to use a Public address to see if it helps (by setting the rpa_refresh_timeout field of your wiced_bt_cfg_settings_t structure to 0).


                      I think that the address resolution database is updated using the wiced_bt_dev_add_device_to_address_resolution_db API.




                      • 8. Re: Encrypt connection without pairing

                        Hi Patrick,


                        Yes, I dumped data from events. I saw that those fields are used but I was wondering if I can I leave them empty in general case. Actually, looks like I can leave them empty.


                        Anyway, I was able to setup encryption without pairing. Tricky part is that I was receiving 2 unexpected events BTM_PAIRED_DEVICE_LINK_KEYS_REQUEST_EVT even before starting encryption process. Once I skipped those by not responding with keys and only responded with keys to later events everything started to work. I asked a seperate question about this - https://community.cypress.com/message/230509?et=notification.mention#230509 . Maybe you can help there as well, would be great !


                        Thank you for your support.