gioblu / PJON

PJON (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol.
Other
2.73k stars 239 forks source link

ESPNow: Encryption not working #415

Open toi-go opened 2 years ago

toi-go commented 2 years ago

Documentation at https://github.com/gioblu/PJON/blob/master/src/strategies/ESPNOW/README.md suggests that communication would be encrypted if a PMK is passed to the set_pmk method:

void setup() {
  // Note PMK is 16 bytes, to store it in a char use char[17] or add an extra byte for the null terminator
  char pmk[17] = "\x2b\xb2\x1e\x7a\x83\x13\x76\x9f\xf8\xa9\x3b\x1b\x5b\x52\xd0\x70";
  PJON<ESPNOW> bus(44);

  bus.strategy.set_channel(6);
  bus.strategy.set_pmk(pmk);
}

For me, this is not the case: My two nodes are still able to communicate with each other even if both nodes do the above with a different PMK or if only one of them does set a PMK.

Apparently, add_peer in ESPNOWHelper.h does not set the encrypt flag:

    memset(peer, 0, sizeof(esp_now_peer_info_t));
    peer->channel = _channel;
    peer->ifidx = ESPNOW_WIFI_IF;
    if(IS_BROADCAST_ADDR(mac_addr))
      peer->encrypt = false;
    // else {
    //   peer->encrypt = true;
    //   memcpy(peer->lmk, _esp_pmk, 16);
    // }
    memcpy(peer->peer_addr, mac_addr, ESP_NOW_ETH_ALEN);
    ESP_ERROR_CHECK(esp_now_add_peer(peer));
gioblu commented 2 years ago

Ciao @toi-go thank you very much, this is bad. I will fix it ASAP. Could you provide with testing? I am now far from my electronics stash.

gioblu commented 2 years ago

Here is the fix: https://github.com/gioblu/PJON/commit/5f790b3c05a63a0c2854a72ad66d9566e388ae56 If you can give it a try.

toi-go commented 2 years ago

Hi @gioblu ,

thank you for providing the patch. Unfortunately, with it, my two ESP32 cannot communicate with each other - no matter if I call bus.strategy.set_pmk or not. So, there must be another problem.

To test, I've used the ping example at examples/ESP32/ESPNOW/PlatformIO. My setup() functions looks like this:

void setup()
{
  Serial.begin(115200);
  Serial.println("Receiver started.");

  // Note PMK is 16 bytes, to store it in a char use char[17] or add an extra byte for the null terminator
  char pmk[17] = "\x2b\xb2\x1e\x7a\x83\x13\x76\x9f\xf8\xa9\x3b\x1b\x5b\x52\xd0\x70";

  bus.strategy.set_channel(6);
  bus.strategy.set_pmk(pmk);

  bus.set_receiver(receiver_function);
  bus.begin();
};
void setup()
{
  Serial.begin(115200);
  Serial.println("Transmitter started.");

  // Note PMK is 16 bytes, to store it in a char use char[17] or add an extra byte for the null terminator
  char pmk[17] = "\x2b\xb2\x1e\x7a\x83\x13\x76\x9f\xf8\xa9\x3b\x1b\x5b\x52\xd0\x70";

  bus.strategy.set_channel(6);
  bus.strategy.set_pmk(pmk);

  bus.set_receiver(receiver_function);
  bus.begin();
  bus.send_repeatedly(44, "P", 1, 100000); // Send P to device 44 10 times per second
};
toi-go commented 2 years ago

@gioblu

It seems that the remaining problem is somehow related to autoregistration mode, as it works if it is disabled.

  // Note PMK is 16 bytes, to store it in a char use char[17] or add an extra byte for the null terminator
  char pmk[17] = "\x2b\xb2\x1e\x7a\x83\x13\x76\x9f\xf8\xa9\x3b\x1b\x5b\x52\xd0\x70";

  bus.strategy.set_autoregistration(false);
  bus.strategy.set_channel(6);
  bus.strategy.set_pmk(pmk);

  bus.set_receiver(receiver_function);
  bus.begin();

  uint8_t dev_mac[6] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x11 };  // MAC address of the remote node.
  bus.strategy.add_node(44, dev_mac);

  bus.send_repeatedly(44, "P", 1, 100000); // Send P to device 44 10 times per second

If you register remote nodes manually, you have to use the MAC address of the interface (AP or Station) which is actually in use (depending on CONFIG_STATION_MODE):

From ESPNOWHelper.h

/* ESPNOW can work in both station and softap mode.
   It is configured in menuconfig. */
#if CONFIG_STATION_MODE
  #define ESPNOW_WIFI_MODE WIFI_MODE_STA
  #define ESPNOW_WIFI_IF ESP_IF_WIFI_STA
#else
  #define ESPNOW_WIFI_MODE WIFI_MODE_AP
  #define ESPNOW_WIFI_IF ESP_IF_WIFI_AP
#endif

In my case, CONFIG_STATION_MODE was not defined, so I had to use the MAC address of the AP interface.

To determine the MAC address, I used the following code:

  Serial.println("ESP Board MAC Address:  ");
  #if CONFIG_STATION_MODE
  WiFi.mode(WIFI_MODE_STA);
  Serial.print(" Station interface: ");
  Serial.println(WiFi.macAddress());
  #else
  WiFi.mode(WIFI_MODE_AP);
  Serial.print(" AP interface: ");
  Serial.println(WiFi.softAPmacAddress());
  #endif