|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Secure-side AES-CMAC seam implementation. More...
#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_secure.h"#include "sec_cmac_internal.h"Go to the source code of this file.
Enumerations | |
| enum | aes_dim_t : uint16_t { k_aes_block_bytes = 16U , k_aes_word_bytes = 4U , k_aes_state_cols = 4U , k_aes_max_rk_bytes = 240U } |
| AES dimensions in bytes (FIPS 197). More... | |
| enum | aes_off_t : uint8_t { k_aes_nr_128 = 10U , k_aes_nr_256 = 14U , k_aes_ext_sub_i = 4U , k_aes_col_mask = 3U , k_aes_msb_shift = 7U , k_aes_last_byte = 15U , k_aes_rcon_seed = 1U } |
| AES round counts and small byte offsets (FIPS 197). More... | |
| enum | aes_gf_t : uint8_t { k_aes_field_poly = 0x1BU , k_cmac_rb = 0x87U , k_cmac_pad_marker = 0x80U } |
| GF field constants used by AES / CMAC. More... | |
Functions | |
| static ra8_err_t | internal_cmac_check_args (const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len) |
| Shared precondition check for both CMAC entry points. | |
| static uint8_t | internal_aes_xtime (uint8_t value) |
| Multiply a byte by x in GF(2^8) with the AES reduction poly. | |
| static void | internal_aes_key_expand (const uint8_t *key, uint8_t nk, uint8_t nr, uint8_t *rk) |
| Expand an AES key into the full round-key schedule. | |
| static void | internal_aes_sub_shift (uint8_t *s) |
| Apply SubBytes + ShiftRows to the AES state in place. | |
| static void | internal_aes_mix_columns (uint8_t *s) |
| Apply MixColumns to the AES state in place. | |
| static void | internal_aes_encrypt (const uint8_t *rk, uint8_t nr, const uint8_t *in, uint8_t *out) |
| Encrypt one 16-byte block with AES-nr. | |
| static void | internal_cmac_double (const uint8_t *in, uint8_t *out) |
| Double a 128-bit value in GF(2^128) (CMAC subkey step). | |
| static void | internal_cmac_subkeys (const uint8_t *rk, uint8_t nr, uint8_t *k1, uint8_t *k2) |
| Derive the CMAC subkeys K1 / K2 from the expanded key. | |
| static void | internal_cmac_build_last (const uint8_t *msg, uint32_t msg_len, uint32_t last_off, bool complete, const uint8_t *k1, const uint8_t *k2, uint8_t *last) |
| Fold the (possibly padded) final CMAC block with its subkey. | |
| static void | internal_cmac_tag (const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len, uint8_t *out_mac) |
| Compute the AES-CMAC tag of a message (SP 800-38B). | |
| ra8_err_t | priv_ra8_sec_cmac_compute (const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len, uint8_t *out_mac) |
| Compute the AES-CMAC tag of a message under a symmetric key. | |
| ra8_err_t | priv_ra8_sec_cmac_verify (const uint8_t *key, uint16_t key_len, const uint8_t *msg, uint32_t msg_len, const uint8_t *mac, uint16_t mac_len) |
| Verify an AES-CMAC tag against a message under a symmetric key. | |
Variables | |
| static const char * | s_tag = "SECMAC" |
| Logging / error tag prefix for this module. | |
| static const uint8_t | s_aes_sbox [256] |
| AES S-box (FIPS 197 Fig. | |
Secure-side AES-CMAC seam implementation.
Two interchangeable backends behind the ra8_sec_cmac_* API declared in sec_cmac_internal.h:
Both backends compute the identical standard tag, so the seam is Liskov- substitutable and the wrapped-key blob format is backend-independent.
Definition in file sec_cmac.c.
| enum aes_dim_t : uint16_t |
AES dimensions in bytes (FIPS 197).
Definition at line 222 of file sec_cmac.c.
| enum aes_gf_t : uint8_t |
GF field constants used by AES / CMAC.
| Enumerator | |
|---|---|
| k_aes_field_poly | GF(2^8) reduction poly (FIPS 197 4.2). |
| k_cmac_rb | GF(2^128) constant (SP 800-38B 5.3). |
| k_cmac_pad_marker | CMAC final-block pad bit (SP 800-38B 5.5). |
Definition at line 241 of file sec_cmac.c.
| enum aes_off_t : uint8_t |
AES round counts and small byte offsets (FIPS 197).
Definition at line 230 of file sec_cmac.c.
|
static |
Encrypt one 16-byte block with AES-nr.
FIPS 197 Sec 5.1 cipher: initial AddRoundKey, nr-1 full rounds (SubBytes/ShiftRows/MixColumns/AddRoundKey), final partial round – the per-step transforms live in internal_aes_sub_shift and internal_aes_mix_columns. The state is column-major (byte 4*c+r is row r of column c).
| [in] | rk | Round-key schedule. |
| [in] | nr | Round count (10 or 14). |
| [in] | in | 16-byte plaintext block. |
| [out] | out | 16-byte ciphertext block. |
Definition at line 433 of file sec_cmac.c.
References internal_aes_mix_columns(), internal_aes_sub_shift(), and k_aes_block_bytes.
Referenced by internal_cmac_subkeys(), and internal_cmac_tag().
|
static |
Expand an AES key into the full round-key schedule.
FIPS 197 Sec 5.2 key expansion, parameterised by nk words (4 or 8) and nr rounds (10 or 14).
| [in] | key | Raw key bytes (nk*4 long). |
| [in] | nk | Key words (4 for AES-128, 8 for AES-256). |
| [in] | nr | Round count (10 or 14). |
| [out] | rk | Round-key buffer (16*(nr+1) bytes). |
Definition at line 311 of file sec_cmac.c.
References internal_aes_xtime(), k_aes_ext_sub_i, k_aes_rcon_seed, k_aes_state_cols, k_aes_word_bytes, and s_aes_sbox.
Referenced by internal_cmac_tag().
|
static |
Apply MixColumns to the AES state in place.
FIPS 197 Sec 5.1.3: multiply every state column by the fixed polynomial {03}x^3 + {01}x^2 + {01}x + {02} in GF(2^8), expressed through internal_aes_xtime doublings.
| [in,out] | s | 16-byte AES state. |
Definition at line 395 of file sec_cmac.c.
References internal_aes_xtime(), k_aes_state_cols, and RA8_INTERNAL.
Referenced by internal_aes_encrypt().
|
static |
Apply SubBytes + ShiftRows to the AES state in place.
FIPS 197 Sec 5.1.1/5.1.2: substitute every state byte through the S-box, then rotate row r left by r columns. The state is column-major (byte 4*c+r is row r of column c).
| [in,out] | s | 16-byte AES state. |
Definition at line 361 of file sec_cmac.c.
References k_aes_block_bytes, k_aes_col_mask, k_aes_state_cols, RA8_INTERNAL, and s_aes_sbox.
Referenced by internal_aes_encrypt().
|
static |
Multiply a byte by x in GF(2^8) with the AES reduction poly.
FIPS 197 Sec 4.2: left-shift, conditionally XOR 0x1B on overflow.
| [in] | value | Source byte. |
| value<<1 | When the high bit was clear. |
| (value<<1)^0x1B | When the high bit was set. |
Definition at line 285 of file sec_cmac.c.
References k_aes_field_poly, k_aes_msb_shift, and RA8_INTERNAL.
Referenced by internal_aes_key_expand(), and internal_aes_mix_columns().
|
static |
Fold the (possibly padded) final CMAC block with its subkey.
SP 800-38B Sec 6.2 step 4: a complete final block is XOR-ed with K1; an incomplete (or empty-message) block is padded with 0x80 0x00... and XOR-ed with K2.
| [in] | msg | Message bytes (NULL only when msg_len==0). |
| [in] | msg_len | Message length in bytes. |
| [in] | last_off | Byte offset of the final block within msg. |
| [in] | complete | True when the final block is a whole 16 bytes. |
| [in] | k1 | Subkey for complete final blocks. |
| [in] | k2 | Subkey for padded final blocks. |
| [out] | last | Receives the folded 16-byte final block. |
Definition at line 538 of file sec_cmac.c.
References k_aes_block_bytes, k_cmac_pad_marker, and RA8_INTERNAL.
Referenced by internal_cmac_tag().
|
static |
Shared precondition check for both CMAC entry points.
Validates the key pointer, the key length (AES-128 or AES-256 only), the message pointer/length pairing, and the static message-size cap that keeps every downstream loop provably bounded (NASA Power of 10 Rule 2). Keeping the checks in one helper means the compute and verify paths cannot drift.
| [in] | key | Symmetric CMAC key. |
| [in] | key_len | Key length in bytes. |
| [in] | msg | Message pointer (NULL only when msg_len==0). |
| [in] | msg_len | Message length in bytes. |
| k_ra8_ok | Arguments are well-formed. |
| k_ra8_err_null_ptr | key NULL, or msg NULL with a non-zero msg_len. |
| k_ra8_err_invalid_arg | key_len was neither 16 nor 32. |
| k_ra8_err_invalid_size | msg_len exceeded the static cap. |
Definition at line 80 of file sec_cmac.c.
References k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_sec_cmac_key_128, k_ra8_sec_cmac_key_256, k_ra8_sec_cmac_max_msg_bytes, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by priv_ra8_sec_cmac_compute(), and priv_ra8_sec_cmac_verify().
|
static |
Double a 128-bit value in GF(2^128) (CMAC subkey step).
NIST SP 800-38B Sec 6.1: left-shift the 16-byte value by one bit, XOR-ing the constant Rb (0x87) into the last byte when the top bit was set.
| [in] | in | Source 16-byte value. |
| [out] | out | Doubled 16-byte value. |
Definition at line 472 of file sec_cmac.c.
References k_aes_last_byte, k_aes_msb_shift, k_cmac_rb, and RA8_INTERNAL.
Referenced by internal_cmac_subkeys().
|
static |
Derive the CMAC subkeys K1 / K2 from the expanded key.
SP 800-38B Sec 6.1: L = AES(key, 0^128), K1 = 2L and K2 = 2 * K1 in GF(2^128). The intermediate L value is wiped before returning so only the subkeys leave this frame.
| [in] | rk | Round-key schedule from internal_aes_key_expand. |
| [in] | nr | Round count (10 or 14). |
| [out] | k1 | Receives the full-block subkey K1 (16 bytes). |
| [out] | k2 | Receives the padded-block subkey K2 (16 bytes). |
Definition at line 505 of file sec_cmac.c.
References internal_aes_encrypt(), internal_cmac_double(), k_aes_block_bytes, and ra8_secure_memzero().
Referenced by internal_cmac_tag().
|
static |
Compute the AES-CMAC tag of a message (SP 800-38B).
Derives subkeys K1/K2 via internal_cmac_subkeys, chains the full blocks, and folds the (possibly padded) final block built by internal_cmac_build_last before the last AES call. Handles the empty message as a single padded block per the standard.
| [in] | key | AES key bytes. |
| [in] | key_len | Key length (16 or 32). |
| [in] | msg | Message (NULL only when msg_len==0). |
| [in] | msg_len | Message length (<= k_ra8_sec_cmac_max_msg_bytes). |
| [out] | out_mac | 16-byte tag output. |
Definition at line 589 of file sec_cmac.c.
References internal_aes_encrypt(), internal_aes_key_expand(), internal_cmac_build_last(), internal_cmac_subkeys(), k_aes_block_bytes, k_aes_last_byte, k_aes_max_rk_bytes, k_aes_nr_128, k_aes_nr_256, k_aes_word_bytes, k_ra8_sec_cmac_key_128, RA8_INTERNAL, and ra8_secure_memzero().
Referenced by priv_ra8_sec_cmac_compute(), and priv_ra8_sec_cmac_verify().
|
nodiscard |
Compute the AES-CMAC tag of a message under a symmetric key.
Runs NIST SP 800-38B CMAC over msg with AES as the block cipher. key_len selects AES-128 (k_ra8_sec_cmac_key_128) or AES-256 (k_ra8_sec_cmac_key_256). The 16-byte tag is written to out_mac. The active backend (PSA or the in-tree reference) is chosen at compile time and produces the identical standard tag.
| [in] | key | Symmetric CMAC key (secret; caller-owned secure copy). |
| [in] | key_len | Key length: 16 (AES-128) or 32 (AES-256) bytes. |
| [in] | msg | Message to authenticate; NULL only when msg_len==0. |
| [in] | msg_len | Message length, 0 .. k_ra8_sec_cmac_max_msg_bytes. |
| [out] | out_mac | Destination for the k_ra8_sec_cmac_tag_bytes tag. |
| k_ra8_ok | Tag computed and written. |
| k_ra8_err_null_ptr | key or out_mac (or msg when msg_len!=0) was NULL. |
| k_ra8_err_invalid_arg | key_len was neither 16 nor 32. |
| k_ra8_err_invalid_size | msg_len exceeded the static cap. |
| k_ra8_err_hw_error | PSA backend reported a fault (PSA build). |
Definition at line 632 of file sec_cmac.c.
References internal_cmac_check_args(), internal_cmac_tag(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by priv_ra8_key_import_build_blob().
|
nodiscard |
Verify an AES-CMAC tag against a message under a symmetric key.
Recomputes the CMAC of msg under key and compares it, in constant time, to the caller-supplied mac. A single flipped message or tag byte, or a truncated tag (mac_len != k_ra8_sec_cmac_tag_bytes), makes the verdict fail. The verdict is the module's security-critical decision.
| [in] | key | Symmetric CMAC key (secret; caller-owned secure copy). |
| [in] | key_len | Key length: 16 (AES-128) or 32 (AES-256) bytes. |
| [in] | msg | Authenticated message; NULL only when msg_len==0. |
| [in] | msg_len | Message length, 0 .. k_ra8_sec_cmac_max_msg_bytes. |
| [in] | mac | Candidate tag to check. |
| [in] | mac_len | Length of mac; must equal k_ra8_sec_cmac_tag_bytes. |
| k_ra8_ok | Tag is authentic. |
| k_ra8_err_invalid_arg | Tag mismatch, wrong mac_len, or bad key_len. |
| k_ra8_err_null_ptr | key or mac (or msg when msg_len!=0) was NULL. |
| k_ra8_err_invalid_size | msg_len exceeded the static cap. |
| k_ra8_err_hw_error | PSA backend reported a fault (PSA build). |
Definition at line 647 of file sec_cmac.c.
References internal_cmac_check_args(), internal_cmac_tag(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sec_cmac_tag_bytes, RA8_CHECK_NULL_PTR, ra8_ct_equal(), ra8_secure_memzero(), and s_tag.
Referenced by internal_verify_cmac().
|
static |
AES S-box (FIPS 197 Fig.
7). Standard substitution table.
Definition at line 248 of file sec_cmac.c.
Referenced by internal_aes_key_expand(), and internal_aes_sub_shift().
|
static |
Logging / error tag prefix for this module.
Definition at line 48 of file sec_cmac.c.