87 lines
2.7 KiB
C
87 lines
2.7 KiB
C
|
#pragma once
|
||
|
|
||
|
#include "stdint.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)
|
||
|
|
||
|
/**
|
||
|
* @brief The content of an unlock message.
|
||
|
*
|
||
|
* The content is necessary to ensure freshness of the message
|
||
|
* by requiring a recent time and a monotonously increasing counter.
|
||
|
* This prevents messages from being delayed or being blocked and
|
||
|
* replayed later.
|
||
|
*/
|
||
|
typedef struct {
|
||
|
|
||
|
/**
|
||
|
* The timestamp of message creation
|
||
|
*
|
||
|
* The timestamp is encoded as the epoch time, i.e. seconds since 1970 (GMT).
|
||
|
*
|
||
|
* 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.
|
||
|
*/
|
||
|
uint32_t time;
|
||
|
|
||
|
/**
|
||
|
* The counter of unlock messages
|
||
|
*
|
||
|
* This counter must always increase with each message from the remote
|
||
|
* in order for the messages to be deemed valid. Transfering the counters
|
||
|
* back and forth also gives information about lost messages and potential
|
||
|
* attacks. Both the remote and the device keep a record of at least the
|
||
|
* last used counter.
|
||
|
*/
|
||
|
uint32_t id;
|
||
|
|
||
|
} Message;
|
||
|
|
||
|
/**
|
||
|
* @brief An authenticated message by the mobile device to command unlocking.
|
||
|
*
|
||
|
* The message is protected by a message authentication code (MAC) based on
|
||
|
* a symmetric key shared by the device and the remote. This code ensures
|
||
|
* that the contents of the request were not altered. The message further
|
||
|
* contains a timestamp to ensure that the message is recent, and not replayed
|
||
|
* by an attacker. An additional counter is also included for this purpose,
|
||
|
* which must continously increase for a message to be valid. This increases
|
||
|
* security a bit, since the timestamp validation must be tolerant to some
|
||
|
* inaccuracy due to mismatching clocks.
|
||
|
*/
|
||
|
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 content.
|
||
|
*
|
||
|
* The content is necessary to ensure freshness of the message
|
||
|
* by requiring a recent time and a monotonously increasing counter.
|
||
|
* This prevents messages from being delayed or being blocked and
|
||
|
* replayed later.
|
||
|
*/
|
||
|
Message message;
|
||
|
|
||
|
} AuthenticatedMessage;
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#define MESSAGE_CONTENT_SIZE sizeof(Message)
|
||
|
|
||
|
#define AUTHENTICATED_MESSAGE_SIZE sizeof(AuthenticatedMessage)
|