Create time class

This commit is contained in:
Christoph Hagen 2023-08-09 13:25:19 +02:00
parent 67169240f9
commit d13bf67443
5 changed files with 93 additions and 68 deletions

View File

@ -4,12 +4,13 @@
#include "servo.h" #include "servo.h"
#include "message.h" #include "message.h"
#include "storage.h" #include "storage.h"
#include "fresh.h"
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
class SesameController: public ServerConnectionCallbacks { class SesameController: public ServerConnectionCallbacks {
public: public:
SesameController(ServerConnection* server, ServoController* servo, AsyncWebServer* local, uint8_t remoteDeviceCount); SesameController(ServerConnection* server, ServoController* servo, AsyncWebServer* local, TimeCheck* timeCheck, uint8_t remoteDeviceCount);
void configure(); void configure();
@ -18,6 +19,7 @@ private:
ServerConnection* server; ServerConnection* server;
ServoController* servo; ServoController* servo;
AsyncWebServer* local; AsyncWebServer* local;
TimeCheck* timeCheck;
Storage storage; Storage storage;
// The buffer to hold a received message while it is read // The buffer to hold a received message while it is read

View File

@ -3,6 +3,24 @@
#include <stdint.h> #include <stdint.h>
#include "config.h" #include "config.h"
class TimeCheck {
public:
/**
* @brief Create a time checker instance
*
* Specify the allowed discrepancy between the time of a received message
* and the device time (in seconds).
*
* A stricter (lower) value better prevents against replay attacks,
* but may lead to issues when dealing with slow networks and other
* routing delays.
*
* @param offset The allowed time discrepancy in both directions (seconds)
*/
TimeCheck(uint32_t allowedTimeOffset = 60);
/** /**
* @brief Configure an NTP server to get the current time * @brief Configure an NTP server to get the current time
* *
@ -50,3 +68,16 @@ void setMessageTimeAllowedOffset(uint32_t offset);
* @return false The message time is invalid * @return false The message time is invalid
*/ */
bool isMessageTimeAcceptable(uint32_t messageTime); bool isMessageTimeAcceptable(uint32_t messageTime);
private:
/**
* @brief The allowed discrepancy between the time of a received message
* and the device time (in seconds)
*
* A stricter (lower) value better prevents against replay attacks,
* but may lead to issues when dealing with slow networks and other
* routing delays.
*/
uint32_t allowedOffset;
};

View File

@ -3,8 +3,8 @@
#include "fresh.h" #include "fresh.h"
#include "crypto.h" #include "crypto.h"
SesameController::SesameController(ServerConnection* server, ServoController* servo, AsyncWebServer* local, uint8_t remoteDeviceCount) : SesameController::SesameController(ServerConnection* server, ServoController* servo, AsyncWebServer* local, TimeCheck* timeCheck, uint8_t remoteDeviceCount) :
server(server), servo(servo), local(local), storage(remoteDeviceCount) { server(server), servo(servo), local(local), timeCheck(timeCheck), storage(remoteDeviceCount) {
// Set up response buffer // Set up response buffer
responseStatus = (SesameEvent*) responseBuffer; responseStatus = (SesameEvent*) responseBuffer;
@ -99,7 +99,7 @@ SesameEvent SesameController::verifyAndProcessReceivedMessage(AuthenticatedMessa
if (!storage.isMessageCounterValid(message->message.id, message->message.device)) { if (!storage.isMessageCounterValid(message->message.id, message->message.device)) {
return SesameEvent::MessageCounterInvalid; return SesameEvent::MessageCounterInvalid;
} }
if (!isMessageTimeAcceptable(message->message.time)) { if (!timeCheck->isMessageTimeAcceptable(message->message.time)) {
return SesameEvent::MessageTimeMismatch; return SesameEvent::MessageTimeMismatch;
} }
@ -127,7 +127,7 @@ uint16_t SesameController::prepareResponseBuffer(SesameEvent event, uint8_t devi
if (!allowMessageResponse(event)) { if (!allowMessageResponse(event)) {
return 1; return 1;
} }
responseMessage->message.time = getEpochTime(); responseMessage->message.time = timeCheck->getEpochTime();
responseMessage->message.id = storage.getNextMessageCounter(deviceId); responseMessage->message.id = storage.getNextMessageCounter(deviceId);
responseMessage->message.device = deviceId; responseMessage->message.device = deviceId;
if (!authenticateMessage(responseMessage, localKey, keySize)) { if (!authenticateMessage(responseMessage, localKey, keySize)) {

View File

@ -1,27 +1,17 @@
#include "fresh.h" #include "fresh.h"
#include <Arduino.h> #include <Arduino.h> // configTime()
#include <time.h> #include <time.h>
/** TimeCheck::TimeCheck(uint32_t allowedTimeOffset) {
* @brief The allowed discrepancy between the time of a received message allowedOffset = allowedTimeOffset;
* and the device time (in seconds)
*
* A stricter (lower) value better prevents against replay attacks,
* but may lead to issues when dealing with slow networks and other
* routing delays.
*/
uint32_t allowedOffset = 60;
void setMessageTimeAllowedOffset(uint32_t offset) {
allowedOffset = offset;
} }
void configureNTP(int32_t offsetToGMT, int32_t offsetDaylightSavings, const char* serverUrl) { void TimeCheck::configureNTP(int32_t offsetToGMT, int32_t offsetDaylightSavings, const char* serverUrl) {
configTime(offsetToGMT, offsetDaylightSavings, serverUrl); configTime(offsetToGMT, offsetDaylightSavings, serverUrl);
} }
void printLocalTime() { void TimeCheck::printLocalTime() {
struct tm timeinfo; struct tm timeinfo;
if (getLocalTime(&timeinfo)) { if (getLocalTime(&timeinfo)) {
Serial.println(&timeinfo, "[INFO] Time is %A, %d. %B %Y %H:%M:%S"); Serial.println(&timeinfo, "[INFO] Time is %A, %d. %B %Y %H:%M:%S");
@ -30,7 +20,7 @@ void printLocalTime() {
} }
} }
uint32_t getEpochTime() { uint32_t TimeCheck::getEpochTime() {
time_t now; time_t now;
struct tm timeinfo; struct tm timeinfo;
if (!getLocalTime(&timeinfo)) { if (!getLocalTime(&timeinfo)) {
@ -41,7 +31,7 @@ uint32_t getEpochTime() {
return now; return now;
} }
bool isMessageTimeAcceptable(uint32_t t) { bool TimeCheck::isMessageTimeAcceptable(uint32_t t) {
uint32_t localTime = getEpochTime(); uint32_t localTime = getEpochTime();
if (localTime == 0) { if (localTime == 0) {
Serial.println("No epoch time available"); Serial.println("No epoch time available");

View File

@ -19,13 +19,15 @@
/* Global variables */ /* Global variables */
TimeCheck timeCheck{};
ServerConnection server(serverUrl, serverPort, serverPath); ServerConnection server(serverUrl, serverPort, serverPath);
ServoController servo(pwmTimer, servoFrequency, servoPin); ServoController servo(pwmTimer, servoFrequency, servoPin);
AsyncWebServer local(localPort); AsyncWebServer local(localPort);
SesameController controller(&server, &servo, &local, remoteDeviceCount); SesameController controller(&server, &servo, &local, &timeCheck, remoteDeviceCount);
// Forward declare monitoring functions // Forward declare monitoring functions
void ensureWiFiConnection(uint32_t time); void ensureWiFiConnection(uint32_t time);
@ -75,8 +77,8 @@ void ensureWebSocketConnection(uint32_t time) {
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
Serial.println("[INFO] WiFi connected, opening socket"); Serial.println("[INFO] WiFi connected, opening socket");
server.connect(serverAccessKey); server.connect(serverAccessKey);
configureNTP(timeOffsetToGMT, timeOffsetDaylightSavings, ntpServerUrl); timeCheck.configureNTP(timeOffsetToGMT, timeOffsetDaylightSavings, ntpServerUrl);
printLocalTime(); timeCheck.printLocalTime();
local.begin(); local.begin();
} }
} }