214 lines
5.7 KiB
C
214 lines
5.7 KiB
C
#include "meshframing.h"
|
|
#include "lib/config.h"
|
|
#include "string.h"
|
|
#include "stdio.h"
|
|
#include "sx1262.h"
|
|
#include "util/hexdump.h"
|
|
|
|
FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen) {
|
|
hexdump ("RxDump", data, dataLen);
|
|
FrameStruct frame;
|
|
memset (&frame, 0, sizeof (frame));
|
|
unsigned char index = 0;
|
|
frame.header = data[index++];
|
|
if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
|
|
(frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
|
memcpy (frame.transportCodes, data + index, 4);
|
|
index += 4;
|
|
}
|
|
frame.path.pathLen = data[index++];
|
|
|
|
memcpy (frame.path.path, data + index, frame.path.pathLen);
|
|
index += frame.path.pathLen;
|
|
frame.payloadLen = dataLen - index;
|
|
memcpy (frame.payload, data + index, frame.payloadLen);
|
|
|
|
return frame;
|
|
}
|
|
|
|
void printFrameHeader (FrameStruct frame) {
|
|
switch (frame.header & ROUTE_TYPE_MASK) {
|
|
case ROUTE_TYPE_TRANSPORT_FLOOD:
|
|
printf ("transport flood");
|
|
break;
|
|
|
|
case ROUTE_TYPE_FLOOD:
|
|
printf ("flood");
|
|
break;
|
|
|
|
case ROUTE_TYPE_DIRECT:
|
|
printf ("direct");
|
|
break;
|
|
|
|
case ROUTE_TYPE_TRANSPORT_DIRECT:
|
|
printf ("transport direct");
|
|
break;
|
|
}
|
|
|
|
printf (", payload type is ");
|
|
|
|
switch (frame.header & PAYLOAD_TYPE_MASK) {
|
|
case PAYLOAD_TYPE_REQ:
|
|
printf ("request");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_RESPONSE:
|
|
printf ("response");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_TXT_MSG:
|
|
printf ("text message");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_ACK:
|
|
printf ("acknowledgement");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_ADVERT:
|
|
printf ("advert");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_GRP_TXT:
|
|
printf ("group text");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_GRP_DATA:
|
|
printf ("group data");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_ANON_REQ:
|
|
printf ("anon request");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_PATH:
|
|
printf ("path");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_TRACE:
|
|
printf ("trace");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_MULTIPART:
|
|
printf ("multipart");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_CONTROL:
|
|
printf ("control");
|
|
break;
|
|
|
|
case PAYLOAD_TYPE_RAW_CUSTOM:
|
|
printf ("raw");
|
|
break;
|
|
}
|
|
char version[2];
|
|
version[0] = (frame.header >> 6) + '0';
|
|
version[1] = 0;
|
|
|
|
printf (", payload version is %s ", version);
|
|
|
|
if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
|
|
(frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
|
printf ("Transport codes: %d %d\n", *((uint16_t *)frame.transportCodes),
|
|
*((uint16_t *)&(frame.transportCodes[2])));
|
|
}
|
|
printf ("Path is %d nodes long", frame.path.pathLen);
|
|
|
|
for (uint8_t pathIndex = 0; pathIndex < frame.path.pathLen; pathIndex++) {
|
|
printf ("node %d - %02X, ", pathIndex, frame.path.path[pathIndex]);
|
|
}
|
|
putchar ('\n');
|
|
}
|
|
|
|
void sendFrame (FrameStruct frame) {
|
|
uint8_t txBuf[256];
|
|
size_t offset = 0;
|
|
|
|
txBuf[offset++] = frame.header;
|
|
|
|
if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
|
|
(frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
|
memcpy (txBuf + offset, frame.transportCodes, 4);
|
|
offset += 4;
|
|
}
|
|
|
|
if (frame.path.pathLen > 64) {
|
|
frame.path.pathLen = 64;
|
|
}
|
|
|
|
txBuf[offset++] = frame.path.pathLen;
|
|
|
|
memcpy (txBuf + offset, frame.path.path, frame.path.pathLen);
|
|
offset += frame.path.pathLen;
|
|
|
|
uint16_t maxPayloadLen = 256 - offset;
|
|
|
|
uint16_t payloadLen = frame.payloadLen > maxPayloadLen ? maxPayloadLen : frame.payloadLen;
|
|
|
|
memcpy (txBuf + offset, frame.payload, payloadLen);
|
|
offset += payloadLen;
|
|
|
|
hexdump ("TxDump", txBuf, offset);
|
|
LoRaSend (txBuf, offset, SX126x_TXMODE_SYNC);
|
|
}
|
|
|
|
void retransmitFrame (FrameStruct frame) {
|
|
if (frame.header & ROUTE_TYPE_FLOOD || frame.header & ROUTE_TYPE_TRANSPORT_FLOOD) {
|
|
if (frame.header != DONT_RETRANSMIT_HEADER && frame.path.pathLen + 1 < MAX_FLOOD_TTL) {
|
|
frame.path.path[frame.path.pathLen++] = persistent.pubkey[0];
|
|
}
|
|
}
|
|
|
|
if (frame.header & ROUTE_TYPE_DIRECT || frame.header & ROUTE_TYPE_TRANSPORT_DIRECT) {
|
|
}
|
|
}
|
|
|
|
|
|
// Verify MAC + Decrypt
|
|
|
|
int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8_t *plaintext, size_t plen, uint8_t *output, size_t *olen) {
|
|
if (plen == 0)
|
|
return -1;
|
|
|
|
size_t padded_len = ((plen + 15) / 16) * 16;
|
|
|
|
// prepare padded buffer
|
|
uint8_t padded[padded_len];
|
|
memset(padded, 0, padded_len); // zero padding
|
|
memcpy(padded, plaintext, plen); // copy plaintext
|
|
|
|
// ciphertext will go right after HMAC
|
|
uint8_t *ciphertext = output + HMAC_SIZE;
|
|
|
|
// encrypt plaintext
|
|
aes_encrypt_ecb (aes_key, 16, padded, padded_len, ciphertext);
|
|
|
|
// compute HMAC over ciphertext
|
|
uint8_t mac[32]; // full SHA-256
|
|
hmac_sha256 (aes_key, keySize, ciphertext, padded_len, mac);
|
|
|
|
// copy only HMAC_SIZE bytes of MAC
|
|
memcpy (output, mac, HMAC_SIZE);
|
|
|
|
// return total length = HMAC + ciphertext
|
|
*olen = HMAC_SIZE + padded_len;
|
|
return 0;
|
|
}
|
|
|
|
int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8_t *input, size_t ilen, uint8_t *plaintext) {
|
|
if (ilen <= HMAC_SIZE)
|
|
return -1;
|
|
|
|
const uint8_t *mac = input;
|
|
const uint8_t *ciphertext = input + HMAC_SIZE;
|
|
size_t clen = ilen - HMAC_SIZE;
|
|
|
|
if (clen % 16 != 0) return -2; // must be multiple of block size
|
|
|
|
uint8_t calc_mac[32]; // full SHA-256
|
|
hmac_sha256 (aes_key, keySize, ciphertext, clen, calc_mac);
|
|
|
|
if (memcmp (mac, calc_mac, HMAC_SIZE) != 0)
|
|
return -2;
|
|
|
|
return aes_decrypt_ecb (aes_key, 16, ciphertext, clen, plaintext);
|
|
} |