Skip to content

Commit

Permalink
tests: Add decrypt filter unit tests.
Browse files Browse the repository at this point in the history
This commit implements unit tests for decryption stream filter in SUIT.
As a result of tests implementation and run, minor changes to error
handling were added to decryption filter implementation. Also, some
parameter renamig was applied.

Ref: NCSDK-30925

Signed-off-by: Michal Kozikowski <[email protected]>
  • Loading branch information
nordic-mik7 committed Jan 7, 2025
1 parent 741cb7a commit 0c2651a
Show file tree
Hide file tree
Showing 9 changed files with 652 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ extern "C" {
/**
* @brief Get decrypt filter object
*
* @param[out] dec_sink Pointer to destination sink_stream to pass decrypted data
* @param[out] in_sink Pointer to input sink_stream to pass encrypted data
* @param[in] enc_info Pointer to the structure with encryption info.
* @param[in] class_id Pointer to the manifest class ID of the destination component
* @param[in] enc_sink Pointer to source sink_stream to be filled with encrypted data
* @param[in] out_sink Pointer to output sink_stream to be filled with decrypted data
*
* @return SUIT_PLAT_SUCCESS if success otherwise error code
*/
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *in_sink,
struct suit_encryption_info *enc_info,
const suit_manifest_class_id_t *class_id,
struct stream_sink *enc_sink);
struct stream_sink *out_sink);

