26#include <sys/random.h>
27#if !defined(USE_RF24_LIB_SRC)
28 #include <RF24/RF24.h>
33#define RF24CCM_KEY_SIZE 16
34#define RF24CCM_IV_SIZE 5
35#define RF24CCM_COUNTER_SIZE 3
36#define RF24CCM_MIC_SIZE 4
37#define RF24CCM_NONCE_SIZE 13
38#define RF24CCM_OVERHEAD (RF24CCM_IV_SIZE + RF24CCM_COUNTER_SIZE + RF24CCM_MIC_SIZE)
39#define RF24CCM_FRAME_SIZE 32
45 return (uint8_t)((x << 1) ^ ((x & 0x80) ? 0x1B : 0x00));
48inline uint8_t
rotl8(uint8_t x, uint8_t shift)
50 return (uint8_t)((x << shift) | (x >> (8 - shift)));
54inline const uint8_t*
sbox()
56 static uint8_t box[256];
57 static bool ready =
false;
61 p = (uint8_t)(p ^ (p << 1) ^ ((p & 0x80) ? 0x1B : 0x00));
62 q ^= (uint8_t)(q << 1);
63 q ^= (uint8_t)(q << 2);
64 q ^= (uint8_t)(q << 4);
76inline void aesExpandKey(
const uint8_t key[16], uint8_t roundKeys[176])
78 const uint8_t* sb =
sbox();
80 memcpy(roundKeys, key, 16);
81 for (uint8_t i = 16; i < 176; i += 4) {
82 uint8_t t[4] = {roundKeys[i - 4], roundKeys[i - 3], roundKeys[i - 2], roundKeys[i - 1]};
85 t[0] = (uint8_t)(sb[t[1]] ^ rcon);
91 for (uint8_t j = 0; j < 4; j++) {
92 roundKeys[i + j] = (uint8_t)(roundKeys[i - 16 + j] ^ t[j]);
97inline void aesEncryptBlock(
const uint8_t roundKeys[176],
const uint8_t in[16], uint8_t out[16])
99 const uint8_t* sb =
sbox();
101 for (uint8_t i = 0; i < 16; i++) {
102 s[i] = (uint8_t)(in[i] ^ roundKeys[i]);
104 for (uint8_t round = 1; round <= 10; round++) {
105 for (uint8_t i = 0; i < 16; i++) {
126 for (uint8_t c = 0; c < 16; c += 4) {
127 uint8_t a0 = s[c], a1 = s[c + 1], a2 = s[c + 2], a3 = s[c + 3];
128 uint8_t all = (uint8_t)(a0 ^ a1 ^ a2 ^ a3);
129 s[c] = (uint8_t)(a0 ^ all ^
xtime((uint8_t)(a0 ^ a1)));
130 s[c + 1] = (uint8_t)(a1 ^ all ^
xtime((uint8_t)(a1 ^ a2)));
131 s[c + 2] = (uint8_t)(a2 ^ all ^
xtime((uint8_t)(a2 ^ a3)));
132 s[c + 3] = (uint8_t)(a3 ^ all ^
xtime((uint8_t)(a3 ^ a0)));
135 for (uint8_t i = 0; i < 16; i++) {
136 s[i] ^= roundKeys[round * 16 + i];
143inline void ccmMac(
const uint8_t roundKeys[176],
const uint8_t* nonce, uint8_t nonceLen,
const uint8_t* aad,
size_t aadLen,
144 const uint8_t* msg,
size_t msgLen, uint8_t micLen, uint8_t mac[16])
146 const uint8_t L = (uint8_t)(15 - nonceLen);
147 uint8_t block[16] = {0};
148 block[0] = (uint8_t)((aadLen ? 0x40 : 0x00) | (((micLen - 2) / 2) << 3) | (L - 1));
149 memcpy(&block[1], nonce, nonceLen);
150 for (uint8_t i = 0; i < L; i++) {
151 block[15 - i] = (uint8_t)(i <
sizeof(
size_t) ? (msgLen >> (8 * i)) : 0);
156 memset(block, 0,
sizeof(block));
157 block[0] = (uint8_t)(aadLen >> 8);
158 block[1] = (uint8_t)aadLen;
160 for (
size_t i = 0; i < aadLen; i++) {
161 block[pos++] = aad[i];
163 for (uint8_t j = 0; j < 16; j++) {
167 memset(block, 0,
sizeof(block));
172 for (uint8_t j = 0; j < 16; j++) {
179 for (
size_t i = 0; i < msgLen; i += 16) {
180 size_t n = (msgLen - i < 16) ? msgLen - i : 16;
181 for (
size_t j = 0; j < n; j++) {
182 mac[j] ^= msg[i + j];
189inline void ccmCtr(
const uint8_t roundKeys[176],
const uint8_t* nonce, uint8_t nonceLen,
const uint8_t* in,
size_t len,
190 uint8_t* out, uint8_t s0[16])
192 const uint8_t L = (uint8_t)(15 - nonceLen);
193 uint8_t ctr[16] = {0};
195 ctr[0] = (uint8_t)(L - 1);
196 memcpy(&ctr[1], nonce, nonceLen);
199 uint32_t counter = 1;
200 for (
size_t i = 0; i < len; i += 16, counter++) {
201 for (uint8_t j = 0; j < L; j++) {
202 ctr[15 - j] = (uint8_t)(j < 4 ? (counter >> (8 * j)) : 0);
205 size_t n = (len - i < 16) ? len - i : 16;
206 for (
size_t j = 0; j < n; j++) {
207 out[i + j] = (uint8_t)(in[i + j] ^ stream[j]);
213inline void ccmEncrypt(
const uint8_t roundKeys[176],
const uint8_t* nonce, uint8_t nonceLen,
const uint8_t* aad,
size_t aadLen,
214 const uint8_t* in,
size_t len, uint8_t* out, uint8_t* mic, uint8_t micLen)
216 uint8_t mac[16], s0[16];
217 ccmMac(roundKeys, nonce, nonceLen, aad, aadLen, in, len, micLen, mac);
218 ccmCtr(roundKeys, nonce, nonceLen, in, len, out, s0);
219 for (uint8_t i = 0; i < micLen; i++) {
220 mic[i] = (uint8_t)(mac[i] ^ s0[i]);
225inline bool ccmDecrypt(
const uint8_t roundKeys[176],
const uint8_t* nonce, uint8_t nonceLen,
const uint8_t* aad,
size_t aadLen,
226 const uint8_t* in,
size_t len,
const uint8_t* mic, uint8_t micLen, uint8_t* out)
228 uint8_t mac[16], s0[16];
229 ccmCtr(roundKeys, nonce, nonceLen, in, len, out, s0);
230 ccmMac(roundKeys, nonce, nonceLen, aad, aadLen, out, len, micLen, mac);
232 for (uint8_t i = 0; i < micLen; i++) {
233 diff |= (uint8_t)(mac[i] ^ s0[i] ^ mic[i]);
275 packetCounter = counter;
282 delay = delay > minRetryDelay ? delay : minRetryDelay;
283 count = count > minRetryCount ? count : minRetryCount;
285 RF24::setRetries(delay, count);
291 return RF24::getDynamicPayloadSize();
296 uint8_t size = RF24::getDynamicPayloadSize();
301 RF24::read(frame, size);
302 if (!decryptFrame(frame, size)) {
310 void read(
void* buf, uint8_t len)
313 RF24::read(buf, len);
320 memcpy(buf, rxPlain, len < rxLength ? len : rxLength);
324 bool write(
const void* buf, uint8_t len)
326 return write(buf, len,
false);
329 bool write(
const void* buf, uint8_t len,
const bool multicast)
332 return RF24::write(buf, len, multicast);
335 if (!encryptFrame(buf, len, frame)) {
346 bool writeFast(
const void* buf, uint8_t len,
const bool multicast)
349 return RF24::writeFast(buf, len, multicast);
352 if (!encryptFrame(buf, len, frame)) {
355 return RF24::writeFast(frame, (uint8_t)(len +
RF24CCM_OVERHEAD), multicast);
359 uint8_t roundKeys[176] = {0};
361 uint32_t packetCounter = randomCounter();
363 uint8_t rxLength = 0;
364 bool rxPending =
false;
366 static uint32_t randomCounter()
369 if (getrandom(&value,
sizeof(value), 0) !=
sizeof(value)) {
372 return value & 0xFFFFFF;
375 static void buildNonce(
const uint8_t* iv,
const uint8_t* counter, uint8_t nonce[
RF24CCM_NONCE_SIZE])
392 uint32_t counter = packetCounter;
393 packetCounter = (packetCounter + 1) & 0xFFFFFF;
396 counterBytes[i] = (uint8_t)(counter >> (8 * i));
400 buildNonce(frame, counterBytes, nonce);
401 const uint8_t aad = 0x00;
408 bool decryptFrame(
const uint8_t* frame, uint8_t size)
413 const uint8_t* iv = frame;
419 buildNonce(iv, counter, nonce);
420 const uint8_t aad = 0x00;
425 rxLength = cipherLength;
438 uint8_t minRetryDelay = 15;
439 uint8_t minRetryCount = 15;
#define RF24CCM_NONCE_SIZE
Definition RF24CCM.h:37
#define RF24CCM_MIC_SIZE
Definition RF24CCM.h:36
#define RF24CCM_COUNTER_SIZE
Definition RF24CCM.h:35
#define RF24CCM_OVERHEAD
Definition RF24CCM.h:38
#define RF24CCM_KEY_SIZE
Definition RF24CCM.h:33
#define RF24CCM_FRAME_SIZE
Definition RF24CCM.h:39
#define RF24CCM_IV_SIZE
Definition RF24CCM.h:34
void setKey(const uint8_t key[RF24CCM_KEY_SIZE])
Definition RF24CCM.h:266
uint32_t decryptFailures
Definition RF24CCM.h:263
bool write(const void *buf, uint8_t len)
Definition RF24CCM.h:324
void setCounter(uint32_t counter)
Definition RF24CCM.h:273
void read(void *buf, uint8_t len)
Definition RF24CCM.h:310
bool writeFast(const void *buf, uint8_t len, const bool multicast)
Definition RF24CCM.h:346
uint8_t getDynamicPayloadSize(void)
Definition RF24CCM.h:288
bool writeFast(const void *buf, uint8_t len)
Definition RF24CCM.h:341
bool write(const void *buf, uint8_t len, const bool multicast)
Definition RF24CCM.h:329
void setRetries(uint8_t delay, uint8_t count)
Definition RF24CCM.h:279
bool enableEncryption
Definition RF24CCM.h:260
uint8_t rotl8(uint8_t x, uint8_t shift)
Definition RF24CCM.h:48
void aesEncryptBlock(const uint8_t roundKeys[176], const uint8_t in[16], uint8_t out[16])
Definition RF24CCM.h:97
void ccmCtr(const uint8_t roundKeys[176], const uint8_t *nonce, uint8_t nonceLen, const uint8_t *in, size_t len, uint8_t *out, uint8_t s0[16])
Definition RF24CCM.h:189
const uint8_t * sbox()
Definition RF24CCM.h:54
uint8_t xtime(uint8_t x)
Definition RF24CCM.h:43
void ccmEncrypt(const uint8_t roundKeys[176], const uint8_t *nonce, uint8_t nonceLen, const uint8_t *aad, size_t aadLen, const uint8_t *in, size_t len, uint8_t *out, uint8_t *mic, uint8_t micLen)
Definition RF24CCM.h:213
bool ccmDecrypt(const uint8_t roundKeys[176], const uint8_t *nonce, uint8_t nonceLen, const uint8_t *aad, size_t aadLen, const uint8_t *in, size_t len, const uint8_t *mic, uint8_t micLen, uint8_t *out)
Definition RF24CCM.h:225
void aesExpandKey(const uint8_t key[16], uint8_t roundKeys[176])
Definition RF24CCM.h:76
void ccmMac(const uint8_t roundKeys[176], const uint8_t *nonce, uint8_t nonceLen, const uint8_t *aad, size_t aadLen, const uint8_t *msg, size_t msgLen, uint8_t micLen, uint8_t mac[16])
Definition RF24CCM.h:143