Skip to content

Commit 728080b

Browse files
nordic-mik7rlubos
authored andcommitted
tests: Add decrypt filter unit tests.
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]>
1 parent 3bf7d40 commit 728080b

File tree

9 files changed

+619
-29
lines changed

9 files changed

+619
-29
lines changed

subsys/suit/stream/stream_filters/include/suit_decrypt_filter.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ extern "C" {
1818
/**
1919
* @brief Get decrypt filter object
2020
*
21-
* @param[out] dec_sink Pointer to destination sink_stream to pass decrypted data
21+
* @param[out] in_sink Pointer to input sink_stream to pass encrypted data
2222
* @param[in] enc_info Pointer to the structure with encryption info.
2323
* @param[in] class_id Pointer to the manifest class ID of the destination component
24-
* @param[in] enc_sink Pointer to source sink_stream to be filled with encrypted data
24+
* @param[in] out_sink Pointer to output sink_stream to be filled with decrypted data
2525
*
2626
* @return SUIT_PLAT_SUCCESS if success otherwise error code
2727
*/
28-
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
28+
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *in_sink,
2929
struct suit_encryption_info *enc_info,
3030
const suit_manifest_class_id_t *class_id,
31-
struct stream_sink *enc_sink);
31+
struct stream_sink *out_sink);
3232

3333
#ifdef __cplusplus
3434
}

