-
Notifications
You must be signed in to change notification settings - Fork 1.3k
nrf_security: cracen: Add support for multipart cmac to lm20 #22912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
degjorva
wants to merge
1
commit into
nrfconnect:main
Choose a base branch
from
degjorva:cmac-multipart-lm20-workaround
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,13 +53,3 @@ psa_status_t cracen_cmac_update(cracen_mac_operation_t *operation, const uint8_t | |
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_cmac_finish(cracen_mac_operation_t *operation); | ||
|
||
/** | ||
* @brief Compute a CMAC in a single pass, without context switching. | ||
* | ||
* @note This function assumes the setup function is called first. | ||
* | ||
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_cmac_compute(cracen_mac_operation_t *operation, const uint8_t *input, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this removed? I see that the function is implemented in cracen_mac_cmac.c. |
||
size_t input_length, uint8_t *mac); |
222 changes: 222 additions & 0 deletions
222
subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_sw_mac_cmac.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* | ||
* Copyright (c) 2025 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
*/ | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <psa/crypto.h> | ||
#include <sxsymcrypt/blkcipher.h> | ||
#include <sxsymcrypt/keyref.h> | ||
#include "cracen_sw_mac_cmac.h" | ||
#include <sxsymcrypt/aes.h> | ||
|
||
#define CMAC_PADDING_BYTE (0x80) | ||
#define AES_CMAC_MSB (0x80) | ||
#define CMAC_CONSTANT_RB (0x87) | ||
|
||
static psa_status_t cracen_aes_ecb_encrypt(const struct sxkeyref *key, const uint8_t *input, | ||
uint8_t *output) | ||
{ | ||
struct sxblkcipher blkciph; | ||
int sx_status; | ||
|
||
sx_status = sx_blkcipher_create_aesecb_enc(&blkciph, key); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
sx_status = sx_blkcipher_crypt(&blkciph, input, SX_BLKCIPHER_AES_BLK_SZ, output); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
sx_status = sx_blkcipher_run(&blkciph); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
sx_status = sx_blkcipher_wait(&blkciph); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
return PSA_SUCCESS; | ||
} | ||
|
||
psa_status_t cracen_sw_cmac_setup(cracen_mac_operation_t *operation, | ||
const psa_key_attributes_t *attributes, const uint8_t *key_buffer, | ||
size_t key_buffer_size) | ||
{ | ||
psa_status_t status = PSA_SUCCESS; | ||
int sx_status; | ||
|
||
/* Only AES-CMAC is supported */ | ||
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) { | ||
return PSA_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
if (key_buffer_size != 16 && key_buffer_size != 24 && key_buffer_size != 32) { | ||
return PSA_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
/* Load the key reference */ | ||
if (key_buffer_size > sizeof(operation->cmac.key_buffer)) { | ||
return PSA_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
memcpy(operation->cmac.key_buffer, key_buffer, key_buffer_size); | ||
status = cracen_load_keyref(attributes, operation->cmac.key_buffer, key_buffer_size, | ||
&operation->cmac.keyref); | ||
if (status != PSA_SUCCESS) { | ||
return status; | ||
} | ||
|
||
sx_status = sx_mac_create_aescmac(&operation->cmac.ctx, &operation->cmac.keyref); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
operation->bytes_left_for_next_block = SX_BLKCIPHER_AES_BLK_SZ; | ||
operation->is_first_block = true; | ||
|
||
return PSA_SUCCESS; | ||
} | ||
|
||
static void left_shift_block(const uint8_t *in, uint8_t *out) | ||
{ | ||
uint8_t carry = 0; | ||
uint8_t byte; | ||
|
||
for (int i = SX_BLKCIPHER_AES_BLK_SZ - 1; i >= 0; i--) { | ||
byte = in[i]; | ||
out[i] = (byte << 1) | carry; | ||
carry = (byte & AES_CMAC_MSB) ? 1 : 0; | ||
} | ||
} | ||
|
||
psa_status_t cracen_cmac_derive_subkeys(cracen_mac_operation_t *operation, uint8_t *k1, uint8_t *k2) | ||
{ | ||
uint8_t empty_block[SX_BLKCIPHER_AES_BLK_SZ] = {0}; | ||
uint8_t L[SX_BLKCIPHER_AES_BLK_SZ]; /* L is defined in RFC 4493 */ | ||
psa_status_t status = cracen_aes_ecb_encrypt(&operation->cmac.keyref, empty_block, L); | ||
|
||
if (status != PSA_SUCCESS) { | ||
return status; | ||
} | ||
|
||
left_shift_block(L, k1); | ||
if (L[0] & AES_CMAC_MSB) { | ||
k1[SX_BLKCIPHER_AES_BLK_SZ - 1] ^= CMAC_CONSTANT_RB; | ||
} | ||
|
||
left_shift_block(k1, k2); | ||
if (k1[0] & AES_CMAC_MSB) { | ||
k2[SX_BLKCIPHER_AES_BLK_SZ - 1] ^= CMAC_CONSTANT_RB; | ||
} | ||
return PSA_SUCCESS; | ||
} | ||
|
||
psa_status_t cracen_sw_cmac_update(cracen_mac_operation_t *operation, const uint8_t *data, | ||
size_t data_len) | ||
{ | ||
psa_status_t psa_status; | ||
size_t bytes_to_copy; | ||
size_t remaining = data_len; | ||
size_t offset = 0; | ||
|
||
while (remaining > 0) { | ||
bytes_to_copy = SX_BLKCIPHER_AES_BLK_SZ - operation->cmac.sw_ctx.partial_len; | ||
if (bytes_to_copy > remaining) { | ||
bytes_to_copy = remaining; | ||
} | ||
|
||
memcpy(operation->cmac.sw_ctx.partial_block + operation->cmac.sw_ctx.partial_len, | ||
data + offset, bytes_to_copy); | ||
operation->cmac.sw_ctx.partial_len += bytes_to_copy; | ||
offset += bytes_to_copy; | ||
remaining -= bytes_to_copy; | ||
|
||
/* Only encrypt a full block if we know more data is coming */ | ||
if (operation->cmac.sw_ctx.partial_len == SX_BLKCIPHER_AES_BLK_SZ && | ||
remaining > 0) { | ||
cracen_xorbytes(operation->cmac.sw_ctx.mac_state, | ||
operation->cmac.sw_ctx.partial_block, | ||
SX_BLKCIPHER_AES_BLK_SZ); | ||
psa_status = cracen_aes_ecb_encrypt(&operation->cmac.keyref, | ||
operation->cmac.sw_ctx.mac_state, | ||
operation->cmac.sw_ctx.mac_state); | ||
if (psa_status != PSA_SUCCESS) { | ||
return psa_status; | ||
} | ||
operation->cmac.sw_ctx.partial_len = 0; | ||
memset(operation->cmac.sw_ctx.partial_block, 0, SX_BLKCIPHER_AES_BLK_SZ); | ||
} | ||
} | ||
|
||
return PSA_SUCCESS; | ||
} | ||
|
||
psa_status_t cracen_sw_cmac_finish(cracen_mac_operation_t *operation) | ||
{ | ||
psa_status_t psa_status; | ||
uint8_t last_block[SX_BLKCIPHER_AES_BLK_SZ] = {0}; | ||
uint8_t k1[SX_BLKCIPHER_AES_BLK_SZ]; /* k1 is defined in RFC 4493 */ | ||
uint8_t k2[SX_BLKCIPHER_AES_BLK_SZ]; /* k2 is defined in RFC 4493 */ | ||
|
||
psa_status = cracen_cmac_derive_subkeys(operation, k1, k2); | ||
if (psa_status != PSA_SUCCESS) { | ||
return psa_status; | ||
} | ||
|
||
/* If full block, XOR with K1; otherwise pad and XOR with K2 */ | ||
if (operation->cmac.sw_ctx.partial_len == SX_BLKCIPHER_AES_BLK_SZ) { | ||
cracen_xorbytes(operation->cmac.sw_ctx.partial_block, k1, SX_BLKCIPHER_AES_BLK_SZ); | ||
memcpy(last_block, operation->cmac.sw_ctx.partial_block, SX_BLKCIPHER_AES_BLK_SZ); | ||
} else { | ||
memcpy(last_block, operation->cmac.sw_ctx.partial_block, | ||
operation->cmac.sw_ctx.partial_len); | ||
|
||
last_block[operation->cmac.sw_ctx.partial_len] = CMAC_PADDING_BYTE; | ||
cracen_xorbytes(last_block, k2, SX_BLKCIPHER_AES_BLK_SZ); | ||
} | ||
|
||
/* Final MAC: encrypt (mac_state XOR last_block) */ | ||
cracen_xorbytes(operation->cmac.sw_ctx.mac_state, last_block, SX_BLKCIPHER_AES_BLK_SZ); | ||
|
||
psa_status = | ||
cracen_aes_ecb_encrypt(&operation->cmac.keyref, operation->cmac.sw_ctx.mac_state, | ||
operation->cmac.sw_ctx.mac_state); | ||
if (psa_status != PSA_SUCCESS) { | ||
return psa_status; | ||
} | ||
|
||
memcpy(operation->input_buffer, operation->cmac.sw_ctx.mac_state, SX_BLKCIPHER_AES_BLK_SZ); | ||
operation->mac_size = SX_BLKCIPHER_AES_BLK_SZ; | ||
|
||
return PSA_SUCCESS; | ||
} | ||
|
||
/* Single-shot operations still use hw cmac */ | ||
psa_status_t cracen_sw_cmac_compute(cracen_mac_operation_t *operation, const uint8_t *input, | ||
size_t input_length, uint8_t *mac) | ||
{ | ||
int sx_status; | ||
|
||
sx_status = sx_mac_feed(&operation->cmac.ctx, input, input_length); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
sx_status = sx_mac_generate(&operation->cmac.ctx, mac); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
sx_status = sx_mac_wait(&operation->cmac.ctx); | ||
if (sx_status != SX_OK) { | ||
return silex_statuscodes_to_psa(sx_status); | ||
} | ||
|
||
return PSA_SUCCESS; | ||
} |
66 changes: 66 additions & 0 deletions
66
subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_sw_mac_cmac.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright (c) 2025 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
*/ | ||
|
||
#include <psa/crypto.h> | ||
#include "common.h" | ||
#include "cracen_psa_primitives.h" | ||
|
||
/** | ||
* @brief Setup for software based CMAC operation | ||
* | ||
* This function initializes a CMAC operation with the provided key attributes | ||
* and key buffer. It prepares the operation structure for subsequent CMAC | ||
* processing. This operation runs cmac in software using hardware AES-ECB primitives | ||
* | ||
* @param[in,out] operation Pointer to the CMAC operation structure to be initialized. | ||
* @param[in] attributes Pointer to the key attributes structure. | ||
* @param[in] key_buffer Pointer to the buffer containing the key material. | ||
* @param[in] key_buffer_size Size of the key buffer in bytes. | ||
* | ||
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_sw_cmac_setup(cracen_mac_operation_t *op, | ||
const psa_key_attributes_t *attributes, const uint8_t *key_buffer, | ||
size_t key_buffer_size); | ||
|
||
/** | ||
* @brief Update function software based CMAC operation | ||
* | ||
* This function processes a chunk of input data as part of a CMAC operation. | ||
* It can be called multiple times to process data in chunks. | ||
* This operation runs cmac in software using hardware AES-ECB primitives | ||
* | ||
* @param[in,out] operation Pointer to the CMAC operation structure. | ||
* @param[in] input Pointer to the input data buffer. | ||
* @param[in] input_length Length of the input data in bytes. | ||
* | ||
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_sw_cmac_update(cracen_mac_operation_t *op, const uint8_t *data, | ||
size_t data_len); | ||
|
||
/** | ||
* @brief Function to finalize a C software based CMAC operation. | ||
* | ||
* This function completes the CMAC operation and releases any resources | ||
* associated with it. It should be called after all input data has been | ||
* processed. This operation runs cmac in software using hardware AES-ECB primitives | ||
* | ||
* @param[in,out] operation Pointer to the CMAC operation structure. | ||
* | ||
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_sw_cmac_finish(cracen_mac_operation_t *op); | ||
|
||
/** | ||
* @brief Compute a CMAC in a single pass, without context switching. | ||
* | ||
* @note This function assumes the setup function is called first. | ||
* | ||
* @return PSA_SUCCESS on success or a valid PSA status code. | ||
*/ | ||
psa_status_t cracen_cmac_compute(cracen_mac_operation_t *op, const uint8_t *input, | ||
size_t input_length, uint8_t *mac); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs to be conditionally included as well since it will increase stack usage for all the targets otherwise.