<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LESC Static OOB?</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/116040/lesc-static-oob</link><description>I am working in NCS v2.7.0 for nRF52833 DevKits, and trying to set up a secure BLE connection to allow remote control of the device over GATT. 
 My devices are headless IOT devices, so there is no possibility for a true OOB data pathway and no user nearby</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Sun, 10 Nov 2024 14:19:52 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/116040/lesc-static-oob" /><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509781?ContentTypeID=1</link><pubDate>Sun, 10 Nov 2024 14:19:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9ed3196c-102c-491c-ab8b-926c0efb1d91</guid><dc:creator>Emil Lenngren</dc:creator><description>&lt;p&gt;You skip the Security Manager Protocol entirely and install the LTK directly. I&amp;#39;m not super familiar with the SDK here but it seems you can use the `bt_keys_store` function, which is otherwise used by the SMP module when pairing finishes. See&amp;nbsp;&lt;a href="https://github.com/nrfconnect/sdk-zephyr/blob/main/subsys/bluetooth/host/keys.h#L188"&gt;https://github.com/nrfconnect/sdk-zephyr/blob/main/subsys/bluetooth/host/keys.h#L188&lt;/a&gt;. You can do your ECDH exchange over some custom GATT characteristic or L2CAP CoC.&lt;/p&gt;
&lt;p&gt;See&amp;nbsp;&lt;a id="i1" href="https://devzone.nordicsemi.com/f/nordic-q-a/112415/connection-using-old-pairing-information-saved/491888"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/112415/connection-using-old-pairing-information-saved/491888&lt;/a&gt;&amp;nbsp;for an example. Note that you should simulate (mark) that the key was generated using LESC, so set the `keys` field to `BT_KEYS_LTK_P256`, `flags` to `BT_KEYS_SC`, `enc_size` to `BT_SMP_MAX_ENC_KEY_SIZE` and ediv and rand to 0.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509779?ContentTypeID=1</link><pubDate>Sun, 10 Nov 2024 13:52:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:781e054e-5a37-43c7-a6ed-45f667cdf95a</guid><dc:creator>Jeremy</dc:creator><description>&lt;p&gt;That first suggestion makes sense conceptually, but how would that be implemented with NCS? Would you just make a new simplified security manager to handle that process and set up the connection, or is there a way to use the SDK&amp;#39;s &amp;#39;smp&amp;#39; module and set your own LTK?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509755?ContentTypeID=1</link><pubDate>Sat, 09 Nov 2024 13:05:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:deec6584-371b-481c-8cb0-0fbe273c87d9</guid><dc:creator>Emil Lenngren</dc:creator><description>&lt;p&gt;If you control both sides, why don&amp;#39;t you just skip the standard BLE pairing step altogether and generate LTK in your own way?&lt;/p&gt;
&lt;p&gt;If the two devices initially share a 16 byte secret S (as I assume they do from your question), you can generate an LTK by first performing ECDH resulting in shared secret E, then let the LTK be for example HMAC(S, E). That way you get forward secrecy.&lt;/p&gt;
&lt;p&gt;Another way would be to use standard LESC numeric comparison. You can encrypt the 6 digits that are supposed to be shown on the display with your shared key and some AEAD cipher, send it over BLE characteristic to the other device. After decrypting it, accept if correct. Same in the other direction. Just make sure the Additional Data is different for every direction to avoid reflection attack.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509737?ContentTypeID=1</link><pubDate>Fri, 08 Nov 2024 20:09:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f0a37510-67d7-4cbb-a267-0ec63e0ae441</guid><dc:creator>Jeremy</dc:creator><description>&lt;p&gt;&amp;#39;bt_le_oob_get_local&amp;#39; fetches the&amp;nbsp;bt_le_oob object generated behind the scenes, and if BT_TESTING and BT_OOB_DATA_FIXED are set it overrides that random generation with a fixed value, but a &amp;#39;bt_le_oob&amp;#39; is both a random value, and a confirm value that is related to the random value and the generated public key.&lt;/p&gt;
&lt;p&gt;&amp;#39;Local&amp;#39; and &amp;#39;Remote&amp;#39; are cross wired so even if only one piece of OOB data is being exchanged, it is local to one device, and remote to the other, and for the remote device the expected confirm value is the one based on the peer public key, not the one internally generated. Even if both devices are running DATA_FIXED to see the same random value, they will have different confirm values that are not interchangeable.&lt;/p&gt;
&lt;p&gt;If you were to push that example to escalate the connection to security level 4, I believe it would fail validation of the OOB data even if the random value matches. At least that was my experience until I started generating the confirm values using the remote public key.&lt;/p&gt;
&lt;p&gt;My example is fully working, it just requires changes to the SDK that will get a bit more complicated if I ever need to handle more then one connection.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509391?ContentTypeID=1</link><pubDate>Thu, 07 Nov 2024 09:23:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e29e1a8d-cb71-40a7-ab32-e59c52cf6850</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Update: I see your previous replied that you mentioned it couldn&amp;#39;t work. I will have to check it out but we don&amp;#39;t have a NFC reader to test with the central_nfc_pairing so it can be difficult. My suspicion is that you may need to make sure it&amp;#39;s only one way communication and on the other side you need to set the random value to 0.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509390?ContentTypeID=1</link><pubDate>Thu, 07 Nov 2024 09:09:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:46d382eb-7234-4d29-b24f-644071482ea6</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Jeremy,&amp;nbsp;&lt;br /&gt;Sorry for the late reply.&amp;nbsp;&lt;br /&gt;I did a quick test here with the peripheral_nfc_pairing sample and I can see that I have the same local random oob (1 2 3 4 5 ...)&amp;nbsp;as expected from the code in smp.c :&amp;nbsp;&lt;br /&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1730970445722v1.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;here is where I printed it out:&amp;nbsp;&lt;br /&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1730970477732v2.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I simply added this in to prj.conf:&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;CONFIG_BT_OOB_DATA_FIXED&lt;/span&gt;&lt;span&gt;=y&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;CONFIG_BT_TESTING&lt;/span&gt;&lt;span&gt;=y&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;My assumption is that having a hardcoded r value is all it need to be able to do the static OOB ? And you don&amp;#39;t have to calculate the sc key on&amp;nbsp; your own in the application as you showed in the last reply ?&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/509020?ContentTypeID=1</link><pubDate>Mon, 04 Nov 2024 21:46:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eeb7c443-ad38-4778-9ea9-fa278452bd9d</guid><dc:creator>Jeremy</dc:creator><description>&lt;p&gt;Got it working!&lt;/p&gt;
&lt;p&gt;Tested a bit and I believe that &amp;#39;LOCAL_ONLY&amp;#39; will only work if the other side is expecting the connection to be &amp;#39;REMOTE_ONLY&amp;#39;, which still requires some transfer of data between the two devices. In the hids example for instance, one part of the setup is to copy the random/confirm values from the central device.&lt;/p&gt;
&lt;p&gt;However, before the OOB data check, both devices do exchange public keys, and all you need to generate a &amp;#39;confirm&amp;#39; value is a public key and the right 16 &amp;#39;random&amp;#39; bytes.&lt;/p&gt;
&lt;p&gt;I did need to poke two holes into smp.c; one to fetch the locally generated public key for local confirmation, and one for the remote public key associated with the current connection for the remote confirmation. Currently my remote fetch code is cheating a bit and blindly fetching index 0 from the smp pool, but currently I have&amp;nbsp;&amp;#39;CONFIG_BT_MAX_CONN&amp;#39; set to 1 so this works.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;smp.c hacks:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;const uint8_t *bt_smp_get_sc_public_key(void)
{
    return sc_public_key;
}

