esp-idf: [TW#26741] BLE generating and resolving random mac addresses does not work correctly (IDFGH-10752)

@Weijian-Espressif @Yulong-espressif I think that values for esp_ble_addr_type_t are not correctly enumerated. According to bluetooth specs:

BLUETOOTH SPECIFICATION Version 5.0 | Vol 6, Part B page 2557 The random device address may be of either of the following two sub-types: • Static address • Private address.

A static address is a 48-bit randomly generated address and shall meet the following requirements: • The two most significant bits of the address shall be equal to 1

But all 3 non public types are generating address of type resolvable private address. How do i know:

BLUETOOTH SPECIFICATION Version 5.0 | Vol 6, Part B page 2558 To generate a resolvable private address, the device must have either the Local Identity Resolving Key (IRK) or the Peer Identity Resolving Key (IRK). The resolvable private address shall be generated with the IRK and a randomly generated 24-bit number. The random number is known as prand and shall meet the following requirements: • The two most significant bits of prand shall be equal to 0 and 1 as shown in Figure 1.4

I (739) SampleClient: Advertised Device: Name: ESP32, Address: 48:ed:1c:cf:37:0f, serviceUUID: 00001234-0000-1000-8000-00805f9b34fb, txPower: 3

As we can see most significant value is 0x48 which is 0100 1000.

Also resolvable private address is recognized as BLE_ADDR_TYPE_RANDOM.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 20 (10 by maintainers)

Most upvoted comments

@Weijian-Espressif Most likely there is easier way to do it or more elegant, but this is my address generator. Maybe its not pretty but i think it works just like i expecting:

void BLEAdvertising::setPrivateAddress(esp_ble_addr_type_t type) {
	esp_bd_addr_t addr;
	m_advParams.own_addr_type = type;

	if(type == BLE_ADDR_TYPE_RPA_PUBLIC) {
		esp_ble_gap_config_local_privacy(true);
		return;
	}
	else{
		mbedtls_ctr_drbg_context ctr_drbg;
		mbedtls_entropy_context entropy;
		mbedtls_md_context_t ctx;

		char pers[] = "aes generate key";
		int ret;
		unsigned char key[BLOCK_SIZE] = {0};
		const char inp[] = "random static address";
		unsigned char outp[BLOCK_SIZE/2];

		mbedtls_entropy_init( &entropy );
		mbedtls_ctr_drbg_init( &ctr_drbg );

		if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
			(unsigned char *) pers, strlen( pers ) ) ) != 0 )
		{
			printf( " failed\n ! mbedtls_ctr_drbg_init returned -0x%04x\n", -ret );
			goto exit;
		}

		if( ( ret = mbedtls_ctr_drbg_random( &ctr_drbg, key, BLOCK_SIZE ) ) != 0 )
		{
			printf( " failed\n ! mbedtls_ctr_drbg_random returned -0x%04x\n", -ret );
			goto exit;
		}

		mbedtls_md_init(&ctx);
		mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(HMAC), true);
		mbedtls_md_hmac_starts(&ctx, (const unsigned char *)key, BLOCK_SIZE);
		mbedtls_md_hmac_update(&ctx, (const unsigned char *)inp, strlen(inp));
		mbedtls_md_hmac_finish(&ctx, outp);
		mbedtls_md_free(&ctx);
		ESP_LOG_BUFFER_HEX("random key", key, BLOCK_SIZE);
		ESP_LOG_BUFFER_HEX("HASH step 2", outp, BLOCK_SIZE/2);

		memcpy(addr, outp, 6);
	}
	if(type == BLE_ADDR_TYPE_RANDOM) {
		addr[0] &= 0x3F;  // <--- Format of non-resolvable private address 00xx xxxx
	}
	else{
		addr[0] |= 0xC0;  // <--- Format of static address 11xx xxxx
	}

	esp_ble_gap_set_rand_addr(addr);
	ESP_LOG_BUFFER_HEX("random address", addr, 6);
	exit:
	return;
}

@chegewara esp_ble_gap_set_rand_addr can set random address.

  1. BLE_ADDR_TYPE_PUBLIC use public address
  2. BLE_ADDR_TYPE_RANDOM use static random address, if not exist, use resolvable address, Otherwise report error
  3. BLE_ADDR_TYPE_RPA_RANDOM use resolvable address, if not exist, use random address, Otherwise report error
  4. BLE_ADDR_TYPE_RPA_PUBLIC use resolvable address, if not exist, use public address

you can set adv param or scan param to switch address.

btw your time is not wasted, now i ca help other users answering their questions:

https://www.esp32.com/viewtopic.php?f=13&t=7657