subsys/suit/stream/stream_filters/src/suit_decrypt_filter.c

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(suit_decrypt_filter, CONFIG_SUIT_LOG_LEVEL);
2424
struct decrypt_ctx {
2525
mbedtls_svc_key_id_t cek_key_id;
2626
psa_aead_operation_t operation;
27-
struct stream_sink enc_sink;
27+
struct stream_sink out_sink;
2828
size_t tag_size;
2929
size_t stored_tag_bytes;
3030
uint8_t tag[PSA_AEAD_TAG_MAX_SIZE];
@@ -67,8 +67,8 @@ static suit_plat_err_t erase(void *ctx)
6767
decrypt_ctx->stored_tag_bytes = 0;
6868
memset(decrypt_ctx->tag, 0, sizeof(decrypt_ctx->tag));
6969

70-
if (decrypt_ctx->enc_sink.erase != NULL) {
71-
res = decrypt_ctx->enc_sink.erase(decrypt_ctx->enc_sink.ctx);
70+
if (decrypt_ctx->out_sink.erase != NULL) {
71+
res = decrypt_ctx->out_sink.erase(decrypt_ctx->out_sink.ctx);
7272
}
7373
} else {
7474
res = SUIT_PLAT_ERR_INVAL;
@@ -131,7 +131,7 @@ static suit_plat_err_t write(void *ctx, const uint8_t *buf, size_t size)
131131
goto cleanup;
132132
}
133133

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

137137
if (err != SUIT_PLAT_SUCCESS) {
@@ -195,13 +195,17 @@ static suit_plat_err_t flush(void *ctx)
195195
} else {
196196
LOG_INF("Firmware decryption successful");
197197

198-
/* Using enc_sink without a write API is blocked by the filter constructor.
198+
/* Using out_sink without a write API is blocked by the filter constructor.
199199
*/
200200
if (decrypted_len > 0) {
201-
res = decrypt_ctx->enc_sink.write(decrypt_ctx->enc_sink.ctx,
201+
res = decrypt_ctx->out_sink.write(decrypt_ctx->out_sink.ctx,
202202
decrypted_buf, decrypted_len);
203203
if (res != SUIT_PLAT_SUCCESS) {
204204
LOG_ERR("Failed to write decrypted data: %d", res);
205+
/* Revert all the changes so that
206+
* no decrypted data remains
207+
*/
208+
erase(decrypt_ctx);
205209
}
206210
}
207211
}
@@ -236,16 +240,16 @@ static suit_plat_err_t release(void *ctx)
236240

237241
suit_plat_err_t res = flush(ctx);
238242

239-
if (decrypt_ctx->enc_sink.release != NULL) {
243+
if (decrypt_ctx->out_sink.release != NULL) {
240244
suit_plat_err_t release_ret =
241-
decrypt_ctx->enc_sink.release(decrypt_ctx->enc_sink.ctx);
245+
decrypt_ctx->out_sink.release(decrypt_ctx->out_sink.ctx);
242246

243247
if (res == SUIT_SUCCESS) {
244248
res = release_ret;
245249
}
246250
}
247251

248-
zeroize(&decrypt_ctx->enc_sink, sizeof(struct stream_sink));
252+
zeroize(&decrypt_ctx->out_sink, sizeof(struct stream_sink));
249253

250254
decrypt_ctx->in_use = false;
251255

@@ -261,8 +265,8 @@ static suit_plat_err_t used_storage(void *ctx, size_t *size)
261265
return SUIT_PLAT_ERR_INVAL;
262266
}
263267

264-
if (decrypt_ctx->enc_sink.used_storage != NULL) {
265-
return decrypt_ctx->enc_sink.used_storage(decrypt_ctx->enc_sink.ctx, size);
268+
if (decrypt_ctx->out_sink.used_storage != NULL) {
269+
return decrypt_ctx->out_sink.used_storage(decrypt_ctx->out_sink.ctx, size);
266270
}
267271

268272
return SUIT_PLAT_ERR_UNSUPPORTED;
@@ -344,10 +348,10 @@ static suit_plat_err_t get_psa_alg_info(enum suit_cose_alg cose_alg_id, psa_algo
344348
return SUIT_PLAT_SUCCESS;
345349
}
346350

347-
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
351+
suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *in_sink,
348352
struct suit_encryption_info *enc_info,
349353
const suit_manifest_class_id_t *class_id,
350-
struct stream_sink *enc_sink)
354+
struct stream_sink *out_sink)
351355
{
352356
suit_plat_err_t ret = SUIT_PLAT_SUCCESS;
353357

@@ -356,8 +360,8 @@ suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
356360
return SUIT_PLAT_ERR_BUSY;
357361
}
358362

359-
if ((enc_info == NULL) || (enc_sink == NULL) || (dec_sink == NULL) ||
360-
(enc_sink->write == NULL) || class_id == NULL) {
363+
if ((enc_info == NULL) || (out_sink == NULL) || (in_sink == NULL) ||
364+
(out_sink->write == NULL) || class_id == NULL) {
361365
return SUIT_PLAT_ERR_INVAL;
362366
}
363367

@@ -403,23 +407,30 @@ suit_plat_err_t suit_decrypt_filter_get(struct stream_sink *dec_sink,
403407

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

410+
if (status != PSA_SUCCESS) {
411+
LOG_ERR("Failed to pass additional data for authentication operation: %d", status);
412+
psa_aead_abort(&ctx.operation);
413+
ctx.in_use = false;
414+
return SUIT_PLAT_ERR_CRASH;
415+
}
416+
406417
ctx.stored_tag_bytes = 0;
407-
memcpy(&ctx.enc_sink, enc_sink, sizeof(struct stream_sink));
418+
memcpy(&ctx.out_sink, out_sink, sizeof(struct stream_sink));
408419

409-
dec_sink->ctx = &ctx;
420+
in_sink->ctx = &ctx;
410421

411-
dec_sink->write = write;
412-
dec_sink->erase = erase;
413-
dec_sink->release = release;
414-
dec_sink->flush = flush;
415-
if (enc_sink->used_storage != NULL) {
416-
dec_sink->used_storage = used_storage;
422+
in_sink->write = write;
423+
in_sink->erase = erase;
424+
in_sink->release = release;
425+
in_sink->flush = flush;
426+
if (out_sink->used_storage != NULL) {
427+
in_sink->used_storage = used_storage;
417428
} else {
418-
dec_sink->used_storage = NULL;
429+
in_sink->used_storage = NULL;
419430
}
420431

421432
/* Seeking is not possible on encrypted payload. */
422-
dec_sink->seek = NULL;
433+
in_sink->seek = NULL;
423434

424435
return SUIT_PLAT_SUCCESS;
425436
}

tests/subsys/suit/unit/mocks/include/mock_suit_crypto.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ FAKE_VALUE_FUNC(psa_status_t, psa_hash_abort, psa_hash_operation_t *);
1818
FAKE_VALUE_FUNC(psa_status_t, psa_hash_verify, psa_hash_operation_t *, const uint8_t *, size_t);
1919
FAKE_VALUE_FUNC(psa_status_t, psa_verify_message, mbedtls_svc_key_id_t, psa_algorithm_t,
2020
const uint8_t *, size_t, const uint8_t *, size_t);
21+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_update, psa_aead_operation_t *, const uint8_t *, size_t,
22+
uint8_t *, size_t, size_t *);
23+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_abort, psa_aead_operation_t *);
24+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_verify, psa_aead_operation_t *, uint8_t *, size_t, size_t *,
25+
const uint8_t *, size_t);
26+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_set_nonce, psa_aead_operation_t *, const uint8_t *, size_t);
27+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_update_ad, psa_aead_operation_t *, const uint8_t *, size_t);
28+
FAKE_VALUE_FUNC(psa_status_t, psa_aead_decrypt_setup, psa_aead_operation_t *,
29+
mbedtls_svc_key_id_t, psa_algorithm_t);
2130