#ifdef __cplusplus
}
Expand Down
59 changes: 34 additions & 25 deletions subsys/suit/stream/stream_filters/src/suit_decrypt_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(suit_decrypt_filter, CONFIG_SUIT_LOG_LEVEL);
struct decrypt_ctx {
mbedtls_svc_key_id_t cek_key_id;
psa_aead_operation_t operation;
struct stream_sink enc_sink;
struct stream_sink out_sink;
size_t tag_size;
size_t stored_tag_bytes;
uint8_t tag[PSA_AEAD_TAG_MAX_SIZE];
Expand Down Expand Up @@ -67,8 +67,8 @@ static suit_plat_err_t erase(void *ctx)
decrypt_ctx->stored_tag_bytes = 0;
memset(decrypt_ctx->tag, 0, sizeof(decrypt_ctx->tag));

if (decrypt_ctx->enc_sink.erase != NULL) {
res = decrypt_ctx->enc_sink.erase(decrypt_ctx->enc_sink.ctx);
if (decrypt_ctx->out_sink.erase != NULL) {
res = decrypt_ctx->out_sink.erase(decrypt_ctx->out_sink.ctx);
}
} else {
res = SUIT_PLAT_ERR_INVAL;
Expand Down Expand Up @@ -131,7 +131,7 @@ static suit_plat_err_t write(void *ctx, const uint8_t *buf, size_t size)
goto cleanup;
}

err = decrypt_ctx->enc_sink.write(decrypt_ctx->enc_sink.ctx, decrypted_buf,
err = decrypt_ctx->out_sink.write(decrypt_ctx->out_sink.ctx, decrypted_buf,
decrypted_len);

if (err != SUIT_PLAT_SUCCESS) {
Expand Down Expand Up @@ -195,13 +195,15 @@ static suit_plat_err_t flush(void *ctx)
} else {
LOG_INF("Firmware decryption successful");

/* Using enc_sink without a write API is blocked by the filter constructor.
/* Using out_sink without a write API is blocked by the filter constructor.
*/
if (decrypted_len > 0) {
res = decrypt_ctx->enc_sink.write(decrypt_ctx->enc_sink.ctx,
res = decrypt_ctx->out_sink.write(decrypt_ctx->out_sink.ctx,
decrypted_buf, decrypted_len);
if (res != SUIT_PLAT_SUCCESS) {
LOG_ERR("Failed to write decrypted data: %d", res);
/* Revert all the changes so that no decrypted data remains */

Check warning on line 205 in subsys/suit/stream/stream_filters/src/suit_decrypt_filter.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE_COMMENT

subsys/suit/stream/stream_filters/src/suit_decrypt_filter.c:205 line length of 102 exceeds 100 columns
erase(decrypt_ctx);
}
}
}
Expand Down Expand Up @@ -236,16 +238,16 @@ static suit_plat_err_t release(void *ctx)

suit_plat_err_t res = flush(ctx);

if (decrypt_ctx->enc_sink.release != NULL) {
if (decrypt_ctx->out_sink.release != NULL) {
suit_plat_err_t release_ret =
decrypt_ctx->enc_sink.release(decrypt_ctx->enc_sink.ctx);
decrypt_ctx->out_sink.release(decrypt_ctx->out_sink.ctx);

if (res == SUIT_SUCCESS) {
res = release_ret;
}
}

zeroize(&decrypt_ctx->enc_sink, sizeof(struct stream_sink));
zeroize(&decrypt_ctx->out_sink, sizeof(struct stream_sink));

decrypt_ctx->in_use = false;

Expand All @@ -261,8 +263,8 @@ static suit_plat_err_t used_storage(void *ctx, size_t *size)
return SUIT_PLAT_ERR_INVAL;
}

if (decrypt_ctx->enc_sink.used_storage != NULL) {
return decrypt_ctx->enc_sink.used_storage(decrypt_ctx->enc_sink.ctx, size);
if (decrypt_ctx->out_sink.used_storage != NULL) {
return decrypt_ctx->out_sink.used_storage(decrypt_ctx->out_sink.ctx, size);
}

return SUIT_PLAT_ERR_UNSUPPORTED;
Expand Down Expand Up @@ -344,10 +346,10 @@ static suit_plat_err_t get_psa_alg_info(enum suit_cose_alg cose_alg_id, psa_algo
return SUIT_PLAT_SUCCESS;
}

suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *in_sink,
struct suit_encryption_info *enc_info,
const suit_manifest_class_id_t *class_id,
struct stream_sink *enc_sink)
struct stream_sink *out_sink)
{
suit_plat_err_t ret = SUIT_PLAT_SUCCESS;

Expand All @@ -356,8 +358,8 @@ suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
return SUIT_PLAT_ERR_BUSY;
}

if ((enc_info == NULL) || (enc_sink == NULL) || (dec_sink == NULL) ||
(enc_sink->write == NULL) || class_id == NULL) {
if ((enc_info == NULL) || (out_sink == NULL) || (in_sink == NULL) ||
(out_sink->write == NULL) || class_id == NULL) {
return SUIT_PLAT_ERR_INVAL;
}

Expand Down Expand Up @@ -403,23 +405,30 @@ suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,

status = psa_aead_update_ad(&ctx.operation, enc_info->aad.value, enc_info->aad.len);

if (status != PSA_SUCCESS) {
LOG_ERR("Failed to pass additional data for authentication operation: %d", status);
psa_aead_abort(&ctx.operation);
ctx.in_use = false;
return SUIT_PLAT_ERR_CRASH;
}

ctx.stored_tag_bytes = 0;
memcpy(&ctx.enc_sink, enc_sink, sizeof(struct stream_sink));
memcpy(&ctx.out_sink, out_sink, sizeof(struct stream_sink));

dec_sink->ctx = &ctx;
in_sink->ctx = &ctx;

dec_sink->write = write;
dec_sink->erase = erase;
dec_sink->release = release;
dec_sink->flush = flush;
if (enc_sink->used_storage != NULL) {
dec_sink->used_storage = used_storage;
in_sink->write = write;
in_sink->erase = erase;
in_sink->release = release;
in_sink->flush = flush;
if (out_sink->used_storage != NULL) {
in_sink->used_storage = used_storage;
} else {
dec_sink->used_storage = NULL;
in_sink->used_storage = NULL;
}

/* Seeking is not possible on encrypted payload. */
dec_sink->seek = NULL;
in_sink->seek = NULL;

return SUIT_PLAT_SUCCESS;
}
15 changes: 15 additions & 0 deletions tests/subsys/suit/unit/mocks/include/mock_suit_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ FAKE_VALUE_FUNC(psa_status_t, psa_hash_abort, psa_hash_operation_t *);
FAKE_VALUE_FUNC(psa_status_t, psa_hash_verify, psa_hash_operation_t *, const uint8_t *, size_t);
FAKE_VALUE_FUNC(psa_status_t, psa_verify_message, mbedtls_svc_key_id_t, psa_algorithm_t,
const uint8_t *, size_t, const uint8_t *, size_t);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_update, psa_aead_operation_t *, const uint8_t *, size_t,
uint8_t *, size_t, size_t *);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_abort, psa_aead_operation_t *);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_verify, psa_aead_operation_t *, uint8_t *, size_t, size_t *,
const uint8_t *, size_t);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_set_nonce, psa_aead_operation_t *, const uint8_t *, size_t);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_update_ad, psa_aead_operation_t *, const uint8_t *, size_t);
FAKE_VALUE_FUNC(psa_status_t, psa_aead_decrypt_setup, psa_aead_operation_t *,
mbedtls_svc_key_id_t, psa_algorithm_t);

