2024-06-27 22:35:58 -06:00
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ChaChaPoly.h>
|
|
|
|
#include <HardwareSerial.h>
|
2024-06-30 19:00:22 -06:00
|
|
|
#include "Crypto.h"
|
2024-06-27 22:35:58 -06:00
|
|
|
|
|
|
|
void print_hex(const unsigned char *data, size_t length) {
|
|
|
|
for (size_t i = 0; i < length; ++i) {
|
|
|
|
Serial.printf("%02x", data[i]);
|
|
|
|
}
|
|
|
|
Serial.println();
|
|
|
|
}
|
|
|
|
|
|
|
|
void encrypt_string(const unsigned char *input, size_t length, unsigned char *output) {
|
|
|
|
ChaChaPoly chachaPoly;
|
|
|
|
|
|
|
|
// Initialize the encryption key
|
|
|
|
unsigned char key[32];
|
|
|
|
for (int i = 0; i < 32; ++i) {
|
|
|
|
sscanf(CHACHA20_KEY + 2*i, "%02x", &key[i]);
|
|
|
|
}
|
|
|
|
chachaPoly.setKey(key, sizeof(key));
|
|
|
|
|
|
|
|
// Generate a random nonce (IV)
|
|
|
|
unsigned char nonce[12];
|
|
|
|
esp_fill_random(nonce, sizeof(nonce)); // Use the ESP-IDF random number generator
|
|
|
|
chachaPoly.setIV(nonce, sizeof(nonce));
|
|
|
|
|
|
|
|
// Encrypt the input data
|
|
|
|
chachaPoly.encrypt(output + sizeof(nonce), input, length);
|
|
|
|
|
|
|
|
// Compute the authentication tag
|
|
|
|
chachaPoly.computeTag(output + sizeof(nonce) + length, chachaPoly.tagSize());
|
|
|
|
|
|
|
|
// Prepend the nonce to the output
|
|
|
|
memcpy(output, nonce, sizeof(nonce));
|
|
|
|
|
|
|
|
chachaPoly.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void decrypt_string(const unsigned char *input, size_t length, unsigned char *output) {
|
|
|
|
ChaChaPoly chachaPoly;
|
|
|
|
|
|
|
|
// Initialize the decryption key
|
|
|
|
unsigned char key[32];
|
|
|
|
for (int i = 0; i < 32; ++i) {
|
|
|
|
sscanf(CHACHA20_KEY + 2*i, "%02x", &key[i]);
|
|
|
|
}
|
|
|
|
chachaPoly.setKey(key, sizeof(key));
|
|
|
|
|
|
|
|
// Extract the nonce (IV) from the input
|
|
|
|
unsigned char nonce[12];
|
|
|
|
memcpy(nonce, input, sizeof(nonce));
|
|
|
|
chachaPoly.setIV(nonce, sizeof(nonce));
|
|
|
|
|
|
|
|
// Check that length is long enough to contain a nonce and a tag.
|
|
|
|
if (length < sizeof(nonce) + chachaPoly.tagSize()) {
|
|
|
|
Serial.print("[CHACHA] Input too short to contain nonce and tag: ");
|
|
|
|
print_hex(input, length);
|
|
|
|
output[0] = '\0'; // Set output to an empty string
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrypt the input data
|
|
|
|
size_t decryptedLength = length - sizeof(nonce) - chachaPoly.tagSize();
|
|
|
|
chachaPoly.decrypt(output, input + sizeof(nonce), decryptedLength);
|
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
// String decryptedString = "";
|
|
|
|
// for (size_t i = 0; i < decryptedLength; i++) {
|
|
|
|
// decryptedString += (char)output[i];
|
|
|
|
// }
|
|
|
|
// Serial.println(decryptedString);
|
2024-06-27 22:35:58 -06:00
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
const unsigned char *tagPtr = input + sizeof(nonce) + decryptedLength; // actual tag
|
|
|
|
uint8_t computedTag[16]; // computed tag
|
|
|
|
chachaPoly.computeTag(computedTag, sizeof(computedTag));
|
2024-06-27 22:35:58 -06:00
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
// Serial.print("Tag: ");
|
|
|
|
// for (size_t i = 0; i < chachaPoly.tagSize(); i++) {
|
|
|
|
// Serial.print(tagPtr[i], HEX);
|
|
|
|
// Serial.print(" ");
|
|
|
|
// }
|
|
|
|
// Serial.println();
|
|
|
|
// Serial.print("Computed Tag: ");
|
|
|
|
// for (size_t i = 0; i < sizeof(computedTag); i++) {
|
|
|
|
// Serial.print(computedTag[i], HEX);
|
|
|
|
// Serial.print(" ");
|
|
|
|
// }
|
|
|
|
// Serial.println();
|
|
|
|
|
|
|
|
///// BEGIN TAG VERIFY
|
|
|
|
// The crypto library implementation of tag verification crashes.
|
|
|
|
|
|
|
|
// Can never match if the expected tag length is too long.
|
|
|
|
if (chachaPoly.tagSize() > 16) {
|
|
|
|
Serial.println("[CHACHA] Authentication failed: expected tag length is too long");
|
|
|
|
output[0] = '\0'; // Set output to an empty string
|
|
|
|
return;
|
2024-06-27 22:35:58 -06:00
|
|
|
}
|
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
// Compute the tag and check it.
|
|
|
|
bool equal = secure_compare(computedTag, tagPtr, chachaPoly.tagSize());
|
|
|
|
clean(computedTag);
|
2024-06-27 22:35:58 -06:00
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
if (!equal) {
|
|
|
|
Serial.println("[CHACHA] Authentication failed!");
|
|
|
|
output[0] = '\0';
|
2024-06-27 22:35:58 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
///// END TAG VERIFY
|
2024-06-27 22:35:58 -06:00
|
|
|
|
2024-06-30 19:00:22 -06:00
|
|
|
output[decryptedLength] = '\0';
|
2024-06-27 22:35:58 -06:00
|
|
|
chachaPoly.clear();
|
|
|
|
}
|