This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2541 keyfob link re-encryption issue

On a keyfob based off the CC2541MINI-DK reference design + v1.4.0 of the TI BLE stack (with GAP_BONDINGS_MAX=1) I'm seeing an encryption failure issue that's really hard to cause. But once the issue happens, I can reproduce it over and over again.

Here's how a keyfob that's now in the 'bad' state behaves with BTool:

1. Establish link.
2. Pair + Bond.
3. Save LTK.
4. Encrypt link using saved LTK. This is successful.
5. Terminate link.
6. Re-establish link.
7. Re-encrypt the link using saved LTK (from step 4). This fails with status 0x06 ("Invalid Event Id").

The screen logs from an example Btool session is attached.

Under normal conditions, steps 1-7 are always successful no matter how many times I run the sequence. But once the keyfob is in a bad state, step 7 fails consistently; yet step 4 is always successful.

Power cycling the keyfob does not fix the issue. But I've discovered that triggering "ERASE_ALL_BONDS" (using a UI hook I had put in earlier) causes the issue to go away. This suggests that the BondManager is getting into a state where it's unable to store the LTK onto flash, yet correctly uses it for re-encryption initially. Somehow ERASE_ALL_BONDS seems to restore the BondManagar back to working state.

Can anyone help with ideas on what might be causing this problem and how we could fix it?

I have a couple of keyfobs in this 'bad' state if more logs are needed.

Thanks in advance

[Update, 11-SEP-2014] There is indeed another post in this forum with symptoms/behaviours that identically map to mine above, but which appeared after mine. No resolution on it yet.

  • Hello Roshan,

    It sounds like you have already found out what the problem is and have an effective solution for it which is to erase all bonds if the 0x06 status is returned.  You can do a further search in the forum to see other post on GAP BONDING and LTK.  I have not encountered this problem.

    Thanks,

  • Hi Greenja, I've only discovered a problem but not its root-cause.

    The ERASE_ALL_BONDS is not a field-viable solution as it's only part of a debug hook that I put in while trying to reproduce and characterize this issue. (Erasing any bond intrinsically creates a security issue around an already authenticated peripheral.) I mentioned the ERASE_ALL_BONDS observation only as a data point. Perhaps those who are experts at the gapBondMgr and the OSAL SNV implementations may be able to use that information to guess what might be going on.

    I did search through the forum earlier but didn't see any thing pertinent to the behaviours I'm seeing.

  • This issue, in retrospect, has a trivial root-cause.

    In the default keyfob project GAP_BONDINGS_MAX is set to 10. If the keyfob is bonded with 10 different centrals (each with unique BD ADDRs), then the bonds array gets filled leaving no empty slots. Now, if an 11th central tries to bond with the same keyfob, the generated LTK is no longer stored on the flash. A subsequent connection with the 11th central will, thus, always fails to encrypt.

    This is also why the ERASE_ALL_BONDS fixes the issue by deleting stored LTKs and opening up free slots. In theory, ERASE_SINGLE_BOND will do it too.

    A right way to fix this issue is to track the last saved bond index and overwrite the next location (in a circular buffer fashion) with the new incoming LTK. I would suggest TI to update their BLE stack implementation to treat the bonds[] as a circular buffer instead of as a linear array.

  • Hi Roshan,

    I'm glad you found a fix - I want to make sure I completely understand it so I can see if it applies to my problem, too.

    You mentioned earlier that you have GAP_BONDINGS_MAX set to 1. I have the same thing, the goal being to only let 1 central bond with the device. To bond something else, we want to have to manually erase all bonds. Is that also your goal?

    I don't follow how this root cause you've identified effects the ability of a single client to bond, though. If after a fresh programming I add one bond, why would it fail to be added to the list of LTKs stored in flash?

    Thanks,

    Chris

  • > To bond something else, we want to have to manually erase all bonds. Is that also your goal?

    In my case, the goal was to avoid manual intervention as much as possible, and automatically overwrite the LTK of the oldest device in the bonds[] array (which, with GAP_BONDINGS_MAX=1, is the previous/only LTK).

    Unfortunately, when I started on the keyfob project, I had the mistaken impression that the bonds[] array was already implemented as a circular buffer. This is why it took me sometime to narrow down the true root cause.

    If after a fresh programming I add one bond, why would it fail to be added to the list of LTKs stored in flash?

    That would depend on multiple factors. Does your programming include an 'erase flash' procedure before the code is provisioned or does it simply do an Over-the-Air-Deployment (OAD)? For the former, the LTKs on flash are cleared for sure; for the latter the bonds[] array continues to be the RAM shadow of the LTKs already present in flash. In the OAD case you would see the issue if a central with a different BD addr (or same central using a randomized BD addr each time) tries to connect + re-encrypt the connection after a re-programming. Does that make sense?