Skip to content

[TW#20355] ESP-NOW encryption #114

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

Open
Tareq-Sulaiman opened this issue Apr 9, 2018 · 8 comments
Open

[TW#20355] ESP-NOW encryption #114

Tareq-Sulaiman opened this issue Apr 9, 2018 · 8 comments

Comments

@Tareq-Sulaiman
Copy link

There seems to be a lack of information in the documentation about how to set a key for the communication in ESP-NOW.
it all works fine until I add an encryption key in the master device, then the receiver does not receive data anymore.
When I add the key, the send callback still registers a value 0 for the status register, which implies that the receiver should receive data properly, yet it is not happening.
And if I use a NULL key does the data get sent unencrypted? or does it get encrypted but with a default key.

@FayeY FayeY changed the title ESP-NOW encryption [TW#20355] ESP-NOW encryption Apr 16, 2018
@nemonote01
Copy link

Hi Tareq-Sulaiman,
ESP-NOW doc

Here is an example of esp-now:

#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"

#include "driver/uart.h"

#include "espnow.h"


#define CONTROLLER
//#define SLAVE


uint8_t kok[16]= {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
uint8_t key[16]= {0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44};

uint8_t controller_mac[6] = {0xA0, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
uint8_t slave_mac[6] = {0xA2, 0x55, 0x55, 0x55, 0x55, 0x55};

static os_timer_t g_esp_now_timer;
uint8_t send_count=0;
uint8_t recvcount=0;
static void ICACHE_FLASH_ATTR
user_esp_now_recv_cb(u8 *macaddr, u8 *data, u8 len)
{
	int i;
	os_printf("recv from: ");
	for(i = 0; i < 6; i++){
		os_printf("%X", macaddr[i]);
	}
	os_printf(",data: ");
    for(i=0;i<len;i++){
        os_printf("%c",data[i]);
    }
	os_printf(", recv count:%d\n", recvcount++);
}

static void ICACHE_FLASH_ATTR
user_esp_now_send_cb(u8 *mac_addr, u8 status)
{
    os_printf("send count:%d\n",++send_count);

	if(status){
		os_printf("SEND FAIL!\r\n");
	}
}

static void ICACHE_FLASH_ATTR
user_esp_now_timer(void* arg)
{
	esp_now_send(arg, "Hello World!", os_strlen("Hello World!"));
}

void ICACHE_FLASH_ATTR
user_esp_now_timer_init(u8 *mac)
{
	os_timer_disarm(&g_esp_now_timer);
	os_timer_setfn(&g_esp_now_timer, (os_timer_func_t *)user_esp_now_timer, mac);
	os_timer_arm(&g_esp_now_timer, 3000, 1);
}

/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}

/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
    os_printf("SDK version:%s\n", system_get_sdk_version());

#if defined(SLAVE)
	wifi_set_opmode_current(SOFTAP_MODE);
	wifi_set_macaddr(SOFTAP_IF, slave_mac);
#else
	wifi_set_opmode_current(STATION_MODE);
	wifi_set_macaddr(STATION_IF, controller_mac);
#endif

	if (esp_now_init()==0) {
		os_printf("esp_now init ok\n");

		esp_now_register_recv_cb(user_esp_now_recv_cb);
		esp_now_register_send_cb(user_esp_now_send_cb);

		esp_now_set_kok(kok, 16);

#if defined(SLAVE)
		os_printf("slave\n");
		esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
		esp_now_add_peer(controller_mac, ESP_NOW_ROLE_CONTROLLER, 1, key, 16);
		esp_now_set_peer_key(controller_mac, key, 16);

#else
		os_printf("Controller\r\n");
		esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
		esp_now_add_peer(slave_mac, ESP_NOW_ROLE_SLAVE, 1, key, 16);
		esp_now_set_peer_key(slave_mac, key, 16);
		wifi_station_disconnect();
		user_esp_now_timer_init(slave_mac);
#endif
	} else {
		os_printf("esp_now init failed\n");
	}
}

@Tareq-Sulaiman
Copy link
Author

Well thank you very much for responding @Junhao-Espressif !
The problem was that I wasn't adding the controller as a peer from the Slave side, once added it works as expected.
But I still think that the ESP-NOW guide should be improved and have other examples, because I have seen a lot of confusion on related issues.

@mars000
Copy link

mars000 commented Jun 17, 2018

If I don't use my own keys does ESP-NOW use a default key and therefore encrypt all communications in any way ? If so what level of encryption is enabled by default ?

@mischmerz
Copy link

mischmerz commented Jul 6, 2018

Something is completely broken :(

Here's the situation:

A) Controller (no crypto) -> Slave (no crypto) = ok
B) Controller (with crypto) -> Slave (with crypto) = ok
C) Controller (no crypto) -> Slave(with crypto) = ok <----- ????
D) Controller (invalid crypto) -> Slave(with crypto) = fail

In other words - the slave can't verify if the controller used any crypto at all. There is no way for the slave to authenticate the controller. I might be doing something wrong .. but .. what?

m.

@ramiws
Copy link

ramiws commented Dec 6, 2020

Something is completely broken :(

Here's the situation:

A) Controller (no crypto) -> Slave (no crypto) = ok
B) Controller (with crypto) -> Slave (with crypto) = ok
C) Controller (no crypto) -> Slave(with crypto) = ok <----- ????
D) Controller (invalid crypto) -> Slave(with crypto) = fail

In other words - the slave can't verify if the controller used any crypto at all. There is no way for the slave to authenticate the controller. I might be doing something wrong .. but .. what?

m.

I have discovered the same thing, did you manage to find a fix? How come anyone with ESP can spoof and send data to my Slave (with crypto)

@RutgerOlsbergs
Copy link

Has anything happened with this issue? Just noticed the same behaviour today and it's a major security concern.

@ChuckMash
Copy link

ChuckMash commented Jul 23, 2024

Looks like this is still an issue. I noticed this today.

An ESP8266 without encryption can successfully send ESP-NOW to an ESP8266 with encryption.
This does not appear to impact the ESP32 implementation.

Looks same as #141 and #311

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants