Add Phase 9C security hardening
Generate exact-hash SDK source overrides without modifying dependencies. Harden SSH allocation and algorithm policy, tighten web authentication cleanup, and add focused host contract tests and documentation.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
# Include after project(): IDF component targets and their final source lists exist.
|
||||
if(CMAKE_VERSION VERSION_LESS 3.18)
|
||||
message(FATAL_ERROR "Security overrides need CMake 3.18 source-property directory support")
|
||||
endif()
|
||||
|
||||
set(_sak_security_script "${CMAKE_CURRENT_LIST_DIR}/../tools/security_overrides.py")
|
||||
get_filename_component(_sak_security_script "${_sak_security_script}" REALPATH)
|
||||
if(NOT PYTHON)
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
set(_sak_security_python "${Python3_EXECUTABLE}")
|
||||
else()
|
||||
set(_sak_security_python "${PYTHON}")
|
||||
endif()
|
||||
idf_build_get_property(_sak_security_idf IDF_PATH)
|
||||
execute_process(
|
||||
COMMAND "${_sak_security_python}" "${_sak_security_script}"
|
||||
--idf-path "${_sak_security_idf}"
|
||||
--project-dir "${PROJECT_SOURCE_DIR}"
|
||||
--binary-dir "${CMAKE_BINARY_DIR}"
|
||||
RESULT_VARIABLE _sak_security_result
|
||||
OUTPUT_VARIABLE _sak_security_stdout
|
||||
ERROR_VARIABLE _sak_security_stderr
|
||||
)
|
||||
if(NOT _sak_security_result EQUAL 0)
|
||||
message(FATAL_ERROR "SDK security override generation failed:\n${_sak_security_stdout}${_sak_security_stderr}")
|
||||
endif()
|
||||
include("${CMAKE_BINARY_DIR}/security_overrides/manifest.cmake")
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
|
||||
"${_sak_security_script}" "${SAK_SECURITY_VERSION_HEADER}")
|
||||
|
||||
# Public extension point: the Python Entry registry supplies the mapping. This
|
||||
# function is backend-agnostic; a later pinned project/vendor source uses it too.
|
||||
function(sak_security_replace_source component original generated)
|
||||
idf_component_get_property(_target "${component}" COMPONENT_LIB)
|
||||
if(NOT TARGET "${_target}")
|
||||
message(FATAL_ERROR "Security override: missing component target ${component}")
|
||||
endif()
|
||||
get_target_property(_source_dir "${_target}" SOURCE_DIR)
|
||||
get_target_property(_sources "${_target}" SOURCES)
|
||||
get_filename_component(_expected "${original}" REALPATH)
|
||||
set(_matches 0)
|
||||
set(_replaced)
|
||||
foreach(_source IN LISTS _sources)
|
||||
if(_source MATCHES "\\$<")
|
||||
# An expression could hide an additional copy of the protected source.
|
||||
message(FATAL_ERROR "Security override: unaudited source expression in ${component}: ${_source}")
|
||||
endif()
|
||||
get_filename_component(_absolute "${_source}" ABSOLUTE BASE_DIR "${_source_dir}")
|
||||
get_filename_component(_absolute "${_absolute}" REALPATH)
|
||||
if(_absolute STREQUAL _expected)
|
||||
math(EXPR _matches "${_matches} + 1")
|
||||
|
||||
list(APPEND _replaced "${generated}")
|
||||
else()
|
||||
list(APPEND _replaced "${_source}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT _matches EQUAL 1)
|
||||
message(FATAL_ERROR "Security override: ${component} needs exactly one ${original}; found ${_matches}")
|
||||
endif()
|
||||
|
||||
# Target flags/includes/definitions are retained because the target is not
|
||||
# replaced. Preserve source-specific properties in the owning directory too.
|
||||
set(_properties COMPILE_FLAGS COMPILE_OPTIONS COMPILE_DEFINITIONS
|
||||
INCLUDE_DIRECTORIES OBJECT_DEPENDS OBJECT_OUTPUTS LANGUAGE
|
||||
SKIP_PRECOMPILE_HEADERS SKIP_UNITY_BUILD_INCLUSION
|
||||
SKIP_LINTING HEADER_FILE_ONLY)
|
||||
set(_configs DEBUG RELEASE RELWITHDEBINFO MINSIZEREL
|
||||
${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
|
||||
foreach(_config IN LISTS _configs)
|
||||
string(TOUPPER "${_config}" _config)
|
||||
list(APPEND _properties "COMPILE_DEFINITIONS_${_config}")
|
||||
endforeach()
|
||||
foreach(_property IN LISTS _properties)
|
||||
get_property(_is_set SOURCE "${_expected}" DIRECTORY "${_source_dir}"
|
||||
PROPERTY "${_property}" SET)
|
||||
if(_is_set)
|
||||
get_property(_value SOURCE "${_expected}" DIRECTORY "${_source_dir}"
|
||||
PROPERTY "${_property}")
|
||||
set_property(SOURCE "${generated}" DIRECTORY "${_source_dir}"
|
||||
PROPERTY "${_property}" "${_value}")
|
||||
endif()
|
||||
endforeach()
|
||||
get_filename_component(_original_dir "${original}" DIRECTORY)
|
||||
get_property(_includes SOURCE "${generated}" DIRECTORY "${_source_dir}"
|
||||
PROPERTY INCLUDE_DIRECTORIES)
|
||||
# Restore the implicit quoted-include search directory lost by relocating C.
|
||||
set_property(SOURCE "${generated}" DIRECTORY "${_source_dir}"
|
||||
PROPERTY INCLUDE_DIRECTORIES "${_original_dir};${_includes}")
|
||||
set_property(TARGET "${_target}" PROPERTY SOURCES "${_replaced}")
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
|
||||
"${original}" "${generated}")
|
||||
message(STATUS "Security override: ${component}: ${original} -> ${generated}")
|
||||
endfunction()
|
||||
|
||||
foreach(_sak_security_id IN LISTS SAK_SECURITY_OVERRIDE_IDS)
|
||||
sak_security_replace_source(
|
||||
"${SAK_SECURITY_${_sak_security_id}_COMPONENT}"
|
||||
"${SAK_SECURITY_${_sak_security_id}_ORIGINAL}"
|
||||
"${SAK_SECURITY_${_sak_security_id}_GENERATED}")
|
||||
endforeach()
|
||||
Reference in New Issue
Block a user