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

Hazelnet Client public API. More...

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

Go to the source code of this file.

Data Structures

struct  hzl_ClientConfig
 Hazelnet Client constant configuration. More...
 
struct  hzl_ClientGroupConfig
 Hazelnet Client constant Group configuration. More...
 
struct  hzl_ClientGroupState
 Hazelnet Client variable State. More...
 
struct  hzl_ClientCtx
 Configuration and status of the HazelNet Client library. More...
 

Typedefs

typedef struct hzl_ClientConfig hzl_ClientConfig_t
 Hazelnet Client constant configuration. More...
 
typedef struct hzl_ClientGroupConfig hzl_ClientGroupConfig_t
 Hazelnet Client constant Group configuration. More...
 
typedef struct hzl_ClientGroupState hzl_ClientGroupState_t
 Hazelnet Client variable State. More...
 
typedef struct hzl_ClientCtx hzl_ClientCtx_t
 Configuration and status of the HazelNet Client library. More...
 

Functions

 _Static_assert (sizeof(hzl_ClientConfig_t)==22, "The size of the Client Config struct must be exactly 22 B")
 Double-checking the size of the hzl_ClientConfig_t struct to avoid unexpected paddings. More...
 
 _Static_assert (sizeof(hzl_ClientGroupConfig_t)==12, "The size of the Client Group Config struct must be exactly 12 B")
 Double-checking the size of the hzl_ClientGroupConfig_t struct to avoid unexpected paddings. More...
 
 _Static_assert (sizeof(hzl_ClientGroupState_t)==64, "The size of the Client Group state struct must be exactly 64 B")
 Double-checking the size of the hzl_ClientGroupState_t struct to avoid unexpected paddings. More...
 
HZL_API hzl_Err_t hzl_ClientInit (hzl_ClientCtx_t *ctx)
 Initialisation of the Client. More...
 
HZL_API hzl_Err_t hzl_ClientDeInit (hzl_ClientCtx_t *ctx)
 Deinitialisation of the Client, securely clearing the state. More...
 
HZL_API hzl_Err_t hzl_ClientBuildRequest (hzl_CbsPduMsg_t *requestPdu, hzl_ClientCtx_t *ctx, hzl_Gid_t groupId)
 Builds a Request message, asking for the Session information for a specific group, even if the Session is already established, unless a handshake is already ongoing. More...
 
