Skip to content
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

tests: Add decrypt filter unit tests. #19772

Merged
merged 1 commit into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
61 changes: 36 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,17 @@ 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
*/
erase(decrypt_ctx);
}
}
}
Expand Down Expand Up @@ -236,16 +240,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 +265,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 +348,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 +360,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 +407,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) 2025 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) 2025 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) 2025 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