Hazelnet 3.0.0
Reference implementation of the CAN Bus Security (CBS) protocol
|
Hazelnet Server public API. More...
#include "hzl.h"
Go to the source code of this file.
Data Structures | |
struct | hzl_ServerConfig |
Hazelnet Server constant configuration. More... | |
struct | hzl_ServerClientsConfig |
Hazelnet Server constant per-Client configuration. More... | |
struct | hzl_ServerGroupConfig |
Hazelnet Server constant Group configuration. More... | |
struct | hzl_ServerGroupState |
Hazelnet Server variable State. More... | |
struct | hzl_ServerCtx |
Configuration and status of the HazelNet Server library. More... | |
Macros | |
#define | HZL_SERVER_MAX_AMOUNT_OF_CLIENTS 32U |
Maximum amount of Clients overall this Server supports. More... | |
#define | HZL_SERVER_LARGEST_MAX_COUNTER_NONCE_DELAY (1U << 22U) |
Largest Max-Counter-Nonce value allowed in the Server configuration. More... | |
#define | HZL_SERVER_MAX_COUNTER_NONCE_UPPER_LIMIT 0xFFFF80U |
Largest Counter-Nonce-Upper-Limit value allowed in the Server configuration. More... | |
Typedefs | |
typedef uint32_t | hzl_ServerBitMap_t |
Integer data type used for the bitmap of Clients that must support HZL_SERVER_MAX_AMOUNT_OF_CLIENTS bits. More... | |
typedef struct hzl_ServerConfig | hzl_ServerConfig_t |
Hazelnet Server constant configuration. More... | |
typedef struct hzl_ServerClientsConfig | hzl_ServerClientConfig_t |
Hazelnet Server constant per-Client configuration. More... | |
typedef struct hzl_ServerGroupConfig | hzl_ServerGroupConfig_t |
Hazelnet Server constant Group configuration. More... | |
typedef struct hzl_ServerGroupState | hzl_ServerGroupState_t |
Hazelnet Server variable State. More... | |
typedef struct hzl_ServerCtx | hzl_ServerCtx_t |
Configuration and status of the HazelNet Server library. More... | |
Functions | |
_Static_assert (sizeof(hzl_ServerConfig_t)==3, "The size of the Server Config struct must be exactly 3 B") | |
Double-checking the size of the hzl_ServerConfig_t struct to avoid unexpected paddings. More... | |
_Static_assert (sizeof(hzl_ServerClientConfig_t)==17, "The size of the Server-side Client Config struct must be exactly 17 B") | |
Double-checking the size of the hzl_ServerClientConfig_t struct to avoid unexpected paddings. More... | |
_Static_assert (sizeof(hzl_ServerGroupConfig_t)==24, "The size of the Server Group Config struct must be exactly 24 B") | |
Double-checking the size of the hzl_ServerGroupConfig_t struct to avoid unexpected paddings. More... | |
_Static_assert (sizeof(hzl_ServerGroupState_t)==52, "The size of the Server Group State struct must be exactly 52 B") | |
Double-checking the size of the hzl_ServerGroupState_t struct to avoid unexpected paddings. More... | |
HZL_API hzl_Err_t | hzl_ServerInit (hzl_ServerCtx_t *ctx) |
Initialisation of the Server. More... | |
HZL_API hzl_Err_t | hzl_ServerDeInit (hzl_ServerCtx_t *ctx) |
Deinitialisation of the Server, securely clearing the state. More... | |
HZL_API hzl_Err_t | hzl_ServerBuildUnsecured (hzl_CbsPduMsg_t *unsecuredPdu, const hzl_ServerCtx_t *ctx, const uint8_t *userData, size_t userDataLen, hzl_Gid_t groupId) |
Builds an unsecured message in plaintext. More... | |
HZL_API hzl_Err_t | hzl_ServerBuildSecuredFd (hzl_CbsPduMsg_t *securedPdu, hzl_ServerCtx_t *ctx, const uint8_t *userData, size_t userDataLen, hzl_Gid_t groupId) |
Builds a secured message, encrypted, authenticated and timely, only for the given group to be able to read. More... | |
HZL_API hzl_Err_t | hzl_ServerProcessReceived (hzl_CbsPduMsg_t *reactionPdu, hzl_RxSduMsg_t *receivedUserData, hzl_ServerCtx_t *ctx, const uint8_t *receivedPdu, size_t receivedPduLen, hzl_CanId_t receivedCanId) |
Validates, unpacks and decrypts (if necessary) any received message, preparing an automatic response when required. More... | |
HZL_API hzl_Err_t | hzl_ServerForceSessionRenewal (hzl_CbsPduMsg_t *renewalPdu, hzl_ServerCtx_t *ctx, hzl_Gid_t groupId) |
Forcibly start a Session Renewal Phase, unless one is already ongoing or no Clients are currently enabled (have Requested the STK) to process the REN message. More... | |
Hazelnet Server public API.
Hazelnet implements the CAN Bus Security (CBS) protocol, which secures the CAN FD traffic providing encryption, authenticity and freshness of the messages.
The user of the library must handle the physical transmission and reception manually as this library only handles the building of messages to transmit and processing of received messages. The internal library state keeps track of ongoing handshakes, timeouts and other events per each Group.
The intended usage of the library is listed in an example snippet in the readme.
#define HZL_SERVER_MAX_AMOUNT_OF_CLIENTS 32U |
Maximum amount of Clients overall this Server supports.
At Context initialisation the amount of Clients in hzl_ServerConfig_t may be any value <= this limit.
The per-Group configuration hzl_ServerGroupConfig_t contains a static-sized bitmap of Clients in it which is limited to 32 bits to spare memory. One bit is reserved for the Server.
#define HZL_SERVER_LARGEST_MAX_COUNTER_NONCE_DELAY (1U << 22U) |
Largest Max-Counter-Nonce value allowed in the Server configuration.
2^22 = 4'194'304. Unitless.
#define HZL_SERVER_MAX_COUNTER_NONCE_UPPER_LIMIT 0xFFFF80U |
Largest Counter-Nonce-Upper-Limit value allowed in the Server configuration.
2^24 - 2^7 = 16777088 = 0xFFFF80, i.e. 128 less than the counter nonce max.
typedef uint32_t hzl_ServerBitMap_t |
Integer data type used for the bitmap of Clients that must support HZL_SERVER_MAX_AMOUNT_OF_CLIENTS bits.
typedef struct hzl_ServerConfig hzl_ServerConfig_t |
Hazelnet Server constant configuration.
Single instance on the Server. Initialised by the user, not modified by the Server.
typedef struct hzl_ServerClientsConfig hzl_ServerClientConfig_t |
Hazelnet Server constant per-Client configuration.
Unique per Client, multiple instances on the Server. Initialised by the user, not modified by the Server.
typedef struct hzl_ServerGroupConfig hzl_ServerGroupConfig_t |
Hazelnet Server constant Group configuration.
Unique per Group, multiple instances on the Server. Initialised by the user, not modified by the Server.
typedef struct hzl_ServerGroupState hzl_ServerGroupState_t |
Hazelnet Server variable State.
Single instance per Group, multiple instances per Server. Initialised, modified, managed and cleared fully by the Server: the user MUST NOT touch its contents.
typedef struct hzl_ServerCtx hzl_ServerCtx_t |
Configuration and status of the HazelNet Server library.
Initialised by the user on embedded, loaded from file on an OS.
_Static_assert | ( | sizeof(hzl_ServerConfig_t) | = =3 , |
"The size of the Server Config struct must be exactly 3 B" | |||
) |
Double-checking the size of the hzl_ServerConfig_t struct to avoid unexpected paddings.
_Static_assert | ( | sizeof(hzl_ServerClientConfig_t) | = =17 , |
"The size of the Server-side Client Config struct must be exactly 17 B" | |||
) |
Double-checking the size of the hzl_ServerClientConfig_t struct to avoid unexpected paddings.
_Static_assert | ( | sizeof(hzl_ServerGroupConfig_t) | = =24 , |
"The size of the Server Group Config struct must be exactly 24 B" | |||
) |
Double-checking the size of the hzl_ServerGroupConfig_t struct to avoid unexpected paddings.
_Static_assert | ( | sizeof(hzl_ServerGroupState_t) | = =52 , |
"The size of the Server Group State struct must be exactly 52 B" | |||
) |
Double-checking the size of the hzl_ServerGroupState_t struct to avoid unexpected paddings.
HZL_API hzl_Err_t hzl_ServerInit | ( | hzl_ServerCtx_t * | ctx | ) |
Initialisation of the Server.
To be called once before any other function. Checks the configuration thoroughly, initialises the states.
After initialisation, the Server will have all Session information generated and ready to transmit Responses upon Requests and ready to transmit a new Secured message.
[in,out] | ctx | prepared with the proper structs and function pointers by the user before calling this function. Further initialisation performed by this function. See hzl_ServerCtx_t for details. |
HZL_API hzl_Err_t hzl_ServerDeInit | ( | hzl_ServerCtx_t * | ctx | ) |
Deinitialisation of the Server, securely clearing the state.
To be called after the Server is not used anymore or before entering a low-power mode.
Other fields of the context are untouched (configuration and IO functions), so the context may be reused for another hzl_ServerInit() call after the deinitialisation.
[in,out] | ctx | context with state to clear. Not NULL. |
HZL_OK | on success. |
HZL_ERR_NULL_CTX | |
HZL_ERR_NULL_CONFIG_SERVER | |
HZL_ERR_NULL_STATES_GROUPS |
HZL_API hzl_Err_t hzl_ServerBuildUnsecured | ( | hzl_CbsPduMsg_t * | unsecuredPdu, |
const hzl_ServerCtx_t * | ctx, | ||
const uint8_t * | userData, | ||
size_t | userDataLen, | ||
hzl_Gid_t | groupId | ||
) |
Builds an unsecured message in plaintext.
This message may be transmitted at any point in time, as long as the context is initialised. This means even before or during a handshake for the given Group.
The message may be built and transmitted **even if the group
does not exist** in the configuration. This is allowed in order to communicate with some devices that don't have a preconfigured Group in common with this one. No error is raised.
[out] | unsecuredPdu | UAD message in packed format, ready to transmit. Not NULL. |
[in] | ctx | just to access configurations and functions. No change in the state. Not NULL. |
[in] | userData | plaintext data (SDU) to pack not-obfuscated, not-authenticated. Can be NULL only if userDataLen is zero. |
[in] | userDataLen | length of userData in bytes. |
[in] | groupId | destination group identifier (expected receivers). It may also be a GID not listed in the context's configuration. |
HZL_OK | on success. |
Same | values as hzl_ServerInit() in case the context has NULL pointers. |
HZL_ERR_NULL_PDU | if unsecuredPdu is NULL. |
HZL_ERR_NULL_SDU | if userData is NULL and userDataLen is > 0. |
HZL_ERR_TOO_LONG_SDU | if userDataLen is too large for the underlying PDU. |
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE | when groupId would not fit in the packed CBS header. |
HZL_API hzl_Err_t hzl_ServerBuildSecuredFd | ( | hzl_CbsPduMsg_t * | securedPdu, |
hzl_ServerCtx_t * | ctx, | ||
const uint8_t * | userData, | ||
size_t | userDataLen, | ||
hzl_Gid_t | groupId | ||
) |
Builds a secured message, encrypted, authenticated and timely, only for the given group to be able to read.
[out] | securedPdu | CBS message in packed format, ready to transmit. Not NULL. |
[in,out] | ctx | to access configurations and update the group states. Not NULL. |
[in] | userData | plaintext data (SDU) to pack encrypted and authenticated. Can be NULL only if userDataLen is zero. |
[in] | userDataLen | length of userData in bytes. |
[in] | groupId | destination group identifier (the Parties that can decrypt). |
HZL_OK | on successful building of the Secured Application Data. |
HZL_ERR_NO_POTENTIAL_RECEIVER | if no Request was received yet from any Client in the requested Group groupId . If transmitted, the message could not be decrypted by anyone, because no Client has yet the Session information. |
Same | values as hzl_ServerInit() in case the context has NULL pointers. |
HZL_ERR_NULL_PDU | if securedPdu is NULL. |
HZL_ERR_NULL_SDU | if userData is NULL and userDataLen is > 0. |
HZL_ERR_TOO_LONG_SDU | if userDataLen is too large for the underlying PDU. |
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE | when groupId would not fit in the packed CBS header. |
HZL_ERR_UNKNOWN_GROUP | when group is not supported in the context's configuration. |
HZL_ERR_CANNOT_GENERATE_RANDOM | |
HZL_ERR_CANNOT_GENERATE_NON_ZERO_RANDOM | |
HZL_ERR_CANNOT_GET_CURRENT_TIME |
HZL_API hzl_Err_t hzl_ServerProcessReceived | ( | hzl_CbsPduMsg_t * | reactionPdu, |
hzl_RxSduMsg_t * | receivedUserData, | ||
hzl_ServerCtx_t * | ctx, | ||
const uint8_t * | receivedPdu, | ||
size_t | receivedPduLen, | ||
hzl_CanId_t | receivedCanId | ||
) |
Validates, unpacks and decrypts (if necessary) any received message, preparing an automatic response when required.
Handles automatically messages of different types, making a variety of checks for the correctness, integrity, authenticity of the message (note: the latter is not guaranteed for Unsecured messages). Updates the internal state automatically to keep track of the changing nonces and Session states.
[out] | reactionPdu | CBS message in packed format, ready to transmit, generated as an automatic, internal reaction to the just received message. No need to transmit if hzl_CbsPduMsg_t.dataLen is zero. Not NULL. Transmit any data even if the return error code is non-OK. |
[out] | receivedUserData | plaintext user data extracted out of receivedPdu . If the processed message contained no user data (was an internal message), the field hzl_RxSduMsg_t.isForUser is false. The whole struct is securely cleared (zeroed out) before anything else is attempted; thus it's full of zeros in case of errors. This is done to clear any lingering data if the buffer is reused, to avoid leaking information about previously-decrypted messages. Not NULL. |
[in,out] | ctx | to access configurations and update the group states. Not NULL. |
[in] | receivedPdu | packed CBS message as received from the underlying layer. Not NULL. |
[in] | receivedPduLen | length of receivedPdu in bytes. |
[in] | receivedCanId | identifier of the underlying layer's PDU, passed as-is to receivedUserData . |
HZL_OK | on success. |
HZL_ERR_MSG_IGNORED | when the message has another destination. |
Same | values as hzl_ServerInit() in case the context has NULL pointers. |
HZL_ERR_NULL_PDU | if receivedUserData or receivedPduLen are NULL. |
HZL_ERR_NULL_SDU | if userData is NULL. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_HEADER | when the canFdMsg->dataLen is too short to even contain a CBS message with the currently configured Header Type in the ctx. |
HZL_ERR_INVALID_PAYLOAD_TYPE | on unsupported PTY field in the CBS Header. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_SADFD,HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_REQ | when the received message is too short to contain the data is should as indicated in its header (or also in the payload length field in case of Secured Application Data messages). |
HZL_ERR_TOO_LONG_CIPHERTEXT | if the received Secured Application Data message claims to contain too much data to fit into the underlying layer's message. |
HZL_ERR_SESSION_NOT_ESTABLISHED | when the current state indicates no session key and counter nonce have been established for this group yet. |
HZL_ERR_SECWARN_MESSAGE_FROM_MYSELF | when the received message seems to originate from the receiver itself. |
HZL_ERR_SECWARN_SERVER_ONLY_MESSAGE | when the received message that can only be sent by the server |
HZL_ERR_SECWARN_RECEIVED_OVERFLOWN_NONCE | if the received nonce is overflown |
HZL_ERR_SECWARN_OLD_MESSAGE | if the received nonce is old, indicating a potential replay attack |
HZL_ERR_SECWARN_INVALID_TAG | when the message integrity and authenticity cannot be guaranteed |
HZL_ERR_CANNOT_GENERATE_RANDOM | |
HZL_ERR_CANNOT_GENERATE_NON_ZERO_RANDOM | |
HZL_ERR_CANNOT_GET_CURRENT_TIME |
HZL_API hzl_Err_t hzl_ServerForceSessionRenewal | ( | hzl_CbsPduMsg_t * | renewalPdu, |
hzl_ServerCtx_t * | ctx, | ||
hzl_Gid_t | groupId | ||
) |
Forcibly start a Session Renewal Phase, unless one is already ongoing or no Clients are currently enabled (have Requested the STK) to process the REN message.
[out] | renewalPdu | REN message in packed format, ready to transmit. Not NULL. |
[in,out] | ctx | to access configurations and update the group states. Not NULL. |
[in] | groupId | destination group identifier (the Parties that can decrypt). |
HZL_OK | on success. |
HZL_ERR_NO_POTENTIAL_RECEIVER | if no Request was received yet from any Client in the requested Group groupId . If transmitted, the message could not be validated by anyone, because no Client has yet the Session information. |
Same | values as hzl_ServerInit() in case the context has NULL pointers. |
HZL_ERR_NULL_PDU | if renewalPdu is NULL. |
HZL_ERR_UNKNOWN_GROUP | when group is not supported in the context's configuration. |
HZL_ERR_CANNOT_GET_CURRENT_TIME |