static inline void mock_suit_crypto_reset(void)
{
Expand All @@ -26,6 +35,12 @@ static inline void mock_suit_crypto_reset(void)
RESET_FAKE(psa_hash_abort);
RESET_FAKE(psa_hash_verify);
RESET_FAKE(psa_verify_message);
RESET_FAKE(psa_aead_update);
RESET_FAKE(psa_aead_abort);
RESET_FAKE(psa_aead_verify);
RESET_FAKE(psa_aead_set_nonce);
RESET_FAKE(psa_aead_update_ad);
RESET_FAKE(psa_aead_decrypt_setup);
}

#endif /* MOCK_SUIT_CRYPTO_H__ */
3 changes: 3 additions & 0 deletions tests/subsys/suit/unit/mocks/include/mock_suit_mci.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ FAKE_VALUE_FUNC(int, suit_mci_manifest_parent_child_declaration_validate,
FAKE_VALUE_FUNC(int, suit_mci_manifest_process_dependency_validate,
const suit_manifest_class_id_t *, const suit_manifest_class_id_t *);
FAKE_VALUE_FUNC(int, suit_mci_init);
FAKE_VALUE_FUNC(int, suit_mci_fw_encryption_key_id_validate, const suit_manifest_class_id_t *,
uint32_t);

static inline void mock_suit_mci_reset(void)
{
Expand All @@ -74,6 +76,7 @@ static inline void mock_suit_mci_reset(void)
RESET_FAKE(suit_mci_manifest_process_dependency_validate);
RESET_FAKE(suit_mci_manifest_parent_child_declaration_validate);
RESET_FAKE(suit_mci_init);
RESET_FAKE(suit_mci_fw_encryption_key_id_validate);
}

#endif /* MOCK_SUIT_MCI_H__ */
20 changes: 20 additions & 0 deletions tests/subsys/suit/unit/suit_decrypt_filter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

include(../cmake/test_template.cmake)

project(suit_decrypt_filter)
target_include_directories(testbinary PRIVATE
${SUIT_SUBSYS_DIR}/stream/stream_filters/include
${SUIT_SUBSYS_DIR}/utils/include/
)

target_sources(testbinary PRIVATE
src/main.c
${SUIT_SUBSYS_DIR}/stream/stream_filters/src/suit_decrypt_filter.c
)
10 changes: 10 additions & 0 deletions tests/subsys/suit/unit/suit_decrypt_filter/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# Include and define MOCK_* Kconfigs
rsource "../mocks/Kconfig"

source "Kconfig.zephyr"
16 changes: 16 additions & 0 deletions tests/subsys/suit/unit/suit_decrypt_filter/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_MOCK_SUIT_PROCESSOR=y
CONFIG_MOCK_SUIT_PLATFORM=y
CONFIG_MOCK_DIGEST_SINK=y
CONFIG_MOCK_GENERIC_ADDRESS_STREAMER=y
CONFIG_MOCK_SUIT_UTILS=y
CONFIG_MOCK_SUIT_MEMPTR_STORAGE=y
CONFIG_MOCK_SUIT_CRYPTO=y
CONFIG_MOCK_SUIT_MCI=y
CONFIG_MOCK_SUIT_METADATA=y
CONFIG_MOCK_SUIT_PLATFORM_INTERNAL=y
Loading

0 comments on commit 0c2651a

Please sign in to comment.