Skip to content

Commit

Permalink
Merge pull request #9 from TMRh20/CCMEncryption
Browse files Browse the repository at this point in the history
CCM AES encryption
  • Loading branch information
TMRh20 authored May 26, 2023
2 parents 0490d9b + 8d44451 commit 76b3911
Show file tree
Hide file tree
Showing 7 changed files with 1,866 additions and 965 deletions.
168 changes: 168 additions & 0 deletions examples/RF24/GettingStartedEncryption/GettingStartedEncryption.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* See documentation at https://nRF24.github.io/RF24
* See License information at root directory of this library
* Author: Brendan Doherty (2bndy5)
*/

/**
* A simple example of sending data from 1 nRF24L01 transceiver to another.
*
* This example was written to be used on 2 devices acting as "nodes".
* Use the Serial Monitor to change each node's behavior.
*/
#include <SPI.h>
#include "printf.h"
#include "nrf_to_nrf.h"

uint8_t myKey[16] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};

// instantiate an object for the nRF24L01 transceiver
nrf_to_nrf radio; // using pin 7 for the CE pin, and pin 8 for the CSN pin

// Let these addresses be used for the pair
uint8_t address[][6] = { "1Node", "2Node" };
// It is very helpful to think of an address as a path instead of as
// an identifying device destination

// to use different addresses on a pair of radios, we need a variable to
// uniquely identify which address this radio will use to transmit
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit

// Used to control whether this node is sending or receiving
bool role = false; // true = TX role, false = RX role

// For this example, we'll be using a payload containing
// a single float number that will be incremented
// on every successful transmission
float payload = 0.0;

void setup() {

Serial.begin(115200);
while (!Serial) {
// some boards need to wait to ensure access to serial over USB
}

// initialize the transceiver on the SPI bus
if (!radio.begin()) {
Serial.println(F("radio hardware is not responding!!"));
while (1) {} // hold in infinite loop
}

// print example's introductory prompt
Serial.println(F("RF24/examples/GettingStarted"));

// To set the radioNumber via the Serial monitor on startup
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
while (!Serial.available()) {
// wait for user input
}
char input = Serial.parseInt();
radioNumber = input == 1;
Serial.print(F("radioNumber = "));
Serial.println((int)radioNumber);

// role variable is hardcoded to RX behavior, inform the user of this
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

// Set the PA Level low to try preventing power supply related problems
// because these examples are likely run with nodes in close proximity to
// each other.
radio.setPALevel(NRF_PA_LOW); // RF24_PA_MAX is default.

// save on transmission time by setting the radio to only transmit the
// number of bytes we need to transmit a float
radio.setPayloadSize(sizeof(payload)+12); // float datatype occupies 4 bytes + 12 bytes for encryption overhead
//radio.enableDynamicPayloads();
// set the TX address of the RX node into the TX pipe
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0

// set the RX address of the TX node into a RX pipe
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1

// additional setup specific to the node's role
if (role) {
radio.stopListening(); // put radio in TX mode
} else {
radio.startListening(); // put radio in RX mode
}

// For debugging info
// printf_begin(); // needed only once for printing details
// radio.printDetails(); // (smaller) function that prints raw register values
// radio.printPrettyDetails(); // (larger) function that prints human readable data
radio.setKey(myKey); // Set our key
radio.setCounter(54321); // Set our counter
radio.enableEncryption = true; // Enable encryption

} // setup

void loop() {

if (role) {
// This device is a TX node

unsigned long start_timer = micros(); // start the timer
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report

unsigned long end_timer = micros(); // end the timer

if (report) {
Serial.print(F("Transmission successful! ")); // payload was delivered
Serial.print(F("Time to transmit = "));
Serial.print(end_timer - start_timer); // print the timer result
Serial.print(F(" us. Sent: "));
Serial.println(payload); // print payload sent
payload += 0.1; // increment float payload
} else {
Serial.println(F("Transmission failed or timed out")); // payload was not delivered
}

// to make this example readable in the serial monitor
delay(1000); // slow transmissions down by 1 second

} else {
// This device is a RX node

uint8_t pipe;
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
//uint8_t bytes = radio.getDynamicPayloadSize();//
uint8_t bytes = sizeof(payload); // get the size of the payload with 4 bytes subtracted for encryption overhead
radio.read(&payload, bytes); // fetch payload from FIFO
Serial.print(F("Received "));
Serial.print(bytes); // print the size of the payload
Serial.print(F(" bytes on pipe "));
Serial.print(pipe); // print the pipe number
Serial.print(F(": "));
Serial.println();
Serial.println(payload); // print the payload's value



//radio.decrypt(payload,8);
//Serial.print("fin");
//Serial.println(radio.outBuffer[3]);
}
} // role

if (Serial.available()) {
// change the role via the serial monitor

char c = toupper(Serial.read());
if (c == 'T' && !role) {
// Become the TX node

role = true;
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
radio.stopListening();

} else if (c == 'R' && role) {
// Become the RX node

role = false;
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
radio.startListening();
}
}

} // loop
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/** RF24Mesh_Example.ino by TMRh20
This example sketch shows how to manually configure a node via RF24Mesh, and send data to the
master node.
The nodes will refresh their network address as soon as a single write fails. This allows the
nodes to change position in relation to each other and the master node.
*/


#include "nrf_to_nrf.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>
//#include <printf.h>

//Set up our encryption key
uint8_t myKey[16] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};

