Compare commits
No commits in common. "9f8d9a9f51b9c3566be95dfc5ce992b462765a54" and "ac40656c1c642fceee6b59af23e85d28fa32efa7" have entirely different histories.
9f8d9a9f51
...
ac40656c1c
@ -1,62 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "relay/interface/CryptoSource.h"
|
|
||||||
#include "ESP32NoiseSource.h"
|
|
||||||
|
|
||||||
class ESP32CryptoSource: CryptoSource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ESP32CryptoSource(const char* rngInitTag);
|
|
||||||
|
|
||||||
bool isAvailable() override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new random private key
|
|
||||||
*
|
|
||||||
* @param key The output buffer where the key will be stored
|
|
||||||
* @return true The key was created
|
|
||||||
* @return false The key could not be created
|
|
||||||
*/
|
|
||||||
bool createPrivateKey(PrivateKey* key) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a the public key corresponding to a private key
|
|
||||||
*
|
|
||||||
* @param privateKey The private key to use
|
|
||||||
* @param publicKey The output buffer where the public key will be stored
|
|
||||||
* @return true The key was created
|
|
||||||
* @return false The key could not be created
|
|
||||||
*/
|
|
||||||
bool createPublicKey(const PrivateKey* privateKey, PublicKey* publicKey) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sign a message
|
|
||||||
*
|
|
||||||
* @param message The message payload to include in the message
|
|
||||||
* @param length The length of the payload
|
|
||||||
* @param signature The output buffer where the signature is written
|
|
||||||
* @return true The signature was created
|
|
||||||
* @return false The signature creation failed
|
|
||||||
*/
|
|
||||||
bool sign(const uint8_t *message, uint16_t length, Signature* signature, const PrivateKey* privateKey, const PublicKey* publicKey) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Verify a message
|
|
||||||
*
|
|
||||||
* @param signature The message signature
|
|
||||||
* @param publicKey The public key with which the message was signed
|
|
||||||
* @param message The pointer to the message data
|
|
||||||
* @param length The length of the message
|
|
||||||
* @return true The signature is valid
|
|
||||||
* @return false The signature is invalid
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
verify(const Signature* signature, const PublicKey* publicKey, const void *message, uint16_t length) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
ESP32NoiseSource noise{};
|
|
||||||
};
|
|
@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <NoiseSource.h>
|
|
||||||
|
|
||||||
/// @brief The size of the internal buffer when generating entropy
|
|
||||||
constexpr size_t randomNumberBatchSize = 32;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A noise source for crypto operations specifically for the ESP32.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class ESP32NoiseSource: public NoiseSource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* \brief Constructs a new random noise source.
|
|
||||||
*/
|
|
||||||
ESP32NoiseSource();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Destroys this random noise source.
|
|
||||||
*/
|
|
||||||
~ESP32NoiseSource() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Determine if the noise source is still calibrating itself.
|
|
||||||
*
|
|
||||||
* Noise sources that require calibration start doing so at system startup
|
|
||||||
* and then switch over to random data generation once calibration is complete.
|
|
||||||
* Since no random data is being generated during calibration, the output
|
|
||||||
* from `RNGClass::rand()` and `RNG.rand()` may be predictable.
|
|
||||||
* Use `RNGClass::available()` or `RNG.available()` to determine
|
|
||||||
* when sufficient entropy is available to generate good random values.
|
|
||||||
*
|
|
||||||
* It is possible that the noise source never exits calibration. This can
|
|
||||||
* happen if the input voltage is insufficient to trigger noise or if the
|
|
||||||
* noise source is not connected. Noise sources may also periodically
|
|
||||||
* recalibrate themselves.
|
|
||||||
*
|
|
||||||
* @return Returns true if calibration is in progress; false if the noise
|
|
||||||
* source is generating valid random data.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool calibrating() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stirs entropy from this noise source into the global random
|
|
||||||
* number pool.
|
|
||||||
*
|
|
||||||
* This function should call `output()` to add the entropy from this noise
|
|
||||||
* source to the global random number pool.
|
|
||||||
*
|
|
||||||
* The noise source should batch up the entropy data, providing between
|
|
||||||
* 16 and 48 bytes of data each time. If the noise source does not have
|
|
||||||
* sufficient entropy data at the moment, it should return without stiring
|
|
||||||
* the current data in.
|
|
||||||
*/
|
|
||||||
void stir() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/// @brief Temporary buffer to hold random bytes before handing them to the crypto module
|
|
||||||
uint8_t data[randomNumberBatchSize];
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
#include "relay/interface/StorageSource.h"
|
|
||||||
|
|
||||||
class ESP32StorageSource: StorageSource {
|
|
||||||
|
|
||||||
bool writeByteAtIndex(uint8_t byte, uint16_t index) override;
|
|
||||||
|
|
||||||
bool canProvideStorageWithSize(uint16_t size) override;
|
|
||||||
|
|
||||||
bool commitData();
|
|
||||||
|
|
||||||
uint8_t readByteAtIndex(uint16_t index) override;
|
|
||||||
|
|
||||||
uint16_t readBytes(uint16_t startIndex, uint16_t count, uint8_t* output) override;
|
|
||||||
|
|
||||||
uint16_t writeBytes(uint8_t* bytes, uint16_t count, uint16_t startIndex) override;
|
|
||||||
};
|
|
@ -1,68 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "relay/CryptoPrimitives.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An abstract definition of an instance capable of crypto operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CryptoSource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Indicate that the crypto functions can be used.
|
|
||||||
*
|
|
||||||
* @return true The crypto functions are available
|
|
||||||
* @return false Some error prevents the use of the crypto functions.
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool isAvailable() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new random private key
|
|
||||||
*
|
|
||||||
* @param key The output buffer where the key will be stored
|
|
||||||
* @return true The key was created
|
|
||||||
* @return false The key could not be created
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool createPrivateKey(PrivateKey* key) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a the public key corresponding to a private key
|
|
||||||
*
|
|
||||||
* @param privateKey The private key to use
|
|
||||||
* @param publicKey The output buffer where the public key will be stored
|
|
||||||
* @return true The key was created
|
|
||||||
* @return false The key could not be created
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool createPublicKey(const PrivateKey* privateKey, PublicKey* publicKey) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sign a message
|
|
||||||
*
|
|
||||||
* @param message The message payload to include in the message
|
|
||||||
* @param length The length of the payload
|
|
||||||
* @param signature The output buffer where the signature is written
|
|
||||||
* @return true The signature was created
|
|
||||||
* @return false The signature creation failed
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool sign(const uint8_t *message, uint16_t length, Signature* signature, const PrivateKey* privateKey, const PublicKey* publicKey) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Verify a message
|
|
||||||
*
|
|
||||||
* @param signature The message signature
|
|
||||||
* @param publicKey The public key with which the message was signed
|
|
||||||
* @param message The pointer to the message data
|
|
||||||
* @param length The length of the message
|
|
||||||
* @return true The signature is valid
|
|
||||||
* @return false The signature is invalid
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool verify(const Signature* signature, const PublicKey* publicKey, const void *message, uint16_t length) = 0;
|
|
||||||
};
|
|
@ -1,98 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An abstract interface for persistent storage
|
|
||||||
*
|
|
||||||
* @note It is assumed that read operations are cached and therefore quick.
|
|
||||||
*/
|
|
||||||
class StorageSource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write a byte to disk
|
|
||||||
*
|
|
||||||
* @note The data is only persisted if the function `commitData()` is called afterwards.
|
|
||||||
*
|
|
||||||
* @param byte The byte to write
|
|
||||||
* @param index The index where to write the byte
|
|
||||||
* @return true
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool writeByteAtIndex(uint8_t byte, uint16_t index) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Ensure that enough storage is available for all data
|
|
||||||
*
|
|
||||||
* @param size
|
|
||||||
* @return true The space was initialized an has sufficient size
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool canProvideStorageWithSize(uint16_t size) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write the data to persistent storage after a block of bytes was changed.
|
|
||||||
*
|
|
||||||
* @return true The data was persisted
|
|
||||||
* @return false The data could not be saved
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
bool commitData() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a single byte from persistent storage
|
|
||||||
*
|
|
||||||
* @param index The index of the byte in the data
|
|
||||||
* @return uint8_t The byte at the given index
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
uint8_t readByteAtIndex(uint16_t index) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a number of bytes from storage
|
|
||||||
*
|
|
||||||
* @param startIndex The index of the start byte
|
|
||||||
* @param count The number of bytes to read
|
|
||||||
* @param output The location to write the bytes
|
|
||||||
* @return uint8_t The number of bytes read
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
uint16_t readBytes(uint16_t startIndex, uint16_t count, uint8_t* output) {
|
|
||||||
uint16_t endIndex = startIndex + count;
|
|
||||||
if (endIndex < startIndex) {
|
|
||||||
return 0; // Overflow
|
|
||||||
}
|
|
||||||
for (uint16_t i = 0; i < endIndex; i += 1) {
|
|
||||||
output[i] = readByteAtIndex(startIndex + i);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write a number of bytes to storage
|
|
||||||
*
|
|
||||||
* @note The data is only persisted if the function `commitData()` is called afterwards.
|
|
||||||
*
|
|
||||||
* @param bytes The memory holding the bytes
|
|
||||||
* @param count The number of bytes to write
|
|
||||||
* @param startIndex The index where the bytes should be written
|
|
||||||
* @return uint16_t The number of bytes written to storage
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
uint16_t writeBytes(uint8_t* bytes, uint16_t count, uint16_t startIndex) {
|
|
||||||
uint16_t endIndex = startIndex + count;
|
|
||||||
if (endIndex < startIndex) {
|
|
||||||
return 0; // Overflow
|
|
||||||
}
|
|
||||||
for (uint16_t i = 0; i < endIndex; i += 1) {
|
|
||||||
if (!writeByteAtIndex(bytes[i], startIndex + i)) {
|
|
||||||
return i; // Failed to write byte
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
};
|
|
@ -18,6 +18,6 @@ lib_deps =
|
|||||||
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
||||||
arduino-libraries/Ethernet@^2.0.2
|
arduino-libraries/Ethernet@^2.0.2
|
||||||
https://github.com/christophhagen/arduinoWebSockets#master
|
https://github.com/christophhagen/arduinoWebSockets#master
|
||||||
rweather/Crypto@^0.4.0
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
build_flags= -D WEBSOCKETS_NETWORK_TYPE=NETWORK_W5100
|
build_flags= -D WEBSOCKETS_NETWORK_TYPE=NETWORK_W5100
|
@ -1,29 +0,0 @@
|
|||||||
#include "interface/ESP32CryptoSource.h"
|
|
||||||
|
|
||||||
#include <Ed25519.h>
|
|
||||||
#include <RNG.h>
|
|
||||||
#include <NoiseSource.h>
|
|
||||||
|
|
||||||
ESP32CryptoSource::ESP32CryptoSource(const char* rngInitTag) {
|
|
||||||
RNG.begin(rngInitTag);
|
|
||||||
RNG.addNoiseSource(noise);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32CryptoSource::createPrivateKey(PrivateKey* key) {
|
|
||||||
Ed25519::generatePrivateKey(key->bytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32CryptoSource::createPublicKey(const PrivateKey* privateKey, PublicKey* publicKey) {
|
|
||||||
Ed25519::derivePublicKey(publicKey->bytes, privateKey->bytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32CryptoSource::sign(const uint8_t *message, uint16_t length, Signature* signature, const PrivateKey* privateKey, const PublicKey* publicKey) {
|
|
||||||
Ed25519::sign(signature->bytes, privateKey->bytes, publicKey->bytes, message, length);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32CryptoSource::verify(const Signature* signature, const PublicKey* publicKey, const void *message, uint16_t length) {
|
|
||||||
return Ed25519::verify(signature->bytes, publicKey->bytes, message, length);
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
#include "interface/ESP32NoiseSource.h"
|
|
||||||
|
|
||||||
#include <esp_random.h>
|
|
||||||
#include <bootloader_random.h>
|
|
||||||
|
|
||||||
ESP32NoiseSource::ESP32NoiseSource() {
|
|
||||||
// Ensure that there is randomness even if Bluetooth and WiFi are disabled
|
|
||||||
bootloader_random_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32NoiseSource::calibrating() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP32NoiseSource::stir() {
|
|
||||||
esp_fill_random(data, randomNumberBatchSize);
|
|
||||||
output(data, randomNumberBatchSize, randomNumberBatchSize * 8);
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#include "interface/ESP32StorageSource.h"
|
|
||||||
#include <EEPROM.h>
|
|
||||||
|
|
||||||
bool ESP32StorageSource::writeByteAtIndex(uint8_t byte, uint16_t index) {
|
|
||||||
// TODO: What does return value mean?
|
|
||||||
EEPROM.writeByte((int) index, byte);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32StorageSource::canProvideStorageWithSize(uint16_t size) {
|
|
||||||
return EEPROM.begin(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP32StorageSource::commitData() {
|
|
||||||
return EEPROM.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ESP32StorageSource::readByteAtIndex(uint16_t index) {
|
|
||||||
return EEPROM.readByte((int) index);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ESP32StorageSource::readBytes(uint16_t startIndex, uint16_t count, uint8_t* output) {
|
|
||||||
return EEPROM.readBytes(startIndex, output, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ESP32StorageSource::writeBytes(uint8_t* bytes, uint16_t count, uint16_t startIndex) {
|
|
||||||
return EEPROM.writeBytes(startIndex, bytes, count);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user