HZL_API hzl_Err_t hzl_ClientBuildUnsecured (hzl_CbsPduMsg_t *unsecuredPdu, const hzl_ClientCtx_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_ClientBuildSecuredFd (hzl_CbsPduMsg_t *securedPdu, hzl_ClientCtx_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_ClientProcessReceived (hzl_CbsPduMsg_t *reactionPdu, hzl_RxSduMsg_t *receivedUserData, hzl_ClientCtx_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...
 

Detailed Description

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

Typedef Documentation

◆ hzl_ClientConfig_t

Hazelnet Client constant configuration.

Single instance per Client. Initialised by the user, not modified by the Client. Initialised by the user, not modified by the Client.

◆ hzl_ClientGroupConfig_t

Hazelnet Client constant Group configuration.

Unique per Group, multiple instances per Client. Initialised by the user, not modified by the Client.

◆ hzl_ClientGroupState_t

Hazelnet Client variable State.

Single instance per Group, multiple instances per Client. Initialised, modified, managed and cleared fully by the Client: the user MUST NOT touch its contents.

◆ hzl_ClientCtx_t

Configuration and status of the HazelNet Client library.

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

Function Documentation

◆ _Static_assert() [1/3]

_Static_assert ( sizeof(hzl_ClientConfig_t = =22,
"The size of the Client Config struct must be exactly 22 B"   
)

Double-checking the size of the hzl_ClientConfig_t struct to avoid unexpected paddings.

◆ _Static_assert() [2/3]

_Static_assert ( sizeof(hzl_ClientGroupConfig_t = =12,
"The size of the Client Group Config struct must be exactly 12 B"   
)

Double-checking the size of the hzl_ClientGroupConfig_t struct to avoid unexpected paddings.

◆ _Static_assert() [3/3]

_Static_assert ( sizeof(hzl_ClientGroupState_t = =64,
"The size of the Client Group state struct must be exactly 64 B"   
)

Double-checking the size of the hzl_ClientGroupState_t struct to avoid unexpected paddings.

◆ hzl_ClientInit()

HZL_API hzl_Err_t hzl_ClientInit ( hzl_ClientCtx_t ctx)

Initialisation of the Client.

To be called once before any other function. Checks the configuration thoroughly, initialises the states.

After initialisation, the Client will not have the Session information required to transmit a new Secured message; a Request message must be transmitted first with the hzl_ClientBuildRequest() function after initialisation and a Response must be received.

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_ClientCtx_t for details.
Return values
HZL_OKon success.
HZL_ERR_NULL_CTX
HZL_ERR_NULL_CONFIG_CLIENT
HZL_ERR_INVALID_HEADER_TYPE
HZL_ERR_ZERO_GROUPS
HZL_ERR_TOO_MANY_GROUPS_FOR_CONFIGURED_HEADER_TYPE
HZL_ERR_LTK_IS_ALL_ZEROS
HZL_ERR_SERVER_SID_ASSIGNED_TO_CLIENT
HZL_ERR_SID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE
HZL_ERR_NULL_CONFIG_GROUPS
HZL_ERR_GIDS_ARE_NOT_PRESORTED_STRICTLY_ASCENDING
HZL_ERR_MISSING_GID_0
HZL_ERR_INVALID_MAX_CTRNONCE_DELAY
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE
HZL_ERR_NULL_STATES_GROUPS
HZL_ERR_NULL_CURRENT_TIME_FUNC
HZL_ERR_NULL_TRNG_FUNC

◆ hzl_ClientDeInit()

HZL_API hzl_Err_t hzl_ClientDeInit ( hzl_ClientCtx_t ctx)

Deinitialisation of the Client, securely clearing the state.

To be called after the Client 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_ClientInit call after the deinitialisation.

Clearing the state when not in use forces the Client to start new handshakes after waking up upon transmitting a new Secured message. This can also be done manually with the hzl_ClientBuildRequest() function.

Parameters
[in,out]ctxcontext with state to clear. Not NULL.
Return values
HZL_OKon success.
HZL_ERR_NULL_CTX
HZL_ERR_NULL_CONFIG_CLIENT
HZL_ERR_NULL_STATES_GROUPS

◆ hzl_ClientBuildRequest()

HZL_API hzl_Err_t hzl_ClientBuildRequest ( hzl_CbsPduMsg_t requestPdu,
hzl_ClientCtx_t ctx,
hzl_Gid_t  groupId 
)

Builds a Request message, asking for the Session information for a specific group, even if the Session is already established, unless a handshake is already ongoing.

The transmission of a Request is mandatory before hzl_ClientBuildSecuredFd() can be used. This function is useful to perform the handshake in advance even if there is no Secured Application Data to transmit right now, to spare time later one when there is some to transmit.

Parameters
[out]requestPduREQ 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 will be able to decrypt).
Return values
HZL_OKon success.
HZL_ERR_HANDSHAKE_ONGOINGif a handshake is already ongoing right now. It should be enough to just wait for the current handshake to complete, no need to build a new Request.
Samevalues as hzl_ClientInit() in case the context has NULL pointers.
HZL_ERR_NULL_PDUif requestPdu is NULL.
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_ClientBuildUnsecured()

HZL_API hzl_Err_t hzl_ClientBuildUnsecured ( hzl_CbsPduMsg_t unsecuredPdu,
const hzl_ClientCtx_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_ClientInit() 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_ClientBuildSecuredFd()

HZL_API hzl_Err_t hzl_ClientBuildSecuredFd ( hzl_CbsPduMsg_t securedPdu,
hzl_ClientCtx_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.

Before using this function, a Request message must be built with hzl_ClientBuildRequest(), transmitted and a Response must be received and processed with hzl_ClientProcessReceived().

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_SESSION_NOT_ESTABLISHEDif the message could not be built yet, a Request must be started with a Request message and a Response must be received. Use hzl_ClientBuildRequest() first.
Samevalues as hzl_ClientInit() 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_ClientProcessReceived()

HZL_API hzl_Err_t hzl_ClientProcessReceived ( hzl_CbsPduMsg_t reactionPdu,
hzl_RxSduMsg_t receivedUserData,
hzl_ClientCtx_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. Not NULL. No need to transmit if hzl_CbsPduMsg_t.dataLen is zero. Not NULL.
[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_ClientInit() 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_RES,HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_RENwhen 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 but is has another SID
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