Skip to content

Commit 6320c1f

Browse files
committed
tests: Add KMU basic tests
Added basic tests for KMU key provisioning. Co-authored-by: Grzegorz Chwierut <grzegorz.chwierut@nordicsemi.no> Signed-off-by: Lukasz Fundakowski <lukasz.fundakowski@nordicsemi.no>
1 parent 33a457e commit 6320c1f

16 files changed

Lines changed: 314 additions & 0 deletions

File tree

CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
# Scripts
7575
/scripts/ @nrfconnect/ncs-bm
76+
/scripts/pytest_plugins/ @nrfconnect/ncs-eris
7677
/scripts/requirements-*.txt @nrfconnect/ncs-co-build-system
7778

7879
# Subsystems
@@ -96,6 +97,7 @@
9697
/tests/lib/bluetooth/ble_adv/ @nrfconnect/ncs-bm-test
9798
/tests/subsys/bluetooth/services/ @nrfconnect/ncs-bm @nrfconnect/ncs-bm-test
9899
/tests/subsys/fs/bm_zms/ @nrfconnect/ncs-bm @rghaddab
100+
/tests/subsys/kmu/ @nrfconnect/ncs-eris
99101
/tests/subsys/storage/bm_storage/ @nrfconnect/ncs-bm
100102

101103
# Zephyr module

scripts/pytest_plugins/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Shared Python's libraries for the `pytest-twister-harness`
2+
3+
The package contains plugins for pytest that can be used in twister tests
4+
and other shared Python modules for testing framework.
5+
It is required to export PYTHONPATH with the path to `nrf-bm\scripts`
6+
so this shared library is available for pytest tests.
7+
8+
For example:
9+
```sh
10+
PYTHONPATH=$PYTHONPATH:$ZEPHYR_BASE/../nrf-bm/scripts $ZEPHYR_BASE/scripts/twister -T $ZEPHYR_BASE/../nrf-bm/tests/subsys/kmu/hello_for_kmu -p bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot --device-testing --device-serial /dev/ttyACM1 --west-flash="--erase"
11+
```

scripts/pytest_plugins/plugin.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
#
3+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
4+
5+
"""Pytest plugin to share common fixtures among the tests."""
6+
7+
import os
8+
from pathlib import Path
9+
10+
import pytest
11+
from twister_harness.device.device_adapter import DeviceAdapter
12+
from twister_harness.fixtures import determine_scope
13+
14+
15+
@pytest.fixture(scope="session")
16+
def nrf_bm_path() -> Path:
17+
"""Return path to sdk-bm repository."""
18+
return Path(__file__).parents[2]
19+
20+
21+
@pytest.fixture(scope="session")
22+
def zephyr_base() -> Path:
23+
"""Return path to zephyr repository."""
24+
return Path(os.getenv("ZEPHYR_BASE", ""))
25+
26+
27+
@pytest.fixture(scope=determine_scope)
28+
def no_reset(device_object: DeviceAdapter):
29+
"""Do not reset after flashing."""
30+
device_object.device_config.west_flash_extra_args.append("--no-reset")
31+
yield
32+
device_object.device_config.west_flash_extra_args.remove("--no-reset")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
#
3+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
#
3+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
4+
5+
import logging
6+
import os
7+
import shlex
8+
import subprocess
9+
from pathlib import Path
10+
from typing import Literal
11+
12+
logger = logging.getLogger(__name__)
13+
14+
15+
def normalize_path(path: str) -> str:
16+
path = os.path.expanduser(os.path.expandvars(path))
17+
path = os.path.normpath(os.path.abspath(path))
18+
return path
19+
20+
21+
def run_command(command: list[str], timeout: int = 30) -> None:
22+
logger.info(f"CMD: {shlex.join(command)}")
23+
ret: subprocess.CompletedProcess = subprocess.run(
24+
command,
25+
text=True,
26+
stdout=subprocess.PIPE,
27+
stderr=subprocess.STDOUT,
28+
timeout=timeout,
29+
)
30+
if ret.returncode:
31+
logger.error(f"Failed command: {shlex.join(command)}")
32+
logger.info(ret.stdout)
33+
raise subprocess.CalledProcessError(ret.returncode, command)
34+
35+
36+
def reset_board(dev_id: str | None = None):
37+
"""Reset device."""
38+
command = ["nrfutil", "device", "reset"]
39+
if dev_id:
40+
command.extend(["--serial-number", dev_id])
41+
run_command(command)
42+
43+
44+
def erase_board(dev_id: str | None):
45+
"""Run nrfutil device erase command."""
46+
command = ["nrfutil", "device", "erase"]
47+
if dev_id:
48+
command.extend(["--serial-number", dev_id])
49+
run_command(command)
50+
51+
52+
def provision_keys_for_kmu(
53+
keys: list[str] | list[Path] | str | Path,
54+
*,
55+
keyname: Literal["UROT_PUBKEY", "BL_PUBKEY", "APP_PUBKEY"] = "BL_PUBKEY",
56+
policy: Literal["revokable", "lock", "lock-last"] | None = None,
57+
dev_id: str | None = None,
58+
):
59+
"""Upload keys with west provision command."""
60+
logger.info("Provision keys using west command.")
61+
command = ["west", "ncs-provision", "upload", "--keyname", keyname]
62+
if policy:
63+
command += ["--policy", policy]
64+
if dev_id:
65+
command += ["--dev-id", dev_id]
66+
if not isinstance(keys, list):
67+
keys = [keys]
68+
for key in keys:
69+
assert os.path.exists(key), f"Key file does not exist: {key}"
70+
command += ["--key", normalize_path(str(key))]
71+
72+
run_command(command)
73+
logger.info("Keys provisioned successfully")

tests/subsys/kmu/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# KMU tests
2+
3+
This directory contains test scenarios for Bare Metal KMU.
4+
5+
## Run tests
6+
7+
To run tests one must export PYTHONPATH with the path to `nrf-bm/scripts` directory,
8+
so all packages from that directory are available for Python (it is exported in `conftest.py`).
9+
10+
To run tests for `hello_for_kmu` with twister execute the example command:
11+
```sh
12+
$ZEPHYR_BASE/scripts/twister -T $ZEPHYR_BASE/../nrf-bm/tests/subsys/kmu/hello_for_kmu -p bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot --device-testing --device-serial /dev/ttyACM1 --west-flash="--erase"
13+
```
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
project(hello_for_kmu)
11+
12+
target_sources(app PRIVATE src/main.c)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
6+
CONFIG_LOG=y
7+
CONFIG_LOG_BACKEND_BM_UARTE=y
8+
9+
CONFIG_CLOCK_CONTROL=y
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <stdio.h>
8+
9+
int main(void)
10+
{
11+
printf("Hello World! %s\n", CONFIG_BOARD_TARGET);
12+
13+
return 0;
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
SB_CONFIG_BM_BOOTLOADER_MCUBOOT_SIGNATURE_USING_KMU=y

0 commit comments

Comments
 (0)