From ef8ee8aedff5a642c0cf8e10997ad1bb373bf0a2 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 25 Mar 2024 10:27:06 +0200 Subject: [PATCH 1/5] feat(espefuse): Improves help for burn_efuse cmd Closes https://github.com/espressif/esp-idf/issues/13456 --- espefuse/efuse/base_operations.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/espefuse/efuse/base_operations.py b/espefuse/efuse/base_operations.py index d95b3095b..ccf7efe21 100644 --- a/espefuse/efuse/base_operations.py +++ b/espefuse/efuse/base_operations.py @@ -65,12 +65,11 @@ def check_efuse_name(efuse_name, efuse_list): ) burn.add_argument( "name_value_pairs", - help="Name of efuse register and New value pairs to burn", + help="Name of efuse field and new value pairs to burn. EFUSE_NAME: " + "[{}].".format(", ".join([e.name for e in efuses.efuses])), action=ActionEfuseValuePair, nargs="+", - metavar="[EFUSE_NAME VALUE] [{} VALUE".format( - " VALUE] [".join([e.name for e in efuses.efuses]) - ), + metavar="[EFUSE_NAME VALUE]", efuse_choices=[e.name for e in efuses.efuses] + [name for e in efuses.efuses for name in e.alt_names if name != ""], efuses=efuses, From 450db240a4986c630e4045bdfa0ed53ec332d012 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Fri, 29 Mar 2024 13:26:04 +0300 Subject: [PATCH 2/5] fix(espefuse): Fix burn_key for ECDSA_KEY, it can read pem file --- espefuse/efuse/esp32c5/operations.py | 11 +++++-- espefuse/efuse/esp32c5beta3/operations.py | 11 +++++-- espefuse/efuse/esp32c61/operations.py | 2 +- test/test_espefuse.py | 37 +++++++++++++++++------ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/espefuse/efuse/esp32c5/operations.py b/espefuse/efuse/esp32c5/operations.py index 76ac62ef5..1fca6bcb6 100644 --- a/espefuse/efuse/esp32c5/operations.py +++ b/espefuse/efuse/esp32c5/operations.py @@ -236,14 +236,21 @@ def burn_key(esp, efuses, args, digest=None): block = efuses.blocks[block_num] if digest is None: - data = datafile.read() + if keypurpose == "ECDSA_KEY": + sk = espsecure.load_ecdsa_signing_key(datafile) + data = sk.to_string() + if len(data) == 24: + # the private key is 24 bytes long for NIST192p, and 8 bytes of padding + data = b"\x00" * 8 + data + else: + data = datafile.read() else: data = datafile print(" - %s" % (efuse.name), end=" ") revers_msg = None if efuses[block.key_purpose_name].need_reverse(keypurpose): - revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" + revers_msg = f"\tReversing byte order for {keypurpose} hardware peripheral" data = data[::-1] print( "-> [{}]".format( diff --git a/espefuse/efuse/esp32c5beta3/operations.py b/espefuse/efuse/esp32c5beta3/operations.py index 2ee4c24b6..fbd721bd6 100644 --- a/espefuse/efuse/esp32c5beta3/operations.py +++ b/espefuse/efuse/esp32c5beta3/operations.py @@ -236,14 +236,21 @@ def burn_key(esp, efuses, args, digest=None): block = efuses.blocks[block_num] if digest is None: - data = datafile.read() + if keypurpose == "ECDSA_KEY": + sk = espsecure.load_ecdsa_signing_key(datafile) + data = sk.to_string() + if len(data) == 24: + # the private key is 24 bytes long for NIST192p, and 8 bytes of padding + data = b"\x00" * 8 + data + else: + data = datafile.read() else: data = datafile print(" - %s" % (efuse.name), end=" ") revers_msg = None if efuses[block.key_purpose_name].need_reverse(keypurpose): - revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" + revers_msg = f"\tReversing byte order for {keypurpose} hardware peripheral" data = data[::-1] print( "-> [{}]".format( diff --git a/espefuse/efuse/esp32c61/operations.py b/espefuse/efuse/esp32c61/operations.py index b678c2ac8..230656555 100644 --- a/espefuse/efuse/esp32c61/operations.py +++ b/espefuse/efuse/esp32c61/operations.py @@ -304,7 +304,7 @@ def burn_key(esp, efuses, args, digest=None): if digest is None: if keypurpose == "ECDSA_KEY": - sk = espsecure._load_ecdsa_signing_key(datafile) + sk = espsecure.load_ecdsa_signing_key(datafile) data = sk.to_string() if len(data) == 24: # the private key is 24 bytes long for NIST192p, and 8 bytes of padding diff --git a/test/test_espefuse.py b/test/test_espefuse.py index 5824ab56b..78ddffeef 100755 --- a/test/test_espefuse.py +++ b/test/test_espefuse.py @@ -902,6 +902,9 @@ def test_burn_key_one_key_block_with_fe_and_sb_keys(self): "esp32c6", "esp32h2", "esp32p4", + "esp32c5", + "esp32c5beta3", + "esp32c61", ], reason="Only chips with 6 keys", ) @@ -910,9 +913,13 @@ def test_burn_key_with_6_keys(self): BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_256_KEY_1 \ BLOCK_KEY1 {IMAGES_DIR}/256bit_1 XTS_AES_256_KEY_2 \ BLOCK_KEY2 {IMAGES_DIR}/256bit_2 XTS_AES_128_KEY" - if arg_chip in ["esp32c3", "esp32c6"] or arg_chip in [ + if arg_chip in [ + "esp32c3", + "esp32c6", "esp32h2", "esp32h2beta1", + "esp32c5", + "esp32c5beta3", ]: cmd = cmd.replace("XTS_AES_256_KEY_1", "XTS_AES_128_KEY") cmd = cmd.replace("XTS_AES_256_KEY_2", "XTS_AES_128_KEY") @@ -986,8 +993,8 @@ def test_burn_key_with_34_coding_scheme(self): self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_2") @pytest.mark.skipif( - arg_chip not in ["esp32s2", "esp32s3", "esp32p4"], - reason="512 bit keys are only supported on ESP32-S2, S3, and P4", + arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], + reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", ) def test_burn_key_512bit(self): self.espefuse_py( @@ -1004,8 +1011,8 @@ def test_burn_key_512bit(self): ) @pytest.mark.skipif( - arg_chip not in ["esp32s2", "esp32s3", "esp32p4"], - reason="512 bit keys are only supported on ESP32-S2, S3, and P4", + arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], + reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", ) def test_burn_key_512bit_non_consecutive_blocks(self): # Burn efuses separately to test different kinds @@ -1047,8 +1054,8 @@ def test_burn_key_512bit_non_consecutive_blocks(self): ) in output @pytest.mark.skipif( - arg_chip not in ["esp32s2", "esp32s3", "esp32p4"], - reason="512 bit keys are only supported on ESP32-S2, S3, and P4", + arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], + reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", ) def test_burn_key_512bit_non_consecutive_blocks_loop_around(self): self.espefuse_py( @@ -1080,7 +1087,7 @@ def test_burn_key_512bit_non_consecutive_blocks_loop_around(self): ) in output @pytest.mark.skipif( - arg_chip not in ["esp32h2", "esp32p4"], + arg_chip not in ["esp32h2", "esp32c5", "esp32c5beta3", "esp32c61", "esp32p4"], reason="These chips support ECDSA_KEY", ) def test_burn_key_ecdsa_key(self): @@ -1106,7 +1113,7 @@ def test_burn_key_ecdsa_key(self): ) in output @pytest.mark.skipif( - arg_chip not in ["esp32h2", "esp32p4"], + arg_chip not in ["esp32h2", "esp32c5", "esp32c5beta3", "esp32c61", "esp32p4"], reason="These chips support ECDSA_KEY", ) def test_burn_key_ecdsa_key_check_byte_order(self): @@ -1211,6 +1218,9 @@ def test_burn_block_data_with_1_key_block(self): "esp32c6", "esp32h2", "esp32p4", + "esp32c5", + "esp32c5beta3", + "esp32c61", ], reason="Only chip with 6 keys", ) @@ -1349,6 +1359,9 @@ def test_burn_block_data_with_offset_1_key_block(self): "esp32c6", "esp32h2", "esp32p4", + "esp32c5", + "esp32c5beta3", + "esp32c61", ], reason="Only chips with 6 keys", ) @@ -1545,6 +1558,9 @@ def test_burn_key_from_digest2(self): "esp32c6", "esp32h2", "esp32p4", + "esp32c5", + "esp32c5beta3", + "esp32c61", ], reason="Supports 6 key blocks", ) @@ -1657,6 +1673,9 @@ def test_burn_bit_for_chips_with_1_key_block(self): "esp32c6", "esp32h2", "esp32p4", + "esp32c5", + "esp32c5beta3", + "esp32c61", ], reason="Only chip with 6 keys", ) From 1505a253ef892df9642ce68b52b0195db479875e Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 4 Apr 2024 16:20:39 +0200 Subject: [PATCH 3/5] ci: Test with latest Python --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ee9e2795..bae1e5888 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -120,6 +120,19 @@ host_tests: # some .coverage files in sub-directories are not collected on some runners, move them first - find . -mindepth 2 -type f -name ".coverage*" -print -exec mv --backup=numbered {} . \; +host_tests_latest_python: + <<: *host_tests_template + image: python:3.12-bullseye + variables: + PYTEST_ADDOPTS: "-sv --junitxml=test/report.xml --color=yes" + script: + - pytest ${CI_PROJECT_DIR}/test/test_imagegen.py + - pytest ${CI_PROJECT_DIR}/test/test_espsecure.py + - pytest ${CI_PROJECT_DIR}/test/test_merge_bin.py + - pytest ${CI_PROJECT_DIR}/test/test_image_info.py + - pytest ${CI_PROJECT_DIR}/test/test_modules.py + - pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32 + # A new job "host_test_hsm" is created for the test "test_espsecure_hsm.py" which runs an ubuntu image, # because python-pkcs11 (v0.7.0) package is compiled using GLIBC_2.34 but docker image python:3.7-bullseye # support versions only upto GLIBC_2.31. From d2913680a44374ba23d70b60bf500eb3c80f7e1d Mon Sep 17 00:00:00 2001 From: Peter Dragun Date: Fri, 5 Apr 2024 09:40:22 +0200 Subject: [PATCH 4/5] ci: add mypy checks to pre-commit --- .mypy.ini | 13 +++++++++++++ .pre-commit-config.yaml | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 .mypy.ini diff --git a/.mypy.ini b/.mypy.ini new file mode 100644 index 000000000..d836b95ac --- /dev/null +++ b/.mypy.ini @@ -0,0 +1,13 @@ +[mypy] + # Disallows defining functions with incomplete type annotations + disallow_incomplete_defs = false + # Disallows defining functions without type annotations or with incomplete type annotations + disallow_untyped_defs = false + # Suppress error messages about imports that cannot be resolved + ignore_missing_imports = true + # Specifies the Python version used to parse and check the target program + python_version = 3.9 + # Shows errors for missing return statements on some execution paths + warn_no_return = true + # Shows a warning when returning a value with type Any from a function declared with a non- Any return type + warn_return_any = true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 464843542..d1286ad0a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,13 @@ repos: - id: sphinx-lint name: Lint RST files in docs folder using Sphinx Lint files: ^((docs/en)/.*\.(rst|inc))|CONTRIBUTING.rst$ + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.4.1 # the last version running on py3.7 + hooks: + - id: mypy + additional_dependencies: [types-all] + # ignore wrapper scripts because of name colision with efuse/__init__.py etc. + exclude: test/|docs/|espefuse.py|espsecure.py|esptool.py - repo: https://github.com/codespell-project/codespell rev: v2.2.5 hooks: From 55b338a92e443dfaacb63d7d5a2f2f8df35468b7 Mon Sep 17 00:00:00 2001 From: Peter Dragun Date: Fri, 5 Apr 2024 09:41:12 +0200 Subject: [PATCH 5/5] fix: fix type annotation to comply with mypy --- espefuse/efuse/base_fields.py | 5 +++-- espefuse/efuse/esp32c61/mem_definition.py | 3 ++- espefuse/efuse/esp32h2beta1/mem_definition.py | 3 ++- espefuse/efuse/esp32p4/mem_definition.py | 3 ++- espefuse/efuse/mem_definition_base.py | 9 +++++---- esptool/bin_image.py | 4 ++-- esptool/loader.py | 6 +++++- esptool/targets/esp32h2beta1.py | 4 +++- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/espefuse/efuse/base_fields.py b/espefuse/efuse/base_fields.py index 4cecd09d2..5dedd9f2b 100644 --- a/espefuse/efuse/base_fields.py +++ b/espefuse/efuse/base_fields.py @@ -12,6 +12,7 @@ import esptool from . import util +from typing import List class CheckArgValue(object): @@ -441,8 +442,8 @@ class EspEfusesBase(object): """ _esp = None - blocks = [] - efuses = [] + blocks: List[EfuseBlockBase] = [] + efuses: List = [] coding_scheme = None force_write_always = None batch_mode_cnt = 0 diff --git a/espefuse/efuse/esp32c61/mem_definition.py b/espefuse/efuse/esp32c61/mem_definition.py index be9279e3a..94b57b959 100644 --- a/espefuse/efuse/esp32c61/mem_definition.py +++ b/espefuse/efuse/esp32c61/mem_definition.py @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later import os +from typing import List import yaml @@ -119,7 +120,7 @@ def __init__(self) -> None: # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 self.BLOCK2_CALIBRATION_EFUSES = [] - self.CALC = [] + self.CALC: List = [] dir_name = os.path.dirname(os.path.abspath(__file__)) dir_name, file_name = os.path.split(dir_name) diff --git a/espefuse/efuse/esp32h2beta1/mem_definition.py b/espefuse/efuse/esp32h2beta1/mem_definition.py index ee2f00697..8c694306e 100644 --- a/espefuse/efuse/esp32h2beta1/mem_definition.py +++ b/espefuse/efuse/esp32h2beta1/mem_definition.py @@ -9,6 +9,7 @@ import yaml from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +from typing import List class EfuseDefineRegisters(EfuseRegistersBase): @@ -115,7 +116,7 @@ def __init__(self) -> None: # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 self.BLOCK2_CALIBRATION_EFUSES = [] - self.CALC = [] + self.CALC: List = [] dir_name = os.path.dirname(os.path.abspath(__file__)) dir_name, file_name = os.path.split(dir_name) diff --git a/espefuse/efuse/esp32p4/mem_definition.py b/espefuse/efuse/esp32p4/mem_definition.py index 73ab05e28..9d3d2a5b7 100644 --- a/espefuse/efuse/esp32p4/mem_definition.py +++ b/espefuse/efuse/esp32p4/mem_definition.py @@ -13,6 +13,7 @@ EfuseFieldsBase, EfuseRegistersBase, ) +from typing import List class EfuseDefineRegisters(EfuseRegistersBase): @@ -119,7 +120,7 @@ def __init__(self) -> None: # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 self.BLOCK2_CALIBRATION_EFUSES = [] - self.CALC = [] + self.CALC: List = [] dir_name = os.path.dirname(os.path.abspath(__file__)) dir_name, file_name = os.path.split(dir_name) diff --git a/espefuse/efuse/mem_definition_base.py b/espefuse/efuse/mem_definition_base.py index 21ae698b3..434b3a911 100644 --- a/espefuse/efuse/mem_definition_base.py +++ b/espefuse/efuse/mem_definition_base.py @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later from collections import namedtuple +from typing import Optional, List class EfuseRegistersBase(object): @@ -19,9 +20,9 @@ class EfuseRegistersBase(object): class EfuseBlocksBase(object): - BLOCKS = None + BLOCKS: Optional[List] = None NamedtupleBlock = namedtuple( - "Block", + "NamedtupleBlock", "name alias id rd_addr wr_addr write_disable_bit " "read_disable_bit len key_purpose", ) @@ -49,7 +50,7 @@ class Field: word = None pos = None bit_len = 0 - alt_names = [] + alt_names: List[str] = [] type = "" write_disable_bit = None read_disable_bit = None @@ -61,7 +62,7 @@ class Field: class EfuseFieldsBase(object): def __init__(self, e_desc) -> None: - self.ALL_EFUSES = [] + self.ALL_EFUSES: List = [] def set_category_and_class_type(efuse, name): def includes(name, names): diff --git a/esptool/bin_image.py b/esptool/bin_image.py index a54620200..2bef3b3d2 100644 --- a/esptool/bin_image.py +++ b/esptool/bin_image.py @@ -11,7 +11,7 @@ import re import struct import tempfile -from typing import BinaryIO, Optional +from typing import IO, Optional from intelhex import HexRecordError, IntelHex @@ -43,7 +43,7 @@ def align_file_position(f, size): f.seek(align, 1) -def intel_hex_to_bin(file: BinaryIO, start_addr: Optional[int] = None) -> BinaryIO: +def intel_hex_to_bin(file: IO[bytes], start_addr: Optional[int] = None) -> IO[bytes]: """Convert IntelHex file to temp binary file with padding from start_addr If hex file was detected return temp bin file object; input file otherwise""" INTEL_HEX_MAGIC = b":" diff --git a/esptool/loader.py b/esptool/loader.py index 55a941299..af4dc54af 100644 --- a/esptool/loader.py +++ b/esptool/loader.py @@ -13,6 +13,8 @@ import struct import sys import time +from typing import Optional + from .config import load_config_file from .reset import ( @@ -59,7 +61,7 @@ print( "The installed version (%s) of pyserial appears to be too old for esptool.py " "(Python interpreter %s). Check the README for installation instructions." - % (sys.VERSION, sys.executable) + % (serial.VERSION, sys.executable) ) raise except Exception: @@ -185,6 +187,8 @@ class ESPLoader(object): CHIP_NAME = "Espressif device" IS_STUB = False + STUB_CLASS: Optional[object] = None + BOOTLOADER_IMAGE: Optional[object] = None DEFAULT_PORT = "/dev/ttyUSB0" diff --git a/esptool/targets/esp32h2beta1.py b/esptool/targets/esp32h2beta1.py index 49e38e44a..117e5fb6b 100644 --- a/esptool/targets/esp32h2beta1.py +++ b/esptool/targets/esp32h2beta1.py @@ -8,6 +8,8 @@ from .esp32c3 import ESP32C3ROM from ..util import FatalError, NotImplementedInROMError +from typing import List + class ESP32H2BETA1ROM(ESP32C3ROM): CHIP_NAME = "ESP32-H2(beta1)" @@ -66,7 +68,7 @@ class ESP32H2BETA1ROM(ESP32C3ROM): FLASH_ENCRYPTED_WRITE_ALIGN = 16 - MEMORY_MAP = [] + MEMORY_MAP: List = [] FLASH_FREQUENCY = { "48m": 0xF,