Skip to content

Fix Out-Of-Band (OOB) data generation for BLE OOB pairing #9339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 18, 2019

Conversation

costanic
Copy link
Contributor

Description

OOB data is cryptographic material exchanged by two peers prior to pairing with the BLE OOB pairing method. After trading OOB data, during the BLE OOB pairing process, peers exchange their public keys, validate the previously exchanged OOB data against the peer's public key, and calculate encryption keys using a combination of the peer's public key and OOB data and the local private key. In this way, man in the middle attacks and passive eavesdropping are prevented.

There are a few bugs in the BLE GenericSecurityManager and Nordic PAL SecurityManager that prevent OOB data from being generated correctly such that a peer is unable to mathematically validate the OOB data and public key received from the Nordic device.

These issues occur on a Nordic nRF52-DK and prevent the nRF52-DK from pairing with a Linux device using the OOB pairing method. With these fixes, the Nordic nRF52-DK successfully pairs with a Linux device using the OOB pairing method.

Pull request type

[X] Fix
[ ] Refactor
[ ] Target update
[ ] Functionality change
[ ] Docs update
[ ] Test update
[ ] Breaking change

Reviewers

@ciarmcom ciarmcom requested a review from a team January 10, 2019 16:00
@ciarmcom
Copy link
Member

@costanic, thank you for your changes.
@ARMmbed/mbed-os-pan @ARMmbed/mbed-os-maintainers please review.

@ciarmcom ciarmcom requested a review from a team January 10, 2019 16:00
Copy link
Member

@pan- pan- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @costanic for this submission and the detailed commit messages. Here's my comments:

_oob_local_address = *address;
/* this will be updated when calculation completes,
* a value of all zeros is an invalid random value */
set_all_zeros(_oob_local_random);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This modification to _oob_local_random should be reverted if generate_secure_connections_oob fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no problem, should be easy enough.

@@ -681,8 +676,8 @@ ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply(

uint32_t err = sd_ble_gap_lesc_oob_data_set(
connection,
pairing_cb->own_oob ? &oob_own : NULL,
pairing_cb->peer_oob ? &oob_peer : NULL
&oob_own,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content in oob_own or oob_peer should be all zeros if not available (according to the BT spec); however the nordic documentation state that we should pass NULL when this is the case. I wonder if we should look at the content then pass NULL if N/A instead of unconditionally passing the value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i'll take a closer look

The GenericSecurityManager tracks the most recent OOB data generated
by the PAL and the PAL function to generate OOB data is expected to
be asynchronous such that the OOB data is returned via a callback.

There was a race condition on the security manager's oob data variable
because it was cleared (set to all zeros) after calling PAL generate.
The expectation was that the clear operation would occur before the
callback executed, but this is proving to not be the case.  Instead,
the callback is being executed as if it were syncronous with PAL
generate, then PAL generate returns and the oob data is cleared,
thereby losing the generated oob data that was set in the callback.

To fix the issue, clear the oob data variables before calling into
the PAL.
The function in the Nordic SDK for generating OOB data,
sd_ble_gap_lesc_oob_data_get, requires local LE Secure Connection
P256 Public Keys in {X,Y} format, but was being supplied with
the local secret key.  This caused the generated OOB data to
fail to correspond to the Public Keys, which caused a mismatch
during the OOB pairing phase of the OOB confirmation value by
a remote peer when attempting to verify the OOB data against
the Public Keys, ultimately causing the OOB pairing request to
fail with a Confirm Value Failed (0x04) error.
the own_oob and peer_oob flags were not being set to 1 even though
an OOB pairing request was in progress, which therefore prevented
OOB data from being passed down to the softdevice during a OOB
pairing operation, thus causing the OOB pairing process to fail.
@costanic
Copy link
Contributor Author

Thanks for the feedback. I've updated the PR based on review comments.

set_all_zeros(_oob_local_random);
} else if (status != BLE_ERROR_NOT_IMPLEMENTED) {
status = _pal.generate_secure_connections_oob();
if (status != BLE_ERROR_NONE && status != BLE_ERROR_NOT_IMPLEMENTED) {
Copy link
Member

@paul-szczepanek-arm paul-szczepanek-arm Jan 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to now: return status; below (on line 676 using the new count)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status is returned on line 670 for the failure case. Do you mean you want BLE_ERROR_NOT_IMPLEMENTED to be able to be propagated back to the user? This was not the case originally.

Copy link
Member

@paul-szczepanek-arm paul-szczepanek-arm Jan 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, it needs to be hidden - bundling this together with legacy was not a good idea, we have to hide the SC failure since it's optional

@costanic
Copy link
Contributor Author

Any additional feedback on this PR?

Copy link
Member

@pan- pan- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks all good on my end.
@paul-szczepanek-arm Anything to add ?

@cmonr
Copy link
Contributor

cmonr commented Jan 17, 2019

CI started

@mbed-ci
Copy link

mbed-ci commented Jan 17, 2019

Test run: FAILED

Summary: 1 of 7 test jobs failed
Build number : 1
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-IAR

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 17, 2019

One breakage on master needs to be addressed asap, the current build was aborted and will be restarted within today.

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 17, 2019

CI restarted

@mbed-ci
Copy link

mbed-ci commented Jan 17, 2019

Test run: SUCCESS

Summary: 11 of 11 test jobs passed
Build number : 2
Build artifacts

@cmonr cmonr merged commit fd2a96e into ARMmbed:master Jan 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants