Hazelnet 3.0.0
Reference implementation of the CAN Bus Security (CBS) protocol
|
General public definitions used used by both the Hazelnet Server and Client. More...
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <Windows.h>
#include <sysinfoapi.h>
#include <bcrypt.h>
#include <stdio.h>
#include <stdlib.h>
Go to the source code of this file.
Data Structures | |
struct | hzl_Header |
Unpacked CBS Header. More... | |
struct | hzl_CbsPduMsg |
Packed CBS PDU (Protocol Data Unit message) ready to be transmitted by the library user. More... | |
struct | hzl_RxMsg |
Unpacked received SDU (Service Data Unit message) after validation (and optional decryption). More... | |
struct | hzl_Io_t |
Functions used by Hazelnet to interact with the rest of the system in order to obtain random numbers, the current time and to transmit messages. More... | |
Macros | |
#define | HZL_VERSION "v3.0.0" |
Hazelnet Client and Server library version using semantic versioning. More... | |
#define | HZL_CBS_PROTOCOL_VERSION_SUPPORTED "v1.3" |
Version of the CAN Bus Security protocol that the Client and Server libraries implement. More... | |
#define | HZL_OS_AVAILABLE 1 |
True when a desktop operating system was found. More... | |
#define | HZL_OS_AVAILABLE_WIN 1 |
True when a Windows operating system was found. More... | |
#define | HZL_OS_AVAILABLE_NIX 0 |
True when a Unix-like operating system was found, e.g. More... | |
#define | HZL_API __declspec(dllexport) |
Identifier of the public library API functions. More... | |
#define | HZL_SET_BY_USER |
Identifier of the struct fields of the public API the user must set manually. More... | |
#define | HZL_SERVER_SID 0U |
Source Identifier of the Server, always zero. More... | |
#define | HZL_BROADCAST_GID 0U |
Group Identifier reserved for broadcasting, always zero. More... | |
#define | HZL_LTK_LEN 16U |
Length of the Long Term Key in bytes. More... | |
#define | HZL_STK_LEN 16U |
Length of the Short Term Key in bytes. More... | |
#define | HZL_IS_SECURITY_WARNING(err) ((err) >= 1 && (err) <= 15) |
Macro checking whether the hzl_Err_t error code is a standard CBS security warning (case: true). More... | |
#define | HZL_MAX_CAN_FD_DATA_LEN 64U |
Maximum length of the CAN FD frame's payload in bytes. More... | |
#define | HZL_MAX_TRNG_TRIES_FOR_NONZERO_VALUE 20U |
Amount of consecutive TRNG invocations that must provide all-zero bytes to give up the random number generation. More... | |
#define | HZL_LARGEST_MAX_COUNTER_NONCE_DELAY (1U << 22U) |
Largest Max-Counter-Nonce value allowed in the Group configurations. More... | |
Typedefs | |
typedef enum hzl_Err | hzl_Err_t |
Hazelnet error code, returned by all API functions. More... | |
typedef enum hzl_HeaderType | hzl_HeaderType_t |
Standard CBS header types. More... | |
typedef uint8_t | hzl_Gid_t |
Group Identifier data type. More... | |
typedef uint8_t | hzl_Sid_t |
Source Identifier data type. More... | |
typedef uint8_t | hzl_Pty_t |
Payload Type data type. More... | |
typedef uint32_t | hzl_CanId_t |
CAN message identifier data type, able to hold both 11- or 29-bits values. More... | |
typedef uint64_t | hzl_ReqNonce_t |
Request Nonce data type. More... | |
typedef uint64_t | hzl_ResNonce_t |
Response Nonce data type. More... | |
typedef uint32_t | hzl_Timestamp_t |
Opaque timestamp (timer, rolling counter) with milliseconds accuracy. More... | |
typedef uint32_t | hzl_CtrNonce_t |
Counter Nonce data type. More... | |
typedef struct hzl_Header | hzl_Header_t |
Unpacked CBS Header. More... | |
typedef struct hzl_CbsPduMsg | hzl_CbsPduMsg_t |
Packed CBS PDU (Protocol Data Unit message) ready to be transmitted by the library user. More... | |
typedef struct hzl_RxMsg | hzl_RxSduMsg_t |
Unpacked received SDU (Service Data Unit message) after validation (and optional decryption). More... | |
typedef hzl_Err_t(* | hzl_TrngFunc) (uint8_t *bytes, size_t amount) |
True-random number generator function. More... | |
typedef hzl_Err_t(* | hzl_TimestampFunc) (hzl_Timestamp_t *timestamp) |
Current-time timestamp generating function with millisecond accuracy. More... | |
General public definitions used used by both the Hazelnet Server and Client.
#define HZL_VERSION "v3.0.0" |
Hazelnet Client and Server library version using semantic versioning.
#define HZL_CBS_PROTOCOL_VERSION_SUPPORTED "v1.3" |
Version of the CAN Bus Security protocol that the Client and Server libraries implement.
#define HZL_OS_AVAILABLE 1 |
True when a desktop operating system was found.
This implies that the following features are available and Hazelnet will use them: file system, malloc, real time clock and true-random number generator.
Dev note 2021-01-13: tried replacing the OS-dependant current-time function with the standard C11 timespec_get()
from time.h
, but it does not work: the function cannot be found by the linker.
#define HZL_OS_AVAILABLE_WIN 1 |
True when a Windows operating system was found.
#define HZL_OS_AVAILABLE_NIX 0 |
#define HZL_API __declspec(dllexport) |
Identifier of the public library API functions.
Used to add any exporting keywords in front of the functions for DLL compilation, which happens on Windows-only. Empty on other OS.
#define HZL_SET_BY_USER |
Identifier of the struct fields of the public API the user must set manually.
#define HZL_SERVER_SID 0U |
Source Identifier of the Server, always zero.
#define HZL_BROADCAST_GID 0U |
Group Identifier reserved for broadcasting, always zero.
#define HZL_LTK_LEN 16U |
Length of the Long Term Key in bytes.
#define HZL_STK_LEN 16U |
Length of the Short Term Key in bytes.
#define HZL_IS_SECURITY_WARNING | ( | err | ) | ((err) >= 1 && (err) <= 15) |
Macro checking whether the hzl_Err_t error code is a standard CBS security warning (case: true).
False otherwise.
#define HZL_MAX_CAN_FD_DATA_LEN 64U |
Maximum length of the CAN FD frame's payload in bytes.
#define HZL_MAX_TRNG_TRIES_FOR_NONZERO_VALUE 20U |
Amount of consecutive TRNG invocations that must provide all-zero bytes to give up the random number generation.
The probability that this happens is quit low: Assuming that each TRNG call generates only 1 byte (which is not always the case, often is more), there is 1/(2^8) chance for that byte to be zero and 1/(256^maxTries) for every byte to be zero. For 20 tries, this is 1/(2^8^20) == 1/(2^160), which is far less common than guessing the correct AES-128 key of a ciphertext.
#define HZL_LARGEST_MAX_COUNTER_NONCE_DELAY (1U << 22U) |
Largest Max-Counter-Nonce value allowed in the Group configurations.
2^22 = 4'194'304. Unitless.
typedef enum hzl_HeaderType hzl_HeaderType_t |
Standard CBS header types.
typedef uint8_t hzl_Gid_t |
Group Identifier data type.
typedef uint8_t hzl_Sid_t |
Source Identifier data type.
typedef uint8_t hzl_Pty_t |
Payload Type data type.
typedef uint32_t hzl_CanId_t |
CAN message identifier data type, able to hold both 11- or 29-bits values.
typedef uint64_t hzl_ReqNonce_t |
Request Nonce data type.
typedef uint64_t hzl_ResNonce_t |
Response Nonce data type.
typedef uint32_t hzl_Timestamp_t |
Opaque timestamp (timer, rolling counter) with milliseconds accuracy.
With 32 bits we can represent time intervals of up to 2^32-1 ms = 4294967295 ms = 49 days, 17 hours, 2 minutes, 47.295 seconds, which is more than enough for a relative timestamp with just some local accuracy (to answer the question "has enough time passed since the last timestamp").
It does not matter what is the exact value of the timestamp, where is it reference point. It's used only to measure time differences. A rolling counter incremented every millisecond is enough.
typedef uint32_t hzl_CtrNonce_t |
Counter Nonce data type.
typedef struct hzl_Header hzl_Header_t |
Unpacked CBS Header.
typedef struct hzl_CbsPduMsg hzl_CbsPduMsg_t |
Packed CBS PDU (Protocol Data Unit message) ready to be transmitted by the library user.
typedef struct hzl_RxMsg hzl_RxSduMsg_t |
Unpacked received SDU (Service Data Unit message) after validation (and optional decryption).
typedef hzl_Err_t(* hzl_TrngFunc) (uint8_t *bytes, size_t amount) |
True-random number generator function.
[out] | bytes | where to write the amount of random bytes. Untouched on error. It's never NULL. |
[in] | amount | number of bytes to generate. May be zero. |
HZL_OK | on success |
HZL_ERR_CANNOT_GENERATE_RANDOM | on error. |
typedef hzl_Err_t(* hzl_TimestampFunc) (hzl_Timestamp_t *timestamp) |
Current-time timestamp generating function with millisecond accuracy.
The generated timestamp does not necessarily represent the current date and time, it's only used to measure how much time passed since it was generated. The timestamp must represent milliseconds from whatever point in time (e.g. 1970-01-01 00:00:00 or also last Tuesday at 11:55).
One example implementation is taking the current Unix time (epoch format) in milliseconds. Another is to provide a rolling counter in milliseconds without a specified starting point in time. If said counter is expected to roll around in a reasonable time,
[out] | timestamp | current time. Untouched on error. It's never NULL. |
HZL_OK | on success |
HZL_ERR_CANNOT_GET_CURRENT_TIME | when requesting the current timer/clock to the OS or driver fails. |
enum hzl_Err |
Hazelnet error code, returned by all API functions.
Enumerator | |
---|---|
HZL_OK | Successful completion of the operation. |
HZL_ERR_SECWARN_INVALID_TAG | Received message is not intact or not authentic or does not use the proper values in the hashing/authenticating operations. CBS standard security warning "INV". |
HZL_ERR_SECWARN_MESSAGE_FROM_MYSELF | Received message contained the receiver's Source Identfi␜er as the transmitter's identity. CBS standard security warning "MFM". |
HZL_ERR_SECWARN_NOT_EXPECTING_A_RESPONSE | The Client received a Response addressed to it while not expecting any. Client-side only. CBS standard security warning "NER". |
HZL_ERR_SECWARN_SERVER_ONLY_MESSAGE | Received message is of a type which only the Session Server can transmit, but the transmitter's identity was not the Session Server. CBS standard security warning "SOM". |
HZL_ERR_SECWARN_RESPONSE_TIMEOUT | The Client did not receive a Response to its Request within the preconfi␜gured timeout. Client-side only. CBS standard security warning "RTO". |
HZL_ERR_SECWARN_OLD_MESSAGE | Received message contained a too-old counter nonce. CBS standard security warning "OLD". |
HZL_ERR_SECWARN_DENIAL_OF_SERVICE | The Party is receiving too many suspect messages. CBS standard security warning "DOS". NOTE: the Client library does NOT implement this check. |
HZL_ERR_SECWARN_NOT_IN_GROUP | The Client the Request originated from does not belong into the requested Group. Server-side only. CBS standard security warning "NIG". |
HZL_ERR_SECWARN_RECEIVED_OVERFLOWN_NONCE | Received message contained a Counter Nonce that exceeded its maximum allowed value. CBS standard security warning "RON". |
HZL_ERR_SECWARN_RECEIVED_ZERO_KEY | Received Response message, once decrypted, contained an all-zeros STKG that cannot be used. Client-side only. CBS standard security warning "RZK". |
HZL_ERR_SECWARN_RFU_1 | Reserved warning code for future use. |
HZL_ERR_SECWARN_RFU_2 | Reserved warning code for future use. |
HZL_ERR_SECWARN_RFU_3 | Reserved warning code for future use. |
HZL_ERR_SECWARN_RFU_4 | Reserved warning code for future use. |
HZL_ERR_SECWARN_RFU_5 | Reserved warning code for future use. |
HZL_ERR_PROGRAMMING | Default error value that should never appear, as it should be replaced with another one. Either the code is buggy or the functionality is not implemented yet. |
HZL_ERR_NULL_CTX | The function requires a pointer to the Hazelnet context, but NULL was provided. |
HZL_ERR_NULL_CONFIG_CLIENT | The context contains a NULL pointer to the Client configuration struct.
|
HZL_ERR_NULL_CONFIG_SERVER | The context contains a NULL pointer to the Server configuration struct.
|
HZL_ERR_ZERO_GROUPS | The Party configuration contains zero Groups. |
HZL_ERR_LTK_IS_ALL_ZEROS | The configured Client's Long Term Key (or at least 1 of them for the Server) is uninitialised, just full of zeros. |
HZL_ERR_INVALID_HEADER_TYPE | The Party configuration contains an unknown or unsupported CBS Header Type. |
HZL_ERR_SERVER_SID_ASSIGNED_TO_CLIENT | The Client configuration contains a Source Identifier (SID) equal to the one used by the Server HZL_SERVER_SID. |
HZL_ERR_SIDS_ARE_NOT_PRESORTED_STRICTLY_ASCENDING | The array of Client configurations must be sorted from smallest to largest SID without repeated SIDs.
|
HZL_ERR_GAP_IN_SIDS | The array of Client configurations must have all SIDs from 1 to hzl_ServerConfig_t.amountOfClients without gaps, extremes included.
|
HZL_ERR_SID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE | The Party configuration contains a Source Identifier (SID) that has a value that would not fit into the bits available for it in the CBS Header. Either choose a different (smaller) SID or choose a different Header Type (note: for the whole bus) that would have more bits available for the SID field. |
HZL_ERR_TOO_MANY_GROUPS_FOR_CONFIGURED_HEADER_TYPE | The party configurations contains an amount of Groups that implies there is at least one Group with a GID value that would not fit into the bits available for it in the CBS Header. Either configure fewer Groups for this Party or choose a different Header Type (note: for the whole bus) that would have more bits available for the GID field. |
HZL_ERR_ZERO_CLIENTS | The Server configuration contains zero Clients. |
HZL_ERR_TOO_MANY_CLIENTS | The Server configuration contains more Clients that it can hold in the bitmap of Clients in each Group. |
HZL_ERR_TOO_MANY_CLIENTS_FOR_CONFIGURED_HEADER_TYPE | The Server configurations contains an amount of Groups that implies there is at least one Client with a SID value that would not fit into the bits available for it in the CBS Header. Either configure fewer Clients or choose a different Header Type (note: for the whole bus) that would have more bits available for the SID field. |
HZL_ERR_NULL_CONFIG_CLIENTS | The context contains a NULL pointer to the array of Client configuration structs.
|
HZL_ERR_NULL_CONFIG_GROUPS | The context contains a NULL pointer to the Client configuration struct (on a Client) or array of (on a Server). |
HZL_ERR_GIDS_ARE_NOT_PRESORTED_STRICTLY_ASCENDING | The array of Group configurations must be sorted from smallest to largest GID without repeated GIDs. |
HZL_ERR_GAP_IN_GIDS | The array of Group configurations must contain all GIDs from 0 to hzl_ServerConfig_t.amountOfGroups-1 without gaps, expremes included. |
HZL_ERR_MISSING_GID_0 | The array of Group configurations must have the GID == 0 (broadcast Group) HZL_BROADCAST_GID. The sorting rule implies it must be at the first position (array index 0). |
HZL_ERR_INVALID_MAX_CTRNONCE_DELAY | The array of Group configuration has at least one Group where the max Counter Nonce Delay field is out of valid domain as specified by the CBS protocol. |
HZL_ERR_GID_TOO_LARGE_FOR_CONFIGURED_HEADER_TYPE | The array of Group configurations has at least one Group with a GID value that would not fit into the bits available for it in the CBS Header. Either configure the Group to use a smaller GID (note: for the whole bus) or choose a different Header Type (note: for the whole bus) that would have more bits available for the GID field. |
HZL_ERR_TOO_LARGE_CTRNONCE_UPPER_LIMIT | The Server-side array of Group configuration has at least one Group where the Counter Nonce upper limit field is out of valid domain as specified by the CBS protocol. |
HZL_ERR_INVALID_DELAY_BETWEEN_REN_NOTIFICATIONS | The Server-side array of Group configuration has at least one Group where the delay between successive Session renewal notification messages field is out of valid domain as specified by the CBS protocol. |
HZL_ERR_CLIENTS_BITMAP_ZERO_CLIENTS | The Server-side array of Group configuration has at least one Group where the bitmap of Clients in the Group contains no Clients at all. |
HZL_ERR_CLIENTS_BITMAP_UNKNOWN_SID | The Server-side array of Group configuration has at least one Group where the bitmap of Clients in the Group contains a Client not listed in the array of Client configurations. |
HZL_ERR_CLIENTS_BITMAP_INVALID_BROADCAST_GROUP | The Server-side array of Group configuration has the broadcast Group with GID == HZL_BROADCAST_GID that does not contain exactly all the Clients listed in the array of Client configurations. |
HZL_ERR_NULL_STATES_GROUPS | The context contains a NULL pointer to the Group states array. |
HZL_ERR_NULL_CURRENT_TIME_FUNC | The function pointer to the timestamping function is NULL.
|
HZL_ERR_NULL_TRNG_FUNC | The function pointer to the true-random number generating function is NULL.
|
HZL_ERR_NULL_PDU | The pointer to the Protocol Data Unit (packed CBS message) to transmit or the just-received one is NULL, but its indicated data length is not zero. |
HZL_ERR_NULL_SDU | The pointer to the Service Data Unit (unpacked user data) to transmit or the just-received one is NULL, but its indicated data length is not zero. |
HZL_ERR_UNKNOWN_GROUP | The user-specified Group (GID) for transmission or the received message's GID field indicate a Group not available in the Party's configuration and thus cannot be cryptographically processed. |
HZL_ERR_UNKNOWN_SOURCE | The received message's SID field indicates a Source not available in the Server's configuration and thus cannot be cryptographically processed. |
HZL_ERR_SESSION_NOT_ESTABLISHED | The Group the message is addressed to has no valid Session information in the local state. The message cannot be transmitted securely (when the error occurs on TX) or cannot be decrypted and validated (when on RX). |
HZL_ERR_TOO_LONG_SDU | The user-provided data to be transmitted is too long to fit into the specified message type. |
HZL_ERR_HANDSHAKE_ONGOING | The building of the message could not be performed right now, as the handshake process (exchange of Request and Response messages) is ongoing. The user has to retry after the handshake is completed.
|
HZL_ERR_NO_POTENTIAL_RECEIVER | The building of the Secured Application Data or a Session Renewal Notification could not be performed on Server-side, because no Client would be able to validate/decrypt the message, as no Client so far in the given Group has sent a Request to obtain the Session information.
|
HZL_ERR_RENEWAL_ONGOING | The building of the message could not be performed right now, as the Session renewal phase is ongoing. The user has to retry after is it completed.
|
HZL_ERR_INVALID_PAYLOAD_TYPE | The received message contains an unknown PTY field. Its data has an unknown structure. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_HEADER | The received message is too short to even contain the CBS header. Its metadata cannot be parsed. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_SADFD | The received Secured Application Data over CAN FD (SADFD) message is too short to be a valid SADFD message. Either it's too short to contain even the metadata parts of the SADFD message or the in-message indicated SDU length (ptlen field) is too large compared to the overall message length (example: 40 B long message overall, internally stating it has 60 B). |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_REQ | The received Request (REQ) message is too short to be a valid REQ message. Its fields cannot be parsed. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_RES | The received Response (RES) message is too short to be a valid RES message. Its fields cannot be parsed. |
HZL_ERR_TOO_SHORT_PDU_TO_CONTAIN_REN | The received Session Renewal Notification (REN) message is too short to be a valid REN message. Its fields cannot be parsed. |
HZL_ERR_TOO_LONG_CIPHERTEXT | The received Secured Application Data contains a too large value in the plaintext length field, thus it cannot be processed, as it would overflow the valid memory. |
HZL_ERR_MSG_IGNORED | The received message is ignored as it's not addressed to this Party or is redundant. |
HZL_ERR_SECWARN_RECEIVED_ZERO_REQNONCE | The received Request message contained an all-zeros Request Nonce. |
HZL_ERR_CANNOT_GET_CURRENT_TIME | The timestamping function failed to provide the current time. This could be an issue anywhere in the OS/driver providing the time down to the clock hardware. |
HZL_ERR_CANNOT_GENERATE_RANDOM | The true-random number generation function failed to provide a random number. This could be an issue anywhere in the OS/driver providing the number down to the TRNG hardware (if any) not having enough entropy. |
HZL_ERR_CANNOT_GENERATE_NON_ZERO_RANDOM | The true-random number generation failed to provide a non-zero arrays of bytes for too many times in a row. As the required arrays of bytes must be not-all-zeros, in the (very rare) case they are, simply new random values are requested to the TRNG. If this check fails for way too many times in row, the random number generation is seriously corrupted, probably a hardware issue.
|
HZL_ERR_NULL_FILENAME | The configuration file name string is NULL. |
HZL_ERR_CANNOT_OPEN_CONFIG_FILE | The configuration file could not be opened. This could be most commonly an incorrect path to the file/incorrect file name or a reading-permission error. |
HZL_ERR_UNEXPECTED_EOF | The configuration file was shorter than expected, some parts of the configuration are left out. The length of the file is parametric to the amount of Groups. |
HZL_ERR_INVALID_FILE_MAGIC_NUMBER | The magic number "HZL\0" (4 ASCII-encoded bytes) was not found at the beginning of the file as expected. The value is used as a double-check that the loaded file is of the correct format (to avoid loading say a JPEG instead of the Hazelnet configuration. |
HZL_ERR_MALLOC_FAILED | Heap-memory allocation failure: out of memory. |
enum hzl_HeaderType |