uint8_t *bt_smp_get_pkey(uint8_t smp_index)
{
	return (uint8_t*)&amp;amp;bt_smp_pool[smp_index].pkey;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Updated &amp;#39;oob_data_request&amp;#39; handler. Identical for both sides:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;crypto/bt_crypto.h&amp;quot;

// Hacked into the SDK smp.c to fetch the local &amp;#39;sc_public_key&amp;#39; value
extern const uint8_t *bt_smp_get_sc_public_key(void);
// Hacked into the SDK smp.c to fetch the remote public key for the current connection
extern uint8_t *bt_smp_get_pkey(uint8_t smp_index);

static struct bt_le_oob_sc_data oob_local;
static struct bt_le_oob_sc_data oob_remote;
static const uint8_t static_r[16] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE
};


static void oob_data_request(struct bt_conn *conn, struct bt_conn_oob_info *info)
{
	printk(&amp;quot;OOB data requested\n&amp;quot;);

    if (info-&amp;gt;type != BT_CONN_OOB_LE_SC) {
        printk(&amp;quot;OOB type not LE SC, rejected\n&amp;quot;);
        return;
    }

	if (info-&amp;gt;lesc.oob_config != BT_CONN_OOB_BOTH_PEERS) {
		printk(&amp;quot;LESC OOB config not supported (oob_config=%d)\n&amp;quot;, info-&amp;gt;lesc.oob_config);
		return;
	}

	int err;
	uint8_t * pkey = bt_smp_get_pkey(0);

	// Compute oob_remote &amp;#39;confirm&amp;#39; value using pkey from the smp_public_key message
	memcpy(oob_remote.r, static_r, 16);
	err = bt_crypto_f4(pkey, pkey, &amp;amp;oob_remote.r, 0, &amp;amp;oob_remote.c);
	if (err) {
		printk(&amp;quot;Error generating remote OOB confirm value: %d\n&amp;quot;, err);
		return;
	}

	// Computer oob_local &amp;#39;confirm&amp;#39; value using the public key generated locally for this connection
	memcpy(oob_local.r, static_r, 16);
	err = bt_crypto_f4(bt_smp_get_sc_public_key(), bt_smp_get_sc_public_key(), &amp;amp;oob_local.r, 0, &amp;amp;oob_local.c);
	if (err) {
		printk(&amp;quot;Error generating local OOB confirm value: %d\n&amp;quot;, err);
		return;
	}

	err = bt_le_oob_set_sc_data(conn, &amp;amp;oob_local, &amp;amp;oob_remote);
	if (err) {
		printk(&amp;quot;Error while setting OOB data: %d\n&amp;quot;, err);
	}
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Is there any more elegant way to accomplish this? Or is there some way to infer &amp;#39;bt_smp_pool&amp;#39; index based on the &amp;#39;conn&amp;#39; passed into the &amp;#39;oob_data_request&amp;#39; callback? I could extend the callback to send additional details back, but I&amp;#39;m trying to limit my SDK changes.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;br /&gt;Jeremy&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/508952?ContentTypeID=1</link><pubDate>Mon, 04 Nov 2024 13:00:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:55165463-26ff-4124-80fb-4d235d475c56</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Jeremy,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We would need to check if the OOB communication is both way or one way only. Normally on our board it&amp;#39;s usually BT_CONN_OOB_LOCAL_ONLY&amp;nbsp;meaning the OOB data r&amp;amp;c&amp;nbsp; is to be offered from the nRF52 and being read by the peer.&amp;nbsp;&lt;br /&gt;Could you take a look at this ticket:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/110895/factory-pairing-two-nrf52840"&gt;Factory-pairing two nRF52840&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I think it&amp;#39;s very similar to what you want to achieve. Please take a look at the peripheral_hids_keyboard.&lt;br /&gt;Could you try to test that example with&amp;nbsp;&lt;span&gt;CONFIG_BT_OOB_DATA_FIXED&amp;nbsp; ?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LESC Static OOB?</title><link>https://devzone.nordicsemi.com/thread/508881?ContentTypeID=1</link><pubDate>Sun, 03 Nov 2024 10:13:53 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3290f961-a0a8-4f06-8c24-2ac1fa2c2a47</guid><dc:creator>Jeremy</dc:creator><description>&lt;p&gt;So I&amp;#39;ve done some more digging, and think I&amp;#39;m missing something more basic. I&amp;#39;ve removed my own attempts to inject a static &amp;#39;r&amp;#39; value and instead just set&amp;nbsp;CONFIG_BT_TESTING and CONFIG_BT_OOB_DATA_FIXED to &amp;#39;y&amp;#39; in &amp;#39;prj.conf&amp;#39;. This appears to effectively do what I was trying to do, only with a fixed-in-the-SDK static value ... and is still failing the same as before.&lt;/p&gt;
&lt;p&gt;The new simplified code implemented on both central and peripheral now is:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static struct bt_le_oob oob_local_full;

static void oob_data_request(struct bt_conn *conn, struct bt_conn_oob_info *info)
{
	int err;
	
    if (info-&amp;gt;type != BT_CONN_OOB_LE_SC) {
        printk(&amp;quot;OOB type not LE SC, rejected\n&amp;quot;);
        return;
    }

    printk(&amp;quot;OOB data requested\n&amp;quot;);
	
	err = bt_le_oob_set_sc_data(conn, &amp;amp;oob_local_full.le_sc_data, NULL);
	if (err) {
		printk(&amp;quot;Error while setting OOB data: %d\n&amp;quot;, err);
	}
}


int main(void)
{
	...
	
	bt_le_oob_get_local(0, &amp;amp;oob_local_full);

	...
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With debugging I can confirm this leads to identical &amp;#39;r&amp;#39; values being seeded onto both devices and being supplied&amp;nbsp;in smp-&amp;gt;oodb_local, but they are still returning status 0xB. Any help would be appreciated.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;br /&gt;Jeremy&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>