1# Copyright (c) 2023 Nordic Semiconductor ASA
2#
3# SPDX-License-Identifier: Apache-2.0
4from __future__ import annotations
5
6import logging
7
8from pathlib import Path
9from twister_harness import DeviceAdapter, Shell, MCUmgr
10from utils import (
11    find_in_config,
12    match_lines,
13    match_no_lines,
14    check_with_shell_command,
15    check_with_mcumgr_command,
16)
17from test_upgrade import create_signed_image
18
19
20logger = logging.getLogger(__name__)
21
22
23def test_downgrade_prevention(dut: DeviceAdapter, shell: Shell, mcumgr: MCUmgr):
24    """
25    Verify that the application is not downgraded
26    1) Device flashed with MCUboot and an application that contains SMP server.
27       Image version is 1.1.1+1
28    2) Prepare an update of an application containing the SMP server, where
29       image version is 0.0.0 (lower than version of the original app)
30    3) Upload the application update to slot 1 using mcumgr
31    4) Flag the application update in slot 1 as 'pending' by using mcumgr 'test'
32    5) Restart the device, verify that downgrade prevention mechanism
33       blocked the image swap
34    6) Verify that the original application is booted (version 1.1.1)
35    """
36    origin_version = find_in_config(
37        Path(dut.device_config.app_build_dir) / 'zephyr' / '.config',
38        'CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION'
39    )
40    check_with_shell_command(shell, origin_version)
41    assert origin_version != '0.0.0+0'
42
43    logger.info('Prepare upgrade image with lower version')
44    image_to_test = create_signed_image(dut.device_config.build_dir,
45                                        dut.device_config.app_build_dir, '0.0.0+0')
46
47    logger.info('Upload image with mcumgr')
48    dut.disconnect()
49    mcumgr.image_upload(image_to_test)
50
51    logger.info('Test uploaded APP image')
52    second_hash = mcumgr.get_hash_to_test()
53    mcumgr.image_test(second_hash)
54    mcumgr.reset_device()
55
56    dut.connect()
57    output = dut.readlines_until('Launching primary slot application')
58    match_no_lines(output, ['Starting swap using move algorithm'])
59    match_lines(output, ['erased due to downgrade prevention'])
60    logger.info('Verify that the original APP is booted')
61    check_with_shell_command(shell, origin_version)
62    dut.disconnect()
63    check_with_mcumgr_command(mcumgr, origin_version)
64