Hazelnet 3.0.0
Reference implementation of the CAN Bus Security (CBS) protocol
Data Structures | Macros | Typedefs | Functions
hzl_Server.h File Reference

Hazelnet Server public API. More...

#include "hzl.h"
Include dependency graph for hzl_Server.h:
This graph shows which files directly or indirectly include this file:

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...
 

Detailed Description

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.

Macro Definition Documentation

◆ HZL_SERVER_MAX_AMOUNT_OF_CLIENTS

#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.

◆ HZL_SERVER_LARGEST_MAX_COUNTER_NONCE_DELAY

#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.

◆ HZL_SERVER_MAX_COUNTER_NONCE_UPPER_LIMIT

#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 Documentation

◆ hzl_ServerBitMap_t

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.

◆ hzl_ServerConfig_t

Hazelnet Server constant configuration.

Single instance on the Server. Initialised by the user, not modified by the Server.

◆ 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.

◆ 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.

◆ 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.

◆ hzl_ServerCtx_t

Configuration and status of the HazelNet Server library.

Initialised by the user on embedded, loaded from file on an OS.

Function Documentation

◆ _Static_assert() [1/4]

_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() [2/4]

_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() [3/4]

_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() [4/4]

_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_ServerInit()

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.

Warning
The Server must be fully initialised before the Clients, otherwise it cannot supply the Session information to them upon Request.
Parameters
[in,out]ctxprepared 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.
Return values
HZL_OKon success.
HZL_ERR_NULL_CTX
HZL_ERR_NULL_CONFIG_SERVER
HZL_ERR_INVALID_HEADER_TYPE
HZL_ERR_ZERO_GROUPS
HZL_ERR_TOO_MANY_GROUPS_FOR_CONFIGURED_HEADER_TYPE
HZL_ERR_ZERO_CLIENTS
HZL_ERR_TOO_MANY_CLIENTS_FOR_CONFIGURED_HEADER_TYPE
HZL_ERR_NULL_CONFIG_CLIENTS
HZL_ERR_LTK_IS_ALL_ZEROS
HZL_ERR_SERVER_SID_ASSIGNED_TO_CLIENT
HZL_ERR_SIDS_ARE_NOT_PRESORTED_STRICTLY_ASCENDING
HZL_ERR_GAP_IN_SIDS
HZL_ERR_NULL_CONFIG_GROUPS
HZL_ERR_GIDS_ARE_NOT_PRESORTED_STRICTLY_ASCENDING
HZL_ERR_GAP_IN_GIDS
HZL_ERR_MISSING_GID_0
HZL_ERR_INVALID_MAX_CTRNONCE_DELAY
HZL_ERR_TOO_LARGE_CTRNONCE_UPPER_LIMIT
HZL_ERR_INVALID_DELAY_BETWEEN_REN_NOTIFICATIONS
HZL_ERR_CLIENTS_BITMAP_ZERO_CLIENTS
HZL_ERR_CLIENTS_BITMAP_UNKNOWN_SID
HZL_ERR_CLIENTS_BITMAP_INVALID_BROADCAST_GROUP
HZL_ERR_NULL_STATES_GROUPS
HZL_ERR_NULL_CURRENT_TIME_FUNC
HZL_ERR_NULL_TRNG_FUNC
HZL_ERR_CANNOT_GET_CURRENT_TIME
HZL_ERR_CANNOT_GENERATE_RANDOM
HZL_ERR_CANNOT_GENERATE_NON_ZERO_RANDOM

◆ hzl_ServerDeInit()

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.

Warning
Deinitialising the Server means that no Client will be able to obtain the current session information, effectively preventing handshakes and thus secure communication. Be sure to run it only when the Server is really not in use anymore by any Client.
Parameters
[in,out]ctxcontext with state to clear. Not NULL.
Return values
HZL_OKon success.
HZL_ERR_NULL_CTX
HZL_ERR_NULL_CONFIG_SERVER
HZL_ERR_NULL_STATES_GROUPS

◆ hzl_ServerBuildUnsecured()

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.

