#pragma once #include /** * @brief The size of the message counter in bytes (uint32_t) */ #define MESSAGE_COUNTER_SIZE sizeof(uint32_t) /** * @brief Configure an NTP server to get the current time * * @param offsetToGMT The timezone offset in seconds * @param offsetDaylightSavings The daylight savings offset in seconds * @param serverUrl The url of the NTP server */ void configureNTP(int32_t offsetToGMT, int32_t offsetDaylightSavings, const char* serverUrl); /** * @brief Print the current time to the serial output * * The time must be initialized by calling `configureNTP()` before use. */ void printLocalTime(); /** * Gets the current epoch time */ uint32_t getEpochTime(); /** * @brief The allowed time discrepancy (in seconds) * * Specifies 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 offset in both directions (seconds) */ void setMessageTimeAllowedOffset(uint32_t offset); /** * @brief Check wether the time of a message is within the allowed bounds regarding freshness. * * The timestamp is used to ensure 'freshness' of the messages, * i.e. that they are not unreasonably delayed or captured and * later replayed by an attacker. * * @param messageTime The timestamp of the message (seconds since epoch) * @return true The time is within the acceptable offset of the local time * @return false The message time is invalid */ bool isMessageTimeAcceptable(uint32_t messageTime); /** * @brief Initialize the use of the message counter API * * The message counter is stored in EEPROM, which must be initialized before use. * * @note The ESP32 does not have a true EEPROM, * which is emulated using a section of the flash memory. */ void prepareMessageCounterUsage(); /** * @brief Get the expected count for the next message. * * The counter is stored in EEPROM to persist across restarts * * @return The next counter to use by the remote */ uint32_t getNextMessageCounter(); /** * @brief Print info about the current message counter to the serial output * */ void printMessageCounter(); /** * @brief Check if a received counter is valid * * The counter is valid if it is larger than the previous counter * (larger or equal to the next expected counter). * * @param counter The counter to check * @return true The counter is valid * @return false The counter belongs to an old message */ bool isMessageCounterValid(uint32_t counter); /** * @brief Mark a counter of a message as used. * * The counter value is stored in EEPROM to persist across restarts. * * All messages with counters lower than the given one will become invalid. * * @param counter The counter used in the last message. */ void didUseMessageCounter(uint32_t counter); /** * @brief Reset the message counter. * * @warning The counter should never be reset in production environments, * and only together with a new secret key. Otherwise old messages may be * used for replay attacks. * */ void resetMessageCounter();