144 lines
3.7 KiB
C++
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.
|
|
TextReceived = 1,
|
|
|
|
/// @brief An unexpected socket event occured while performing the exchange.
|
|
UnexpectedSocketEvent = 2,
|
|
|
|
/// @brief The received message size is invalid.
|
|
InvalidMessageSize = 3,
|
|
|
|
/// @brief The message signature was incorrect.
|
|
MessageAuthenticationFailed = 4,
|
|
|
|
/// @brief The server challenge of the message did not match previous messages
|
|
ServerChallengeMismatch = 5,
|
|
|
|
/// @brief The client challenge of the message did not match previous messages
|
|
ClientChallengeInvalid = 6,
|
|
|
|
/// @brief An unexpected or unsupported message type was received
|
|
InvalidMessageType = 7,
|
|
|
|
/// @brief A message is already being processed
|
|
TooManyRequests = 8,
|
|
|
|
/// @brief The received message result was invalid
|
|
InvalidMessageResult = 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);
|
|
|