Warning
Use it only on data that was already secured by other means by the application or for debugging purposes. The usage of this type of message to transmit plaintext data is strongly discouraged.
Parameters
[out]unsecuredPduUAD message in packed format, ready to transmit. Not NULL.
[in]ctxjust to access configurations and functions. No change in the state. Not NULL.
[in]userDataplaintext data (SDU) to pack not-obfuscated, not-authenticated. Can be NULL only if userDataLen is zero.
[in]userDataLenlength of userData in bytes.
[in]groupIddestination group identifier (expected receivers). It may also be a GID not listed in the context's configuration.
Return values
HZL_OKon success.
Samevalues as hzl_ServerInit() in case the context has NULL pointers.
HZL_ERR_NULL_PDUif unsecuredPdu is NULL.
HZL_ERR_NULL_SDUif userData is NULL and userDataLen is > 0.
HZL_ERR_TOO_LONG_SDUif userDataLen is too large for the underlying PDU.
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPEwhen groupId would not fit in the packed CBS header.

◆ hzl_ServerBuildSecuredFd()

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.

Parameters
[out]securedPduCBS message in packed format, ready to transmit. Not NULL.
[in,out]ctxto access configurations and update the group states. Not NULL.
[in]userDataplaintext data (SDU) to pack encrypted and authenticated. Can be NULL only if userDataLen is zero.
[in]userDataLenlength of userData in bytes.
[in]groupIddestination group identifier (the Parties that can decrypt).
Return values
HZL_OKon successful building of the Secured Application Data.
HZL_ERR_NO_POTENTIAL_RECEIVERif 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.
Samevalues as hzl_ServerInit() in case the context has NULL pointers.
HZL_ERR_NULL_PDUif securedPdu is NULL.
HZL_ERR_NULL_SDUif userData is NULL and userDataLen is > 0.
HZL_ERR_TOO_LONG_SDUif userDataLen is too large for the underlying PDU.
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPEwhen groupId would not fit in the packed CBS header.
HZL_ERR_UNKNOWN_GROUPwhen 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_ServerProcessReceived()

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.

Parameters
[out]reactionPduCBS 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]receivedUserDataplaintext 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]ctxto access configurations and update the group states. Not NULL.
[in]receivedPdupacked CBS message as received from the underlying layer. Not NULL.
[in]receivedPduLenlength of receivedPdu in bytes.
[in]receivedCanIdidentifier of the underlying layer's PDU, passed as-is to receivedUserData.
Return values
HZL_OKon success.
HZL_ERR_MSG_IGNOREDwhen the message has another destination.
Samevalues as hzl_ServerInit() in case the context has NULL pointers.
HZL_ERR_NULL_PDUif receivedUserData or receivedPduLen are NULL.
HZL_ERR_NULL_SDUif userData is NULL.
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_HEADERwhen 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_TYPEon unsupported PTY field in the CBS Header.
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_SADFD,HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_REQwhen 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_CIPHERTEXTif the received Secured Application Data message claims to contain too much data to fit into the underlying layer's message.
HZL_ERR_SESSION_NOT_ESTABLISHEDwhen the current state indicates no session key and counter nonce have been established for this group yet.
HZL_ERR_SECWARN_MESSAGE_FROM_MYSELFwhen the received message seems to originate from the receiver itself.
HZL_ERR_SECWARN_SERVER_ONLY_MESSAGEwhen the received message that can only be sent by the server
HZL_ERR_SECWARN_RECEIVED_OVERFLOWN_NONCEif the received nonce is overflown
HZL_ERR_SECWARN_OLD_MESSAGEif the received nonce is old, indicating a potential replay attack
HZL_ERR_SECWARN_INVALID_TAGwhen 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_ServerForceSessionRenewal()

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.

Parameters
[out]renewalPduREN message in packed format, ready to transmit. Not NULL.
[in,out]ctxto access configurations and update the group states. Not NULL.
[in]groupIddestination group identifier (the Parties that can decrypt).
Return values
HZL_OKon success.
HZL_ERR_NO_POTENTIAL_RECEIVERif 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.
Samevalues as hzl_ServerInit() in case the context has NULL pointers.
HZL_ERR_NULL_PDUif renewalPdu is NULL.
HZL_ERR_UNKNOWN_GROUPwhen group is not supported in the context's configuration.
HZL_ERR_CANNOT_GET_CURRENT_TIME