2231
static inline void mock_suit_crypto_reset(void)
2332
{
@@ -26,6 +35,12 @@ static inline void mock_suit_crypto_reset(void)
2635
RESET_FAKE(psa_hash_abort);
2736
RESET_FAKE(psa_hash_verify);
2837
RESET_FAKE(psa_verify_message);
38+
RESET_FAKE(psa_aead_update);
39+
RESET_FAKE(psa_aead_abort);
40+
RESET_FAKE(psa_aead_verify);
41+
RESET_FAKE(psa_aead_set_nonce);
42+
RESET_FAKE(psa_aead_update_ad);
43+
RESET_FAKE(psa_aead_decrypt_setup);
2944
}
3045

3146
#endif /* MOCK_SUIT_CRYPTO_H__ */

tests/subsys/suit/unit/mocks/include/mock_suit_mci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ FAKE_VALUE_FUNC(int, suit_mci_manifest_parent_child_declaration_validate,
4848
FAKE_VALUE_FUNC(int, suit_mci_manifest_process_dependency_validate,
4949
const suit_manifest_class_id_t *, const suit_manifest_class_id_t *);
5050
FAKE_VALUE_FUNC(int, suit_mci_init);
51+
FAKE_VALUE_FUNC(int, suit_mci_fw_encryption_key_id_validate, const suit_manifest_class_id_t *,
52+
uint32_t);
5153

5254
static inline void mock_suit_mci_reset(void)
5355
{
@@ -74,6 +76,7 @@ static inline void mock_suit_mci_reset(void)
7476
RESET_FAKE(suit_mci_manifest_process_dependency_validate);
7577
RESET_FAKE(suit_mci_manifest_parent_child_declaration_validate);
7678
RESET_FAKE(suit_mci_init);
79+
RESET_FAKE(suit_mci_fw_encryption_key_id_validate);
7780
}
7881

7982
#endif /* MOCK_SUIT_MCI_H__ */
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
include(../cmake/test_template.cmake)
10+
11+
project(suit_decrypt_filter)
12+
target_include_directories(testbinary PRIVATE
13+
${SUIT_SUBSYS_DIR}/stream/stream_filters/include
14+
${SUIT_SUBSYS_DIR}/utils/include/
15+
)
16+
17+
target_sources(testbinary PRIVATE
18+
src/main.c
19+
${SUIT_SUBSYS_DIR}/stream/stream_filters/src/suit_decrypt_filter.c
20+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# Include and define MOCK_* Kconfigs
8+
rsource "../mocks/Kconfig"
9+
10+
source "Kconfig.zephyr"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
CONFIG_MOCK_SUIT_PROCESSOR=y
8+
CONFIG_MOCK_SUIT_PLATFORM=y
9+
CONFIG_MOCK_DIGEST_SINK=y
10+
CONFIG_MOCK_GENERIC_ADDRESS_STREAMER=y
11+
CONFIG_MOCK_SUIT_UTILS=y
12+
CONFIG_MOCK_SUIT_MEMPTR_STORAGE=y
13+
CONFIG_MOCK_SUIT_CRYPTO=y
14+
CONFIG_MOCK_SUIT_MCI=y
15+
CONFIG_MOCK_SUIT_METADATA=y
16+
CONFIG_MOCK_SUIT_PLATFORM_INTERNAL=y

0 commit comments

Comments
 (0)