/**** Configure the nrf24l01 CE and CS pins ****/
nrf_to_nrf radio;

RF24Network network(radio);
RF24Mesh mesh(radio, network);

/*
* User Configuration: nodeID - A unique identifier for each radio. Allows addressing
* to change dynamically with physical changes to the mesh.
*
* In this example, configuration takes place below, prior to uploading the sketch to the device
* A unique value from 1-255 must be configured for each node.
*/
#define nodeID 1


uint32_t displayTimer = 0;

struct payload_t {
unsigned long ms;
unsigned long counter;
};

void setup() {

Serial.begin(115200);
while (!Serial) {
// some boards need this because of native USB capability
}
delay(5000);
// Set the nodeID manually
mesh.setNodeID(nodeID);
radio.begin();
radio.setKey(myKey); // Set our key and IV
radio.enableEncryption = true; // Enable encryption
radio.enableDynamicPayloads(123); //This is important to call so the encryption overhead will not be included in the 32-byte limit
//To overcome the 32-byte limit, edit RF24Network.h and set MAX_FRAME_SIZE to 111
// Connect to the mesh
Serial.println(F("Connecting to the mesh..."));
if (!mesh.begin()) {
if (radio.isChipConnected()) {
do {
// mesh.renewAddress() will return MESH_DEFAULT_ADDRESS on failure to connect
Serial.println(F("Could not connect to network.\nConnecting to the mesh..."));
} while (mesh.renewAddress() == MESH_DEFAULT_ADDRESS);
} else {
Serial.println(F("Radio hardware not responding."));
while (1) {
// hold in an infinite loop
}
}
}
radio.setPALevel(NRF_PA_MIN);
}



void loop() {

mesh.update();

// Send to the master node every second
if (millis() - displayTimer >= 1000) {
displayTimer = millis();

// Send an 'M' type message containing the current millis()
//if (!mesh.write(&displayTimer, 'M', sizeof(displayTimer))) {
RF24NetworkHeader header(0,'M');
if(!network.write(header,&displayTimer,sizeof(displayTimer) ) ){
// If a write fails, check connectivity to the mesh network
if (!mesh.checkConnection()) {
//refresh the network address
Serial.println("Renewing Address");
if (mesh.renewAddress() == MESH_DEFAULT_ADDRESS) {
//If address renewal fails, reconfigure the radio and restart the mesh
//This allows recovery from most if not all radio errors
mesh.begin();
}
} else {
Serial.println("Send fail, Test OK");
}
} else {
Serial.print("Send OK: ");
Serial.println(displayTimer);
}
}

while (network.available()) {
RF24NetworkHeader header;
payload_t payload;
network.read(header, &payload, sizeof(payload));
Serial.print("Received packet #");
Serial.print(payload.counter);
Serial.print(" at ");
Serial.println(payload.ms);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <nrf_to_nrf.h>



/** RF24Mesh_Example_Master.ino by TMRh20
*
*
* This example sketch shows how to manually configure a node via RF24Mesh as a master node, which
* will receive all data from sensor nodes.
*
* The nodes can change physical or logical position in the network, and reconnect through different
* routing nodes as required. The master node manages the address assignments for the individual nodes
* in a manner similar to DHCP.
*
*/

#include "nrf_to_nrf.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>

//Set up our encryption key
uint8_t myKey[16] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};

/***** Configure the chosen CE,CS pins *****/
nrf_to_nrf radio;
RF24Network network(radio);
RF24Mesh mesh(radio, network);

uint32_t displayTimer = 0;

void setup() {
Serial.begin(115200);
while (!Serial) {
// some boards need this because of native USB capability
}

radio.begin();
radio.setKey(myKey); // Set our key and IV
radio.enableEncryption = true; // Enable encryption
radio.enableDynamicPayloads(123); //This is important to call so the encryption overhead will not be included in the 32-byte limit
//To overcome the 32-byte limit, edit RF24Network.h and set MAX_FRAME_SIZE to 111

// Set the nodeID to 0 for the master node
mesh.setNodeID(0);
Serial.println(mesh.getNodeID());
// Connect to the mesh
if (!mesh.begin()) {
// if mesh.begin() returns false for a master node, then radio.begin() returned false.
Serial.println(F("Radio hardware not responding."));
while (1) {
// hold in an infinite loop
}
}
}


void loop() {

// Call mesh.update to keep the network updated
mesh.update();

// In addition, keep the 'DHCP service' running on the master node so addresses will
// be assigned to the sensor nodes
mesh.DHCP();


// Check for incoming data from the sensors
if (network.available()) {
RF24NetworkHeader header;
network.peek(header);

uint32_t dat = 0;
switch (header.type) {
// Display the incoming millis() values from the sensor nodes
case 'M':
network.read(header, &dat, sizeof(dat));
Serial.println(dat);
break;
default:
network.read(header, 0, 0);
Serial.println(header.type);
break;
}
}

if (millis() - displayTimer > 5000) {
displayTimer = millis();
Serial.println(" ");
Serial.println(F("********Assigned Addresses********"));
for (int i = 0; i < mesh.addrListTop; i++) {
Serial.print("NodeID: ");
Serial.print(mesh.addrList[i].nodeID);
Serial.print(" RF24Network Address: 0");
Serial.println(mesh.addrList[i].address, OCT);
}
Serial.println(F("**********************************"));
}
}
Loading

0 comments on commit 76b3911

Please sign in to comment.