mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'change/secure_boot_signing_key_type_check' into 'master'
Validate secure boot signing key type at configure time See merge request espressif/esp-idf!49529
This commit is contained in:
@@ -76,6 +76,38 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
endif()
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
|
||||
# Re-run CMake if the signing key file changes, so the key type check below is re-evaluated
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${secure_boot_signing_key}")
|
||||
|
||||
# Check that the signing key type matches the selected app signing scheme,
|
||||
# as the signing step derives the signature type from the key itself.
|
||||
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
set(key_check_args --scheme rsa)
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
set(key_check_args --scheme ecdsa_v1)
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
|
||||
if(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
|
||||
set(key_check_args --scheme ecdsa_v2 --ecdsa-key-size 256)
|
||||
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS)
|
||||
set(key_check_args --scheme ecdsa_v2 --ecdsa-key-size 384)
|
||||
else()
|
||||
set(key_check_args --scheme ecdsa_v2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(key_check_args)
|
||||
idf_build_get_property(python PYTHON)
|
||||
execute_process(
|
||||
COMMAND ${python} "${CMAKE_CURRENT_LIST_DIR}/scripts/check_secure_boot_signing_key.py"
|
||||
${key_check_args} "${secure_boot_signing_key}"
|
||||
RESULT_VARIABLE key_check_result
|
||||
ERROR_VARIABLE key_check_error
|
||||
OUTPUT_QUIET)
|
||||
if(NOT key_check_result EQUAL 0)
|
||||
message(FATAL_ERROR "CONFIG_SECURE_BOOT_SIGNING_KEY check failed: ${key_check_error}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Check that the Secure Boot signing key matches the selected app signing
|
||||
# scheme. The signing step (espsecure sign-data) derives the signature type
|
||||
# from the key file itself, so a mismatching key would produce an image that
|
||||
# only fails signature verification at boot.
|
||||
#
|
||||
# Invoked at configure time from components/bootloader/project_include.cmake.
|
||||
# Exits non-zero with an explanatory message on a mismatch.
|
||||
import argparse
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||
|
||||
ECDSA_KEY_SIZE_TO_CURVE = {
|
||||
'256': 'secp256r1',
|
||||
'384': 'secp384r1',
|
||||
}
|
||||
|
||||
|
||||
def key_description(key: object) -> str:
|
||||
if isinstance(key, rsa.RSAPrivateKey):
|
||||
return f'an RSA {key.key_size}-bit key'
|
||||
if isinstance(key, ec.EllipticCurvePrivateKey):
|
||||
return f'an ECDSA key (curve {key.curve.name})'
|
||||
return f'a {type(key).__name__} key'
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Check that the secure boot signing key matches the selected app signing scheme'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--scheme',
|
||||
choices=['rsa', 'ecdsa_v1', 'ecdsa_v2'],
|
||||
required=True,
|
||||
help='App signing scheme selected in sdkconfig',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--ecdsa-key-size',
|
||||
choices=sorted(ECDSA_KEY_SIZE_TO_CURVE),
|
||||
default=None,
|
||||
help='ECDSA key size selected in sdkconfig (ECDSA V2 scheme only)',
|
||||
)
|
||||
parser.add_argument('key_file', help='Path to the secure boot signing key')
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
with open(args.key_file, 'rb') as f:
|
||||
key = load_pem_private_key(f.read(), password=None)
|
||||
except Exception:
|
||||
raise SystemExit(
|
||||
f'{args.key_file} could not be parsed as a PEM private key. '
|
||||
'Secure boot signing keys must be unencrypted PEM private keys.'
|
||||
)
|
||||
|
||||
if args.scheme == 'rsa':
|
||||
if not isinstance(key, rsa.RSAPrivateKey):
|
||||
raise SystemExit(
|
||||
f'{args.key_file} is {key_description(key)}, but the selected app signing scheme '
|
||||
'requires an RSA key. Update the App Signing Scheme choice or point '
|
||||
'CONFIG_SECURE_BOOT_SIGNING_KEY to a matching key.'
|
||||
)
|
||||
return
|
||||
|
||||
if args.scheme in ('ecdsa_v1', 'ecdsa_v2'):
|
||||
if not isinstance(key, ec.EllipticCurvePrivateKey):
|
||||
raise SystemExit(
|
||||
f'{args.key_file} is {key_description(key)}, but the selected app signing scheme '
|
||||
'requires an ECDSA key. Update the App Signing Scheme choice or point '
|
||||
'CONFIG_SECURE_BOOT_SIGNING_KEY to a matching key.'
|
||||
)
|
||||
|
||||
if args.scheme == 'ecdsa_v1':
|
||||
expected_curve = ECDSA_KEY_SIZE_TO_CURVE['256']
|
||||
else:
|
||||
expected_curve = ECDSA_KEY_SIZE_TO_CURVE.get(args.ecdsa_key_size or '', '')
|
||||
|
||||
if expected_curve and key.curve.name != expected_curve:
|
||||
raise SystemExit(
|
||||
f'{args.key_file} is {key_description(key)}, but the selected app signing scheme '
|
||||
f'requires curve {expected_curve}. Signature verification would fail at boot. '
|
||||
'Update the ECDSA key size choice or point CONFIG_SECURE_BOOT_SIGNING_KEY to '
|
||||
'a matching key.'
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user