Sesame-Device/include/message.h
2023-12-11 00:05:18 +01:00

144 lines
3.7 KiB
C++

#pragma once
#include <stdint.h>
#include <stddef.h>
/**
* @brief The size of a message authentication code
*
* The MAC size is determined by the size of the output
* of the hash function used. In this case, for SHA256,
* the size is 32 bytes (= 256 bit)
*/
#define SHA256_MAC_SIZE 32
#pragma pack(push, 1)
enum class MessageType: uint8_t {
/// @brief The initial message from remote to device to request a challenge.
initial = 0,
/// @brief The second message in an unlock with the challenge from the device to the remote
challenge = 1,
/// @brief The third message with the signed challenge from the remote to the device
request = 2,
/// @brief The final message with the unlock result from the device to the remote
response = 3,
};
enum class MessageResult: uint8_t {
/// @brief The message was accepted.
MessageAccepted = 0,
/// @brief The web socket received text while waiting for binary data.
TextReceivedOverSocket = 1,
/// @brief An unexpected socket event occured while performing the exchange.
UnexpectedSocketEvent = 2,
/// @brief The received message size is invalid.
InvalidMessageSizeFromRemote = 3,
/// @brief The message signature was incorrect.
InvalidSignatureFromRemote = 4,
/// @brief The server challenge of the message did not match previous messages
InvalidServerChallengeFromRemote = 5,
/// @brief The client challenge of the message did not match previous messages
InvalidClientChallengeFromRemote = 6,
/// @brief An unexpected or unsupported message type was received
InvalidMessageTypeFromRemote = 7,
/// @brief A message is already being processed
TooManyRequests = 8,
/// @brief The received message result was invalid
InvalidMessageResultFromRemote = 9,
/// @brief An invalid Url parameter was set sending a message to the device over a local connection
InvalidUrlParameter = 10,
};
/**
* @brief A generic message to exchange during challenge-response authentication.
*/
typedef struct {
/// @brief The type of message being sent.
MessageType messageType;
/**
* @brief The random nonce created by the remote
*
* This nonce is a random number created by the remote, different for each unlock request.
* It is set for all message types.
*/
uint32_t clientChallenge;
/**
* @brief A random number to sign by the remote
*
* This nonce is set by the server after receiving an initial message.
* It is set for the message types `challenge`, `request`, and `response`.
*/
uint32_t serverChallenge;
/**
* @brief The response status for the previous message.
*
* It is set only for messages from the server, e.g. the `challenge` and `response` message types.
* Must be set to `MessageAccepted` for other messages.
*/
MessageResult result;
} Message;
/**
* @brief The signed version of a message.
*
*/
typedef struct {
/**
* @brief The authentication code of the message
*
* The code is created by performing HMAC-SHA256
* over the bytes of the `Message`.
*/
uint8_t mac[SHA256_MAC_SIZE];
/// @brief The message
Message message;
} SignedMessage;
constexpr size_t messageCounterSize = sizeof(uint32_t);
#pragma pack(pop)
constexpr int MESSAGE_CONTENT_SIZE = sizeof(Message);
constexpr int SIGNED_MESSAGE_SIZE = sizeof(SignedMessage);
/**
* @brief A callback for messages received over the socket
*
* The first parameter is a pointer to the byte buffer.
* The second parameter indicates the number of received bytes.
*/
typedef void (*MessageCallback)(uint8_t* payload, size_t length);
/**
* @brief A callback for socket errors
*/
typedef void (*ErrorCallback)(MessageResult event);