espressif / ESP8266_NONOS_SDK

ESP8266 nonOS SDK
Other
918 stars 533 forks source link

[TW#20355] ESP-NOW encryption #114

Open Tareq-Sulaiman opened 6 years ago

Tareq-Sulaiman commented 6 years ago

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.

nemonote01 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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.

NickChungVietNam commented 5 years ago

Read this sample code : https://www.espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf and https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/include/espnow.h

ramiws commented 3 years ago

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 commented 2 years ago

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