1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-30 22:43:08 +03:00

Merge branch 'development' into development-restricted

This commit is contained in:
Waleed Elmelegy
2024-07-05 10:29:03 +01:00
349 changed files with 32722 additions and 15171 deletions

22
tests/.gitignore vendored
View File

@ -3,22 +3,26 @@
*.log
/test_suite*
data_files/mpi_write
data_files/hmac_drbg_seed
data_files/ctr_drbg_seed
data_files/entropy_seed
/data_files/mpi_write
/data_files/hmac_drbg_seed
/data_files/ctr_drbg_seed
/data_files/entropy_seed
include/alt-extra/psa/crypto_platform_alt.h
include/alt-extra/psa/crypto_struct_alt.h
include/test/instrument_record_status.h
/include/alt-extra/psa/crypto_platform_alt.h
/include/alt-extra/psa/crypto_struct_alt.h
/include/test/instrument_record_status.h
src/libmbed*
/src/libmbed*
libtestdriver1/*
/libtestdriver1/*
###START_GENERATED_FILES###
# Generated source files
/suites/*.generated.data
/suites/test_suite_config.mbedtls_boolean.data
/suites/test_suite_config.psa_boolean.data
/suites/test_suite_psa_crypto_storage_format.v[0-9]*.data
/suites/test_suite_psa_crypto_storage_format.current.data
/src/test_keys.h
/src/test_certs.h
###END_GENERATED_FILES###

View File

@ -21,7 +21,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/suites)
execute_process(
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
--list-for-cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/..
@ -33,7 +33,19 @@ string(REGEX REPLACE "[^;]*/" ""
execute_process(
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_config_tests.py
--list-for-cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/..
OUTPUT_VARIABLE
base_config_generated_data_files)
string(REGEX REPLACE "[^;]*/" ""
base_config_generated_data_files "${base_config_generated_data_files}")
execute_process(
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
--list-for-cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/..
@ -45,7 +57,7 @@ string(REGEX REPLACE "[^;]*/" ""
execute_process(
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
--list-for-cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/..
@ -61,11 +73,15 @@ set(base_generated_data_files
string(REGEX REPLACE "([^;]+)" "suites/\\1"
all_generated_data_files "${base_generated_data_files}")
set(bignum_generated_data_files "")
set(config_generated_data_files "")
set(ecp_generated_data_files "")
set(psa_generated_data_files "")
foreach(file ${base_bignum_generated_data_files})
list(APPEND bignum_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file})
endforeach()
foreach(file ${base_config_generated_data_files})
list(APPEND config_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file})
endforeach()
foreach(file ${base_ecp_generated_data_files})
list(APPEND ecp_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file})
endforeach()
@ -81,16 +97,31 @@ if(GEN_FILES)
${CMAKE_CURRENT_SOURCE_DIR}/..
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
--directory ${CMAKE_CURRENT_BINARY_DIR}/suites
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_core.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod_raw.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_common.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_core.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_mod_raw.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_mod.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
)
add_custom_command(
OUTPUT
${config_generated_data_files}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/..
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_config_tests.py
--directory ${CMAKE_CURRENT_BINARY_DIR}/suites
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_config_tests.py
# Do not declare the configuration files as dependencies: they
# change too often in ways that don't affect the result
# ((un)commenting some options).
)
add_custom_command(
OUTPUT
@ -99,14 +130,14 @@ if(GEN_FILES)
${CMAKE_CURRENT_SOURCE_DIR}/..
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
--directory ${CMAKE_CURRENT_BINARY_DIR}/suites
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/ecp.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_common.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/ecp.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
)
add_custom_command(
OUTPUT
@ -115,20 +146,20 @@ if(GEN_FILES)
${CMAKE_CURRENT_SOURCE_DIR}/..
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
--directory ${CMAKE_CURRENT_BINARY_DIR}/suites
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/crypto_data_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/crypto_knowledge.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/macro_collector.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/psa_information.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/psa_storage.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_config.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_values.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_extra.h
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/crypto_data_tests.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/crypto_knowledge.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/macro_collector.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/psa_information.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/psa_storage.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/include/psa/crypto_config.h
${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/include/psa/crypto_values.h
${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/include/psa/crypto_extra.h
)
else()
@ -142,6 +173,7 @@ endif()
# With this line, only 4 sub-makefiles include the above command, that reduces
# the risk of a race.
add_custom_target(test_suite_bignum_generated_data DEPENDS ${bignum_generated_data_files})
add_custom_target(test_suite_config_generated_data DEPENDS ${config_generated_data_files})
add_custom_target(test_suite_ecp_generated_data DEPENDS ${ecp_generated_data_files})
add_custom_target(test_suite_psa_generated_data DEPENDS ${psa_generated_data_files})
# If SKIP_TEST_SUITES is not defined with -D, get it from the environment.
@ -199,6 +231,10 @@ function(add_test_suite suite_name)
set(data_file
${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
set(dependency test_suite_bignum_generated_data)
elseif(";${config_generated_data_names};" MATCHES ";${data_name};")
set(data_file
${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
set(dependency test_suite_bignum_generated_data)
elseif(";${ecp_generated_data_names};" MATCHES ";${data_name};")
set(data_file
${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
@ -210,7 +246,11 @@ function(add_test_suite suite_name)
else()
set(data_file
${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data)
set(dependency test_suite_bignum_generated_data test_suite_ecp_generated_data test_suite_psa_generated_data)
set(dependency
test_suite_bignum_generated_data
test_suite_config_generated_data
test_suite_ecp_generated_data
test_suite_psa_generated_data)
endif()
add_custom_command(
@ -220,7 +260,7 @@ function(add_test_suite suite_name)
test_suite_${data_name}.c
COMMAND
${MBEDTLS_PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_test_code.py
-f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
-d ${data_file}
-t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
@ -229,7 +269,7 @@ function(add_test_suite suite_name)
--helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
-o .
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_test_code.py
${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
${data_file}
${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function

View File

@ -7,6 +7,7 @@ TEST_FLAGS ?= $(if $(filter-out 0 OFF Off off NO No no FALSE False false N n,$(C
# Also include library headers, for the sake of invasive tests.
LOCAL_CFLAGS += -I../library
# Enable definition of various functions used throughout the testsuite
# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
# on non-POSIX platforms.
@ -16,29 +17,46 @@ ifdef RECORD_PSA_STATUS_COVERAGE_LOG
LOCAL_CFLAGS += -Werror -DRECORD_PSA_STATUS_COVERAGE_LOG
endif
.PHONY: generated_files
GENERATED_BIGNUM_DATA_FILES := $(patsubst tests/%,%,$(shell \
$(PYTHON) scripts/generate_bignum_tests.py --list || \
$(PYTHON) ../framework/scripts/generate_bignum_tests.py --list || \
echo FAILED \
))
ifeq ($(GENERATED_BIGNUM_DATA_FILES),FAILED)
$(error "$(PYTHON) scripts/generate_bignum_tests.py --list" failed)
$(error "$(PYTHON) ../framework/scripts/generate_bignum_tests.py --list" failed)
endif
GENERATED_DATA_FILES += $(GENERATED_BIGNUM_DATA_FILES)
GENERATED_CONFIG_DATA_FILES := $(patsubst tests/%,%,$(shell \
$(PYTHON) ../framework/scripts/generate_config_tests.py --list || \
echo FAILED \
))
ifeq ($(GENERATED_CONFIG_DATA_FILES),FAILED)
$(error "$(PYTHON) ../framework/scripts/generate_config_tests.py --list" failed)
endif
GENERATED_DATA_FILES += $(GENERATED_CONFIG_DATA_FILES)
GENERATED_ECP_DATA_FILES := $(patsubst tests/%,%,$(shell \
$(PYTHON) scripts/generate_ecp_tests.py --list || \
$(PYTHON) ../framework/scripts/generate_ecp_tests.py --list || \
echo FAILED \
))
ifeq ($(GENERATED_ECP_DATA_FILES),FAILED)
$(error "$(PYTHON) scripts/generate_ecp_tests.py --list" failed)
$(error "$(PYTHON) ../framework/scripts/generate_ecp_tests.py --list" failed)
endif
GENERATED_DATA_FILES += $(GENERATED_ECP_DATA_FILES)
GENERATED_PSA_DATA_FILES := $(patsubst tests/%,%,$(shell \
$(PYTHON) scripts/generate_psa_tests.py --list || \
$(PYTHON) ../framework/scripts/generate_psa_tests.py --list || \
echo FAILED \
))
ifeq ($(GENERATED_PSA_DATA_FILES),FAILED)
$(error "$(PYTHON) scripts/generate_psa_tests.py --list" failed)
$(error "$(PYTHON) ../framework/scripts/generate_psa_tests.py --list" failed)
endif
GENERATED_FILES := $(GENERATED_PSA_DATA_FILES) $(GENERATED_ECP_DATA_FILES) $(GENERATED_BIGNUM_DATA_FILES)
GENERATED_DATA_FILES += $(GENERATED_PSA_DATA_FILES)
GENERATED_FILES = $(GENERATED_DATA_FILES)
GENERATED_FILES += src/test_keys.h src/test_certs.h
.PHONY: generated_files
generated_files: $(GENERATED_FILES)
# generate_bignum_tests.py and generate_psa_tests.py spend more time analyzing
@ -47,50 +65,68 @@ generated_files: $(GENERATED_FILES)
# It's rare not to want all the outputs. So always generate all of its outputs.
# Use an intermediate phony dependency so that parallel builds don't run
# a separate instance of the recipe for each output file.
.SECONDARY: generated_bignum_test_data generated_ecp_test_data generated_psa_test_data
$(GENERATED_BIGNUM_DATA_FILES): $(gen_file_dep) generated_bignum_test_data
generated_bignum_test_data: scripts/generate_bignum_tests.py
generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_common.py
generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_core.py
generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod_raw.py
generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod.py
generated_bignum_test_data: ../scripts/mbedtls_dev/test_case.py
generated_bignum_test_data: ../scripts/mbedtls_dev/test_data_generation.py
generated_bignum_test_data: ../framework/scripts/generate_bignum_tests.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_common.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_core.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_mod_raw.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_mod.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/test_case.py
generated_bignum_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
generated_bignum_test_data:
echo " Gen $(GENERATED_BIGNUM_DATA_FILES)"
$(PYTHON) scripts/generate_bignum_tests.py
$(PYTHON) ../framework/scripts/generate_bignum_tests.py
.SECONDARY: generated_bignum_test_data
# We deliberately omit the configuration files (mbedtls_config.h,
# crypto_config.h) from the depenency list because during development
# and on the CI, we often edit those in a way that doesn't change the
# output, to comment out certain options, or even to remove certain
# lines which do affect the output negatively (it will miss the
# corresponding test cases).
$(GENERATED_CONFIG_DATA_FILES): $(gen_file_dep) generated_config_test_data
generated_config_test_data: ../framework/scripts/generate_config_tests.py
generated_config_test_data: ../scripts/config.py
generated_config_test_data: ../framework/scripts/mbedtls_framework/test_case.py
generated_config_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
generated_config_test_data:
echo " Gen $(GENERATED_CONFIG_DATA_FILES)"
$(PYTHON) ../framework/scripts/generate_config_tests.py
.SECONDARY: generated_config_test_data
$(GENERATED_ECP_DATA_FILES): $(gen_file_dep) generated_ecp_test_data
generated_ecp_test_data: scripts/generate_ecp_tests.py
generated_ecp_test_data: ../scripts/mbedtls_dev/bignum_common.py
generated_ecp_test_data: ../scripts/mbedtls_dev/ecp.py
generated_ecp_test_data: ../scripts/mbedtls_dev/test_case.py
generated_ecp_test_data: ../scripts/mbedtls_dev/test_data_generation.py
generated_ecp_test_data: ../framework/scripts/generate_ecp_tests.py
generated_ecp_test_data: ../framework/scripts/mbedtls_framework/bignum_common.py
generated_ecp_test_data: ../framework/scripts/mbedtls_framework/ecp.py
generated_ecp_test_data: ../framework/scripts/mbedtls_framework/test_case.py
generated_ecp_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
generated_ecp_test_data:
echo " Gen $(GENERATED_ECP_DATA_FILES)"
$(PYTHON) scripts/generate_ecp_tests.py
$(PYTHON) ../framework/scripts/generate_ecp_tests.py
.SECONDARY: generated_ecp_test_data
$(GENERATED_PSA_DATA_FILES): $(gen_file_dep) generated_psa_test_data
generated_psa_test_data: scripts/generate_psa_tests.py
generated_psa_test_data: ../scripts/mbedtls_dev/crypto_data_tests.py
generated_psa_test_data: ../scripts/mbedtls_dev/crypto_knowledge.py
generated_psa_test_data: ../scripts/mbedtls_dev/macro_collector.py
generated_psa_test_data: ../scripts/mbedtls_dev/psa_information.py
generated_psa_test_data: ../scripts/mbedtls_dev/psa_storage.py
generated_psa_test_data: ../scripts/mbedtls_dev/test_case.py
generated_psa_test_data: ../scripts/mbedtls_dev/test_data_generation.py
generated_psa_test_data: ../framework/scripts/generate_psa_tests.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/crypto_data_tests.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/crypto_knowledge.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/macro_collector.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/psa_information.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/psa_storage.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/test_case.py
generated_psa_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
## The generated file only depends on the options that are present in
## crypto_config.h, not on which options are set. To avoid regenerating this
## file all the time when switching between configurations, don't declare
## crypto_config.h as a dependency. Remove this file from your working tree
## if you've just added or removed an option in crypto_config.h.
#generated_psa_test_data: ../include/psa/crypto_config.h
generated_psa_test_data: ../include/psa/crypto_values.h
generated_psa_test_data: ../include/psa/crypto_extra.h
#generated_psa_test_data: ../tf-psa-crypto/include/psa/crypto_config.h
generated_psa_test_data: ../tf-psa-crypto/include/psa/crypto_values.h
generated_psa_test_data: ../tf-psa-crypto/include/psa/crypto_extra.h
generated_psa_test_data: suites/test_suite_psa_crypto_metadata.data
generated_psa_test_data:
echo " Gen $(GENERATED_PSA_DATA_FILES) ..."
$(PYTHON) scripts/generate_psa_tests.py
$(PYTHON) ../framework/scripts/generate_psa_tests.py
.SECONDARY: generated_psa_test_data
# A test application is built for each suites/test_suite_*.data file.
# Application name is same as .data file's base name and can be
@ -98,7 +134,7 @@ generated_psa_test_data:
DATA_FILES := $(wildcard suites/test_suite_*.data)
# Make sure that generated data files are included even if they don't
# exist yet when the makefile is parsed.
DATA_FILES += $(filter-out $(DATA_FILES),$(GENERATED_FILES))
DATA_FILES += $(filter-out $(DATA_FILES),$(GENERATED_DATA_FILES))
APPS = $(basename $(subst suites/,,$(DATA_FILES)))
# Construct executable name by adding OS specific suffix $(EXEXT).
@ -112,6 +148,13 @@ all: $(BINARIES)
mbedtls_test: $(MBEDTLS_TEST_OBJS)
src/test_certs.h: ../framework/scripts/generate_test_cert_macros.py \
$($(PYTHON) ../framework/scripts/generate_test_cert_macros.py --list-dependencies)
$(PYTHON) ../framework/scripts/generate_test_cert_macros.py --output $@
src/test_keys.h: ../framework/scripts/generate_test_keys.py
$(PYTHON) ../framework/scripts/generate_test_keys.py --output $@
TEST_OBJS_DEPS = $(wildcard include/test/*.h include/test/*/*.h)
ifdef RECORD_PSA_STATUS_COVERAGE_LOG
# Explicitly depend on this header because on a clean copy of the source tree,
@ -119,6 +162,7 @@ ifdef RECORD_PSA_STATUS_COVERAGE_LOG
# therefore the wildcard enumeration above doesn't include it.
TEST_OBJS_DEPS += include/test/instrument_record_status.h
endif
TEST_OBJS_DEPS += src/test_certs.h src/test_keys.h
# Rule to compile common test C files in src folder
src/%.o : src/%.c $(TEST_OBJS_DEPS)
@ -151,9 +195,9 @@ c: $(C_FILES)
# dot in .c file's base name.
#
.SECONDEXPANSION:
%.c: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/host_test.function
%.c: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data ../framework/scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/host_test.function
echo " Gen $@"
$(PYTHON) scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
$(PYTHON) ../framework/scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
-d suites/$*.data \
-t suites/main_test.function \
-p suites/host_test.function \
@ -168,11 +212,14 @@ $(BINARIES): %$(EXEXT): %.c $(MBEDLIBS) $(TEST_OBJS_DEPS) $(MBEDTLS_TEST_OBJS)
clean:
ifndef WINDOWS
$(MAKE) -C psa-client-server/psasim clean
rm -rf $(BINARIES) *.c *.datax
rm -f src/*.o src/drivers/*.o src/test_helpers/*.o src/libmbed*
rm -f src/*.o src/drivers/*.o src/test_helpers/*.o src/libmbed* src/test_keys.h src/test_certs.h
rm -f src/test_keys.h src/test_certs.h
rm -f include/test/instrument_record_status.h
rm -f include/alt-extra/*/*_alt.h
rm -rf libtestdriver1
rm -rf libpsaclient libpsaserver
rm -f ../library/libtestdriver1.a
else
if exist *.c del /Q /F *.c
@ -180,6 +227,8 @@ else
if exist *.datax del /Q /F *.datax
if exist src/*.o del /Q /F src/*.o
if exist src/drivers/*.o del /Q /F src/drivers/*.o
if exist src/test_keys.h del /Q /F src/test_keys.h
if exist src/test_certs.h del /Q /F src/test_cers.h
if exist src/test_helpers/*.o del /Q /F src/test_helpers/*.o
if exist src/libmbed* del /Q /F src/libmed*
if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
@ -194,6 +243,10 @@ test: check
# Generate variants of some headers for testing
include/alt-extra/%_alt.h: ../include/%.h
perl -p -e 's/^(# *(define|ifndef) +\w+_)H\b/$${1}ALT_H/' $< >$@
include/alt-extra/%_alt.h: ../tf-psa-crypto/include/%.h
perl -p -e 's/^(# *(define|ifndef) +\w+_)H\b/$${1}ALT_H/' $< >$@
include/alt-extra/%_alt.h: ../tf-psa-crypto/drivers/builtin/include/%.h
perl -p -e 's/^(# *(define|ifndef) +\w+_)H\b/$${1}ALT_H/' $< >$@
# Generate test library
@ -202,7 +255,14 @@ include/alt-extra/%_alt.h: ../include/%.h
# library. Add a LIBTESTDRIVER1_/libtestdriver1_ to mbedtls_xxx and psa_xxx
# symbols.
define libtestdriver1_rewrite :=
s!^(\s*#\s*include\s*[\"<])(mbedtls|psa)/!$${1}libtestdriver1/include/$${2}/!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/build_info.h!$${1}libtestdriver1/include/mbedtls/build_info.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/mbedtls_config.h!$${1}libtestdriver1/include/mbedtls/mbedtls_config.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/config_adjust_legacy_crypto.h!$${1}libtestdriver1/include/mbedtls/config_adjust_legacy_crypto.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/config_adjust_x509.h!$${1}libtestdriver1/include/mbedtls/config_adjust_x509.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/config_adjust_ssl.h!$${1}libtestdriver1/include/mbedtls/config_adjust_ssl.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/check_config.h!$${1}libtestdriver1/include/mbedtls/check_config.h!; \
s!^(\s*#\s*include\s*[\"<])mbedtls/!$${1}libtestdriver1/tf-psa-crypto/drivers/builtin/include/mbedtls/!; \
s!^(\s*#\s*include\s*[\"<])psa/!$${1}libtestdriver1/tf-psa-crypto/include/psa/!; \
next if /^\s*#\s*include/; \
s/\b(?=MBEDTLS_|PSA_)/LIBTESTDRIVER1_/g; \
s/\b(?=mbedtls_|psa_)/libtestdriver1_/g;
@ -215,6 +275,7 @@ libtestdriver1.a:
mkdir ./libtestdriver1
cp -Rf ../library ./libtestdriver1
cp -Rf ../include ./libtestdriver1
cp -Rf ../tf-psa-crypto ./libtestdriver1
cp -Rf ../scripts ./libtestdriver1
mkdir ./libtestdriver1/3rdparty
touch ./libtestdriver1/3rdparty/Makefile.inc
@ -227,22 +288,24 @@ libtestdriver1.a:
# library the test library is intended to be linked with extended by
# ./include/test/drivers/crypto_config_test_driver_extension.h to
# mirror the PSA_ACCEL_* macros.
mv ./libtestdriver1/include/psa/crypto_config.h ./libtestdriver1/include/psa/crypto_config.h.bak
head -n -1 ./libtestdriver1/include/psa/crypto_config.h.bak > ./libtestdriver1/include/psa/crypto_config.h
cat ./include/test/drivers/crypto_config_test_driver_extension.h >> ./libtestdriver1/include/psa/crypto_config.h
echo "#endif /* PSA_CRYPTO_CONFIG_H */" >> ./libtestdriver1/include/psa/crypto_config.h
mv ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h.bak
head -n -1 ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h.bak > ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h
cat ./include/test/drivers/crypto_config_test_driver_extension.h >> ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h
echo "#endif /* PSA_CRYPTO_CONFIG_H */" >> ./libtestdriver1/tf-psa-crypto/include/psa/crypto_config.h
# Prefix MBEDTLS_* PSA_* symbols with LIBTESTDRIVER1_ as well as
# mbedtls_* psa_* symbols with libtestdriver1_ to avoid symbol clash
# when this test driver library is linked with the Mbed TLS library.
perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/library/*.[ch]
perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/include/*/*.h
perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/tf-psa-crypto/include/*/*.h
perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/tf-psa-crypto/drivers/builtin/include/*/*.h
$(MAKE) -C ./libtestdriver1/library CFLAGS="-I../../ $(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a
cp ./libtestdriver1/library/libmbedcrypto.a ../library/libtestdriver1.a
ifdef RECORD_PSA_STATUS_COVERAGE_LOG
include/test/instrument_record_status.h: ../include/psa/crypto.h Makefile
include/test/instrument_record_status.h: ../tf-psa-crypto/include/psa/crypto.h Makefile
echo " Gen $@"
sed <../include/psa/crypto.h >$@ -n 's/^psa_status_t \([A-Za-z0-9_]*\)(.*/#define \1(...) RECORD_STATUS("\1", \1(__VA_ARGS__))/p'
sed <../tf-psa-crypto/include/psa/crypto.h >$@ -n 's/^psa_status_t \([A-Za-z0-9_]*\)(.*/#define \1(...) RECORD_STATUS("\1", \1(__VA_ARGS__))/p'
endif

View File

@ -96,6 +96,7 @@ FILTER=""
EXCLUDE='NULL\|ARIA\|CHACHA20_POLY1305'
VERBOSE=""
MEMCHECK=0
MIN_TESTS=1
PRESERVE_LOGS=0
PEERS="OpenSSL$PEER_GNUTLS mbedTLS"
@ -116,6 +117,7 @@ print_usage() {
printf " -M|--memcheck\tCheck memory leaks and errors.\n"
printf " -v|--verbose\tSet verbose output.\n"
printf " --list-test-cases\tList all potential test cases (No Execution)\n"
printf " --min \tMinimum number of non-skipped tests (default 1)\n"
printf " --outcome-file\tFile where test outcomes are written\n"
printf " \t(default: \$MBEDTLS_TEST_OUTCOME_FILE, none if empty)\n"
printf " --preserve-logs\tPreserve logs of successful tests as well\n"
@ -190,6 +192,9 @@ get_options() {
list_test_cases
exit $?
;;
--min)
shift; MIN_TESTS=$1
;;
--outcome-file)
shift; MBEDTLS_TEST_OUTCOME_FILE=$1
;;
@ -588,7 +593,18 @@ add_mbedtls_ciphersuites()
# o_check_ciphersuite STANDARD_CIPHER_SUITE
o_check_ciphersuite()
{
if [ "${O_SUPPORT_ECDH}" = "NO" ]; then
# skip DTLS when lack of support was declared
if test "$OSSL_NO_DTLS" -gt 0 && is_dtls "$MODE"; then
SKIP_NEXT_="YES"
fi
# skip DTLS 1.2 is support was not detected
if [ "$O_SUPPORT_DTLS12" = "NO" -a "$MODE" = "dtls12" ]; then
SKIP_NEXT="YES"
fi
# skip static ECDH when OpenSSL doesn't support it
if [ "${O_SUPPORT_STATIC_ECDH}" = "NO" ]; then
case "$1" in
*ECDH_*) SKIP_NEXT="YES"
esac
@ -665,10 +681,25 @@ setup_arguments()
esac
case $($OPENSSL ciphers ALL) in
*ECDH-ECDSA*|*ECDH-RSA*) O_SUPPORT_ECDH="YES";;
*) O_SUPPORT_ECDH="NO";;
*ECDH-ECDSA*|*ECDH-RSA*) O_SUPPORT_STATIC_ECDH="YES";;
*) O_SUPPORT_STATIC_ECDH="NO";;
esac
case $($OPENSSL ciphers ALL) in
*DES-CBC-*) O_SUPPORT_SINGLE_DES="YES";;
*) O_SUPPORT_SINGLE_DES="NO";;
esac
# OpenSSL <1.0.2 doesn't support DTLS 1.2. Check if OpenSSL
# supports -dtls1_2 from the s_server help. (The s_client
# help isn't accurate as of 1.0.2g: it supports DTLS 1.2
# but doesn't list it. But the s_server help seems to be
# accurate.)
O_SUPPORT_DTLS12="NO"
if $OPENSSL s_server -help 2>&1 | grep -q "^ *-dtls1_2 "; then
O_SUPPORT_DTLS12="YES"
fi
if [ "X$VERIFY" = "XYES" ];
then
M_SERVER_ARGS="$M_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required"
@ -1109,19 +1140,6 @@ for MODE in $MODES; do
[Oo]pen*)
if test "$OSSL_NO_DTLS" -gt 0 && is_dtls "$MODE"; then
continue;
fi
# OpenSSL <1.0.2 doesn't support DTLS 1.2. Check if OpenSSL
# supports $O_MODE from the s_server help. (The s_client
# help isn't accurate as of 1.0.2g: it supports DTLS 1.2
# but doesn't list it. But the s_server help seems to be
# accurate.)
if ! $OPENSSL s_server -help 2>&1 | grep -q "^ *-$O_MODE "; then
continue;
fi
reset_ciphersuites
add_common_ciphersuites
add_openssl_ciphersuites
@ -1225,6 +1243,16 @@ fi
PASSED=$(( $TESTS - $FAILED ))
echo " ($PASSED / $TESTS tests ($SKIPPED skipped$MEMREPORT))"
if [ $((TESTS - SKIPPED)) -lt $MIN_TESTS ]; then
cat <<EOF
Error: Expected to run at least $MIN_TESTS, but only ran $((TESTS - SKIPPED)).
Maybe a bad filter ('$FILTER' excluding '$EXCLUDE') or a bad configuration?
EOF
if [ $FAILED -eq 0 ]; then
FAILED=1
fi
fi
FAILED=$(( $FAILED + $SRVMEM ))
if [ $FAILED -gt 255 ]; then
# Clamp at 255 as caller gets exit code & 0xFF

View File

@ -37,24 +37,61 @@
#endif
/* Use the accelerator driver for all cryptographic mechanisms for which
* the test driver implemented. */
* the test driver is implemented. This is copied from psa/crypto_config.h
* with the parts not implemented by the test driver commented out. */
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DERIVE
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_PASSWORD
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_PASSWORD_HASH
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_HMAC
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DES
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR
//#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RAW_DATA
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY
#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
#define MBEDTLS_PSA_ACCEL_ALG_CTR
#define MBEDTLS_PSA_ACCEL_ALG_CCM
#define MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG
#define MBEDTLS_PSA_ACCEL_ALG_CMAC
#define MBEDTLS_PSA_ACCEL_ALG_CFB
#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
#define MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305
#define MBEDTLS_PSA_ACCEL_ALG_CTR
#define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA
#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING
#define MBEDTLS_PSA_ACCEL_ALG_ECDH
#define MBEDTLS_PSA_ACCEL_ALG_FFDH
#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
#define MBEDTLS_PSA_ACCEL_ALG_JPAKE
#define MBEDTLS_PSA_ACCEL_ALG_GCM
//#define MBEDTLS_PSA_ACCEL_ALG_HKDF
//#define MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT
//#define MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND
#define MBEDTLS_PSA_ACCEL_ALG_HMAC
#define MBEDTLS_PSA_ACCEL_ALG_MD5
#define MBEDTLS_PSA_ACCEL_ALG_OFB
//#define MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC
//#define MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128
#define MBEDTLS_PSA_ACCEL_ALG_RIPEMD160
#define MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP
#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT
#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN
#define MBEDTLS_PSA_ACCEL_ALG_RSA_PSS
#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
@ -62,9 +99,14 @@
#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
#define MBEDTLS_PSA_ACCEL_ALG_SHA_384
#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
#define MBEDTLS_PSA_ACCEL_ALG_XTS
#define MBEDTLS_PSA_ACCEL_ALG_CMAC
#define MBEDTLS_PSA_ACCEL_ALG_HMAC
#define MBEDTLS_PSA_ACCEL_ALG_SHA3_224
#define MBEDTLS_PSA_ACCEL_ALG_SHA3_256
#define MBEDTLS_PSA_ACCEL_ALG_SHA3_384
#define MBEDTLS_PSA_ACCEL_ALG_SHA3_512
#define MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER
//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF
//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS
//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS
#endif /* PSA_CRYPTO_DRIVER_TEST_ALL */

View File

@ -706,17 +706,43 @@ keys_rsa_basic_pwd = testkey
### Password used for PKCS8-encoded encrypted RSA keys
keys_rsa_pkcs8_pwd = PolarSSLTest
### Basic 1024-, 2048- and 4096-bit unencrypted RSA keys from which
### Basic unencrypted RSA keys from which
### all other encrypted RSA keys are derived.
keys_rsa_base =
### TODO: the commands require OpenSSL 1.x to work as desired. With
### OpenSSL 3.x, they produce pkcs8 files.
rsa_pkcs1_768_clear.pem:
$(OPENSSL) genrsa -out $@ 768
keys_rsa_base += rsa_pkcs1_768_clear.pem
rsa_pkcs1_769_clear.pem:
$(OPENSSL) genrsa -out $@ 769
keys_rsa_base += rsa_pkcs1_769_clear.pem
rsa_pkcs1_770_clear.pem:
$(OPENSSL) genrsa -out $@ 770
keys_rsa_base += rsa_pkcs1_770_clear.pem
rsa_pkcs1_776_clear.pem:
$(OPENSSL) genrsa -out $@ 776
keys_rsa_base += rsa_pkcs1_776_clear.pem
rsa_pkcs1_784_clear.pem:
$(OPENSSL) genrsa -out $@ 784
keys_rsa_base += rsa_pkcs1_784_clear.pem
rsa_pkcs1_1024_clear.pem:
$(OPENSSL) genrsa -out $@ 1024
all_final += rsa_pkcs1_1024_clear.pem
keys_rsa_base += rsa_pkcs1_1024_clear.pem
rsa_pkcs1_2048_clear.pem:
$(OPENSSL) genrsa -out $@ 2048
all_final += rsa_pkcs1_2048_clear.pem
keys_rsa_base += rsa_pkcs1_2048_clear.pem
rsa_pkcs1_4096_clear.pem:
$(OPENSSL) genrsa -out $@ 4096
all_final += rsa_pkcs1_4096_clear.pem
keys_rsa_base += rsa_pkcs1_4096_clear.pem
all_final += $(keys_rsa_base)
### PKCS1-encoded, plaintext RSA keys in derived forms
rsa_pkcs1_%.der: rsa_pkcs1_%.pem
$(OPENSSL) pkey -inform PEM -in $< -outform DER -out $@
all_final += $(keys_rsa_base:.pem=.der)
###
### PKCS1-encoded, encrypted RSA keys
@ -1170,8 +1196,8 @@ keys_rsa_enc_pkcs8_v2_4096_sha512: keys_rsa_enc_pkcs8_v2_4096_3des_sha512 keys_r
### Rules to generate all RSA keys from a particular class
###
### Generate basic unencrypted RSA keys
keys_rsa_unenc: rsa_pkcs1_1024_clear.pem rsa_pkcs1_2048_clear.pem rsa_pkcs1_4096_clear.pem
### Generate cleartext RSA keys in derived formats
keys_rsa_cleartext: $(keys_rsa_base) $(keys_rsa_base:.pem=.der)
### Generate PKCS1-encoded encrypted RSA keys
keys_rsa_enc_basic: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
@ -1183,7 +1209,8 @@ keys_rsa_enc_pkcs8_v1: keys_rsa_enc_pkcs8_v1_1024 keys_rsa_enc_pkcs8_v1_2048 key
keys_rsa_enc_pkcs8_v2: keys_rsa_enc_pkcs8_v2_1024 keys_rsa_enc_pkcs8_v2_2048 keys_rsa_enc_pkcs8_v2_4096 keys_rsa_enc_pkcs8_v2_1024_sha224 keys_rsa_enc_pkcs8_v2_2048_sha224 keys_rsa_enc_pkcs8_v2_4096_sha224 keys_rsa_enc_pkcs8_v2_1024_sha256 keys_rsa_enc_pkcs8_v2_2048_sha256 keys_rsa_enc_pkcs8_v2_4096_sha256 keys_rsa_enc_pkcs8_v2_1024_sha384 keys_rsa_enc_pkcs8_v2_2048_sha384 keys_rsa_enc_pkcs8_v2_4096_sha384 keys_rsa_enc_pkcs8_v2_1024_sha512 keys_rsa_enc_pkcs8_v2_2048_sha512 keys_rsa_enc_pkcs8_v2_4096_sha512
### Generate all RSA keys
keys_rsa_all: keys_rsa_unenc keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
keys_rsa_all: keys_rsa_base keys_rsa_cleartext
keys_rsa_all: keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
################################################################
#### Generate various EC keys
@ -1765,6 +1792,22 @@ server2-sha256.crt: server2.req.sha256
$(MBEDTLS_CERT_WRITE) request_file=server2.req.sha256 serial=2 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) not_before=20190210144406 not_after=20290210144406 md=SHA256 version=3 output_file=$@
all_final += server2-sha256.crt
server2-sha256.ku-ka.crt: SERVER2_CRT_SERIAL=22
server2-sha256.ku-ka.crt: SERVER2_KEY_USAGE=key_agreement
server2-sha256.ku-ke.crt: SERVER2_CRT_SERIAL=23
server2-sha256.ku-ke.crt: SERVER2_KEY_USAGE=key_encipherment
server2-sha256.ku-ds.crt: SERVER2_CRT_SERIAL=24
server2-sha256.ku-ds.crt: SERVER2_KEY_USAGE=digital_signature
server2-sha256.ku-ds_ke.crt: SERVER2_CRT_SERIAL=28
server2-sha256.ku-ds_ke.crt: SERVER2_KEY_USAGE=digital_signature,key_encipherment
server2-sha256.ku-%.crt: server2.req.sha256
$(MBEDTLS_CERT_WRITE) request_file=server2.req.sha256 serial=$(SERVER2_CRT_SERIAL) \
issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) \
key_usage="$(SERVER2_KEY_USAGE)" \
not_before=20190210144406 not_after=20290210144406 md=SHA256 version=3 output_file=$@
all_final += server2-sha256.ku-ka.crt server2-sha256.ku-ke.crt server2-sha256.ku-ds.crt server2-sha256.ku-ds_ke.crt
all_final += server2.ku-ka.crt server2.ku-ke.crt server2.ku-ds.crt server2.ku-ds_ke.crt
server2.ku-ka.crt: SERVER2_CRT_SERIAL=42
server2.ku-ka.crt: SERVER2_KEY_USAGE=key_agreement
server2.ku-ke.crt: SERVER2_CRT_SERIAL=43
@ -2075,72 +2118,6 @@ all_final += server2-v1.crt
server2-v1-chain.crt: server2-v1.crt server1-v1.crt
cat $^ > $@
################################################################
#### Generate C format test certs header
################################################################
TEST_CERTS_H_INPUT_FILES=test-ca2.crt \
test-ca2.crt.der \
test-ca2.key.enc \
test-ca2.key.der \
test-ca-sha256.crt \
test-ca-sha256.crt.der \
test-ca-sha1.crt \
test-ca-sha1.crt.der \
test-ca.key \
test-ca.key.der \
server5.crt \
server5.crt.der \
server5.key \
server5.key.der \
server2-sha256.crt \
server2-sha256.crt.der \
server2.crt \
server2.crt.der \
server2.key \
server2.key.der \
cli2.crt \
cli2.crt.der \
cli2.key \
cli2.key.der \
cli-rsa-sha256.crt \
cli-rsa-sha256.crt.der \
cli-rsa.key \
cli-rsa.key.der
../src/test_certs.h: ../scripts/generate_test_cert_macros.py \
$(TEST_CERTS_H_INPUT_FILES)
../scripts/generate_test_cert_macros.py --output $@ \
--string TEST_CA_CRT_EC_PEM=test-ca2.crt \
--binary TEST_CA_CRT_EC_DER=test-ca2.crt.der \
--string TEST_CA_KEY_EC_PEM=test-ca2.key.enc \
--password TEST_CA_PWD_EC_PEM=PolarSSLTest \
--binary TEST_CA_KEY_EC_DER=test-ca2.key.der \
--string TEST_CA_CRT_RSA_SHA256_PEM=test-ca-sha256.crt \
--binary TEST_CA_CRT_RSA_SHA256_DER=test-ca-sha256.crt.der \
--string TEST_CA_CRT_RSA_SHA1_PEM=test-ca-sha1.crt \
--binary TEST_CA_CRT_RSA_SHA1_DER=test-ca-sha1.crt.der \
--string TEST_CA_KEY_RSA_PEM=test-ca.key \
--password TEST_CA_PWD_RSA_PEM=PolarSSLTest \
--binary TEST_CA_KEY_RSA_DER=test-ca.key.der \
--string TEST_SRV_CRT_EC_PEM=server5.crt \
--binary TEST_SRV_CRT_EC_DER=server5.crt.der \
--string TEST_SRV_KEY_EC_PEM=server5.key \
--binary TEST_SRV_KEY_EC_DER=server5.key.der \
--string TEST_SRV_CRT_RSA_SHA256_PEM=server2-sha256.crt \
--binary TEST_SRV_CRT_RSA_SHA256_DER=server2-sha256.crt.der \
--string TEST_SRV_CRT_RSA_SHA1_PEM=server2.crt \
--binary TEST_SRV_CRT_RSA_SHA1_DER=server2.crt.der \
--string TEST_SRV_KEY_RSA_PEM=server2.key \
--binary TEST_SRV_KEY_RSA_DER=server2.key.der \
--string TEST_CLI_CRT_EC_PEM=cli2.crt \
--binary TEST_CLI_CRT_EC_DER=cli2.crt.der \
--string TEST_CLI_KEY_EC_PEM=cli2.key \
--binary TEST_CLI_KEY_EC_DER=cli2.key.der \
--string TEST_CLI_CRT_RSA_PEM=cli-rsa-sha256.crt \
--binary TEST_CLI_CRT_RSA_DER=cli-rsa-sha256.crt.der \
--string TEST_CLI_KEY_RSA_PEM=cli-rsa.key \
--binary TEST_CLI_KEY_RSA_DER=cli-rsa.key.der
################################################################
#### Diffie-Hellman parameters
################################################################
@ -2161,7 +2138,7 @@ all: $(all_intermediate) $(all_final)
.PHONY: default all_final all
.PHONY: keys_rsa_all
.PHONY: keys_rsa_unenc keys_rsa_enc_basic
.PHONY: keys_rsa_enc_basic
.PHONY: keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
.PHONY: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
.PHONY: keys_rsa_enc_pkcs8_v1_1024 keys_rsa_enc_pkcs8_v2_1024

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBywIBAAJhANmJY6FPDF0oqQEJCSrTx+ezfCU8qB6NwF2SqrphhhRFCYaMiKeg
bRVB4pCxjGrDM2iuwlMy2QqJo4TST4MgMbK44fG7fHip+IhD/lJAfSsL56ZKz3T9
tlog4VFGynJL1wIDAQABAmEAjB02Etw7dnWOBaCwSumFxPOSbtmW37clxB+H3+yY
081zyToTewSVvi9loxT5AHshHYt2P+c6ylbUUEV6ZhC3mDqYMcuQmX5pJ2MhaK4T
cCihi9eBhROPzudJ27Jx84wBAjEA9CKkG30d9+PgbUp+KnMxZuavEG4U45EDEUOG
5+MRgSnRlPz8JsiY+Q6ReeBaEZiBAjEA5BvToGaPFSkbFT1HiV4zEEDQoXrNUO/l
vAP6p7fCLh2nnaIRIwuHwxTUhG8pe3hXAjEAzKJAtj3gockjc9ht+n0F2r/f28C5
x6nkTVMxwCsHoCGCaATKAmRAPPrmG6dfN8KBAjAcwNkzPdpJW44bZkcPLL2ZDeJ+
iGE7E5JM2d+Npp8mevx25Uftt/VcBNMpAm4jLy8CMHCcVdhdVFydsL8DSYRnWD8x
1tn1npbAeyiMHBxyhDF9EP1me7rEHvJ4Wl61HSXQNA==
-----END RSA PRIVATE KEY-----

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBzAIBAAJhAbUzqda7ne4UGzC60NkNAXxewl/l7X5W1scvWQVKbshsSQoHcOPj
12RmuuA2sR6MzTNxBxsb52HNbrlqZYN5L07uanwM2bio5xl1SFXN2p3hzE2EHlM1
nBq0sSXbX4Ua+QIDAQABAmEA1RgMVPx3Wp50LkkwGErtiXgKV4GTQzwCTW13f0ur
OYcGBpxf2sOnrWkg9r3RkKlg25cI5IVMb8HhHtmwqGxbmF08zu5e4Jb3zaR59lTs
uOEhVudWBtSRsid6qZug0Pt9AjEBvN2EO7Vn0xMQPphOwMR7htVzxxsADRBHmS+1
pppCFLOpwqVDObcnl3pVw2wGd3PTAjEA+5cKqX6tfKUwNR88/urAGg+T3YsqNs4t
5t5HuGs7AsYj0xDTTvHEsIwaovCEwBKDAjBSTDiWQyz941zx94M6Lh8cBojwoJIV
2JkmQak9NPRcmBAjricNmlB8uWj8ShO4LXkCMQDj0c0c2JIeibLSl7vzFf3oW2zJ
M6iBQkh8g5GsZKVmCKgOC3FdTj6Oo//GxkdfaiMCMQGsQWYVeZ43Eqn+ZYSeX7Sz
Fol0BMyjvKXTpCznqk9+c1T86c9Cw2Rd/7NLJmPmGR4=
-----END RSA PRIVATE KEY-----

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBzQIBAAJhA0tr23/I4PgNNhnJdvdVGlg2hiAKKWD7kYcXGEZgPqTyY1rVND8q
oqI7n9IJiC4A0l+N7lZceGVotMj/dPY1DTMWT01NsEJXh47lQJNdHhpJysZyodmF
+N71sstc2iynMQIDAQABAmEBGOm/nfwGEhg0YLpdSVuq/p6KZbl8trSTb+8dQrNj
qgShWuuQD0ngCTDatlY+aTQTp82hyjT7+EtGfxzofA8pWHSV1uvuJVWamKy8AtV1
YXo5lREZyjTgdJzuKjwIx00BAjEB4XPP3C/etfJzmCcCYoK+TYjSCdYdIbVIZZTR
8xgarUBu2KzedKfcdR0H8yklRpxpAjEBwHe8tsyXpzbX8E0fe+qKGrp/hWeosThd
3LbhYN+6NVs7YUkthICJa4TZfC5qyPuJAjEBxOtjTvvFoxsL/cYs6ymeB2jAVzqT
O0PEcLOY8vzpE7V60eGGgO3taks+UFWT2KKJAjEAhCGDI2SiJe0dsDo41Xyj1f4u
xjJlXFmcJgRn4O/p4ACSPTafR5PLaTdKELFoWvDpAjEBeGO+jrDgz6aoJ7eka8JM
xAWHubm0UPsr7JILYSsxViJFWIVGwIgnJU4Ny8U5LhfS
-----END RSA PRIVATE KEY-----

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBzgIBAAJiANnXRUGM65e+JIE48z8L9fxWiIrBffeFynsFih4lhFrIliTf++Jy
R98lR8TGLO0x2Cosfb+vPcX7+bNdvqOn3q53NcYYFnih7GuNHeC/BAsI6c5H2HT3
Rw3LCJPBk/yXhFsCAwEAAQJhP/xdWV29LbsqGdLSkChBPrdkL+2ZxITF7tC3uxcm
A0x73aT05ZTPy5m1tPTI6XsEjOHlZNkYUkqebCSAk+Jwoi8eMjqkejry7R92SBEx
vRxhSxYkFiY3M1AxUO1km9QZYQIxDz25KT5pjdnXmcXon4wjsplmKlVXRoy11Cju
kLLZLIM+wLW0nhiks0CsrNY6VTcL0wIxDksBCJ3sMRKQcUW/MLmorTHTvV5iraKr
YS5A0e37Y4i/g3VEJrzWaTr1FpKMMwD4WQIxCO9w3KNAku9CHV8P8Gnii9SvNuZt
kmjwOP/+TUrtU9FmOujMiVt9Q7IJChNWg5sQDQIxBMin1Ol+d0I+ZBszDazmPumx
c+1WW8VZVRJ1EY50mHDZoLcsE0cbAGeCRobQM/X8KQIxAbOSOWnQiL+4QuY5rQ05
W2BL3qSET7u75RcT3ePnaZsJf5CweulDtVOVy8cq2sXQWw==
-----END RSA PRIVATE KEY-----

Binary file not shown.

View File

@ -0,0 +1,12 @@
-----BEGIN RSA PRIVATE KEY-----
MIIB0wIBAAJjAL2x2bcoZLRL21gXcWsVJpjy65T7t6lsg/7loYbeZoIM1YCbgOaw
j3c2bkiToc53k1siXpXSLzdIyPCvs7Tm9q1mNHi4pMmiOU/49wXKZzEr8+iIMHXf
GVxysbIsch/1m/yTAgMBAAECYhsXm5CdJETb0Kf0MS6qBqkxiJPun3yDExcElN0+
RkWsr5F+pBpOfS75hya2bxWd3l2WyEA3JTTkveghmsOy3UzPC/IhQLGFYOsRg6ia
yflUVObDrrdmXL0ysI2V4a0770MBAjIA3fXqP6Q8rg5WE2RddFeAGYTmfaDU9RGH
8ee4w0kITTXOr23WHEgIYuspKMB01gvg+QIyANrJMJ8VzwJdeq28KSBTCtQawLGH
mXzzsaSiD14hjEDQnVTkBEWMhtbyudm0NXjuOOsCMXj2gAbW9srUvUwsMlIpLYK6
zvJAKE62kyPeaO7kakXJwS4R6dHX39oo1nGDESllp+ECMgDKEvcgiHEZuyNbIiZO
H8UpoMgHcLn4adDSwYg2JgA3wTb/uFalsiS8lZXImSSmXEkfAjE3y7xpVjmzp3W2
/iNSKwBWTOLyu06KQ03gQEtvuXyEk6Nx+8siz9RHyjKnRL4HzRM9
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIBGDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3
DQEBCwUAA4IBAQAtKutVrQunnzOQg3TP2vnOT8Qr5LrbvsSBaPEm21Oxkpr0gJcC
/BgON5WrBdfpEDZ5jOMGgqdF3AxFzh/Zw1EBr2y2wIcleodtzV5j2fTQV9MPYJ9z
XYfhNsr9idt/i4YCqJSe6lB/+GG/p+9jtMLGMjfSkNnG7ppa7Sv6NVsAxgbKskTw
WU/z7T7Y/afK5omAPpHfWddzCl5o+o9VFi5scYyjv2iNPkRiTMDh4bE8RVm9vxcf
TMH14TSa1Y6OkaTuzJLbU3V8yJZ67s2SK89Trd75SQ+B62nZYe+0NG+6b2s+D97y
ex2x2EbfK/nxEL2Gv7/xG4gcpzxmKObhPpsS
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIBHDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3
DQEBCwUAA4IBAQBZBDKh6TRkGh9ro5l/Rv6/LE9slTLCrAAjCA6fT2dig6WsijmK
OLwjjuWRdKT+SPrm+42db4j++KcPVk/HwPNkbcXF7sAHy13DGi47mi7ySKqCiOZ8
RVnpBWjZJpMzXi5l8RgXGK10v2C4iPX3E7iRw+CYTZjOWfjnzHUWqQ93eu3s6OU3
3FobrPFKYkS9CvqvbGBIqpv8TTAoAvUAsjUbQHY2SlqlJLw2DUmewmeBzS2ItNyp
BO367lTm03z+nG77pZYOhgxch8EA2RcIuoEExj0tHZcG3JLOz60ijqqG1lxjrTXV
qMDRttuL8jisekj4gZD90T9JdMHpz8goNhO7
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIBFjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgMIMA0GCSqGSIb3
DQEBCwUAA4IBAQBsd9wHhcSkcO/AyrHRw33RVgdydoUIcopGHCnl+6ThQj9lM2cF
eh7Zdu2GVyd2yyIeI7c+N1w1NOLxXYk4vviU6J/Jol706UefflMEMHIwgJqakWdj
uq8o7CTOEhMpzSE6AfNj02jLb3qrkoJGB+STIwgx2IYdDzTrIr2Cb2T9zbDJCQBd
l2PTVR5id/+Uy4h+2KNJzgRgOUIPc0eFN0aE5a7IHRx3q7h5h/DbBaQU4tVmaAYF
o/6XlBvwVxan87w+hLfnFHUO7eMe0jnLvH2O+MW4ZeYh4VP2Jq7cLJQgTfCbFK9L
PNG8gfhW71rcMRTxwKM5qziJ8h6PeomSglsO
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIBFzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgUgMA0GCSqGSIb3
DQEBCwUAA4IBAQAuR/fgNifvtW6ukLxp+VFlYael3kAGJpKhe271fjkaqiyBB9Qt
NfFX1HDq1hJe8c8uf+SgFnY6rg1BjdctrEU92avPYjhpsyYEuSjt9LAtLfpeMaWD
ltem8PNh/lkR+v0xqeYsDcHTv/oR9NfCIqoPFWOPlH7CvLowNbI06D8KkKiWAlL1
tC62db6T5sOrmcmyjLoKUyerBqCWC+MM4G+AXMdfp54/xLOvkTq/K1cu1oRIGIYL
SSAtVeRQXqwgaH2M2EkN79joF6XnjGG27TN8rCS7gxJm87vZjtZiSFugwhFFHFhX
Gmp9IkBVZKQci1NbTY18l/2wxFYICv486sAV
-----END CERTIFICATE-----

View File

@ -5,7 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* THIS FILE is generated by `tests/scripts/generate_test_cert_macros.py` */
/* THIS FILE is generated by `framework/scripts/generate_test_cert_macros.py` */
/* *INDENT-OFF* */
{% for mode, name, value in macros %}
@ -40,3 +40,4 @@
{% endif %}
{% endfor %}
/* End of generated file */

View File

@ -1,9 +1,24 @@
/**
* This file is intended to be used to build PSA test driver libraries. It is
* intended to be appended by the test build system to the crypto_config.h file
* of the Mbed TLS library the test library will be linked to. It mirrors the
* PSA_ACCEL_* macros defining the cryptographic operations the test library
* supports.
* This file is intended to be used to build PSA external test driver
* libraries (libtestdriver1).
*
* It is intended to be appended by the test build system to the
* crypto_config.h file of the Mbed TLS library the test library will be
* linked to (see `tests/Makefile` libtestdriver1 target). This is done in
* order to insert it at the right time: after the main configuration
* (PSA_WANT) but before the logic that determines what built-ins to enable
* based on PSA_WANT and MBEDTLS_PSA_ACCEL macros.
*
* It reverses the PSA_ACCEL_* macros defining the cryptographic operations
* that will be accelerated in the main library:
* - When something is accelerated in the main library, we need it supported
* in libtestdriver1, so we disable the accel macro in order to the built-in
* to be enabled.
* - When something is NOT accelerated in the main library, we don't need it
* in libtestdriver1, so we enable its accel macro in order to the built-in
* to be disabled, to keep libtestdriver1 minimal. (We can't adjust the
* PSA_WANT macros as they need to be the same between libtestdriver1 and
* the main library, since they determine the ABI between the two.)
*/
#include "psa/crypto_legacy.h"

View File

@ -26,8 +26,10 @@ typedef struct {
/* Count the amount of times one of the key management driver functions
* is called. */
unsigned long hits;
/* Subset of hits which only counts key operations with EC key */
/* Subset of hits which only counts public key export operations */
unsigned long hits_export_public_key;
/* Subset of hits which only counts key generation operations */
unsigned long hits_generate_key;
/* Location of the last key management driver called to import a key. */
psa_key_location_t location;
} mbedtls_test_driver_key_management_hooks_t;
@ -36,7 +38,7 @@ typedef struct {
* sense that no PSA specification will assign a meaning to this location
* (stated first in version 1.0.1 of the specification) and that it is not
* used as a location of an opaque test drivers. */
#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0, 0, 0x800000 }
#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0, 0, 0, 0x800000 }
static inline mbedtls_test_driver_key_management_hooks_t
mbedtls_test_driver_key_management_hooks_init(void)
{

View File

@ -11,7 +11,7 @@
#include "test/helpers.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include "test/psa_helpers.h"
#include <psa/crypto.h>
#endif
@ -38,12 +38,15 @@
mbedtls_psa_crypto_free(); \
} \
while (0)
#else /*MBEDTLS_PSA_CRYPTO_C */
#elif defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */
#define PSA_INIT() PSA_ASSERT(psa_crypto_init())
#define PSA_DONE() mbedtls_psa_crypto_free();
#else /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */
#define PSA_INIT() ((void) 0)
#define PSA_DONE() ((void) 0)
#endif /* MBEDTLS_PSA_CRYPTO_C */
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
@ -313,7 +316,7 @@ uint64_t mbedtls_test_parse_binary_string(data_t *bin_string);
} \
while (0)
#endif /* MBEDTLS_PSA_CRYPTO_C */
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
/** \def USE_PSA_INIT
*

View File

@ -262,12 +262,15 @@ psa_status_t mbedtls_test_wrap_psa_copy_key(
#define psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key) \
mbedtls_test_wrap_psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key)
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
psa_pake_cipher_suite_t *arg1_cipher_suite);
#define psa_crypto_driver_pake_get_cipher_suite(arg0_inputs, arg1_cipher_suite) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(arg0_inputs, arg1_cipher_suite)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_buffer,
@ -275,13 +278,17 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
size_t *arg3_buffer_length);
#define psa_crypto_driver_pake_get_password(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_password(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_password_len);
#define psa_crypto_driver_pake_get_password_len(arg0_inputs, arg1_password_len) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(arg0_inputs, arg1_password_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_peer_id,
@ -289,13 +296,17 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
size_t *arg3_peer_id_length);
#define psa_crypto_driver_pake_get_peer(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_peer_len);
#define psa_crypto_driver_pake_get_peer_len(arg0_inputs, arg1_peer_len) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(arg0_inputs, arg1_peer_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_user_id,
@ -303,12 +314,15 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
size_t *arg3_user_id_len);
#define psa_crypto_driver_pake_get_user(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_user(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_user_len);
#define psa_crypto_driver_pake_get_user_len(arg0_inputs, arg1_user_len) \
mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(arg0_inputs, arg1_user_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
psa_status_t mbedtls_test_wrap_psa_crypto_init(void);
#define psa_crypto_init() \
@ -566,17 +580,22 @@ psa_status_t mbedtls_test_wrap_psa_mac_verify_setup(
#define psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg) \
mbedtls_test_wrap_psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg)
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_abort(
psa_pake_operation_t *arg0_operation);
#define psa_pake_abort(arg0_operation) \
mbedtls_test_wrap_psa_pake_abort(arg0_operation)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_get_implicit_key(
psa_pake_operation_t *arg0_operation,
psa_key_derivation_operation_t *arg1_output);
#define psa_pake_get_implicit_key(arg0_operation, arg1_output) \
mbedtls_test_wrap_psa_pake_get_implicit_key(arg0_operation, arg1_output)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_input(
psa_pake_operation_t *arg0_operation,
psa_pake_step_t arg1_step,
@ -584,7 +603,9 @@ psa_status_t mbedtls_test_wrap_psa_pake_input(
size_t arg3_input_length);
#define psa_pake_input(arg0_operation, arg1_step, arg2_input, arg3_input_length) \
mbedtls_test_wrap_psa_pake_input(arg0_operation, arg1_step, arg2_input, arg3_input_length)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_output(
psa_pake_operation_t *arg0_operation,
psa_pake_step_t arg1_step,
@ -593,38 +614,49 @@ psa_status_t mbedtls_test_wrap_psa_pake_output(
size_t *arg4_output_length);
#define psa_pake_output(arg0_operation, arg1_step, arg2_output, arg3_output_size, arg4_output_length) \
mbedtls_test_wrap_psa_pake_output(arg0_operation, arg1_step, arg2_output, arg3_output_size, arg4_output_length)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_password_key(
psa_pake_operation_t *arg0_operation,
mbedtls_svc_key_id_t arg1_password);
#define psa_pake_set_password_key(arg0_operation, arg1_password) \
mbedtls_test_wrap_psa_pake_set_password_key(arg0_operation, arg1_password)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_peer(
psa_pake_operation_t *arg0_operation,
const uint8_t *arg1_peer_id,
size_t arg2_peer_id_len);
#define psa_pake_set_peer(arg0_operation, arg1_peer_id, arg2_peer_id_len) \
mbedtls_test_wrap_psa_pake_set_peer(arg0_operation, arg1_peer_id, arg2_peer_id_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_role(
psa_pake_operation_t *arg0_operation,
psa_pake_role_t arg1_role);
#define psa_pake_set_role(arg0_operation, arg1_role) \
mbedtls_test_wrap_psa_pake_set_role(arg0_operation, arg1_role)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_user(
psa_pake_operation_t *arg0_operation,
const uint8_t *arg1_user_id,
size_t arg2_user_id_len);
#define psa_pake_set_user(arg0_operation, arg1_user_id, arg2_user_id_len) \
mbedtls_test_wrap_psa_pake_set_user(arg0_operation, arg1_user_id, arg2_user_id_len)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_setup(
psa_pake_operation_t *arg0_operation,
const psa_pake_cipher_suite_t *arg1_cipher_suite);
#define psa_pake_setup(arg0_operation, arg1_cipher_suite) \
mbedtls_test_wrap_psa_pake_setup(arg0_operation, arg1_cipher_suite)
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
psa_status_t mbedtls_test_wrap_psa_purge_key(
mbedtls_svc_key_id_t arg0_key);

View File

@ -40,7 +40,7 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#if defined(MBEDTLS_SSL_HAVE_AES)
#if defined(MBEDTLS_SSL_HAVE_GCM)
#if defined(MBEDTLS_MD_CAN_SHA384)
#if defined(PSA_WANT_ALG_SHA_384)
#define MBEDTLS_TEST_HAS_TLS1_3_AES_256_GCM_SHA384
#endif
#if defined(MBEDTLS_MD_CAN_SHA256)

View File

@ -1460,8 +1460,10 @@ run_test "TLS 1.3: O->m: all/psk_or_ephemeral, fail, key material mismatch" \
-S "key exchange mode: ephemeral"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_256
run_test "TLS 1.3: O->m: psk_ephemeral group(secp256r1) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
"$O_NEXT_CLI -tls1_3 -msg -allow_no_dhe_kex -groups P-256 \
@ -1473,8 +1475,10 @@ run_test "TLS 1.3: O->m: psk_ephemeral group(secp256r1) check, good" \
-S "key exchange mode: ephemeral"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
run_test "TLS 1.3: O->m: psk_ephemeral group(secp384r1) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
"$O_NEXT_CLI -tls1_3 -msg -allow_no_dhe_kex -groups secp384r1 \
@ -1486,8 +1490,10 @@ run_test "TLS 1.3: O->m: psk_ephemeral group(secp384r1) check, good" \
-S "key exchange mode: ephemeral"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_521
run_test "TLS 1.3: O->m: psk_ephemeral group(secp521r1) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
"$O_NEXT_CLI -tls1_3 -msg -allow_no_dhe_kex -groups secp521r1 \
@ -1499,8 +1505,10 @@ run_test "TLS 1.3: O->m: psk_ephemeral group(secp521r1) check, good" \
-S "key exchange mode: ephemeral"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_MONTGOMERY_255
run_test "TLS 1.3: O->m: psk_ephemeral group(x25519) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
"$O_NEXT_CLI -tls1_3 -msg -allow_no_dhe_kex -groups X25519 \
@ -1512,8 +1520,10 @@ run_test "TLS 1.3: O->m: psk_ephemeral group(x25519) check, good" \
-S "key exchange mode: ephemeral"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_MONTGOMERY_448
run_test "TLS 1.3: O->m: psk_ephemeral group(x448) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
"$O_NEXT_CLI -tls1_3 -msg -allow_no_dhe_kex -groups X448 \
@ -1524,9 +1534,11 @@ run_test "TLS 1.3: O->m: psk_ephemeral group(x448) check, good" \
-s "key exchange mode: psk_ephemeral" \
-S "key exchange mode: ephemeral"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_openssl_tls1_3_with_compatible_ephemeral
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
run_test "TLS 1.3 O->m: psk_ephemeral group(secp256r1->secp384r1) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_list=Client_identity,6162636465666768696a6b6c6d6e6f70,abc,dead,def,beef groups=secp384r1" \
"$O_NEXT_CLI_NO_CERT -tls1_3 -msg -allow_no_dhe_kex -psk_identity Client_identity -psk 6162636465666768696a6b6c6d6e6f70 -groups P-256:P-384" \
@ -1537,12 +1549,13 @@ run_test "TLS 1.3 O->m: psk_ephemeral group(secp256r1->secp384r1) check, good" \
-s "key exchange mode: psk_ephemeral" \
-S "key exchange mode: ephemeral"
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
requires_gnutls_tls1_3
requires_gnutls_next_no_ticket
requires_gnutls_next_disable_tls13_compat
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
requires_config_enabled PSA_WANT_ALG_ECDH
requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
run_test "TLS 1.3 G->m: psk_ephemeral group(secp256r1->secp384r1) check, good" \
"$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_list=Client_identity,6162636465666768696a6b6c6d6e6f70,abc,dead,def,beef groups=secp384r1" \
"$G_NEXT_CLI_NO_CERT --debug=4 --single-key-share --priority NORMAL:-VERS-ALL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+GROUP-SECP384R1 --pskusername Client_identity --pskkey 6162636465666768696a6b6c6d6e6f70 localhost" \

View File

@ -813,6 +813,7 @@ run_test "TLS 1.3 m->m: resumption, cli/tkt kex modes psk_all/psk_all" \
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
@ -826,6 +827,20 @@ run_test "TLS 1.3 m->O: resumption" \
-c "Reconnecting with saved session... ok" \
-c "HTTP/1.0 200 ok"
requires_openssl_tls1_3_with_compatible_ephemeral
requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
requires_config_disabled MBEDTLS_SSL_SESSION_TICKETS
run_test "TLS 1.3 m->O: resumption fails, no ticket support" \
"$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 1" \
"$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
1 \
-c "Protocol is TLSv1.3" \
-C "Saving session for reuse... ok" \
-C "Reconnecting with saved session... ok" \
-c "Ignore NewSessionTicket, not supported."
# No early data m->O tests for the time being. The option -early_data is needed
# to enable early data on OpenSSL server and it is not compatible with the
# -www option we usually use for testing with OpenSSL server (see
@ -858,6 +873,7 @@ run_test "TLS 1.3 m->O: resumption with early data" \
requires_gnutls_tls1_3
requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
@ -875,6 +891,21 @@ requires_gnutls_tls1_3
requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
requires_config_disabled MBEDTLS_SSL_SESSION_TICKETS
run_test "TLS 1.3 m->G: resumption fails, no ticket support" \
"$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert" \
"$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
1 \
-c "Protocol is TLSv1.3" \
-C "Saving session for reuse... ok" \
-C "Reconnecting with saved session... ok" \
-c "Ignore NewSessionTicket, not supported."
requires_gnutls_tls1_3
requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384

View File

@ -0,0 +1,6 @@
### PSA Crypto Client-Server Testing
Everything in this directory should currently be considered experimental. We are adding features and extending CI support for it.
Once stable, of production quality, and being tested by the CI, it will eventually be migrated into
the [MbedTLS framework repository](https://github.com/Mbed-TLS/mbedtls-framework).

View File

@ -0,0 +1,12 @@
bin/*
*.o
*.so
test/psa_ff_bootstrap.c
test/psa_manifest/*
test/client
test/partition
cscope.out
*.orig
*.swp
*.DS_Store
*psa_ff_bootstrap_*

View File

@ -0,0 +1,81 @@
CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L
ifeq ($(DEBUG),1)
override CFLAGS += -DDEBUG -O0 -g
endif
CLIENT_LIBS := -Lclient_libs -lpsaclient -lmbedtls -lmbedx509 -lmbedcrypto
SERVER_LIBS := -Lserver_libs -lmbedcrypto
MBEDTLS_ROOT_PATH = ../../..
COMMON_INCLUDE := -I./include -I$(MBEDTLS_ROOT_PATH)/include \
-I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/include \
-I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/drivers/builtin/include
GENERATED_H_FILES = include/psa_manifest/manifest.h \
include/psa_manifest/pid.h \
include/psa_manifest/sid.h
LIBPSACLIENT_SRC = src/psa_ff_client.c \
src/psa_sim_crypto_client.c \
src/psa_sim_serialise.c
LIBPSACLIENT_OBJS=$(LIBPSACLIENT_SRC:.c=.o)
PSA_CLIENT_BASE_SRC = $(LIBPSACLIENT_SRC) src/client.c
PSA_CLIENT_FULL_SRC = $(LIBPSACLIENT_SRC) \
$(wildcard src/aut_*.c)
PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c
PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \
src/psa_ff_server.c \
src/psa_sim_crypto_server.c \
src/psa_sim_serialise.c
.PHONY: all clean client_libs server_libs
all:
test/seedfile:
dd if=/dev/urandom of=./test/seedfile bs=64 count=1
src/%.o: src/%.c $(GENERATED_H_FILES)
$(CC) $(COMMON_INCLUDE) $(CFLAGS) -c $< $(LDFLAGS) -o $@
client_libs/libpsaclient: $(LIBPSACLIENT_OBJS)
mkdir -p client_libs
$(AR) -src client_libs/libpsaclient.a $(LIBPSACLIENT_OBJS)
test/psa_client_base: $(PSA_CLIENT_BASE_SRC) $(GENERATED_H_FILES) test/seedfile
$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_BASE_SRC) $(CLIENT_LIBS) $(LDFLAGS) -o $@
test/psa_client_full: $(PSA_CLIENT_FULL_SRC) $(GENERATED_H_FILES) test/seedfile
$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_FULL_SRC) $(CLIENT_LIBS) $(LDFLAGS) -o $@
test/psa_server: $(PSA_SERVER_SRC) $(GENERATED_H_FILES)
$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_SERVER_SRC) $(SERVER_LIBS) $(LDFLAGS) -o $@
$(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES): src/manifest.json src/server.c
tools/psa_autogen.py src/manifest.json
# Build MbedTLS libraries (crypto, x509 and tls) and copy them locally to
# build client/server applications.
#
# Note: these rules assume that mbedtls_config.h is already configured by all.sh.
# If not using all.sh then the user must do it manually.
client_libs: client_libs/libpsaclient
client_libs server_libs:
$(MAKE) -C $(MBEDTLS_ROOT_PATH)/library CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a libmbedx509.a libmbedtls.a
mkdir -p $@
cp $(MBEDTLS_ROOT_PATH)/library/libmbed*.a $@/
clean_server_intermediate_files:
rm -f $(PARTITION_SERVER_BOOTSTRAP)
rm -rf include/psa_manifest
clean: clean_server_intermediate_files
rm -f test/psa_client_base test/psa_client_full test/psa_server
rm -rf client_libs server_libs
rm -f test/psa_service_* test/psa_notify_* test/*.log
rm -f test/seedfile

View File

@ -0,0 +1,61 @@
# psasim
This tool simulates a PSA Firmware Framework implementation.
It allows you to develop secure partitions and their clients on a desktop computer.
It should be able to run on all systems that support POSIX and System V IPC:
e.g. macOS, Linux, FreeBSD, and perhaps Windows 10 WSL2.
Please note that the code in this directory is maintained by the Mbed TLS / PSA Crypto project solely for the purpose of testing the use of Mbed TLS with client/service separation. We do not recommend using this code for any other purpose. In particular:
* This simulator is not intended to pass or demonstrate compliance.
* This code is only intended for simulation and does not have any security goals. It does not isolate services from clients.
## Building
To build and run the test program make sure you have `make`, `python` and a
C compiler installed and then enter the following commands:
```sh
make run
```
Optionally the `DEBUG=1` command line option can be enabled to increase verbosity:
```sh
make DEBUG=1 run
```
Once done with the test, it is possible to clean all the generated files with:
```sh
make clean
```
## Features
The implemented API is intended to be compliant with PSA-FF 1.0.0 with the exception of a couple of things that are a work in progress:
* `psa_notify` support
* "strict" policy in manifest
The only supported "interrupts" are POSIX signals, which act
as a "virtual interrupt".
The standard PSA RoT APIs are not included (e.g. cryptography, attestation, lifecycle etc).
## Design
The code is designed to be readable rather than fast or secure.
In this implementation only one message is delivered to a
RoT service at a time.
The code is not thread-safe.
## Unsupported features
Because this is a simulator there are a few things that
can't be reasonably emulated:
* Manifest MMIO regions are unsupported
* Manifest priority field is ignored
* Partition IDs are in fact POSIX `pid_t`, which are only assigned at runtime,
making it infeasible to populate pid.h with correct values.

View File

@ -0,0 +1,75 @@
/* PSA Firmware Framework client header for psasim. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef __PSA_CLIENT_H__
#define __PSA_CLIENT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include "psa/crypto.h"
#include "error_ext.h"
/*********************** PSA Client Macros and Types *************************/
#define PSA_FRAMEWORK_VERSION (0x0100)
#define PSA_VERSION_NONE (0)
/* PSA response types */
#define PSA_CONNECTION_REFUSED PSA_ERROR_CONNECTION_REFUSED
#define PSA_CONNECTION_BUSY PSA_ERROR_CONNECTION_BUSY
#define PSA_DROP_CONNECTION PSA_ERROR_PROGRAMMER_ERROR
/* PSA message handles */
#define PSA_NULL_HANDLE ((psa_handle_t) 0)
#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t) (handle) > 0)
#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t) (handle))
/**
* A read-only input memory region provided to an RoT Service.
*/
typedef struct psa_invec {
const void *base;
size_t len;
} psa_invec;
/**
* A writable output memory region provided to an RoT Service.
*/
typedef struct psa_outvec {
void *base;
size_t len;
} psa_outvec;
/*************************** PSA Client API **********************************/
uint32_t psa_framework_version(void);
uint32_t psa_version(uint32_t sid);
psa_handle_t psa_connect(uint32_t sid, uint32_t version);
psa_status_t psa_call(psa_handle_t handle,
int32_t type,
const psa_invec *in_vec,
size_t in_len,
psa_outvec *out_vec,
size_t out_len);
void psa_close(psa_handle_t handle);
#ifdef __cplusplus
}
#endif
#endif /* __PSA_CLIENT_H__ */

View File

@ -0,0 +1,52 @@
/* Common definitions used for clients and services */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdint.h>
#include <stddef.h>
/* Increasing this might break on some platforms */
#define MAX_FRAGMENT_SIZE 200
#define CONNECT_REQUEST 1
#define CALL_REQUEST 2
#define CLOSE_REQUEST 3
#define VERSION_REQUEST 4
#define READ_REQUEST 5
#define READ_RESPONSE 6
#define WRITE_REQUEST 7
#define WRITE_RESPONSE 8
#define SKIP_REQUEST 9
#define PSA_REPLY 10
#define NON_SECURE (1 << 30)
typedef int32_t psa_handle_t;
#define PSA_MAX_IOVEC (4u)
#define PSA_IPC_CALL (0)
struct message_text {
int qid;
int32_t psa_type;
char buf[MAX_FRAGMENT_SIZE];
};
struct message {
long message_type;
struct message_text message_text;
};
typedef struct vector_sizes {
size_t invec_sizes[PSA_MAX_IOVEC];
size_t outvec_sizes[PSA_MAX_IOVEC];
} vector_sizes_t;
#endif /* _COMMON_H_ */

View File

@ -0,0 +1,19 @@
/* PSA status codes used by psasim. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_ERROR_H
#define PSA_ERROR_H
#include <stdint.h>
#include "common.h"
#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t) -129)
#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t) -130)
#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t) -131)
#endif

View File

@ -0,0 +1,15 @@
/* Declarations of internal functions. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <stdint.h>
#include <service.h>
void raise_signal(psa_signal_t signal);
void __init_psasim(const char **array,
int size,
const int allow_ns_clients_array[32],
const uint32_t versions[32],
const int strict_policy_array[32]);

View File

@ -0,0 +1,17 @@
/* PSA lifecycle states used by psasim. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#define PSA_LIFECYCLE_PSA_STATE_MASK (0xff00u)
#define PSA_LIFECYCLE_IMP_STATE_MASK (0x00ffu)
#define PSA_LIFECYCLE_UNKNOWN (0x0000u)
#define PSA_LIFECYCLE_ASSEMBLY_AND_TEST (0x1000u)
#define PSA_LIFECYCLE_PSA_ROT_PROVISIONING (0x2000u)
#define PSA_LIFECYCLE_SECURED (0x3000u)
#define PSA_LIFECYCLE_NON_PSA_ROT_DEBUG (0x4000u)
#define PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG (0x5000u)
#define PSA_LIFECYCLE_DECOMMISSIONED (0x6000u)
#define psa_rot_lifecycle_state(void) PSA_LIFECYCLE_UNKNOWN

View File

@ -0,0 +1,253 @@
/* PSA Firmware Framework service header for psasim. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef __PSA_SERVICE_H__
#define __PSA_SERVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include "common.h"
#include "psa/crypto.h"
/********************** PSA Secure Partition Macros and Types ****************/
/* PSA wait timeouts */
#define PSA_POLL (0x00000000u)
#define PSA_BLOCK (0x80000000u)
/* A mask value that includes all Secure Partition signals */
#define PSA_WAIT_ANY (~0u)
/* Doorbell signal */
#define PSA_DOORBELL (0x00000008u)
/* PSA message types */
#define PSA_IPC_CONNECT (-1)
#define PSA_IPC_DISCONNECT (-2)
/* Return code from psa_get() */
#define PSA_ERR_NOMSG (INT32_MIN + 3)
/* Store a set of one or more Secure Partition signals */
typedef uint32_t psa_signal_t;
/**
* Describe a message received by an RoT Service after calling \ref psa_get().
*/
typedef struct psa_msg_t {
uint32_t type; /* One of the following values:
* \ref PSA_IPC_CONNECT
* \ref PSA_IPC_CALL
* \ref PSA_IPC_DISCONNECT
*/
psa_handle_t handle; /* A reference generated by the SPM to the
* message returned by psa_get().
*/
int32_t client_id; /* Partition ID of the sender of the message */
void *rhandle; /* Be useful for binding a connection to some
* application-specific data or function
* pointer within the RoT Service
* implementation.
*/
size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input
* vector in bytes.
*/
size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output
* vector in bytes.
*/
} psa_msg_t;
/************************* PSA Secure Partition API **************************/
/**
* \brief Return the Secure Partition interrupt signals that have been asserted
* from a subset of signals provided by the caller.
*
* \param[in] signal_mask A set of signals to query. Signals that are not
* in this set will be ignored.
* \param[in] timeout Specify either blocking \ref PSA_BLOCK or
* polling \ref PSA_POLL operation.
*
* \retval >0 At least one signal is asserted.
* \retval 0 No signals are asserted. This is only seen when
* a polling timeout is used.
*/
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout);
/**
* \brief Retrieve the message which corresponds to a given RoT Service signal
* and remove the message from the RoT Service queue.
*
* \param[in] signal The signal value for an asserted RoT Service.
* \param[out] msg Pointer to \ref psa_msg_t object for receiving
* the message.
*
* \retval PSA_SUCCESS Success, *msg will contain the delivered
* message.
* \retval PSA_ERR_NOMSG Message could not be delivered.
* \retval "Does not return" The call is invalid because one or more of the
* following are true:
* \arg signal has more than a single bit set.
* \arg signal does not correspond to an RoT Service.
* \arg The RoT Service signal is not currently
* asserted.
* \arg The msg pointer provided is not a valid memory
* reference.
*/
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg);
/**
* \brief Associate some RoT Service private data with a client connection.
*
* \param[in] msg_handle Handle for the client's message.
* \param[in] rhandle Reverse handle allocated by the RoT Service.
*
* \retval void Success, rhandle will be provided with all
* subsequent messages delivered on this
* connection.
* \retval "Does not return" msg_handle is invalid.
*/
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
/**
* \brief Read a message parameter or part of a message parameter from a client
* input vector.
*
* \param[in] msg_handle Handle for the client's message.
* \param[in] invec_idx Index of the input vector to read from. Must be
* less than \ref PSA_MAX_IOVEC.
* \param[out] buffer Buffer in the Secure Partition to copy the
* requested data to.
* \param[in] num_bytes Maximum number of bytes to be read from the
* client input vector.
*
* \retval >0 Number of bytes copied.
* \retval 0 There was no remaining data in this input
* vector.
* \retval "Does not return" The call is invalid, one or more of the
* following are true:
* \arg msg_handle is invalid.
* \arg msg_handle does not refer to a
* \ref PSA_IPC_CALL message.
* \arg invec_idx is equal to or greater than
* \ref PSA_MAX_IOVEC.
* \arg the memory reference for buffer is invalid or
* not writable.
*/
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
void *buffer, size_t num_bytes);
/**
* \brief Skip over part of a client input vector.
*
* \param[in] msg_handle Handle for the client's message.
* \param[in] invec_idx Index of input vector to skip from. Must be
* less than \ref PSA_MAX_IOVEC.
* \param[in] num_bytes Maximum number of bytes to skip in the client
* input vector.
*
* \retval >0 Number of bytes skipped.
* \retval 0 There was no remaining data in this input
* vector.
* \retval "Does not return" The call is invalid, one or more of the
* following are true:
* \arg msg_handle is invalid.
* \arg msg_handle does not refer to a
* \ref PSA_IPC_CALL message.
* \arg invec_idx is equal to or greater than
* \ref PSA_MAX_IOVEC.
*/
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes);
/**
* \brief Write a message response to a client output vector.
*
* \param[in] msg_handle Handle for the client's message.
* \param[out] outvec_idx Index of output vector in message to write to.
* Must be less than \ref PSA_MAX_IOVEC.
* \param[in] buffer Buffer with the data to write.
* \param[in] num_bytes Number of bytes to write to the client output
* vector.
*
* \retval void Success
* \retval "Does not return" The call is invalid, one or more of the
* following are true:
* \arg msg_handle is invalid.
* \arg msg_handle does not refer to a
* \ref PSA_IPC_CALL message.
* \arg outvec_idx is equal to or greater than
* \ref PSA_MAX_IOVEC.
* \arg The memory reference for buffer is invalid.
* \arg The call attempts to write data past the end
* of the client output vector.
*/
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
const void *buffer, size_t num_bytes);
/**
* \brief Complete handling of a specific message and unblock the client.
*
* \param[in] msg_handle Handle for the client's message.
* \param[in] status Message result value to be reported to the
* client.
*
* \retval void Success.
* \retval "Does not return" The call is invalid, one or more of the
* following are true:
* \arg msg_handle is invalid.
* \arg An invalid status code is specified for the
* type of message.
*/
void psa_reply(psa_handle_t msg_handle, psa_status_t status);
/**
* \brief Send a PSA_DOORBELL signal to a specific Secure Partition.
*
* \param[in] partition_id Secure Partition ID of the target partition.
*
* \retval void Success.
* \retval "Does not return" partition_id does not correspond to a Secure
* Partition.
*/
void psa_notify(int32_t partition_id);
/**
* \brief Clear the PSA_DOORBELL signal.
*
* \retval void Success.
* \retval "Does not return" The Secure Partition's doorbell signal is not
* currently asserted.
*/
void psa_clear(void);
/**
* \brief Inform the SPM that an interrupt has been handled (end of interrupt).
*
* \param[in] irq_signal The interrupt signal that has been processed.
*
* \retval void Success.
* \retval "Does not return" The call is invalid, one or more of the
* following are true:
* \arg irq_signal is not an interrupt signal.
* \arg irq_signal indicates more than one signal.
* \arg irq_signal is not currently asserted.
*/
void psa_eoi(psa_signal_t irq_signal);
#define psa_panic(X) abort();
#ifdef __cplusplus
}
#endif
#endif /* __PSA_SERVICE_H__ */

View File

@ -0,0 +1,31 @@
/* Common definitions used for clients and services */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "service.h"
#define PRINT(fmt, ...) \
fprintf(stdout, fmt "\n", ##__VA_ARGS__)
#if defined(DEBUG)
#define INFO(fmt, ...) \
fprintf(stdout, "Info (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else /* !DEBUG */
#define INFO(...)
#endif /* DEBUG*/
#define ERROR(fmt, ...) \
fprintf(stderr, "Error (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#define FATAL(fmt, ...) \
{ \
fprintf(stderr, "Fatal (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
abort(); \
}
#define PROJECT_ID 'M'
#define PATHNAMESIZE 256
#define TMP_FILE_BASE_PATH "./"

View File

@ -0,0 +1,71 @@
/**
* This is the base AUT that exectues all other AUTs meant to test PSA APIs
* through PSASIM.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* First include Mbed TLS headers to get the Mbed TLS configuration and
* platform definitions that we'll use in this program. Also include
* standard C headers for functions we'll use here. */
#include "mbedtls/build_info.h"
#include "psa/crypto.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int psa_hash_compute_main(void);
int psa_hash_main(void);
int psa_aead_encrypt_main(char *cipher_name);
int psa_aead_encrypt_decrypt_main(void);
int psa_cipher_encrypt_decrypt_main(void);
int psa_asymmetric_encrypt_decrypt_main(void);
int psa_random_main(void);
int psa_mac_main(void);
int psa_key_agreement_main(void);
int psa_sign_verify_main(void);
int psa_hkdf_main(void);
#define TEST_MODULE(main_func) \
do { \
char title[128] = { 0 }; \
char separator[128] = { 0 }; \
int title_len = snprintf(title, sizeof(title), "=== Test: %s ===", #main_func); \
memset(separator, '=', title_len); \
printf("%s\n%s\n%s\n", separator, title, separator); \
ret = main_func; \
if (ret != 0) { \
goto exit; \
} \
} while (0)
int main()
{
int ret;
TEST_MODULE(psa_hash_compute_main());
TEST_MODULE(psa_hash_main());
TEST_MODULE(psa_aead_encrypt_main("aes128-gcm"));
TEST_MODULE(psa_aead_encrypt_main("aes256-gcm"));
TEST_MODULE(psa_aead_encrypt_main("aes128-gcm_8"));
TEST_MODULE(psa_aead_encrypt_main("chachapoly"));
TEST_MODULE(psa_aead_encrypt_decrypt_main());
TEST_MODULE(psa_cipher_encrypt_decrypt_main());
TEST_MODULE(psa_asymmetric_encrypt_decrypt_main());
TEST_MODULE(psa_random_main());
TEST_MODULE(psa_mac_main());
TEST_MODULE(psa_key_agreement_main());
TEST_MODULE(psa_sign_verify_main());
TEST_MODULE(psa_hkdf_main());
exit:
return (ret != 0) ? 1 : 0;
}

View File

@ -0,0 +1,227 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include "psa/crypto.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char usage[] =
"Usage: aead_demo [aes128-gcm|aes256-gcm|aes128-gcm_8|chachapoly]";
/* Dummy data for encryption: IV/nonce, additional data, 2-part message */
const unsigned char iv1[12] = { 0x00 };
const unsigned char add_data1[] = { 0x01, 0x02 };
const unsigned char msg1_part1[] = { 0x03, 0x04 };
const unsigned char msg1_part2[] = { 0x05, 0x06, 0x07 };
/* Dummy data (2nd message) */
const unsigned char iv2[12] = { 0x10 };
const unsigned char add_data2[] = { 0x11, 0x12 };
const unsigned char msg2_part1[] = { 0x13, 0x14 };
const unsigned char msg2_part2[] = { 0x15, 0x16, 0x17 };
/* Maximum total size of the messages */
#define MSG1_SIZE (sizeof(msg1_part1) + sizeof(msg1_part2))
#define MSG2_SIZE (sizeof(msg2_part1) + sizeof(msg2_part2))
#define MSG_MAX_SIZE (MSG1_SIZE > MSG2_SIZE ? MSG1_SIZE : MSG2_SIZE)
/* Dummy key material - never do this in production!
* 32-byte is enough to all the key size supported by this program. */
const unsigned char key_bytes[32] = { 0x2a };
/* Print the contents of a buffer in hex */
void print_buf(const char *title, uint8_t *buf, size_t len)
{
printf("%s:", title);
for (size_t i = 0; i < len; i++) {
printf(" %02x", buf[i]);
}
printf("\n");
}
/* Run a PSA function and bail out if it fails.
* The symbolic name of the error code can be recovered using:
* programs/psa/psa_constant_name status <value> */
#define PSA_CHECK(expr) \
do \
{ \
status = (expr); \
if (status != PSA_SUCCESS) \
{ \
printf("Error %d at line %d: %s\n", \
(int) status, \
__LINE__, \
#expr); \
goto exit; \
} \
} \
while (0)
/*
* Prepare encryption material:
* - interpret command-line argument
* - set up key
* - outputs: key and algorithm, which together hold all the information
*/
static psa_status_t aead_prepare(const char *info,
psa_key_id_t *key,
psa_algorithm_t *alg)
{
psa_status_t status;
/* Convert arg to alg + key_bits + key_type */
size_t key_bits;
psa_key_type_t key_type;
if (strcmp(info, "aes128-gcm") == 0) {
*alg = PSA_ALG_GCM;
key_bits = 128;
key_type = PSA_KEY_TYPE_AES;
} else if (strcmp(info, "aes256-gcm") == 0) {
*alg = PSA_ALG_GCM;
key_bits = 256;
key_type = PSA_KEY_TYPE_AES;
} else if (strcmp(info, "aes128-gcm_8") == 0) {
*alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 8);
key_bits = 128;
key_type = PSA_KEY_TYPE_AES;
} else if (strcmp(info, "chachapoly") == 0) {
*alg = PSA_ALG_CHACHA20_POLY1305;
key_bits = 256;
key_type = PSA_KEY_TYPE_CHACHA20;
} else {
puts(usage);
return PSA_ERROR_INVALID_ARGUMENT;
}
/* Prepare key attributes */
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, *alg);
psa_set_key_type(&attributes, key_type);
psa_set_key_bits(&attributes, key_bits); // optional
/* Import key */
PSA_CHECK(psa_import_key(&attributes, key_bytes, key_bits / 8, key));
exit:
return status;
}
/*
* Print out some information.
*
* All of this information was present in the command line argument, but his
* function demonstrates how each piece can be recovered from (key, alg).
*/
static void aead_info(psa_key_id_t key, psa_algorithm_t alg)
{
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
(void) psa_get_key_attributes(key, &attr);
psa_key_type_t key_type = psa_get_key_type(&attr);
size_t key_bits = psa_get_key_bits(&attr);
psa_algorithm_t base_alg = PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
size_t tag_len = PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg);
const char *type_str = key_type == PSA_KEY_TYPE_AES ? "AES"
: key_type == PSA_KEY_TYPE_CHACHA20 ? "Chacha"
: "???";
const char *base_str = base_alg == PSA_ALG_GCM ? "GCM"
: base_alg == PSA_ALG_CHACHA20_POLY1305 ? "ChachaPoly"
: "???";
printf("%s, %u, %s, %u\n",
type_str, (unsigned) key_bits, base_str, (unsigned) tag_len);
}
/*
* Encrypt a 2-part message.
*/
static int aead_encrypt(psa_key_id_t key, psa_algorithm_t alg,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *part1, size_t part1_len,
const unsigned char *part2, size_t part2_len)
{
psa_status_t status;
size_t olen, olen_tag;
unsigned char out[PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(MSG_MAX_SIZE)];
unsigned char *p = out, *end = out + sizeof(out);
unsigned char tag[PSA_AEAD_TAG_MAX_SIZE];
psa_aead_operation_t op = PSA_AEAD_OPERATION_INIT;
PSA_CHECK(psa_aead_encrypt_setup(&op, key, alg));
PSA_CHECK(psa_aead_set_nonce(&op, iv, iv_len));
PSA_CHECK(psa_aead_update_ad(&op, ad, ad_len));
PSA_CHECK(psa_aead_update(&op, part1, part1_len, p, end - p, &olen));
p += olen;
PSA_CHECK(psa_aead_update(&op, part2, part2_len, p, end - p, &olen));
p += olen;
PSA_CHECK(psa_aead_finish(&op, p, end - p, &olen,
tag, sizeof(tag), &olen_tag));
p += olen;
memcpy(p, tag, olen_tag);
p += olen_tag;
olen = p - out;
print_buf("out", out, olen);
exit:
psa_aead_abort(&op); // required on errors, harmless on success
return status;
}
/*
* AEAD demo: set up key/alg, print out info, encrypt messages.
*/
static psa_status_t aead_demo(const char *info)
{
psa_status_t status;
psa_key_id_t key;
psa_algorithm_t alg;
PSA_CHECK(aead_prepare(info, &key, &alg));
aead_info(key, alg);
PSA_CHECK(aead_encrypt(key, alg,
iv1, sizeof(iv1), add_data1, sizeof(add_data1),
msg1_part1, sizeof(msg1_part1),
msg1_part2, sizeof(msg1_part2)));
PSA_CHECK(aead_encrypt(key, alg,
iv2, sizeof(iv2), add_data2, sizeof(add_data2),
msg2_part1, sizeof(msg2_part1),
msg2_part2, sizeof(msg2_part2)));
exit:
psa_destroy_key(key);
return status;
}
/*
* Main function
*/
int psa_aead_encrypt_main(char *cipher_name)
{
psa_status_t status = PSA_SUCCESS;
/* Initialize the PSA crypto library. */
PSA_CHECK(psa_crypto_init());
/* Run the demo */
PSA_CHECK(aead_demo(cipher_name));
/* Deinitialize the PSA crypto library. */
mbedtls_psa_crypto_free();
exit:
return status == PSA_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 500
static void print_bytestr(const uint8_t *bytes, size_t len)
{
for (unsigned int idx = 0; idx < len; idx++) {
printf("%02X", bytes[idx]);
}
}
int psa_aead_encrypt_decrypt_main(void)
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
uint8_t encrypt[BUFFER_SIZE] = { 0 };
uint8_t decrypt[BUFFER_SIZE] = { 0 };
const uint8_t plaintext[] = "Hello World!";
const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
uint8_t nonce[PSA_AEAD_NONCE_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CCM)];
size_t nonce_length = sizeof(nonce);
size_t ciphertext_length;
size_t plaintext_length;
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
status = psa_generate_random(nonce, nonce_length);
if (status != PSA_SUCCESS) {
printf("psa_generate_random failed\n");
return EXIT_FAILURE;
}
status = psa_aead_encrypt(key_id, // key
PSA_ALG_CCM, // algorithm
nonce, nonce_length, // nonce
NULL, 0, // additional data
plaintext, sizeof(plaintext), // plaintext
encrypt, sizeof(encrypt), // ciphertext
&ciphertext_length); // length of output
if (status != PSA_SUCCESS) {
printf("psa_aead_encrypt failed\n");
return EXIT_FAILURE;
}
printf("AES-CCM encryption:\n");
printf("- Plaintext: '%s':\n", plaintext);
printf("- Key: ");
print_bytestr(key_bytes, sizeof(key_bytes));
printf("\n- Nonce: ");
print_bytestr(nonce, nonce_length);
printf("\n- No additional data\n");
printf("- Ciphertext:\n");
for (size_t j = 0; j < ciphertext_length; j++) {
if (j % 8 == 0) {
printf("\n ");
}
printf("%02x ", encrypt[j]);
}
printf("\n");
status = psa_aead_decrypt(key_id, // key
PSA_ALG_CCM, // algorithm
nonce, nonce_length, // nonce
NULL, 0, // additional data
encrypt, ciphertext_length, // ciphertext
decrypt, sizeof(decrypt), // plaintext
&plaintext_length); // length of output
if (status != PSA_SUCCESS) {
printf("psa_aead_decrypt failed\n");
return EXIT_FAILURE;
}
if (memcmp(plaintext, decrypt, sizeof(plaintext)) != 0) {
printf("\nEncryption/Decryption failed!\n");
} else {
printf("\nEncryption/Decryption successful!\n");
}
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
return 0;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define KEY_BITS 4096
#define BUFFER_SIZE PSA_BITS_TO_BYTES(KEY_BITS)
static void print_bytestr(const uint8_t *bytes, size_t len)
{
for (unsigned int idx = 0; idx < len; idx++) {
printf("%02X", bytes[idx]);
}
}
int psa_asymmetric_encrypt_decrypt_main(void)
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
uint8_t original[BUFFER_SIZE/2] = { 0 };
uint8_t encrypt[BUFFER_SIZE] = { 0 };
uint8_t decrypt[BUFFER_SIZE] = { 0 };
size_t encrypted_length;
size_t decrypted_length;
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
status = psa_generate_random(original, sizeof(original));
if (status != PSA_SUCCESS) {
printf("psa_generate_random() failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_bits(&attributes, KEY_BITS);
status = psa_generate_key(&attributes, &key_id);
if (status != PSA_SUCCESS) {
printf("psa_generate_key failed (%d)\n", status);
return EXIT_FAILURE;
}
status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
original, sizeof(original), NULL, 0,
encrypt, sizeof(encrypt), &encrypted_length);
if (status != PSA_SUCCESS) {
printf("psa_asymmetric_encrypt failed (%d)\n", status);
return EXIT_FAILURE;
}
status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
encrypt, encrypted_length, NULL, 0,
decrypt, sizeof(decrypt), &decrypted_length);
if (status != PSA_SUCCESS) {
printf("psa_cipher_decrypt failed (%d)\n", status);
return EXIT_FAILURE;
}
if (memcmp(original, decrypt, sizeof(original)) != 0) {
printf("\nEncryption/Decryption failed!\n");
} else {
printf("\nEncryption/Decryption successful!\n");
}
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
return 0;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 4096
static void print_bytestr(const uint8_t *bytes, size_t len)
{
for (unsigned int idx = 0; idx < len; idx++) {
printf("%02X", bytes[idx]);
}
}
int psa_cipher_encrypt_decrypt_main(void)
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
uint8_t original[BUFFER_SIZE] = { 0 };
uint8_t encrypt[BUFFER_SIZE] = { 0 };
uint8_t decrypt[BUFFER_SIZE] = { 0 };
const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
size_t encrypted_length;
size_t decrypted_length;
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
status = psa_generate_random(original, sizeof(original));
if (status != PSA_SUCCESS) {
printf("psa_generate_random() failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
original, sizeof(original),
encrypt, sizeof(encrypt), &encrypted_length);
if (status != PSA_SUCCESS) {
printf("psa_cipher_encrypt failed\n");
return EXIT_FAILURE;
}
status = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING,
encrypt, encrypted_length,
decrypt, sizeof(decrypt), &decrypted_length);
if (status != PSA_SUCCESS) {
printf("psa_cipher_decrypt failed\n");
return EXIT_FAILURE;
}
if (memcmp(original, decrypt, sizeof(original)) != 0) {
printf("\nEncryption/Decryption failed!\n");
} else {
printf("\nEncryption/Decryption successful!\n");
}
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
return 0;
}

View File

@ -0,0 +1,167 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#define HASH_ALG PSA_ALG_SHA_256
static const uint8_t sample_message[] = "Hello World!";
/* sample_message is terminated with a null byte which is not part of
* the message itself so we make sure to subtract it in order to get
* the message length. */
static const size_t sample_message_length = sizeof(sample_message) - 1;
#define EXPECTED_HASH_VALUE { \
0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \
0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
}
static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
static const size_t expected_hash_len = sizeof(expected_hash);
int psa_hash_main(void)
{
psa_status_t status;
uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
size_t hash_length;
psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t cloned_hash_operation = PSA_HASH_OPERATION_INIT;
mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
/* Compute hash using multi-part operation */
status = psa_hash_setup(&hash_operation, HASH_ALG);
if (status == PSA_ERROR_NOT_SUPPORTED) {
mbedtls_printf("unknown hash algorithm supplied\n");
return EXIT_FAILURE;
} else if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_setup failed\n");
return EXIT_FAILURE;
}
status = psa_hash_update(&hash_operation, sample_message, sample_message_length);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_update failed\n");
goto cleanup;
}
status = psa_hash_clone(&hash_operation, &cloned_hash_operation);
if (status != PSA_SUCCESS) {
mbedtls_printf("PSA hash clone failed\n");
goto cleanup;
}
status = psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_length);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_finish failed\n");
goto cleanup;
}
/* Check the result of the operation against the sample */
if (hash_length != expected_hash_len ||
(memcmp(hash, expected_hash, expected_hash_len) != 0)) {
mbedtls_printf("Multi-part hash operation gave the wrong result!\n\n");
goto cleanup;
}
status =
psa_hash_verify(&cloned_hash_operation, expected_hash,
expected_hash_len);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_verify failed\n");
goto cleanup;
} else {
mbedtls_printf("Multi-part hash operation successful!\n");
}
/* A bit of white-box testing: ensure that we can abort an operation more
* times than there are operation slots on the simulator server.
*/
for (int i = 0; i < 200; i++) {
/* This should be a no-op */
status = psa_hash_abort(&hash_operation);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_abort failed\n");
goto cleanup;
}
}
/* Compute hash using multi-part operation using the same operation struct */
status = psa_hash_setup(&hash_operation, HASH_ALG);
if (status == PSA_ERROR_NOT_SUPPORTED) {
mbedtls_printf("unknown hash algorithm supplied\n");
goto cleanup;
} else if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_setup failed: %d\n", status);
goto cleanup;
}
status = psa_hash_update(&hash_operation, sample_message, sample_message_length);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_update failed\n");
goto cleanup;
}
/* Don't use psa_hash_finish() when going to check against an expected result */
status = psa_hash_verify(&hash_operation, expected_hash, expected_hash_len);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_verify failed: %d\n", status);
goto cleanup;
} else {
mbedtls_printf("Second multi-part hash operation successful!\n");
}
/* Clear local variables prior to one-shot hash demo */
memset(hash, 0, sizeof(hash));
hash_length = 0;
/* Compute hash using one-shot function call */
status = psa_hash_compute(HASH_ALG,
sample_message, sample_message_length,
hash, sizeof(hash),
&hash_length);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_compute failed\n");
goto cleanup;
}
if (hash_length != expected_hash_len ||
(memcmp(hash, expected_hash, expected_hash_len) != 0)) {
mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
goto cleanup;
}
mbedtls_printf("One-shot hash operation successful!\n\n");
/* Print out result */
mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
for (size_t j = 0; j < expected_hash_len; j++) {
mbedtls_printf("%02x", hash[j]);
}
mbedtls_printf("\n");
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
cleanup:
psa_hash_abort(&hash_operation);
psa_hash_abort(&cloned_hash_operation);
return EXIT_FAILURE;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#define HASH_ALG PSA_ALG_SHA_256
static const uint8_t sample_message[] = "Hello World!";
/* sample_message is terminated with a null byte which is not part of
* the message itself so we make sure to subtract it in order to get
* the message length. */
static const size_t sample_message_length = sizeof(sample_message) - 1;
#define EXPECTED_HASH_VALUE { \
0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \
0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
}
static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
static const size_t expected_hash_len = sizeof(expected_hash);
int psa_hash_compute_main(void)
{
psa_status_t status;
uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
size_t hash_length;
mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
/* Clear local variables prior to one-shot hash demo */
memset(hash, 0, sizeof(hash));
hash_length = 0;
/* Compute hash using one-shot function call */
status = psa_hash_compute(HASH_ALG,
sample_message, sample_message_length,
hash, sizeof(hash),
&hash_length);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_hash_compute failed\n");
goto cleanup;
}
if (hash_length != expected_hash_len ||
(memcmp(hash, expected_hash, expected_hash_len) != 0)) {
mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
goto cleanup;
}
mbedtls_printf("One-shot hash operation successful!\n\n");
/* Print out result */
mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
for (size_t j = 0; j < expected_hash_len; j++) {
mbedtls_printf("%02x", hash[j]);
}
mbedtls_printf("\n");
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
cleanup:
return EXIT_FAILURE;
}

View File

@ -0,0 +1,121 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
int psa_hkdf_main(void)
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
/* Example test vector from RFC 5869 */
/* Input keying material (IKM) */
unsigned char ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
unsigned char salt[] =
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
/* Context and application specific information, which can be of zero length */
unsigned char info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
/* Expected OKM based on the RFC 5869-provided test vector */
unsigned char expected_okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43,
0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90,
0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4,
0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
0x58, 0x65 };
/* The output size of the HKDF function depends on the hash function used.
* In our case we use SHA-256, which produces a 32 byte fingerprint.
* Therefore, we allocate a buffer of 32 bytes to hold the output keying
* material (OKM).
*/
unsigned char output[32];
psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
printf("PSA Crypto API: HKDF SHA-256 example\n\n");
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
status = psa_import_key(&attributes, ikm, sizeof(ikm), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
status = psa_key_derivation_setup(&operation, alg);
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_setup failed");
return EXIT_FAILURE;
}
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT,
salt, sizeof(salt));
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_input_bytes (salt) failed");
return EXIT_FAILURE;
}
status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_SECRET,
key_id);
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_input_key failed");
return EXIT_FAILURE;
}
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO,
info, sizeof(info));
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_input_bytes (info) failed");
return EXIT_FAILURE;
}
status = psa_key_derivation_output_bytes(&operation, output, sizeof(output));
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_output_bytes failed");
return EXIT_FAILURE;
}
status = psa_key_derivation_abort(&operation);
if (status != PSA_SUCCESS) {
printf("psa_key_derivation_abort failed");
return EXIT_FAILURE;
}
printf("OKM: \n");
for (size_t j = 0; j < sizeof(output); j++) {
if (output[j] != expected_okm[j]) {
printf("\n --- Unexpected outcome!\n");
return EXIT_FAILURE;
}
if (j % 8 == 0) {
printf("\n ");
}
printf("%02x ", output[j]);
}
printf("\n");
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,146 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
#include "mbedtls/debug.h"
#include "mbedtls/platform.h"
#define BUFFER_SIZE 500
#define SERVER_PK_VALUE { \
0x04, 0xde, 0xa5, 0xe4, 0x5d, 0x0e, 0xa3, 0x7f, 0xc5, \
0x66, 0x23, 0x2a, 0x50, 0x8f, 0x4a, 0xd2, 0x0e, 0xa1, \
0x3d, 0x47, 0xe4, 0xbf, 0x5f, 0xa4, 0xd5, 0x4a, 0x57, \
0xa0, 0xba, 0x01, 0x20, 0x42, 0x08, 0x70, 0x97, 0x49, \
0x6e, 0xfc, 0x58, 0x3f, 0xed, 0x8b, 0x24, 0xa5, 0xb9, \
0xbe, 0x9a, 0x51, 0xde, 0x06, 0x3f, 0x5a, 0x00, 0xa8, \
0xb6, 0x98, 0xa1, 0x6f, 0xd7, 0xf2, 0x9b, 0x54, 0x85, \
0xf3, 0x20 \
}
#define KEY_BITS 256
int psa_key_agreement_main(void)
{
psa_status_t status;
psa_key_attributes_t client_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t server_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t client_key_id = 0;
psa_key_id_t server_key_id = 0;
uint8_t client_pk[BUFFER_SIZE] = { 0 };
size_t client_pk_len;
size_t key_bits;
psa_key_type_t key_type;
const uint8_t server_pk[] = SERVER_PK_VALUE;
uint8_t derived_key[BUFFER_SIZE] = { 0 };
size_t derived_key_len;
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&client_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&client_attributes, PSA_ALG_ECDH);
psa_set_key_type(&client_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&client_attributes, KEY_BITS);
/* Generate ephemeral key pair */
status = psa_generate_key(&client_attributes, &client_key_id);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_generate_key failed\n");
return EXIT_FAILURE;
}
status = psa_export_public_key(client_key_id,
client_pk, sizeof(client_pk),
&client_pk_len);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_export_public_key failed\n");
return EXIT_FAILURE;
}
mbedtls_printf("Client Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", client_pk_len);
for (size_t j = 0; j < client_pk_len; j++) {
if (j % 8 == 0) {
mbedtls_printf("\n ");
}
mbedtls_printf("%02x ", client_pk[j]);
}
mbedtls_printf("\n\n");
psa_set_key_usage_flags(&server_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&server_attributes, PSA_ALG_ECDSA_ANY);
psa_set_key_type(&server_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
/* Import server public key */
status = psa_import_key(&server_attributes, server_pk, sizeof(server_pk), &server_key_id);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
status = psa_get_key_attributes(server_key_id, &check_attributes);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_get_key_attributes failed\n");
return EXIT_FAILURE;
}
key_bits = psa_get_key_bits(&check_attributes);
if (key_bits != 256) {
mbedtls_printf("Incompatible key size!\n");
return EXIT_FAILURE;
}
key_type = psa_get_key_type(&check_attributes);
if (key_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
mbedtls_printf("Unsupported key type!\n");
return EXIT_FAILURE;
}
mbedtls_printf("Server Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", sizeof(server_pk));
for (size_t j = 0; j < sizeof(server_pk); j++) {
if (j % 8 == 0) {
mbedtls_printf("\n ");
}
mbedtls_printf("%02x ", server_pk[j]);
}
mbedtls_printf("\n\n");
/* Generate ECDHE derived key */
status = psa_raw_key_agreement(PSA_ALG_ECDH, // algorithm
client_key_id, // client secret key
server_pk, sizeof(server_pk), // server public key
derived_key, sizeof(derived_key), // buffer to store derived key
&derived_key_len);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_raw_key_agreement failed\n");
return EXIT_FAILURE;
}
mbedtls_printf("Derived Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", derived_key_len);
for (size_t j = 0; j < derived_key_len; j++) {
if (j % 8 == 0) {
mbedtls_printf("\n ");
}
mbedtls_printf("%02x ", derived_key[j]);
}
mbedtls_printf("\n");
psa_destroy_key(server_key_id);
psa_destroy_key(client_key_id);
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,162 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
/* constant-time buffer comparison */
static inline int safer_memcmp(const void *a, const void *b, size_t n)
{
size_t i;
volatile const unsigned char *A = (volatile const unsigned char *) a;
volatile const unsigned char *B = (volatile const unsigned char *) b;
volatile unsigned char diff = 0;
for (i = 0; i < n; i++) {
/* Read volatile data in order before computing diff.
* This avoids IAR compiler warning:
* 'the order of volatile accesses is undefined ..' */
unsigned char x = A[i], y = B[i];
diff |= x ^ y;
}
return diff;
}
int psa_mac_main(void)
{
uint8_t input[] = "Hello World!";
psa_status_t status;
size_t mac_size_real = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
uint8_t mac[PSA_MAC_MAX_SIZE];
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
const uint8_t key_bytes[16] = "kkkkkkkkkkkkkkkk";
const uint8_t mbedtls_test_hmac_sha256[] = {
0xae, 0x72, 0x34, 0x5a, 0x10, 0x36, 0xfb, 0x71,
0x35, 0x3c, 0x7d, 0x6c, 0x81, 0x98, 0x52, 0x86,
0x00, 0x4a, 0x43, 0x7c, 0x2d, 0xb3, 0x1a, 0xd8,
0x67, 0xb1, 0xad, 0x11, 0x4d, 0x18, 0x49, 0x8b
};
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE |
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
/* Single-part MAC operation with psa_mac_compute() */
status = psa_mac_compute(key_id,
PSA_ALG_HMAC(PSA_ALG_SHA_256),
input,
sizeof(input),
mac,
sizeof(mac),
&mac_size_real);
if (status != PSA_SUCCESS) {
printf("psa_mac_compute failed\n");
return EXIT_FAILURE;
}
printf("HMAC-SHA-256(%s) with psa_mac_compute():\n", input);
for (size_t j = 0; j < mac_size_real; j++) {
if (j % 8 == 0) {
printf("\n ");
}
printf("%02x ", mac[j]);
}
printf("\n");
if (safer_memcmp(mac,
mbedtls_test_hmac_sha256,
mac_size_real
) != 0) {
printf("\nMAC verified incorrectly!\n");
} else {
printf("\nMAC verified correctly!\n");
}
psa_destroy_key(key_id);
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
/* Single-part MAC operation with psa_mac_verify() */
status = psa_mac_verify(key_id,
PSA_ALG_HMAC(PSA_ALG_SHA_256),
input,
sizeof(input),
mbedtls_test_hmac_sha256,
sizeof(mbedtls_test_hmac_sha256));
if (status != PSA_SUCCESS) {
printf("psa_mac_verify failed\n");
return EXIT_FAILURE;
} else {
printf("psa_mac_verify passed successfully\n");
}
psa_destroy_key(key_id);
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
/* Multi-part MAC operation */
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
if (status != PSA_SUCCESS) {
printf("psa_mac_sign_setup failed\n");
return EXIT_FAILURE;
}
status = psa_mac_update(&operation, input, sizeof(input));
if (status != PSA_SUCCESS) {
printf("psa_mac_update failed\n");
return EXIT_FAILURE;
}
status = psa_mac_sign_finish(&operation, mac, sizeof(mac), &mac_size_real);
if (status != PSA_SUCCESS) {
printf("psa_mac_sign_finish failed\n");
return EXIT_FAILURE;
}
if (safer_memcmp(mac,
mbedtls_test_hmac_sha256,
mac_size_real
) != 0) {
printf("MAC, calculated with multi-part MAC operation, verified incorrectly!\n");
} else {
printf("MAC, calculated with multi-part MAC operation, verified correctly!\n");
}
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include <psa/crypto.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/entropy.h"
#define BUFFER_SIZE 100
int psa_random_main(void)
{
psa_status_t status;
uint8_t output[BUFFER_SIZE] = { 0 };
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
status = psa_generate_random(output, BUFFER_SIZE);
if (status != PSA_SUCCESS) {
printf("psa_generate_random failed\n");
return EXIT_FAILURE;
}
printf("Random bytes generated:\n");
for (size_t j = 0; j < BUFFER_SIZE; j++) {
if (j % 8 == 0) {
printf("\n ");
}
printf("%02x ", output[j]);
}
printf("\n");
mbedtls_psa_crypto_free();
return 0;
}

View File

@ -0,0 +1,93 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "psa/crypto.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#define KEY_BYTES_VALUE { \
0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, 0x38, 0xc4, 0x31, 0xcf, \
0x1d, 0xf1, 0xc9, 0x94, 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, \
0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee \
}
#define PLAINTEXT_VALUE "Hello World!"
/* SHA-256(plaintext) */
#define HASH_VALUE { \
0x5a, 0x09, 0xe8, 0xfa, 0x9c, 0x77, 0x80, 0x7b, 0x24, 0xe9, 0x9c, 0x9c, \
0xf9, 0x99, 0xde, 0xbf, 0xad, 0x84, 0x41, 0xe2, 0x69, 0xeb, 0x96, 0x0e, \
0x20, 0x1f, 0x61, 0xfc, 0x3d, 0xe2, 0x0d, 0x5a \
}
int psa_sign_verify_main(void)
{
psa_status_t status;
psa_key_id_t key_id = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
size_t signature_length;
const uint8_t key_bytes[] = KEY_BYTES_VALUE;
const uint8_t plaintext[] = PLAINTEXT_VALUE;
const uint8_t hash[] = HASH_VALUE;
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_crypto_init failed\n");
return EXIT_FAILURE;
}
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_import_key failed\n");
return EXIT_FAILURE;
}
status = psa_sign_hash(key_id, // key handle
PSA_ALG_ECDSA(PSA_ALG_SHA_256), // signature algorithm
hash, sizeof(hash), // hash of the message
signature, sizeof(signature), // signature (as output)
&signature_length); // length of signature output
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_sign_hash failed\n");
return EXIT_FAILURE;
}
mbedtls_printf("ECDSA-SHA256 signature of SHA-256('%s'):\n", plaintext);
for (size_t j = 0; j < signature_length; j++) {
if (j % 8 == 0) {
mbedtls_printf("\n ");
}
mbedtls_printf("%02x ", signature[j]);
}
mbedtls_printf("\n");
status = psa_verify_hash(key_id, // key handle
PSA_ALG_ECDSA(PSA_ALG_SHA_256), // signature algorithm
hash, sizeof(hash), // hash of message
signature, signature_length); // signature
if (status != PSA_SUCCESS) {
mbedtls_printf("psa_verify_hash failed\n");
return EXIT_FAILURE;
} else {
mbedtls_printf("\nSignature verification successful!\n");
}
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,23 @@
/* psasim test client */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* Includes from mbedtls */
#include "psa/crypto.h"
#include "util.h"
int main()
{
/* psa_crypto_init() connects to the server */
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
ERROR("psa_crypto_init returned %d", status);
return 1;
}
mbedtls_psa_crypto_free();
return 0;
}

View File

@ -0,0 +1,29 @@
{
"psa_framework_version":1.0,
"name":"TEST_PARTITION",
"type":"PSA-ROT",
"priority":"LOW",
"entry_point":"psa_server_main",
"stack_size":"0x400",
"heap_size":"0x100",
"services":[
{
"name":"PSA_SID_CRYPTO",
"sid":"0x0000F000",
"signal":"PSA_CRYPTO",
"non_secure_clients": "true",
"minor_version":1,
"minor_policy":"STRICT"
}
],
"irqs": [
{
"source": "SIGINT",
"signal": "SIGINT_SIG"
},
{
"source": "SIGTSTP",
"signal": "SIGSTP_SIG"
}
]
}

View File

@ -0,0 +1,385 @@
/* PSA firmware framework client API */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "client.h"
#include "common.h"
#include "error_ext.h"
#include "util.h"
typedef struct internal_handle {
int server_qid;
int client_qid;
int internal_server_qid;
int valid;
} internal_handle_t;
typedef struct vectors {
const psa_invec *in_vec;
size_t in_len;
psa_outvec *out_vec;
size_t out_len;
} vectors_t;
/* Note that this implementation is functional and not secure */
int __psa_ff_client_security_state = NON_SECURE;
/* Access to this global is not thread safe */
#define MAX_HANDLES 32
static internal_handle_t handles[MAX_HANDLES] = { { 0 } };
static int get_next_free_handle()
{
/* Never return handle 0 as it's a special null handle */
for (int i = 1; i < MAX_HANDLES; i++) {
if (handles[i].valid == 0) {
return i;
}
}
return -1;
}
static int handle_is_valid(psa_handle_t handle)
{
if (handle > 0 && handle < MAX_HANDLES) {
if (handles[handle].valid == 1) {
return 1;
}
}
ERROR("ERROR: Invalid handle");
return 0;
}
static int get_queue_info(char *path, int *cqid, int *sqid)
{
key_t server_queue_key;
int rx_qid, server_qid;
INFO("Attempting to contact a RoT service queue");
if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) {
ERROR("msgget: rx_qid");
return -1;
}
if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) {
ERROR("ftok");
return -2;
}
if ((server_qid = msgget(server_queue_key, 0)) == -1) {
ERROR("msgget: server_qid");
return -3;
}
*cqid = rx_qid;
*sqid = server_qid;
return 0;
}
static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type,
int *internal_server_qid)
{
struct message response, request;
psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
size_t invec_seek[4] = { 0 };
size_t data_size;
psa_status_t invec, outvec; /* TODO: Should these be size_t ? */
assert(internal_server_qid > 0);
while (1) {
data_size = 0;
invec = 0;
outvec = 0;
/* read response from server */
if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) {
ERROR(" msgrcv failed");
return ret;
}
/* process return message from server */
switch (response.message_type) {
case PSA_REPLY:
memcpy(&ret, response.message_text.buf, sizeof(psa_status_t));
INFO(" Message received from server: %d", ret);
if (type == PSA_IPC_CONNECT && ret > 0) {
*internal_server_qid = ret;
INFO(" ASSSIGNED q ID %d", *internal_server_qid);
ret = PSA_SUCCESS;
}
return ret;
break;
case READ_REQUEST:
/* read data request */
request.message_type = READ_RESPONSE;
assert(vecs != 0);
memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
INFO(" Partition asked for %lu bytes from invec %d", data_size, invec);
/* need to add more checks here */
assert(invec >= 0 && invec < PSA_MAX_IOVEC);
if (data_size > MAX_FRAGMENT_SIZE) {
data_size = MAX_FRAGMENT_SIZE;
}
/* send response */
INFO(" invec_seek[invec] is %lu", invec_seek[invec]);
INFO(" Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]);
memcpy(request.message_text.buf,
(vecs->in_vec[invec].base + invec_seek[invec]),
data_size);
/* update invec base TODO: check me */
invec_seek[invec] = invec_seek[invec] + data_size;
INFO(" Sending message of type %li", request.message_type);
INFO(" with content %s", request.message_text.buf);
if (msgsnd(*internal_server_qid, &request,
sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) {
ERROR("Internal error: failed to respond to read request");
}
break;
case WRITE_REQUEST:
assert(vecs != 0);
request.message_type = WRITE_RESPONSE;
memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t));
memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t));
INFO(" Partition wants to write %lu bytes to outvec %d", data_size, outvec);
assert(outvec >= 0 && outvec < PSA_MAX_IOVEC);
/* copy memory into message and send back amount written */
size_t sofar = vecs->out_vec[outvec].len;
memcpy(vecs->out_vec[outvec].base + sofar,
response.message_text.buf+(sizeof(size_t)*2), data_size);
INFO(" Data size is %lu", data_size);
vecs->out_vec[outvec].len += data_size;
INFO(" Sending message of type %li", request.message_type);
/* send response */
if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) {
ERROR("Internal error: failed to respond to write request");
}
break;
case SKIP_REQUEST:
memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
INFO(" Partition asked to skip %lu bytes in invec %d", data_size, invec);
assert(invec >= 0 && invec < PSA_MAX_IOVEC);
/* update invec base TODO: check me */
invec_seek[invec] = invec_seek[invec] + data_size;
break;
default:
FATAL(" ERROR: unknown internal message type: %ld",
response.message_type);
}
}
}
static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid,
int32_t type, uint32_t minor_version, vectors_t *vecs)
{
psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */
struct message request;
request.message_type = 1; /* TODO: change this */
request.message_text.psa_type = type;
vector_sizes_t vec_sizes;
/* If the client is non-secure then set the NS bit */
if (__psa_ff_client_security_state != 0) {
request.message_type |= NON_SECURE;
}
assert(request.message_type >= 0);
INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type);
INFO(" internal_server_qid = %i", *internal_server_qid);
request.message_text.qid = rx_qid;
if (type == PSA_IPC_CONNECT) {
memcpy(request.message_text.buf, &minor_version, sizeof(minor_version));
request_msg_size = request_msg_size + sizeof(minor_version);
INFO(" Request msg size is %lu", request_msg_size);
} else {
assert(internal_server_qid > 0);
}
if (vecs != NULL && type >= PSA_IPC_CALL) {
memset(&vec_sizes, 0, sizeof(vec_sizes));
/* Copy invec sizes */
for (size_t i = 0; i < (vecs->in_len); i++) {
vec_sizes.invec_sizes[i] = vecs->in_vec[i].len;
INFO(" Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]);
}
/* Copy outvec sizes */
for (size_t i = 0; i < (vecs->out_len); i++) {
vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len;
/* Reset to 0 since we need to eventually fill in with bytes written */
vecs->out_vec[i].len = 0;
}
memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes));
request_msg_size = request_msg_size + sizeof(vec_sizes);
}
INFO(" Sending and then waiting");
/* send message to server */
if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) {
ERROR(" msgsnd failed");
return ret;
}
return process_response(rx_qid, vecs, type, internal_server_qid);
}
uint32_t psa_framework_version(void)
{
return PSA_FRAMEWORK_VERSION;
}
psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
{
int idx;
psa_status_t ret;
char pathname[PATHNAMESIZE] = { 0 };
idx = get_next_free_handle();
/* if there's a free handle available */
if (idx >= 0) {
snprintf(pathname, PATHNAMESIZE - 1, TMP_FILE_BASE_PATH "psa_service_%u", sid);
INFO("Attempting to contact RoT service at %s", pathname);
/* if communication is possible */
if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
ret = send(handles[idx].client_qid,
handles[idx].server_qid,
&handles[idx].internal_server_qid,
PSA_IPC_CONNECT,
minor_version,
NULL);
/* if connection accepted by RoT service */
if (ret >= 0) {
handles[idx].valid = 1;
return idx;
} else {
ERROR("Server didn't like you");
}
} else {
ERROR("Couldn't contact RoT service. Does it exist?");
if (__psa_ff_client_security_state == 0) {
ERROR("Invalid SID");
}
}
}
INFO("Couldn't obtain a free handle");
return PSA_ERROR_CONNECTION_REFUSED;
}
uint32_t psa_version(uint32_t sid)
{
int idx;
psa_status_t ret;
char pathname[PATHNAMESIZE] = { 0 };
idx = get_next_free_handle();
if (idx >= 0) {
snprintf(pathname, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_service_%u", sid);
if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
ret = send(handles[idx].client_qid,
handles[idx].server_qid,
&handles[idx].internal_server_qid,
VERSION_REQUEST,
0,
NULL);
INFO("psa_version: Recieved from server %d", ret);
if (ret > 0) {
return ret;
}
}
}
ERROR("psa_version failed: does the service exist?");
return PSA_VERSION_NONE;
}
psa_status_t psa_call(psa_handle_t handle,
int32_t type,
const psa_invec *in_vec,
size_t in_len,
psa_outvec *out_vec,
size_t out_len)
{
handle_is_valid(handle);
if ((in_len + out_len) > PSA_MAX_IOVEC) {
ERROR("Too many iovecs: %lu + %lu", in_len, out_len);
}
vectors_t vecs = { 0 };
vecs.in_vec = in_vec;
vecs.in_len = in_len;
vecs.out_vec = out_vec;
vecs.out_len = out_len;
return send(handles[handle].client_qid,
handles[handle].server_qid,
&handles[handle].internal_server_qid,
type,
0,
&vecs);
}
void psa_close(psa_handle_t handle)
{
handle_is_valid(handle);
if (send(handles[handle].client_qid, handles[handle].server_qid,
&handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) {
ERROR("ERROR: Couldn't send disconnect msg");
} else {
if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) {
ERROR("ERROR: Failed to delete msg queue");
}
}
INFO("Closing handle %u", handle);
handles[handle].valid = 0;
}

View File

@ -0,0 +1,655 @@
/* PSA Firmware Framework service API */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include "service.h"
#include "init.h"
#include "error_ext.h"
#include "common.h"
#include "util.h"
#define MAX_CLIENTS 128
#define MAX_MESSAGES 32
struct connection {
uint32_t client;
void *rhandle;
int client_to_server_q;
};
/* Note that this implementation is functional and not secure. */
int __psa_ff_client_security_state = NON_SECURE;
static psa_msg_t messages[MAX_MESSAGES]; /* Message slots */
static uint8_t pending_message[MAX_MESSAGES] = { 0 }; /* Booleans indicating active message slots */
static uint32_t message_client[MAX_MESSAGES] = { 0 }; /* Each client's response queue */
static int nsacl[32];
static int strict_policy[32] = { 0 };
static uint32_t rot_svc_versions[32];
static int rot_svc_incoming_queue[32] = { -1 };
static struct connection connections[MAX_CLIENTS] = { { 0 } };
static uint32_t exposed_signals = 0;
void print_vectors(vector_sizes_t *sizes)
{
INFO("Printing iovec sizes");
for (int j = 0; j < PSA_MAX_IOVEC; j++) {
INFO("Invec %d: %lu", j, sizes->invec_sizes[j]);
}
for (int j = 0; j < PSA_MAX_IOVEC; j++) {
INFO("Outvec %d: %lu", j, sizes->outvec_sizes[j]);
}
}
int find_connection(uint32_t client)
{
for (int i = 1; i < MAX_CLIENTS; i++) {
if (client == connections[i].client) {
return i;
}
}
return -1;
}
void destroy_connection(uint32_t client)
{
int idx = find_connection(client);
if (idx >= 0) {
connections[idx].client = 0;
connections[idx].rhandle = 0;
INFO("Destroying connection");
} else {
ERROR("Couldn't destroy connection for %u", client);
}
}
int find_free_connection()
{
INFO("Allocating connection");
return find_connection(0);
}
static void reply(psa_handle_t msg_handle, psa_status_t status)
{
pending_message[msg_handle] = 1;
psa_reply(msg_handle, status);
pending_message[msg_handle] = 0;
}
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
{
psa_signal_t mask;
struct message msg;
vector_sizes_t sizes;
struct msqid_ds qinfo;
uint32_t requested_version;
ssize_t len;
int idx;
if (timeout == PSA_POLL) {
INFO("psa_wait: Called in polling mode");
}
do {
mask = signal_mask;
/* Check the status of each queue */
for (int i = 0; i < 32; i++) {
if (mask & 0x1) {
if (i < 3) {
// do nothing (reserved)
} else if (i == 3) {
// this must be psa doorbell
} else {
/* Check if this signal corresponds to a queue */
if (rot_svc_incoming_queue[i] >= 0 && (pending_message[i] == 0)) {
/* AFAIK there is no "peek" method in SysV, so try to get a message */
len = msgrcv(rot_svc_incoming_queue[i],
&msg,
sizeof(struct message_text),
0,
IPC_NOWAIT);
if (len > 0) {
INFO("Storing that QID in message_client[%d]", i);
INFO("The message handle will be %d", i);
msgctl(rot_svc_incoming_queue[i], IPC_STAT, &qinfo);
messages[i].client_id = qinfo.msg_lspid; /* PID of last msgsnd(2) call */
message_client[i] = msg.message_text.qid;
idx = find_connection(msg.message_text.qid);
if (msg.message_type & NON_SECURE) {
/* This is a non-secure message */
/* Check if NS client is allowed for this RoT service */
if (nsacl[i] <= 0) {
#if 0
INFO(
"Rejecting non-secure client due to manifest security policy");
reply(i, PSA_ERROR_CONNECTION_REFUSED);
continue; /* Skip to next signal */
#endif
}
msg.message_type &= ~(NON_SECURE); /* clear */
messages[i].client_id = messages[i].client_id * -1;
}
INFO("Got a message from client ID %d", messages[i].client_id);
INFO("Message type is %lu", msg.message_type);
INFO("PSA message type is %d", msg.message_text.psa_type);
messages[i].handle = i;
switch (msg.message_text.psa_type) {
case PSA_IPC_CONNECT:
if (len >= 16) {
memcpy(&requested_version, msg.message_text.buf,
sizeof(requested_version));
INFO("Requesting version %u", requested_version);
INFO("Implemented version %u", rot_svc_versions[i]);
/* TODO: need to check whether the policy is strict,
* and if so, then reject the client if the number doesn't match */
if (requested_version > rot_svc_versions[i]) {
INFO(
"Rejecting client because requested version that was too high");
reply(i, PSA_ERROR_CONNECTION_REFUSED);
continue; /* Skip to next signal */
}
if (strict_policy[i] == 1 &&
(requested_version != rot_svc_versions[i])) {
INFO(
"Rejecting client because enforcing a STRICT version policy");
reply(i, PSA_ERROR_CONNECTION_REFUSED);
continue; /* Skip to next signal */
} else {
INFO("Not rejecting client");
}
}
messages[i].type = PSA_IPC_CONNECT;
if (idx < 0) {
idx = find_free_connection();
}
if (idx >= 0) {
connections[idx].client = msg.message_text.qid;
} else {
/* We've run out of system wide connections */
reply(i, PSA_ERROR_CONNECTION_BUSY);
ERROR("Ran out of free connections");
continue;
}
break;
case PSA_IPC_DISCONNECT:
messages[i].type = PSA_IPC_DISCONNECT;
break;
case VERSION_REQUEST:
INFO("Got a version request");
reply(i, rot_svc_versions[i]);
continue; /* Skip to next signal */
break;
default:
/* PSA CALL */
if (msg.message_text.psa_type >= 0) {
messages[i].type = msg.message_text.psa_type;
memcpy(&sizes, msg.message_text.buf, sizeof(sizes));
print_vectors(&sizes);
memcpy(&messages[i].in_size, &sizes.invec_sizes,
(sizeof(size_t) * PSA_MAX_IOVEC));
memcpy(&messages[i].out_size, &sizes.outvec_sizes,
(sizeof(size_t) * PSA_MAX_IOVEC));
} else {
FATAL("UNKNOWN MESSAGE TYPE RECEIVED %li",
msg.message_type);
}
break;
}
messages[i].handle = i;
/* Check if the client has a connection */
if (idx >= 0) {
messages[i].rhandle = connections[idx].rhandle;
} else {
/* Client is begging for a programmer error */
reply(i, PSA_ERROR_PROGRAMMER_ERROR);
continue;
}
/* House keeping */
pending_message[i] = 1; /* set message as pending */
exposed_signals |= (0x1 << i); /* assert the signal */
}
}
}
mask = mask >> 1;
}
}
if ((timeout == PSA_BLOCK) && (exposed_signals > 0)) {
break;
} else {
/* There is no 'select' function in SysV to block on multiple queues, so busy-wait :( */
}
} while (timeout == PSA_BLOCK);
/* Assert signals */
return signal_mask & exposed_signals;
}
static int signal_to_index(psa_signal_t signal)
{
int i;
int count = 0;
int ret = -1;
for (i = 0; i < 32; i++) {
if (signal & 0x1) {
ret = i;
count++;
}
signal = signal >> 1;
}
if (count > 1) {
ERROR("ERROR: Too many signals");
return -1; /* Too many signals */
}
return ret;
}
static void clear_signal(psa_signal_t signal)
{
exposed_signals = exposed_signals & ~signal;
}
void raise_signal(psa_signal_t signal)
{
exposed_signals |= signal;
}
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
{
int index = signal_to_index(signal);
if (index < 0) {
ERROR("Bad signal");
}
clear_signal(signal);
assert(messages[index].handle != 0);
if (pending_message[index] == 1) {
INFO("There is a pending message!");
memcpy(msg, &messages[index], sizeof(struct psa_msg_t));
assert(msg->handle != 0);
return PSA_SUCCESS;
} else {
INFO("no pending message");
}
return PSA_ERROR_DOES_NOT_EXIST;
}
static inline int is_valid_msg_handle(psa_handle_t h)
{
if (h > 0 && h < MAX_MESSAGES) {
return 1;
}
ERROR("Not a valid message handle");
return 0;
}
static inline int is_call_msg(psa_handle_t h)
{
assert(messages[h].type >= PSA_IPC_CALL);
return 1;
}
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
{
is_valid_msg_handle(msg_handle);
int idx = find_connection(message_client[msg_handle]);
INFO("Setting rhandle to %p", rhandle);
assert(idx >= 0);
connections[idx].rhandle = rhandle;
}
/* Sends a message from the server to the client. Does not wait for a response */
static void send_msg(psa_handle_t msg_handle,
int ctrl_msg,
psa_status_t status,
size_t amount,
const void *data,
size_t data_amount)
{
struct message response;
int flags = 0;
assert(ctrl_msg > 0); /* According to System V, it must be greater than 0 */
response.message_type = ctrl_msg;
if (ctrl_msg == PSA_REPLY) {
memcpy(response.message_text.buf, &status, sizeof(psa_status_t));
} else if (ctrl_msg == READ_REQUEST || ctrl_msg == WRITE_REQUEST || ctrl_msg == SKIP_REQUEST) {
memcpy(response.message_text.buf, &status, sizeof(psa_status_t));
memcpy(response.message_text.buf+sizeof(size_t), &amount, sizeof(size_t));
if (ctrl_msg == WRITE_REQUEST) {
/* TODO: Check if too big */
memcpy(response.message_text.buf + (sizeof(size_t) * 2), data, data_amount);
}
}
/* TODO: sizeof doesn't need to be so big here for small responses */
if (msgsnd(message_client[msg_handle], &response, sizeof(response.message_text), flags) == -1) {
ERROR("Failed to reply");
}
}
static size_t skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
{
if (num_bytes < (messages[msg_handle].in_size[invec_idx] - num_bytes)) {
messages[msg_handle].in_size[invec_idx] = messages[msg_handle].in_size[invec_idx] -
num_bytes;
return num_bytes;
} else {
if (num_bytes >= messages[msg_handle].in_size[invec_idx]) {
size_t ret = messages[msg_handle].in_size[invec_idx];
messages[msg_handle].in_size[invec_idx] = 0;
return ret;
} else {
return num_bytes;
}
}
}
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
void *buffer, size_t num_bytes)
{
size_t sofar = 0;
struct message msg = { 0 };
int idx;
ssize_t len;
is_valid_msg_handle(msg_handle);
is_call_msg(msg_handle);
if (invec_idx >= PSA_MAX_IOVEC) {
ERROR("Invalid iovec number");
}
/* If user wants more data than what's available, truncate their request */
if (num_bytes > messages[msg_handle].in_size[invec_idx]) {
num_bytes = messages[msg_handle].in_size[invec_idx];
}
while (sofar < num_bytes) {
INFO("Server: requesting %lu bytes from client", (num_bytes - sofar));
send_msg(msg_handle, READ_REQUEST, invec_idx, (num_bytes - sofar), NULL, 0);
idx = find_connection(message_client[msg_handle]);
assert(idx >= 0);
len = msgrcv(connections[idx].client_to_server_q, &msg, sizeof(struct message_text), 0, 0);
len = (len - offsetof(struct message_text, buf));
if (len < 0) {
FATAL("Internal error: failed to dispatch read request to the client");
}
if (len > (num_bytes - sofar)) {
if ((num_bytes - sofar) > 0) {
memcpy(buffer+sofar, msg.message_text.buf, (num_bytes - sofar));
}
} else {
memcpy(buffer + sofar, msg.message_text.buf, len);
}
INFO("Printing what i got so far: %s", msg.message_text.buf);
sofar = sofar + len;
}
/* Update the seek count */
skip(msg_handle, invec_idx, num_bytes);
INFO("Finished psa_read");
return sofar;
}
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
const void *buffer, size_t num_bytes)
{
size_t sofar = 0;
struct message msg = { 0 };
int idx;
ssize_t len;
is_valid_msg_handle(msg_handle);
is_call_msg(msg_handle);
if (outvec_idx >= PSA_MAX_IOVEC) {
ERROR("Invalid iovec number");
}
if (num_bytes > messages[msg_handle].out_size[outvec_idx]) {
ERROR("Program tried to write too much data %lu/%lu", num_bytes,
messages[msg_handle].out_size[outvec_idx]);
}
while (sofar < num_bytes) {
size_t sending = (num_bytes - sofar);
if (sending > (MAX_FRAGMENT_SIZE - (sizeof(size_t) * 2))) {
sending = MAX_FRAGMENT_SIZE - (sizeof(size_t) * 2);
}
INFO("Server: sending %lu bytes to client, sofar = %lu", sending, (long) sofar);
send_msg(msg_handle, WRITE_REQUEST, outvec_idx, sending, buffer + sofar, sending);
idx = find_connection(message_client[msg_handle]);
assert(idx >= 0);
len = msgrcv(connections[idx].client_to_server_q, &msg, sizeof(struct message_text), 0, 0);
if (len < 1) {
FATAL("Client didn't give me a full response");
}
sofar = sofar + sending;
}
/* Update the seek count */
messages[msg_handle].out_size[outvec_idx] -= num_bytes;
}
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
{
is_valid_msg_handle(msg_handle);
is_call_msg(msg_handle);
size_t ret = skip(msg_handle, invec_idx, num_bytes);
/* notify client to skip */
send_msg(msg_handle, SKIP_REQUEST, invec_idx, num_bytes, NULL, 0);
return ret;
}
static void destroy_temporary_queue(int myqid)
{
if (msgctl(myqid, IPC_RMID, NULL) != 0) {
INFO("ERROR: Failed to delete msg queue %d", myqid);
}
}
static int make_temporary_queue()
{
int myqid;
if ((myqid = msgget(IPC_PRIVATE, 0660)) == -1) {
INFO("msgget: myqid");
return -1;
}
return myqid;
}
/**
* Assumes msg_handle is the index into the message array
*/
void psa_reply(psa_handle_t msg_handle, psa_status_t status)
{
int idx, q;
is_valid_msg_handle(msg_handle);
if (pending_message[msg_handle] != 1) {
ERROR("Not a valid message handle");
}
if (messages[msg_handle].type == PSA_IPC_CONNECT) {
switch (status) {
case PSA_SUCCESS:
idx = find_connection(message_client[msg_handle]);
q = make_temporary_queue();
if (q > 0 && idx >= 0) {
connections[idx].client_to_server_q = q;
status = q;
} else {
FATAL("What happened?");
}
break;
case PSA_ERROR_CONNECTION_REFUSED:
destroy_connection(message_client[msg_handle]);
break;
case PSA_ERROR_CONNECTION_BUSY:
destroy_connection(message_client[msg_handle]);
break;
case PSA_ERROR_PROGRAMMER_ERROR:
destroy_connection(message_client[msg_handle]);
break;
default:
ERROR("Not a valid reply %d", status);
}
} else if (messages[msg_handle].type == PSA_IPC_DISCONNECT) {
idx = find_connection(message_client[msg_handle]);
if (idx >= 0) {
destroy_temporary_queue(connections[idx].client_to_server_q);
}
destroy_connection(message_client[msg_handle]);
}
send_msg(msg_handle, PSA_REPLY, status, 0, NULL, 0);
pending_message[msg_handle] = 0;
message_client[msg_handle] = 0;
}
/* TODO: make sure you only clear interrupt signals, and not others */
void psa_eoi(psa_signal_t signal)
{
int index = signal_to_index(signal);
if (index >= 0 && (rot_svc_incoming_queue[index] >= 0)) {
clear_signal(signal);
} else {
ERROR("Tried to EOI a signal that isn't an interrupt");
}
}
void psa_notify(int32_t partition_id)
{
char pathname[PATHNAMESIZE] = { 0 };
if (partition_id < 0) {
ERROR("Not a valid secure partition");
}
snprintf(pathname, PATHNAMESIZE, "/tmp/psa_notify_%u", partition_id);
INFO("psa_notify: notifying partition %u using %s",
partition_id, pathname);
INFO("psa_notify is unimplemented");
}
void psa_clear(void)
{
clear_signal(PSA_DOORBELL);
}
void __init_psasim(const char **array,
int size,
const int allow_ns_clients_array[32],
const uint32_t versions[32],
const int strict_policy_array[32])
{
static uint8_t library_initialised = 0;
key_t key;
int qid;
FILE *fp;
char doorbell_path[PATHNAMESIZE] = { 0 };
char queue_path[PATHNAMESIZE];
snprintf(doorbell_path, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_notify_%u", getpid());
if (library_initialised > 0) {
return;
} else {
library_initialised = 1;
}
if (size != 32) {
FATAL("Unsupported value. Aborting.");
}
array[3] = doorbell_path;
for (int i = 0; i < 32; i++) {
if (strncmp(array[i], "", 1) != 0) {
INFO("Setting up %s", array[i]);
memset(queue_path, 0, sizeof(queue_path));
snprintf(queue_path, sizeof(queue_path), "%s%s", TMP_FILE_BASE_PATH, array[i]);
/* Create file if doesn't exist */
fp = fopen(queue_path, "ab+");
if (fp) {
fclose(fp);
}
if ((key = ftok(queue_path, PROJECT_ID)) == -1) {
FATAL("Error finding message queue during initialisation");
}
/* TODO: Investigate. Permissions are likely to be too relaxed */
if ((qid = msgget(key, IPC_CREAT | 0660)) == -1) {
FATAL("Error opening message queue during initialisation");
} else {
rot_svc_incoming_queue[i] = qid;
}
}
}
memcpy(nsacl, allow_ns_clients_array, sizeof(int) * 32);
memcpy(strict_policy, strict_policy_array, sizeof(int) * 32);
memcpy(rot_svc_versions, versions, sizeof(uint32_t) * 32);
memset(&connections, 0, sizeof(struct connection) * MAX_CLIENTS);
__psa_ff_client_security_state = 0; /* Set the client status to SECURE */
}

View File

@ -0,0 +1,93 @@
/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef _PSA_FUNCTIONS_CODES_H_
#define _PSA_FUNCTIONS_CODES_H_
enum {
/* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
* and VERSION_REQUEST */
PSA_CRYPTO_INIT = 100,
PSA_AEAD_ABORT,
PSA_AEAD_DECRYPT,
PSA_AEAD_DECRYPT_SETUP,
PSA_AEAD_ENCRYPT,
PSA_AEAD_ENCRYPT_SETUP,
PSA_AEAD_FINISH,
PSA_AEAD_GENERATE_NONCE,
PSA_AEAD_SET_LENGTHS,
PSA_AEAD_SET_NONCE,
PSA_AEAD_UPDATE,
PSA_AEAD_UPDATE_AD,
PSA_AEAD_VERIFY,
PSA_ASYMMETRIC_DECRYPT,
PSA_ASYMMETRIC_ENCRYPT,
PSA_CIPHER_ABORT,
PSA_CIPHER_DECRYPT,
PSA_CIPHER_DECRYPT_SETUP,
PSA_CIPHER_ENCRYPT,
PSA_CIPHER_ENCRYPT_SETUP,
PSA_CIPHER_FINISH,
PSA_CIPHER_GENERATE_IV,
PSA_CIPHER_SET_IV,
PSA_CIPHER_UPDATE,
PSA_COPY_KEY,
PSA_DESTROY_KEY,
PSA_EXPORT_KEY,
PSA_EXPORT_PUBLIC_KEY,
PSA_GENERATE_KEY,
PSA_GENERATE_KEY_EXT,
PSA_GENERATE_RANDOM,
PSA_GET_KEY_ATTRIBUTES,
PSA_HASH_ABORT,
PSA_HASH_CLONE,
PSA_HASH_COMPARE,
PSA_HASH_COMPUTE,
PSA_HASH_FINISH,
PSA_HASH_SETUP,
PSA_HASH_UPDATE,
PSA_HASH_VERIFY,
PSA_IMPORT_KEY,
PSA_INTERRUPTIBLE_GET_MAX_OPS,
PSA_INTERRUPTIBLE_SET_MAX_OPS,
PSA_KEY_DERIVATION_ABORT,
PSA_KEY_DERIVATION_GET_CAPACITY,
PSA_KEY_DERIVATION_INPUT_BYTES,
PSA_KEY_DERIVATION_INPUT_INTEGER,
PSA_KEY_DERIVATION_INPUT_KEY,
PSA_KEY_DERIVATION_KEY_AGREEMENT,
PSA_KEY_DERIVATION_OUTPUT_BYTES,
PSA_KEY_DERIVATION_OUTPUT_KEY,
PSA_KEY_DERIVATION_OUTPUT_KEY_EXT,
PSA_KEY_DERIVATION_SET_CAPACITY,
PSA_KEY_DERIVATION_SETUP,
PSA_MAC_ABORT,
PSA_MAC_COMPUTE,
PSA_MAC_SIGN_FINISH,
PSA_MAC_SIGN_SETUP,
PSA_MAC_UPDATE,
PSA_MAC_VERIFY,
PSA_MAC_VERIFY_FINISH,
PSA_MAC_VERIFY_SETUP,
PSA_PURGE_KEY,
PSA_RAW_KEY_AGREEMENT,
PSA_RESET_KEY_ATTRIBUTES,
PSA_SIGN_HASH,
PSA_SIGN_HASH_ABORT,
PSA_SIGN_HASH_COMPLETE,
PSA_SIGN_HASH_GET_NUM_OPS,
PSA_SIGN_HASH_START,
PSA_SIGN_MESSAGE,
PSA_VERIFY_HASH,
PSA_VERIFY_HASH_ABORT,
PSA_VERIFY_HASH_COMPLETE,
PSA_VERIFY_HASH_GET_NUM_OPS,
PSA_VERIFY_HASH_START,
PSA_VERIFY_MESSAGE,
};
#endif /* _PSA_FUNCTIONS_CODES_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
/* psasim test server */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <unistd.h>
#include <stdio.h>
/* Includes from psasim */
#include "service.h"
#include "error_ext.h"
#include "util.h"
#include "psa_manifest/manifest.h"
#include "psa_functions_codes.h"
/* Includes from mbedtls */
#include "mbedtls/version.h"
#include "psa/crypto.h"
#ifdef DEBUG
#define SERVER_PRINT(fmt, ...) \
PRINT("Server: " fmt, ##__VA_ARGS__)
#else
#define SERVER_PRINT(...)
#endif
#define BUF_SIZE 25
static int kill_on_disconnect = 0; /* Kill the server on client disconnection. */
void parse_input_args(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "k")) != -1) {
switch (opt) {
case 'k':
kill_on_disconnect = 1;
break;
default:
fprintf(stderr, "Usage: %s [-k]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
}
int psa_server_main(int argc, char *argv[])
{
psa_status_t ret = PSA_ERROR_PROGRAMMER_ERROR;
psa_msg_t msg = { -1 };
const int magic_num = 66;
int client_disconnected = 0;
char mbedtls_version[18];
extern psa_status_t psa_crypto_call(psa_msg_t msg);
extern psa_status_t psa_crypto_close(void);
mbedtls_version_get_string_full(mbedtls_version);
SERVER_PRINT("%s", mbedtls_version);
parse_input_args(argc, argv);
SERVER_PRINT("Starting");
while (!(kill_on_disconnect && client_disconnected)) {
psa_signal_t signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
if (signals > 0) {
SERVER_PRINT("Signals: 0x%08x", signals);
}
if (signals & PSA_CRYPTO_SIGNAL) {
if (PSA_SUCCESS == psa_get(PSA_CRYPTO_SIGNAL, &msg)) {
SERVER_PRINT("handle: %d - rhandle: %p", msg.handle, (int *) msg.rhandle);
switch (msg.type) {
case PSA_IPC_CONNECT:
SERVER_PRINT("Got a connection message");
psa_set_rhandle(msg.handle, (void *) &magic_num);
ret = PSA_SUCCESS;
break;
case PSA_IPC_DISCONNECT:
SERVER_PRINT("Got a disconnection message");
ret = PSA_SUCCESS;
client_disconnected = 1;
psa_crypto_close();
break;
default:
SERVER_PRINT("Got an IPC call of type %d", msg.type);
ret = psa_crypto_call(msg);
SERVER_PRINT("Internal function call returned %d", ret);
if (msg.client_id > 0) {
psa_notify(msg.client_id);
} else {
SERVER_PRINT("Client is non-secure, so won't notify");
}
}
psa_reply(msg.handle, ret);
} else {
SERVER_PRINT("Failed to retrieve message");
}
} else if (SIGSTP_SIG & signals) {
SERVER_PRINT("Recieved SIGSTP signal. Gonna EOI it.");
psa_eoi(SIGSTP_SIG);
} else if (SIGINT_SIG & signals) {
SERVER_PRINT("Handling interrupt!");
SERVER_PRINT("Gracefully quitting");
psa_panic();
} else {
SERVER_PRINT("No signal asserted");
}
}
return 0;
}

View File

@ -0,0 +1,16 @@
#!/bin/bash
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
set -e
pkill psa_server || true
# Remove temporary files and logs
rm -f psa_notify_*
rm -f psa_service_*
rm -f psa_server.log
# Remove all IPCs
ipcs -q | awk '{ printf " -q " $2 }' | xargs ipcrm > /dev/null 2>&1 || true

View File

@ -0,0 +1,25 @@
#!/bin/bash
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
# This is a simple bash script that tests psa_client/psa_server interaction.
# This script is automatically executed when "make run" is launched by the
# "psasim" root folder. The script can also be launched manually once
# binary files are built (i.e. after "make test" is executed from the "psasim"
# root folder).
set -e
cd "$(dirname "$0")"
CLIENT_BIN=$1
shift
ipcs | grep q | awk '{ printf " -q " $2 }' | xargs ipcrm > /dev/null 2>&1 || true
./start_server.sh
./$CLIENT_BIN "$@"
# Kill server once client exited
pkill psa_server

View File

@ -0,0 +1,19 @@
#!/bin/bash
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
set -e
# The server creates some local files when it starts up so we can wait for this
# event as signal that the server is ready so that we can start client(s).
function wait_for_server_startup() {
while [ $(find . -name "psa_notify_*" | wc -l) -eq 0 ]; do
sleep 0.1
done
}
$(dirname "$0")/kill_server.sh
$(dirname "$0")/psa_server &
wait_for_server_startup

View File

@ -0,0 +1,174 @@
#!/usr/bin/env python3
"""This hacky script generates a partition from a manifest file"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import json
import os
import sys
from os import listdir
if len(sys.argv) != 2:
print("Usage: psa_autogen <manifest_file>")
sys.exit(1)
FILENAME = str(sys.argv[1])
SCRIPT_PATH = os.path.dirname(__file__)
GENERATED_H_PATH = os.path.join(SCRIPT_PATH, "..", "include", "psa_manifest")
GENERATED_C_PATH = os.path.join(SCRIPT_PATH, "..", "src")
MANIFEST_FILE = os.path.join(GENERATED_H_PATH, "manifest.h")
PID_FILE = os.path.join(GENERATED_H_PATH, "pid.h")
SID_FILE = os.path.join(GENERATED_H_PATH, "sid.h")
with open(str(FILENAME), "r") as read_file:
data = json.load(read_file)
FILENAME = os.path.basename(FILENAME)
FILENAME = FILENAME.split('.')[0]
print("Base filename is " + str(FILENAME))
if str(data['psa_framework_version'] == "1.0"):
entry_point = str(data['entry_point'])
partition_name = str(data['name'])
services = data['services']
try:
irqs = data['irqs']
except KeyError:
irqs = []
try:
os.mkdir(GENERATED_H_PATH)
print("Generating psa_manifest directory")
except OSError:
print("PSA manifest directory already exists")
manifest_content = []
pids_content = []
sids_content = []
if len(services) > 28:
print ("Unsupported number of services")
count = 4 # For creating SID array
nsacl = "const int ns_allowed[32] = { "
policy = "const int strict_policy[32] = { "
qcode = "const char *psa_queues[] = { "
versions = "const uint32_t versions[32] = { "
queue_path = "psa_service_"
start = False
for x in range(0, count):
qcode = qcode + "\"\", "
nsacl = nsacl + "0, "
policy = policy + "0, "
versions = versions + "0, "
# Go through all the services to make sid.h and pid.h
for svc in services:
manifest_content.append("#define {}_SIGNAL 0x{:08x}".format(svc['signal'], 2**count))
sids_content.append("#define {}_SID {}".format(svc['name'], svc['sid']))
qcode = qcode + "\"" + queue_path + str(int(svc['sid'], 16)) + "\","
ns_clients = svc['non_secure_clients']
print(str(svc))
if ns_clients == "true":
nsacl = nsacl + "1, "
else:
nsacl = nsacl + "0, "
try:
versions = versions + str(svc['minor_version']) + ", "
except KeyError:
versions = versions + "1, "
strict = 0
try:
if str(svc['minor_policy']).lower() == "strict":
strict = 1
policy = policy + "1, "
else:
policy = policy + "0, "
except KeyError:
strict = 0
policy = policy + "0, "
count = count+1
sigcode = ""
handlercode = "void __sig_handler(int signo) {\n"
irqcount = count
for irq in irqs:
manifest_content.append("#define {} 0x{:08x}".format(irq['signal'], 2**irqcount))
sigcode = sigcode + " signal({}, __sig_handler);\n".format(irq['source'])
handlercode = handlercode + \
" if (signo == {}) {{ raise_signal(0x{:08x}); }};\n".format(irq['source'], 2**irqcount)
irqcount = irqcount+1
handlercode = handlercode + "}\n"
while (count < 32):
qcode = qcode + "\"\", "
nsacl = nsacl + "0, "
versions = versions + "0, "
policy = policy + "0, "
count = count + 1
qcode = qcode + "};\n"
nsacl = nsacl + "};\n"
versions = versions + "};\n"
policy = policy + "};\n"
with open(MANIFEST_FILE, "wt") as output:
output.write("\n".join(manifest_content))
with open(SID_FILE, "wt") as output:
output.write("\n".join(sids_content))
with open(PID_FILE, "wt") as output:
output.write("\n".join(pids_content))
symbols = []
# Go through source files and look for the entrypoint
for root, directories, filenames in os.walk(GENERATED_C_PATH):
for filename in filenames:
if "psa_ff_bootstrap" in filename or filename == "psa_manifest":
continue
try:
fullpath = os.path.join(root,filename)
with open(fullpath, encoding='utf-8') as currentFile:
text = currentFile.read()
if str(entry_point + "(") in text:
symbols.append(filename)
except IOError:
print("Couldn't open " + filename)
except UnicodeDecodeError:
pass
print(str("Number of entrypoints detected: " + str(len(symbols))))
if len(symbols) < 1:
print("Couldn't find function " + entry_point)
sys.exit(1)
elif len(symbols) > 1:
print("Duplicate entrypoint symbol detected: " + str(symbols))
sys.exit(2)
else:
C_FILENAME = os.path.join(GENERATED_C_PATH, "psa_ff_bootstrap_" + partition_name + ".c")
c_content = []
c_content.append("#include <init.h>")
c_content.append("#include \"" + symbols[0] + "\"")
c_content.append("#include <signal.h>")
c_content.append(qcode)
c_content.append(nsacl)
c_content.append(policy)
c_content.append(versions)
c_content.append(handlercode)
c_content.append("int main(int argc, char *argv[]) {")
c_content.append(" (void) argc;")
c_content.append(sigcode)
c_content.append(" __init_psasim(psa_queues, 32, ns_allowed, versions,"
"strict_policy);")
c_content.append(" " + entry_point + "(argc, argv);")
c_content.append("}")
with open(C_FILENAME, "wt") as output:
output.write("\n".join(c_content))
print("Success")

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,17 @@ def execute_reference_driver_tests(results: Results, ref_component: str, driver_
def analyze_coverage(results: Results, outcomes: Outcomes,
allow_list: typing.List[str], full_coverage: bool) -> None:
"""Check that all available test cases are executed at least once."""
# Make sure that the generated data files are present (and up-to-date).
# This allows analyze_outcomes.py to run correctly on a fresh Git
# checkout.
cp = subprocess.run(['make', 'generated_files'],
cwd='tests',
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
check=False)
if cp.returncode != 0:
sys.stderr.write(cp.stdout.decode('utf-8'))
results.error("Failed \"make generated_files\" in tests. "
"Coverage analysis may be incorrect.")
available = check_test_cases.collect_available_test_cases()
for suite_case in available:
hit = any(suite_case in comp_outcomes.successes or
@ -149,10 +160,10 @@ def analyze_driver_vs_reference(results: Results, outcomes: Outcomes,
# don't issue an error if they're skipped with drivers,
# but issue an error if they're not (means we have a bad entry).
ignored = False
if full_test_suite in ignored_tests:
for str_or_re in ignored_tests[full_test_suite]:
if name_matches_pattern(test_string, str_or_re):
ignored = True
for str_or_re in (ignored_tests.get(full_test_suite, []) +
ignored_tests.get(test_suite, [])):
if name_matches_pattern(test_string, str_or_re):
ignored = True
if not ignored and not suite_case in driver_outcomes.successes:
results.error("PASS -> SKIP/FAIL: {}", suite_case)
@ -231,6 +242,9 @@ KNOWN_TASKS = {
'psa_crypto_low_hash.generated', # testing the builtins
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(MD5|RIPEMD160|SHA[0-9]+)_.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -254,6 +268,10 @@ KNOWN_TASKS = {
'psa_crypto_low_hash.generated',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(MD5|RIPEMD160|SHA[0-9]+)_.*'),
re.compile(r'.*\bMBEDTLS_MD_C\b')
],
'test_suite_md': [
# Builtin HMAC is not supported in the accelerate component.
re.compile('.*HMAC.*'),
@ -293,6 +311,12 @@ KNOWN_TASKS = {
'cipher',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(AES|ARIA|CAMELLIA|CHACHA20|DES)_.*'),
re.compile(r'.*\bMBEDTLS_(CCM|CHACHAPOLY|CMAC|GCM)_.*'),
re.compile(r'.*\bMBEDTLS_AES(\w+)_C\b.*'),
re.compile(r'.*\bMBEDTLS_CIPHER_.*'),
],
# PEM decryption is not supported so far.
# The rest of PEM (write, unencrypted read) works though.
'test_suite_pem': [
@ -346,6 +370,9 @@ KNOWN_TASKS = {
'ecdsa', 'ecdh', 'ecjpake',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(ECDH|ECDSA|ECJPAKE|ECP)_.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -386,6 +413,10 @@ KNOWN_TASKS = {
'ecp', 'ecdsa', 'ecdh', 'ecjpake',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(ECDH|ECDSA|ECJPAKE|ECP)_.*'),
re.compile(r'.*\bMBEDTLS_PK_PARSE_EC_COMPRESSED\b.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -425,6 +456,11 @@ KNOWN_TASKS = {
'bignum.generated', 'bignum.misc',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_BIGNUM_C\b.*'),
re.compile(r'.*\bMBEDTLS_(ECDH|ECDSA|ECJPAKE|ECP)_.*'),
re.compile(r'.*\bMBEDTLS_PK_PARSE_EC_COMPRESSED\b.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -468,6 +504,19 @@ KNOWN_TASKS = {
'bignum.generated', 'bignum.misc',
],
'ignored_tests': {
'ssl-opt': [
# DHE support in TLS 1.2 requires built-in MBEDTLS_DHM_C
# (because it needs custom groups, which PSA does not
# provide), even with MBEDTLS_USE_PSA_CRYPTO.
re.compile(r'PSK callback:.*\bdhe-psk\b.*'),
],
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_BIGNUM_C\b.*'),
re.compile(r'.*\bMBEDTLS_DHM_C\b.*'),
re.compile(r'.*\bMBEDTLS_(ECDH|ECDSA|ECJPAKE|ECP)_.*'),
re.compile(r'.*\bMBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED\b.*'),
re.compile(r'.*\bMBEDTLS_PK_PARSE_EC_COMPRESSED\b.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -506,6 +555,9 @@ KNOWN_TASKS = {
'component_driver': 'test_psa_crypto_config_accel_ffdh',
'ignored_suites': ['dhm'],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_DHM_C\b.*'),
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -528,6 +580,15 @@ KNOWN_TASKS = {
'bignum.generated', 'bignum.misc',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_BIGNUM_C\b.*'),
re.compile(r'.*\bMBEDTLS_(ASN1\w+)_C\b.*'),
re.compile(r'.*\bMBEDTLS_(ECDH|ECDSA|ECP)_.*'),
re.compile(r'.*\bMBEDTLS_PSA_P256M_DRIVER_ENABLED\b.*')
],
'test_suite_config.crypto_combinations': [
'Config: ECC: Weierstrass curves only',
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -553,6 +614,10 @@ KNOWN_TASKS = {
'pk', 'pkwrite', 'pkparse'
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(PKCS1|RSA)_.*'),
re.compile(r'.*\bMBEDTLS_GENPRIME\b.*')
],
'test_suite_platform': [
# Incompatible with sanitizers (e.g. ASan). If the driver
# component uses a sanitizer but the reference component
@ -594,6 +659,10 @@ KNOWN_TASKS = {
'cipher.camellia',
],
'ignored_tests': {
'test_suite_config': [
re.compile(r'.*\bMBEDTLS_(AES|ARIA|CAMELLIA)_.*'),
re.compile(r'.*\bMBEDTLS_AES(\w+)_C\b.*'),
],
'test_suite_cmac': [
# Following tests require AES_C/ARIA_C/CAMELLIA_C to be enabled,
# but these are not available in the accelerated component.

View File

@ -29,8 +29,8 @@ from cryptography import x509
from generate_test_code import FileWrapper
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import build_tree
from mbedtls_dev import logging_util
from mbedtls_framework import build_tree
from mbedtls_framework import logging_util
def check_cryptography_version():
match = re.match(r'^[0-9]+', cryptography.__version__)

View File

@ -103,11 +103,7 @@ echo
echo '################ compat.sh ################'
{
echo '#### compat.sh: Default versions'
sh compat.sh
echo
echo '#### compat.sh: null cipher'
sh compat.sh -e '^$' -f 'NULL'
sh compat.sh -e 'ARIA\|CHACHA'
echo
echo '#### compat.sh: next (ARIA, ChaCha)'

View File

@ -128,9 +128,11 @@ check()
# These checks are common to Mbed TLS and TF-PSA-Crypto
check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c
check tests/scripts/generate_bignum_tests.py $(tests/scripts/generate_bignum_tests.py --list)
check tests/scripts/generate_ecp_tests.py $(tests/scripts/generate_ecp_tests.py --list)
check tests/scripts/generate_psa_tests.py $(tests/scripts/generate_psa_tests.py --list)
check framework/scripts/generate_bignum_tests.py $(framework/scripts/generate_bignum_tests.py --list)
check framework/scripts/generate_config_tests.py $(framework/scripts/generate_config_tests.py --list)
check framework/scripts/generate_ecp_tests.py $(framework/scripts/generate_ecp_tests.py --list)
check framework/scripts/generate_psa_tests.py $(framework/scripts/generate_psa_tests.py --list)
check framework/scripts/generate_test_keys.py tests/src/test_keys.h
check scripts/generate_driver_wrappers.py $library_dir/psa_crypto_driver_wrappers.h $library_dir/psa_crypto_driver_wrappers_no_static.c
# Additional checks for Mbed TLS only
@ -139,6 +141,7 @@ if in_mbedtls_repo; then
check scripts/generate_query_config.pl programs/test/query_config.c
check scripts/generate_features.pl library/version_features.c
check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
check framework/scripts/generate_test_cert_macros.py tests/src/test_certs.h
# generate_visualc_files enumerates source files (library/*.c). It doesn't
# care about their content, but the files must exist. So it must run after
# the step that creates or updates these files.
@ -148,4 +151,4 @@ fi
# Generated files that are present in the repository even in the development
# branch. (This is intended to be temporary, until the generator scripts are
# fully reviewed and the build scripts support a generated header file.)
check tests/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c
check framework/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c

View File

@ -31,14 +31,14 @@ EOF
can_pylint () {
# Pylint 1.5.2 from Ubuntu 16.04 is too old:
# E: 34, 0: Unable to import 'mbedtls_dev' (import-error)
# E: 34, 0: Unable to import 'mbedtls_framework' (import-error)
# Pylint 1.8.3 from Ubuntu 18.04 passed on the first commit containing this line.
check_version pylint 1.8.3
}
can_mypy () {
# mypy 0.770 is too old:
# tests/scripts/test_psa_constant_names.py:34: error: Cannot find implementation or library stub for module named 'mbedtls_dev'
# tests/scripts/test_psa_constant_names.py:34: error: Cannot find implementation or library stub for module named 'mbedtls_framework'
# mypy 0.780 from pip passed on the first commit containing this line.
check_version mypy.version 0.780
}
@ -55,14 +55,14 @@ elif [ "$1" = "--can-mypy" ]; then
fi
echo 'Running pylint ...'
$PYTHON -m pylint scripts/mbedtls_dev/*.py scripts/*.py tests/scripts/*.py || {
$PYTHON -m pylint framework/scripts/*.py framework/scripts/mbedtls_framework/*.py scripts/*.py tests/scripts/*.py || {
echo >&2 "pylint reported errors"
ret=1
}
echo
echo 'Running mypy ...'
$PYTHON -m mypy scripts/*.py tests/scripts/*.py ||
$PYTHON -m mypy framework/scripts/*.py framework/scripts/mbedtls_framework/*.py scripts/*.py tests/scripts/*.py ||
ret=1
exit $ret

View File

@ -24,7 +24,7 @@ except ImportError:
pass
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import build_tree
from mbedtls_framework import build_tree
class FileIssueTracker:
@ -373,7 +373,7 @@ class LicenseIssueTracker(LineIssueTracker):
r'3rdparty/(?!(p256-m)/.*)',
# Documentation explaining the license may have accidental
# false positives.
r'(ChangeLog|LICENSE|[-0-9A-Z_a-z]+\.md)\Z',
r'(ChangeLog|LICENSE|framework\/LICENSE|[-0-9A-Z_a-z]+\.md)\Z',
# Files imported from TF-M, and not used except in test builds,
# may be under a different license.
r'configs/ext/crypto_config_profile_medium\.h\Z',
@ -381,6 +381,7 @@ class LicenseIssueTracker(LineIssueTracker):
r'configs/ext/README\.md\Z',
# Third-party file.
r'dco\.txt\Z',
r'framework\/dco\.txt\Z',
]
path_exemptions = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST +
LICENSE_EXEMPTION_RE_LIST))
@ -486,9 +487,17 @@ class IntegrityChecker:
These are the regular files commited into Git.
"""
bytes_output = subprocess.check_output(['git', '-C', 'framework',
'ls-files', '-z'])
bytes_framework_filepaths = bytes_output.split(b'\0')[:-1]
bytes_framework_filepaths = ["framework/".encode() + filepath
for filepath in bytes_framework_filepaths]
bytes_output = subprocess.check_output(['git', 'ls-files', '-z'])
bytes_filepaths = bytes_output.split(b'\0')[:-1]
bytes_filepaths = bytes_output.split(b'\0')[:-1] + \
bytes_framework_filepaths
ascii_filepaths = map(lambda fp: fp.decode('ascii'), bytes_filepaths)
# Filter out directories. Normally Git doesn't list directories
# (it only knows about the files inside them), but there is
# at least one case where 'git ls-files' includes a directory:

View File

@ -45,7 +45,7 @@ import subprocess
import logging
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import build_tree
from mbedtls_framework import build_tree
# Naming patterns to check against. These are defined outside the NameCheck
@ -238,6 +238,8 @@ class CodeParser():
all_macros["public"] = self.parse_macros([
"include/mbedtls/*.h",
"include/psa/*.h",
"tf-psa-crypto/include/psa/*.h",
"tf-psa-crypto/drivers/builtin/include/mbedtls/*.h",
"3rdparty/everest/include/everest/everest.h",
"3rdparty/everest/include/everest/x25519.h"
])
@ -251,6 +253,8 @@ class CodeParser():
enum_consts = self.parse_enum_consts([
"include/mbedtls/*.h",
"include/psa/*.h",
"tf-psa-crypto/include/psa/*.h",
"tf-psa-crypto/drivers/builtin/include/mbedtls/*.h",
"library/*.h",
"library/*.c",
"3rdparty/everest/include/everest/everest.h",
@ -259,6 +263,8 @@ class CodeParser():
identifiers, excluded_identifiers = self.parse_identifiers([
"include/mbedtls/*.h",
"include/psa/*.h",
"tf-psa-crypto/include/psa/*.h",
"tf-psa-crypto/drivers/builtin/include/mbedtls/*.h",
"library/*.h",
"3rdparty/everest/include/everest/everest.h",
"3rdparty/everest/include/everest/x25519.h"
@ -266,6 +272,8 @@ class CodeParser():
mbed_psa_words = self.parse_mbed_psa_words([
"include/mbedtls/*.h",
"include/psa/*.h",
"tf-psa-crypto/include/psa/*.h",
"tf-psa-crypto/drivers/builtin/include/mbedtls/*.h",
"library/*.h",
"3rdparty/everest/include/everest/everest.h",
"3rdparty/everest/include/everest/x25519.h",

View File

@ -369,7 +369,11 @@ class CipherInfo: # pylint: disable=too-few-public-methods
"""Collect data about cipher.h."""
def __init__(self):
self.base_symbols = set()
with open('include/mbedtls/cipher.h', encoding="utf-8") as fh:
if os.path.isdir('tf-psa-crypto'):
cipher_h_path = 'tf-psa-crypto/drivers/builtin/include/mbedtls/cipher.h'
else:
cipher_h_path = 'include/mbedtls/cipher.h'
with open(cipher_h_path, encoding="utf-8") as fh:
for line in fh:
m = re.match(r' *MBEDTLS_CIPHER_ID_(\w+),', line)
if m and m.group(1) not in ['NONE', 'NULL', '3DES']:

View File

@ -1,187 +0,0 @@
#!/usr/bin/env python3
"""Generate test data for bignum functions.
With no arguments, generate all test data. With non-option arguments,
generate only the specified files.
Class structure:
Child classes of test_data_generation.BaseTarget (file targets) represent an output
file. These indicate where test cases will be written to, for all subclasses of
this target. Multiple file targets should not reuse a `target_basename`.
Each subclass derived from a file target can either be:
- A concrete class, representing a test function, which generates test cases.
- An abstract class containing shared methods and attributes, not associated
with a test function. An example is BignumOperation, which provides
common features used for bignum binary operations.
Both concrete and abstract subclasses can be derived from, to implement
additional test cases (see BignumCmp and BignumCmpAbs for examples of deriving
from abstract and concrete classes).
Adding test case generation for a function:
A subclass representing the test function should be added, deriving from a
file target such as BignumTarget. This test class must set/implement the
following:
- test_function: the function name from the associated .function file.
- test_name: a descriptive name or brief summary to refer to the test
function.
- arguments(): a method to generate the list of arguments required for the
test_function.
- generate_function_tests(): a method to generate TestCases for the function.
This should create instances of the class with required input data, and
call `.create_test_case()` to yield the TestCase.
Additional details and other attributes/methods are given in the documentation
of BaseTarget in test_data_generation.py.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import sys
from abc import ABCMeta
from typing import List
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import test_data_generation
from mbedtls_dev import bignum_common
# Import modules containing additional test classes
# Test function classes in these modules will be registered by
# the framework
from mbedtls_dev import bignum_core, bignum_mod_raw, bignum_mod # pylint: disable=unused-import
class BignumTarget(test_data_generation.BaseTarget):
#pylint: disable=too-few-public-methods
"""Target for bignum (legacy) test case generation."""
target_basename = 'test_suite_bignum.generated'
class BignumOperation(bignum_common.OperationCommon, BignumTarget,
metaclass=ABCMeta):
#pylint: disable=abstract-method
"""Common features for bignum operations in legacy tests."""
unique_combinations_only = True
input_values = [
"", "0", "-", "-0",
"7b", "-7b",
"0000000000000000123", "-0000000000000000123",
"1230000000000000000", "-1230000000000000000"
]
def description_suffix(self) -> str:
#pylint: disable=no-self-use # derived classes need self
"""Text to add at the end of the test case description."""
return ""
def description(self) -> str:
"""Generate a description for the test case.
If not set, case_description uses the form A `symbol` B, where symbol
is used to represent the operation. Descriptions of each value are
generated to provide some context to the test case.
"""
if not self.case_description:
self.case_description = "{} {} {}".format(
self.value_description(self.arg_a),
self.symbol,
self.value_description(self.arg_b)
)
description_suffix = self.description_suffix()
if description_suffix:
self.case_description += " " + description_suffix
return super().description()
@staticmethod
def value_description(val) -> str:
"""Generate a description of the argument val.
This produces a simple description of the value, which is used in test
case naming to add context.
"""
if val == "":
return "0 (null)"
if val == "-":
return "negative 0 (null)"
if val == "0":
return "0 (1 limb)"
if val[0] == "-":
tmp = "negative"
val = val[1:]
else:
tmp = "positive"
if val[0] == "0":
tmp += " with leading zero limb"
elif len(val) > 10:
tmp = "large " + tmp
return tmp
class BignumCmp(BignumOperation):
"""Test cases for bignum value comparison."""
count = 0
test_function = "mpi_cmp_mpi"
test_name = "MPI compare"
input_cases = [
("-2", "-3"),
("-2", "-2"),
("2b4", "2b5"),
("2b5", "2b6")
]
def __init__(self, val_a, val_b) -> None:
super().__init__(val_a, val_b)
self._result = int(self.int_a > self.int_b) - int(self.int_a < self.int_b)
self.symbol = ["<", "==", ">"][self._result + 1]
def result(self) -> List[str]:
return [str(self._result)]
class BignumCmpAbs(BignumCmp):
"""Test cases for absolute bignum value comparison."""
count = 0
test_function = "mpi_cmp_abs"
test_name = "MPI compare (abs)"
def __init__(self, val_a, val_b) -> None:
super().__init__(val_a.strip("-"), val_b.strip("-"))
class BignumAdd(BignumOperation):
"""Test cases for bignum value addition."""
count = 0
symbol = "+"
test_function = "mpi_add_mpi"
test_name = "MPI add"
input_cases = bignum_common.combination_pairs(
[
"1c67967269c6", "9cde3",
"-1c67967269c6", "-9cde3",
]
)
def __init__(self, val_a: str, val_b: str) -> None:
super().__init__(val_a, val_b)
self._result = self.int_a + self.int_b
def description_suffix(self) -> str:
if (self.int_a >= 0 and self.int_b >= 0):
return "" # obviously positive result or 0
if (self.int_a <= 0 and self.int_b <= 0):
return "" # obviously negative result or 0
# The sign of the result is not obvious, so indicate it
return ", result{}0".format('>' if self._result > 0 else
'<' if self._result < 0 else '=')
def result(self) -> List[str]:
return [bignum_common.quote_str("{:x}".format(self._result))]
if __name__ == '__main__':
# Use the section of the docstring relevant to the CLI as description
test_data_generation.main(sys.argv[1:], "\n".join(__doc__.splitlines()[:4]))

View File

@ -1,22 +0,0 @@
#!/usr/bin/env python3
"""Generate test data for ecp functions.
The command line usage, class structure and available methods are the same
as in generate_bignum_tests.py.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import sys
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import test_data_generation
# Import modules containing additional test classes
# Test function classes in these modules will be registered by
# the framework
from mbedtls_dev import ecp # pylint: disable=unused-import
if __name__ == '__main__':
# Use the section of the docstring relevant to the CLI as description
test_data_generation.main(sys.argv[1:], "\n".join(__doc__.splitlines()[:4]))

View File

@ -1,183 +0,0 @@
#!/usr/bin/env python3
#
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
#
"""
Make fuzz like testing for pkcs7 tests
Given a valid DER pkcs7 file add tests to the test_suite_pkcs7.data file
- It is expected that the pkcs7_asn1_fail( data_t *pkcs7_buf )
function is defined in test_suite_pkcs7.function
- This is not meant to be portable code, if anything it is meant to serve as
documentation for showing how those ugly tests in test_suite_pkcs7.data were created
"""
import sys
from os.path import exists
PKCS7_TEST_FILE = "../suites/test_suite_pkcs7.data"
class Test: # pylint: disable=too-few-public-methods
"""
A instance of a test in test_suite_pkcs7.data
"""
def __init__(self, name, depends, func_call):
self.name = name
self.depends = depends
self.func_call = func_call
# pylint: disable=no-self-use
def to_string(self):
return "\n" + self.name + "\n" + self.depends + "\n" + self.func_call + "\n"
class TestData:
"""
Take in test_suite_pkcs7.data file.
Allow for new tests to be added.
"""
mandatory_dep = "MBEDTLS_MD_CAN_SHA256"
test_name = "PKCS7 Parse Failure Invalid ASN1"
test_function = "pkcs7_asn1_fail:"
def __init__(self, file_name):
self.file_name = file_name
self.last_test_num, self.old_tests = self.read_test_file(file_name)
self.new_tests = []
# pylint: disable=no-self-use
def read_test_file(self, file):
"""
Parse the test_suite_pkcs7.data file.
"""
tests = []
if not exists(file):
print(file + " Does not exist")
sys.exit()
with open(file, "r", encoding='UTF-8') as fp:
data = fp.read()
lines = [line.strip() for line in data.split('\n') if len(line.strip()) > 1]
i = 0
while i < len(lines):
if "depends" in lines[i+1]:
tests.append(Test(lines[i], lines[i+1], lines[i+2]))
i += 3
else:
tests.append(Test(lines[i], None, lines[i+1]))
i += 2
latest_test_num = float(tests[-1].name.split('#')[1])
return latest_test_num, tests
def add(self, name, func_call):
self.last_test_num += 1
self.new_tests.append(Test(self.test_name + ": " + name + " #" + \
str(self.last_test_num), "depends_on:" + self.mandatory_dep, \
self.test_function + '"' + func_call + '"'))
def write_changes(self):
with open(self.file_name, 'a', encoding='UTF-8') as fw:
fw.write("\n")
for t in self.new_tests:
fw.write(t.to_string())
def asn1_mutate(data):
"""
We have been given an asn1 structure representing a pkcs7.
We want to return an array of slightly modified versions of this data
they should be modified in a way which makes the structure invalid
We know that asn1 structures are:
|---1 byte showing data type---|----byte(s) for length of data---|---data content--|
We know that some data types can contain other data types.
Return a dictionary of reasons and mutated data types.
"""
# off the bat just add bytes to start and end of the buffer
mutations = []
reasons = []
mutations.append(["00"] + data)
reasons.append("Add null byte to start")
mutations.append(data + ["00"])
reasons.append("Add null byte to end")
# for every asn1 entry we should attempt to:
# - change the data type tag
# - make the length longer than actual
# - make the length shorter than actual
i = 0
while i < len(data):
tag_i = i
leng_i = tag_i + 1
data_i = leng_i + 1 + (int(data[leng_i][1], 16) if data[leng_i][0] == '8' else 0)
if data[leng_i][0] == '8':
length = int(''.join(data[leng_i + 1: data_i]), 16)
else:
length = int(data[leng_i], 16)
tag = data[tag_i]
print("Looking at ans1: offset " + str(i) + " tag = " + tag + \
", length = " + str(length)+ ":")
print(''.join(data[data_i:data_i+length]))
# change tag to something else
if tag == "02":
# turn integers into octet strings
new_tag = "04"
else:
# turn everything else into an integer
new_tag = "02"
mutations.append(data[:tag_i] + [new_tag] + data[leng_i:])
reasons.append("Change tag " + tag + " to " + new_tag)
# change lengths to too big
# skip any edge cases which would cause carry over
if int(data[data_i - 1], 16) < 255:
new_length = str(hex(int(data[data_i - 1], 16) + 1))[2:]
if len(new_length) == 1:
new_length = "0"+new_length
mutations.append(data[:data_i -1] + [new_length] + data[data_i:])
reasons.append("Change length from " + str(length) + " to " \
+ str(length + 1))
# we can add another test here for tags that contain other tags \
# where they have more data than there containing tags account for
if tag in ["30", "a0", "31"]:
mutations.append(data[:data_i -1] + [new_length] + \
data[data_i:data_i + length] + ["00"] + \
data[data_i + length:])
reasons.append("Change contents of tag " + tag + " to contain \
one unaccounted extra byte")
# change lengths to too small
if int(data[data_i - 1], 16) > 0:
new_length = str(hex(int(data[data_i - 1], 16) - 1))[2:]
if len(new_length) == 1:
new_length = "0"+new_length
mutations.append(data[:data_i -1] + [new_length] + data[data_i:])
reasons.append("Change length from " + str(length) + " to " + str(length - 1))
# some tag types contain other tag types so we should iterate into the data
if tag in ["30", "a0", "31"]:
i = data_i
else:
i = data_i + length
return list(zip(reasons, mutations))
if __name__ == "__main__":
if len(sys.argv) < 2:
print("USAGE: " + sys.argv[0] + " <pkcs7_der_file>")
sys.exit()
DATA_FILE = sys.argv[1]
TEST_DATA = TestData(PKCS7_TEST_FILE)
with open(DATA_FILE, 'rb') as f:
DATA_STR = f.read().hex()
# make data an array of byte strings eg ['de','ad','be','ef']
HEX_DATA = list(map(''.join, [[DATA_STR[i], DATA_STR[i+1]] for i in range(0, len(DATA_STR), \
2)]))
# returns tuples of test_names and modified data buffers
MUT_ARR = asn1_mutate(HEX_DATA)
print("made " + str(len(MUT_ARR)) + " new tests")
for new_test in MUT_ARR:
TEST_DATA.add(new_test[0], ''.join(new_test[1]))
TEST_DATA.write_changes()

View File

@ -1,850 +0,0 @@
#!/usr/bin/env python3
"""Generate test data for PSA cryptographic mechanisms.
With no arguments, generate all test data. With non-option arguments,
generate only the specified files.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import enum
import re
import sys
from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import crypto_data_tests
from mbedtls_dev import crypto_knowledge
from mbedtls_dev import macro_collector #pylint: disable=unused-import
from mbedtls_dev import psa_information
from mbedtls_dev import psa_storage
from mbedtls_dev import test_case
from mbedtls_dev import test_data_generation
def test_case_for_key_type_not_supported(
verb: str, key_type: str, bits: int,
dependencies: List[str],
*args: str,
param_descr: str = ''
) -> test_case.TestCase:
"""Return one test case exercising a key creation method
for an unsupported key type or size.
"""
psa_information.hack_dependencies_not_implemented(dependencies)
tc = test_case.TestCase()
short_key_type = crypto_knowledge.short_expression(key_type)
adverb = 'not' if dependencies else 'never'
if param_descr:
adverb = param_descr + ' ' + adverb
tc.set_description('PSA {} {} {}-bit {} supported'
.format(verb, short_key_type, bits, adverb))
tc.set_dependencies(dependencies)
tc.set_function(verb + '_not_supported')
tc.set_arguments([key_type] + list(args))
return tc
class KeyTypeNotSupported:
"""Generate test cases for when a key type is not supported."""
def __init__(self, info: psa_information.Information) -> None:
self.constructors = info.constructors
ALWAYS_SUPPORTED = frozenset([
'PSA_KEY_TYPE_DERIVE',
'PSA_KEY_TYPE_PASSWORD',
'PSA_KEY_TYPE_PASSWORD_HASH',
'PSA_KEY_TYPE_RAW_DATA',
'PSA_KEY_TYPE_HMAC'
])
def test_cases_for_key_type_not_supported(
self,
kt: crypto_knowledge.KeyType,
param: Optional[int] = None,
param_descr: str = '',
) -> Iterator[test_case.TestCase]:
"""Return test cases exercising key creation when the given type is unsupported.
If param is present and not None, emit test cases conditioned on this
parameter not being supported. If it is absent or None, emit test cases
conditioned on the base type not being supported.
"""
if kt.name in self.ALWAYS_SUPPORTED:
# Don't generate test cases for key types that are always supported.
# They would be skipped in all configurations, which is noise.
return
import_dependencies = [('!' if param is None else '') +
psa_information.psa_want_symbol(kt.name)]
if kt.params is not None:
import_dependencies += [('!' if param == i else '') +
psa_information.psa_want_symbol(sym)
for i, sym in enumerate(kt.params)]
if kt.name.endswith('_PUBLIC_KEY'):
generate_dependencies = []
else:
generate_dependencies = \
psa_information.fix_key_pair_dependencies(import_dependencies, 'GENERATE')
import_dependencies = \
psa_information.fix_key_pair_dependencies(import_dependencies, 'BASIC')
for bits in kt.sizes_to_test():
yield test_case_for_key_type_not_supported(
'import', kt.expression, bits,
psa_information.finish_family_dependencies(import_dependencies, bits),
test_case.hex_string(kt.key_material(bits)),
param_descr=param_descr,
)
if not generate_dependencies and param is not None:
# If generation is impossible for this key type, rather than
# supported or not depending on implementation capabilities,
# only generate the test case once.
continue
# For public key we expect that key generation fails with
# INVALID_ARGUMENT. It is handled by KeyGenerate class.
if not kt.is_public():
yield test_case_for_key_type_not_supported(
'generate', kt.expression, bits,
psa_information.finish_family_dependencies(generate_dependencies, bits),
str(bits),
param_descr=param_descr,
)
# To be added: derive
ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
DH_KEY_TYPES = ('PSA_KEY_TYPE_DH_KEY_PAIR',
'PSA_KEY_TYPE_DH_PUBLIC_KEY')
def test_cases_for_not_supported(self) -> Iterator[test_case.TestCase]:
"""Generate test cases that exercise the creation of keys of unsupported types."""
for key_type in sorted(self.constructors.key_types):
if key_type in self.ECC_KEY_TYPES:
continue
if key_type in self.DH_KEY_TYPES:
continue
kt = crypto_knowledge.KeyType(key_type)
yield from self.test_cases_for_key_type_not_supported(kt)
for curve_family in sorted(self.constructors.ecc_curves):
for constr in self.ECC_KEY_TYPES:
kt = crypto_knowledge.KeyType(constr, [curve_family])
yield from self.test_cases_for_key_type_not_supported(
kt, param_descr='type')
yield from self.test_cases_for_key_type_not_supported(
kt, 0, param_descr='curve')
for dh_family in sorted(self.constructors.dh_groups):
for constr in self.DH_KEY_TYPES:
kt = crypto_knowledge.KeyType(constr, [dh_family])
yield from self.test_cases_for_key_type_not_supported(
kt, param_descr='type')
yield from self.test_cases_for_key_type_not_supported(
kt, 0, param_descr='group')
def test_case_for_key_generation(
key_type: str, bits: int,
dependencies: List[str],
*args: str,
result: str = ''
) -> test_case.TestCase:
"""Return one test case exercising a key generation.
"""
psa_information.hack_dependencies_not_implemented(dependencies)
tc = test_case.TestCase()
short_key_type = crypto_knowledge.short_expression(key_type)
tc.set_description('PSA {} {}-bit'
.format(short_key_type, bits))
tc.set_dependencies(dependencies)
tc.set_function('generate_key')
tc.set_arguments([key_type] + list(args) + [result])
return tc
class KeyGenerate:
"""Generate positive and negative (invalid argument) test cases for key generation."""
def __init__(self, info: psa_information.Information) -> None:
self.constructors = info.constructors
ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
DH_KEY_TYPES = ('PSA_KEY_TYPE_DH_KEY_PAIR',
'PSA_KEY_TYPE_DH_PUBLIC_KEY')
@staticmethod
def test_cases_for_key_type_key_generation(
kt: crypto_knowledge.KeyType
) -> Iterator[test_case.TestCase]:
"""Return test cases exercising key generation.
All key types can be generated except for public keys. For public key
PSA_ERROR_INVALID_ARGUMENT status is expected.
"""
result = 'PSA_SUCCESS'
import_dependencies = [psa_information.psa_want_symbol(kt.name)]
if kt.params is not None:
import_dependencies += [psa_information.psa_want_symbol(sym)
for i, sym in enumerate(kt.params)]
if kt.name.endswith('_PUBLIC_KEY'):
# The library checks whether the key type is a public key generically,
# before it reaches a point where it needs support for the specific key
# type, so it returns INVALID_ARGUMENT for unsupported public key types.
generate_dependencies = []
result = 'PSA_ERROR_INVALID_ARGUMENT'
else:
generate_dependencies = \
psa_information.fix_key_pair_dependencies(import_dependencies, 'GENERATE')
for bits in kt.sizes_to_test():
if kt.name == 'PSA_KEY_TYPE_RSA_KEY_PAIR':
size_dependency = "PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= " + str(bits)
test_dependencies = generate_dependencies + [size_dependency]
else:
test_dependencies = generate_dependencies
yield test_case_for_key_generation(
kt.expression, bits,
psa_information.finish_family_dependencies(test_dependencies, bits),
str(bits),
result
)
def test_cases_for_key_generation(self) -> Iterator[test_case.TestCase]:
"""Generate test cases that exercise the generation of keys."""
for key_type in sorted(self.constructors.key_types):
if key_type in self.ECC_KEY_TYPES:
continue
if key_type in self.DH_KEY_TYPES:
continue
kt = crypto_knowledge.KeyType(key_type)
yield from self.test_cases_for_key_type_key_generation(kt)
for curve_family in sorted(self.constructors.ecc_curves):
for constr in self.ECC_KEY_TYPES:
kt = crypto_knowledge.KeyType(constr, [curve_family])
yield from self.test_cases_for_key_type_key_generation(kt)
for dh_family in sorted(self.constructors.dh_groups):
for constr in self.DH_KEY_TYPES:
kt = crypto_knowledge.KeyType(constr, [dh_family])
yield from self.test_cases_for_key_type_key_generation(kt)
class OpFail:
"""Generate test cases for operations that must fail."""
#pylint: disable=too-few-public-methods
class Reason(enum.Enum):
NOT_SUPPORTED = 0
INVALID = 1
INCOMPATIBLE = 2
PUBLIC = 3
def __init__(self, info: psa_information.Information) -> None:
self.constructors = info.constructors
key_type_expressions = self.constructors.generate_expressions(
sorted(self.constructors.key_types)
)
self.key_types = [crypto_knowledge.KeyType(kt_expr)
for kt_expr in key_type_expressions]
def make_test_case(
self,
alg: crypto_knowledge.Algorithm,
category: crypto_knowledge.AlgorithmCategory,
reason: 'Reason',
kt: Optional[crypto_knowledge.KeyType] = None,
not_deps: FrozenSet[str] = frozenset(),
) -> test_case.TestCase:
"""Construct a failure test case for a one-key or keyless operation."""
#pylint: disable=too-many-arguments,too-many-locals
tc = test_case.TestCase()
pretty_alg = alg.short_expression()
if reason == self.Reason.NOT_SUPPORTED:
short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep)
for dep in not_deps]
pretty_reason = '!' + '&'.join(sorted(short_deps))
else:
pretty_reason = reason.name.lower()
if kt:
key_type = kt.expression
pretty_type = kt.short_expression()
else:
key_type = ''
pretty_type = ''
tc.set_description('PSA {} {}: {}{}'
.format(category.name.lower(),
pretty_alg,
pretty_reason,
' with ' + pretty_type if pretty_type else ''))
dependencies = psa_information.automatic_dependencies(alg.base_expression, key_type)
dependencies = psa_information.fix_key_pair_dependencies(dependencies, 'BASIC')
for i, dep in enumerate(dependencies):
if dep in not_deps:
dependencies[i] = '!' + dep
tc.set_dependencies(dependencies)
tc.set_function(category.name.lower() + '_fail')
arguments = [] # type: List[str]
if kt:
key_material = kt.key_material(kt.sizes_to_test()[0])
arguments += [key_type, test_case.hex_string(key_material)]
arguments.append(alg.expression)
if category.is_asymmetric():
arguments.append('1' if reason == self.Reason.PUBLIC else '0')
error = ('NOT_SUPPORTED' if reason == self.Reason.NOT_SUPPORTED else
'INVALID_ARGUMENT')
arguments.append('PSA_ERROR_' + error)
tc.set_arguments(arguments)
return tc
def no_key_test_cases(
self,
alg: crypto_knowledge.Algorithm,
category: crypto_knowledge.AlgorithmCategory,
) -> Iterator[test_case.TestCase]:
"""Generate failure test cases for keyless operations with the specified algorithm."""
if alg.can_do(category):
# Compatible operation, unsupported algorithm
for dep in psa_information.automatic_dependencies(alg.base_expression):
yield self.make_test_case(alg, category,
self.Reason.NOT_SUPPORTED,
not_deps=frozenset([dep]))
else:
# Incompatible operation, supported algorithm
yield self.make_test_case(alg, category, self.Reason.INVALID)
def one_key_test_cases(
self,
alg: crypto_knowledge.Algorithm,
category: crypto_knowledge.AlgorithmCategory,
) -> Iterator[test_case.TestCase]:
"""Generate failure test cases for one-key operations with the specified algorithm."""
for kt in self.key_types:
key_is_compatible = kt.can_do(alg)
if key_is_compatible and alg.can_do(category):
# Compatible key and operation, unsupported algorithm
for dep in psa_information.automatic_dependencies(alg.base_expression):
yield self.make_test_case(alg, category,
self.Reason.NOT_SUPPORTED,
kt=kt, not_deps=frozenset([dep]))
# Public key for a private-key operation
if category.is_asymmetric() and kt.is_public():
yield self.make_test_case(alg, category,
self.Reason.PUBLIC,
kt=kt)
elif key_is_compatible:
# Compatible key, incompatible operation, supported algorithm
yield self.make_test_case(alg, category,
self.Reason.INVALID,
kt=kt)
elif alg.can_do(category):
# Incompatible key, compatible operation, supported algorithm
yield self.make_test_case(alg, category,
self.Reason.INCOMPATIBLE,
kt=kt)
else:
# Incompatible key and operation. Don't test cases where
# multiple things are wrong, to keep the number of test
# cases reasonable.
pass
def test_cases_for_algorithm(
self,
alg: crypto_knowledge.Algorithm,
) -> Iterator[test_case.TestCase]:
"""Generate operation failure test cases for the specified algorithm."""
for category in crypto_knowledge.AlgorithmCategory:
if category == crypto_knowledge.AlgorithmCategory.PAKE:
# PAKE operations are not implemented yet
pass
elif category.requires_key():
yield from self.one_key_test_cases(alg, category)
else:
yield from self.no_key_test_cases(alg, category)
def all_test_cases(self) -> Iterator[test_case.TestCase]:
"""Generate all test cases for operations that must fail."""
algorithms = sorted(self.constructors.algorithms)
for expr in self.constructors.generate_expressions(algorithms):
alg = crypto_knowledge.Algorithm(expr)
yield from self.test_cases_for_algorithm(alg)
class StorageKey(psa_storage.Key):
"""Representation of a key for storage format testing."""
IMPLICIT_USAGE_FLAGS = {
'PSA_KEY_USAGE_SIGN_HASH': 'PSA_KEY_USAGE_SIGN_MESSAGE',
'PSA_KEY_USAGE_VERIFY_HASH': 'PSA_KEY_USAGE_VERIFY_MESSAGE'
} #type: Dict[str, str]
"""Mapping of usage flags to the flags that they imply."""
def __init__(
self,
usage: Iterable[str],
without_implicit_usage: Optional[bool] = False,
**kwargs
) -> None:
"""Prepare to generate a key.
* `usage` : The usage flags used for the key.
* `without_implicit_usage`: Flag to define to apply the usage extension
"""
usage_flags = set(usage)
if not without_implicit_usage:
for flag in sorted(usage_flags):
if flag in self.IMPLICIT_USAGE_FLAGS:
usage_flags.add(self.IMPLICIT_USAGE_FLAGS[flag])
if usage_flags:
usage_expression = ' | '.join(sorted(usage_flags))
else:
usage_expression = '0'
super().__init__(usage=usage_expression, **kwargs)
class StorageTestData(StorageKey):
"""Representation of test case data for storage format testing."""
def __init__(
self,
description: str,
expected_usage: Optional[List[str]] = None,
**kwargs
) -> None:
"""Prepare to generate test data
* `description` : used for the test case names
* `expected_usage`: the usage flags generated as the expected usage flags
in the test cases. CAn differ from the usage flags
stored in the keys because of the usage flags extension.
"""
super().__init__(**kwargs)
self.description = description #type: str
if expected_usage is None:
self.expected_usage = self.usage #type: psa_storage.Expr
elif expected_usage:
self.expected_usage = psa_storage.Expr(' | '.join(expected_usage))
else:
self.expected_usage = psa_storage.Expr(0)
class StorageFormat:
"""Storage format stability test cases."""
def __init__(self, info: psa_information.Information, version: int, forward: bool) -> None:
"""Prepare to generate test cases for storage format stability.
* `info`: information about the API. See the `Information` class.
* `version`: the storage format version to generate test cases for.
* `forward`: if true, generate forward compatibility test cases which
save a key and check that its representation is as intended. Otherwise
generate backward compatibility test cases which inject a key
representation and check that it can be read and used.
"""
self.constructors = info.constructors #type: macro_collector.PSAMacroEnumerator
self.version = version #type: int
self.forward = forward #type: bool
RSA_OAEP_RE = re.compile(r'PSA_ALG_RSA_OAEP\((.*)\)\Z')
BRAINPOOL_RE = re.compile(r'PSA_KEY_TYPE_\w+\(PSA_ECC_FAMILY_BRAINPOOL_\w+\)\Z')
@classmethod
def exercise_key_with_algorithm(
cls,
key_type: psa_storage.Expr, bits: int,
alg: psa_storage.Expr
) -> bool:
"""Whether to exercise the given key with the given algorithm.
Normally only the type and algorithm matter for compatibility, and
this is handled in crypto_knowledge.KeyType.can_do(). This function
exists to detect exceptional cases. Exceptional cases detected here
are not tested in OpFail and should therefore have manually written
test cases.
"""
# Some test keys have the RAW_DATA type and attributes that don't
# necessarily make sense. We do this to validate numerical
# encodings of the attributes.
# Raw data keys have no useful exercise anyway so there is no
# loss of test coverage.
if key_type.string == 'PSA_KEY_TYPE_RAW_DATA':
return False
# OAEP requires room for two hashes plus wrapping
m = cls.RSA_OAEP_RE.match(alg.string)
if m:
hash_alg = m.group(1)
hash_length = crypto_knowledge.Algorithm.hash_length(hash_alg)
key_length = (bits + 7) // 8
# Leave enough room for at least one byte of plaintext
return key_length > 2 * hash_length + 2
# There's nothing wrong with ECC keys on Brainpool curves,
# but operations with them are very slow. So we only exercise them
# with a single algorithm, not with all possible hashes. We do
# exercise other curves with all algorithms so test coverage is
# perfectly adequate like this.
m = cls.BRAINPOOL_RE.match(key_type.string)
if m and alg.string != 'PSA_ALG_ECDSA_ANY':
return False
return True
def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
"""Construct a storage format test case for the given key.
If ``forward`` is true, generate a forward compatibility test case:
create a key and validate that it has the expected representation.
Otherwise generate a backward compatibility test case: inject the
key representation into storage and validate that it can be read
correctly.
"""
verb = 'save' if self.forward else 'read'
tc = test_case.TestCase()
tc.set_description(verb + ' ' + key.description)
dependencies = psa_information.automatic_dependencies(
key.lifetime.string, key.type.string,
key.alg.string, key.alg2.string,
)
dependencies = psa_information.finish_family_dependencies(dependencies, key.bits)
dependencies += psa_information.generate_deps_from_description(key.description)
dependencies = psa_information.fix_key_pair_dependencies(dependencies, 'BASIC')
tc.set_dependencies(dependencies)
tc.set_function('key_storage_' + verb)
if self.forward:
extra_arguments = []
else:
flags = []
if self.exercise_key_with_algorithm(key.type, key.bits, key.alg):
flags.append('TEST_FLAG_EXERCISE')
if 'READ_ONLY' in key.lifetime.string:
flags.append('TEST_FLAG_READ_ONLY')
extra_arguments = [' | '.join(flags) if flags else '0']
tc.set_arguments([key.lifetime.string,
key.type.string, str(key.bits),
key.expected_usage.string,
key.alg.string, key.alg2.string,
'"' + key.material.hex() + '"',
'"' + key.hex() + '"',
*extra_arguments])
return tc
def key_for_lifetime(
self,
lifetime: str,
) -> StorageTestData:
"""Construct a test key for the given lifetime."""
short = lifetime
short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
r'', short)
short = crypto_knowledge.short_expression(short)
description = 'lifetime: ' + short
key = StorageTestData(version=self.version,
id=1, lifetime=lifetime,
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
usage=['PSA_KEY_USAGE_EXPORT'], alg=0, alg2=0,
material=b'L',
description=description)
return key
def all_keys_for_lifetimes(self) -> Iterator[StorageTestData]:
"""Generate test keys covering lifetimes."""
lifetimes = sorted(self.constructors.lifetimes)
expressions = self.constructors.generate_expressions(lifetimes)
for lifetime in expressions:
# Don't attempt to create or load a volatile key in storage
if 'VOLATILE' in lifetime:
continue
# Don't attempt to create a read-only key in storage,
# but do attempt to load one.
if 'READ_ONLY' in lifetime and self.forward:
continue
yield self.key_for_lifetime(lifetime)
def key_for_usage_flags(
self,
usage_flags: List[str],
short: Optional[str] = None,
test_implicit_usage: Optional[bool] = True
) -> StorageTestData:
"""Construct a test key for the given key usage."""
extra_desc = ' without implication' if test_implicit_usage else ''
description = 'usage' + extra_desc + ': '
key1 = StorageTestData(version=self.version,
id=1, lifetime=0x00000001,
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
expected_usage=usage_flags,
without_implicit_usage=not test_implicit_usage,
usage=usage_flags, alg=0, alg2=0,
material=b'K',
description=description)
if short is None:
usage_expr = key1.expected_usage.string
key1.description += crypto_knowledge.short_expression(usage_expr)
else:
key1.description += short
return key1
def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
"""Generate test keys covering usage flags."""
known_flags = sorted(self.constructors.key_usage_flags)
yield self.key_for_usage_flags(['0'], **kwargs)
for usage_flag in known_flags:
yield self.key_for_usage_flags([usage_flag], **kwargs)
for flag1, flag2 in zip(known_flags,
known_flags[1:] + [known_flags[0]]):
yield self.key_for_usage_flags([flag1, flag2], **kwargs)
def generate_key_for_all_usage_flags(self) -> Iterator[StorageTestData]:
known_flags = sorted(self.constructors.key_usage_flags)
yield self.key_for_usage_flags(known_flags, short='all known')
def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
yield from self.generate_keys_for_usage_flags()
yield from self.generate_key_for_all_usage_flags()
def key_for_type_and_alg(
self,
kt: crypto_knowledge.KeyType,
bits: int,
alg: Optional[crypto_knowledge.Algorithm] = None,
) -> StorageTestData:
"""Construct a test key of the given type.
If alg is not None, this key allows it.
"""
usage_flags = ['PSA_KEY_USAGE_EXPORT']
alg1 = 0 #type: psa_storage.Exprable
alg2 = 0
if alg is not None:
alg1 = alg.expression
usage_flags += alg.usage_flags(public=kt.is_public())
key_material = kt.key_material(bits)
description = 'type: {} {}-bit'.format(kt.short_expression(1), bits)
if alg is not None:
description += ', ' + alg.short_expression(1)
key = StorageTestData(version=self.version,
id=1, lifetime=0x00000001,
type=kt.expression, bits=bits,
usage=usage_flags, alg=alg1, alg2=alg2,
material=key_material,
description=description)
return key
def keys_for_type(
self,
key_type: str,
all_algorithms: List[crypto_knowledge.Algorithm],
) -> Iterator[StorageTestData]:
"""Generate test keys for the given key type."""
kt = crypto_knowledge.KeyType(key_type)
for bits in kt.sizes_to_test():
# Test a non-exercisable key, as well as exercisable keys for
# each compatible algorithm.
# To do: test reading a key from storage with an incompatible
# or unsupported algorithm.
yield self.key_for_type_and_alg(kt, bits)
compatible_algorithms = [alg for alg in all_algorithms
if kt.can_do(alg)]
for alg in compatible_algorithms:
yield self.key_for_type_and_alg(kt, bits, alg)
def all_keys_for_types(self) -> Iterator[StorageTestData]:
"""Generate test keys covering key types and their representations."""
key_types = sorted(self.constructors.key_types)
all_algorithms = [crypto_knowledge.Algorithm(alg)
for alg in self.constructors.generate_expressions(
sorted(self.constructors.algorithms)
)]
for key_type in self.constructors.generate_expressions(key_types):
yield from self.keys_for_type(key_type, all_algorithms)
def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
"""Generate test keys for the encoding of the specified algorithm."""
# These test cases only validate the encoding of algorithms, not
# whether the key read from storage is suitable for an operation.
# `keys_for_types` generate read tests with an algorithm and a
# compatible key.
descr = crypto_knowledge.short_expression(alg, 1)
usage = ['PSA_KEY_USAGE_EXPORT']
key1 = StorageTestData(version=self.version,
id=1, lifetime=0x00000001,
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
usage=usage, alg=alg, alg2=0,
material=b'K',
description='alg: ' + descr)
yield key1
key2 = StorageTestData(version=self.version,
id=1, lifetime=0x00000001,
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
usage=usage, alg=0, alg2=alg,
material=b'L',
description='alg2: ' + descr)
yield key2
def all_keys_for_algorithms(self) -> Iterator[StorageTestData]:
"""Generate test keys covering algorithm encodings."""
algorithms = sorted(self.constructors.algorithms)
for alg in self.constructors.generate_expressions(algorithms):
yield from self.keys_for_algorithm(alg)
def generate_all_keys(self) -> Iterator[StorageTestData]:
"""Generate all keys for the test cases."""
yield from self.all_keys_for_lifetimes()
yield from self.all_keys_for_usage_flags()
yield from self.all_keys_for_types()
yield from self.all_keys_for_algorithms()
def all_test_cases(self) -> Iterator[test_case.TestCase]:
"""Generate all storage format test cases."""
# First build a list of all keys, then construct all the corresponding
# test cases. This allows all required information to be obtained in
# one go, which is a significant performance gain as the information
# includes numerical values obtained by compiling a C program.
all_keys = list(self.generate_all_keys())
for key in all_keys:
if key.location_value() != 0:
# Skip keys with a non-default location, because they
# require a driver and we currently have no mechanism to
# determine whether a driver is available.
continue
yield self.make_test_case(key)
class StorageFormatForward(StorageFormat):
"""Storage format stability test cases for forward compatibility."""
def __init__(self, info: psa_information.Information, version: int) -> None:
super().__init__(info, version, True)
class StorageFormatV0(StorageFormat):
"""Storage format stability test cases for version 0 compatibility."""
def __init__(self, info: psa_information.Information) -> None:
super().__init__(info, 0, False)
def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
"""Generate test keys covering usage flags."""
yield from super().all_keys_for_usage_flags()
yield from self.generate_keys_for_usage_flags(test_implicit_usage=False)
def keys_for_implicit_usage(
self,
implyer_usage: str,
alg: str,
key_type: crypto_knowledge.KeyType
) -> StorageTestData:
# pylint: disable=too-many-locals
"""Generate test keys for the specified implicit usage flag,
algorithm and key type combination.
"""
bits = key_type.sizes_to_test()[0]
implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
usage_flags = ['PSA_KEY_USAGE_EXPORT']
material_usage_flags = usage_flags + [implyer_usage]
expected_usage_flags = material_usage_flags + [implicit_usage]
alg2 = 0
key_material = key_type.key_material(bits)
usage_expression = crypto_knowledge.short_expression(implyer_usage, 1)
alg_expression = crypto_knowledge.short_expression(alg, 1)
key_type_expression = key_type.short_expression(1)
description = 'implied by {}: {} {} {}-bit'.format(
usage_expression, alg_expression, key_type_expression, bits)
key = StorageTestData(version=self.version,
id=1, lifetime=0x00000001,
type=key_type.expression, bits=bits,
usage=material_usage_flags,
expected_usage=expected_usage_flags,
without_implicit_usage=True,
alg=alg, alg2=alg2,
material=key_material,
description=description)
return key
def gather_key_types_for_sign_alg(self) -> Dict[str, List[str]]:
# pylint: disable=too-many-locals
"""Match possible key types for sign algorithms."""
# To create a valid combination both the algorithms and key types
# must be filtered. Pair them with keywords created from its names.
incompatible_alg_keyword = frozenset(['RAW', 'ANY', 'PURE'])
incompatible_key_type_keywords = frozenset(['MONTGOMERY'])
keyword_translation = {
'ECDSA': 'ECC',
'ED[0-9]*.*' : 'EDWARDS'
}
exclusive_keywords = {
'EDWARDS': 'ECC'
}
key_types = set(self.constructors.generate_expressions(self.constructors.key_types))
algorithms = set(self.constructors.generate_expressions(self.constructors.sign_algorithms))
alg_with_keys = {} #type: Dict[str, List[str]]
translation_table = str.maketrans('(', '_', ')')
for alg in algorithms:
# Generate keywords from the name of the algorithm
alg_keywords = set(alg.partition('(')[0].split(sep='_')[2:])
# Translate keywords for better matching with the key types
for keyword in alg_keywords.copy():
for pattern, replace in keyword_translation.items():
if re.match(pattern, keyword):
alg_keywords.remove(keyword)
alg_keywords.add(replace)
# Filter out incompatible algorithms
if not alg_keywords.isdisjoint(incompatible_alg_keyword):
continue
for key_type in key_types:
# Generate keywords from the of the key type
key_type_keywords = set(key_type.translate(translation_table).split(sep='_')[3:])
# Remove ambiguous keywords
for keyword1, keyword2 in exclusive_keywords.items():
if keyword1 in key_type_keywords:
key_type_keywords.remove(keyword2)
if key_type_keywords.isdisjoint(incompatible_key_type_keywords) and\
not key_type_keywords.isdisjoint(alg_keywords):
if alg in alg_with_keys:
alg_with_keys[alg].append(key_type)
else:
alg_with_keys[alg] = [key_type]
return alg_with_keys
def all_keys_for_implicit_usage(self) -> Iterator[StorageTestData]:
"""Generate test keys for usage flag extensions."""
# Generate a key type and algorithm pair for each extendable usage
# flag to generate a valid key for exercising. The key is generated
# without usage extension to check the extension compatibility.
alg_with_keys = self.gather_key_types_for_sign_alg()
for usage in sorted(StorageKey.IMPLICIT_USAGE_FLAGS, key=str):
for alg in sorted(alg_with_keys):
for key_type in sorted(alg_with_keys[alg]):
# The key types must be filtered to fit the specific usage flag.
kt = crypto_knowledge.KeyType(key_type)
if kt.is_public() and '_SIGN_' in usage:
# Can't sign with a public key
continue
yield self.keys_for_implicit_usage(usage, alg, kt)
def generate_all_keys(self) -> Iterator[StorageTestData]:
yield from super().generate_all_keys()
yield from self.all_keys_for_implicit_usage()
class PSATestGenerator(test_data_generation.TestGenerator):
"""Test generator subclass including PSA targets and info."""
# Note that targets whose names contain 'test_format' have their content
# validated by `abi_check.py`.
targets = {
'test_suite_psa_crypto_generate_key.generated':
lambda info: KeyGenerate(info).test_cases_for_key_generation(),
'test_suite_psa_crypto_not_supported.generated':
lambda info: KeyTypeNotSupported(info).test_cases_for_not_supported(),
'test_suite_psa_crypto_low_hash.generated':
lambda info: crypto_data_tests.HashPSALowLevel(info).all_test_cases(),
'test_suite_psa_crypto_op_fail.generated':
lambda info: OpFail(info).all_test_cases(),
'test_suite_psa_crypto_storage_format.current':
lambda info: StorageFormatForward(info, 0).all_test_cases(),
'test_suite_psa_crypto_storage_format.v0':
lambda info: StorageFormatV0(info).all_test_cases(),
} #type: Dict[str, Callable[[psa_information.Information], Iterable[test_case.TestCase]]]
def __init__(self, options):
super().__init__(options)
self.info = psa_information.Information()
def generate_target(self, name: str, *target_args) -> None:
super().generate_target(name, self.info)
if __name__ == '__main__':
test_data_generation.main(sys.argv[1:], __doc__, PSATestGenerator)

View File

@ -1,257 +0,0 @@
#!/usr/bin/env python3
"""Generate wrapper functions for PSA function calls.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
### WARNING: the code in this file has not been extensively reviewed yet.
### We do not think it is harmful, but it may be below our normal standards
### for robustness and maintainability.
import argparse
import itertools
import os
from typing import Iterator, List, Optional, Tuple
import scripts_path #pylint: disable=unused-import
from mbedtls_dev import build_tree
from mbedtls_dev import c_parsing_helper
from mbedtls_dev import c_wrapper_generator
from mbedtls_dev import typing_util
class BufferParameter:
"""Description of an input or output buffer parameter sequence to a PSA function."""
#pylint: disable=too-few-public-methods
def __init__(self, i: int, is_output: bool,
buffer_name: str, size_name: str) -> None:
"""Initialize the parameter information.
i is the index of the function argument that is the pointer to the buffer.
The size is argument i+1. For a variable-size output, the actual length
goes in argument i+2.
buffer_name and size_names are the names of arguments i and i+1.
This class does not yet help with the output length.
"""
self.index = i
self.buffer_name = buffer_name
self.size_name = size_name
self.is_output = is_output
class PSAWrapperGenerator(c_wrapper_generator.Base):
"""Generate a C source file containing wrapper functions for PSA Crypto API calls."""
_CPP_GUARDS = ('defined(MBEDTLS_PSA_CRYPTO_C) && ' +
'defined(MBEDTLS_TEST_HOOKS) && \\\n ' +
'!defined(RECORD_PSA_STATUS_COVERAGE_LOG)')
_WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_'
_WRAPPER_NAME_SUFFIX = ''
def gather_data(self) -> None:
root_dir = build_tree.guess_mbedtls_root()
for header_name in ['crypto.h', 'crypto_extra.h']:
header_path = os.path.join(root_dir, 'include', 'psa', header_name)
c_parsing_helper.read_function_declarations(self.functions, header_path)
_SKIP_FUNCTIONS = frozenset([
'mbedtls_psa_external_get_random', # not a library function
'psa_get_key_domain_parameters', # client-side function
'psa_get_key_slot_number', # client-side function
'psa_key_derivation_verify_bytes', # not implemented yet
'psa_key_derivation_verify_key', # not implemented yet
'psa_set_key_domain_parameters', # client-side function
])
def _skip_function(self, function: c_wrapper_generator.FunctionInfo) -> bool:
if function.return_type != 'psa_status_t':
return True
if function.name in self._SKIP_FUNCTIONS:
return True
return False
# PAKE stuff: not implemented yet
_PAKE_STUFF = frozenset([
'psa_crypto_driver_pake_inputs_t *',
'psa_pake_cipher_suite_t *',
])
def _return_variable_name(self,
function: c_wrapper_generator.FunctionInfo) -> str:
"""The name of the variable that will contain the return value."""
if function.return_type == 'psa_status_t':
return 'status'
return super()._return_variable_name(function)
_FUNCTION_GUARDS = c_wrapper_generator.Base._FUNCTION_GUARDS.copy() \
#pylint: disable=protected-access
_FUNCTION_GUARDS.update({
'mbedtls_psa_register_se_key': 'defined(MBEDTLS_PSA_CRYPTO_SE_C)',
'mbedtls_psa_inject_entropy': 'defined(MBEDTLS_PSA_INJECT_ENTROPY)',
'mbedtls_psa_external_get_random': 'defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)',
'mbedtls_psa_platform_get_builtin_key': 'defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)',
})
@staticmethod
def _detect_buffer_parameters(arguments: List[c_parsing_helper.ArgumentInfo],
argument_names: List[str]) -> Iterator[BufferParameter]:
"""Detect function arguments that are buffers (pointer, size [,length])."""
types = ['' if arg.suffix else arg.type for arg in arguments]
# pairs = list of (type_of_arg_N, type_of_arg_N+1)
# where each type_of_arg_X is the empty string if the type is an array
# or there is no argument X.
pairs = enumerate(itertools.zip_longest(types, types[1:], fillvalue=''))
for i, t01 in pairs:
if (t01[0] == 'const uint8_t *' or t01[0] == 'uint8_t *') and \
t01[1] == 'size_t':
yield BufferParameter(i, not t01[0].startswith('const '),
argument_names[i], argument_names[i+1])
@staticmethod
def _write_poison_buffer_parameter(out: typing_util.Writable,
param: BufferParameter,
poison: bool) -> None:
"""Write poisoning or unpoisoning code for a buffer parameter.
Write poisoning code if poison is true, unpoisoning code otherwise.
"""
out.write(' MBEDTLS_TEST_MEMORY_{}({}, {});\n'.format(
'POISON' if poison else 'UNPOISON',
param.buffer_name, param.size_name
))
def _write_poison_buffer_parameters(self, out: typing_util.Writable,
buffer_parameters: List[BufferParameter],
poison: bool) -> None:
"""Write poisoning or unpoisoning code for the buffer parameters.
Write poisoning code if poison is true, unpoisoning code otherwise.
"""
if not buffer_parameters:
return
out.write('#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n')
for param in buffer_parameters:
self._write_poison_buffer_parameter(out, param, poison)
out.write('#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */\n')
@staticmethod
def _parameter_should_be_copied(function_name: str,
_buffer_name: Optional[str]) -> bool:
"""Whether the specified buffer argument to a PSA function should be copied.
"""
# False-positives that do not need buffer copying
if function_name in ('mbedtls_psa_inject_entropy',
'psa_crypto_driver_pake_get_password',
'psa_crypto_driver_pake_get_user',
'psa_crypto_driver_pake_get_peer'):
return False
return True
def _write_function_call(self, out: typing_util.Writable,
function: c_wrapper_generator.FunctionInfo,
argument_names: List[str]) -> None:
buffer_parameters = list(
param
for param in self._detect_buffer_parameters(function.arguments,
argument_names)
if self._parameter_should_be_copied(function.name,
function.arguments[param.index].name))
self._write_poison_buffer_parameters(out, buffer_parameters, True)
super()._write_function_call(out, function, argument_names)
self._write_poison_buffer_parameters(out, buffer_parameters, False)
def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
super()._write_prologue(out, header)
out.write("""
#if {}
#include <psa/crypto.h>
#include <test/memory.h>
#include <test/psa_crypto_helpers.h>
#include <test/psa_test_wrappers.h>
"""
.format(self._CPP_GUARDS))
def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
out.write("""
#endif /* {} */
"""
.format(self._CPP_GUARDS))
super()._write_epilogue(out, header)
class PSALoggingWrapperGenerator(PSAWrapperGenerator, c_wrapper_generator.Logging):
"""Generate a C source file containing wrapper functions that log PSA Crypto API calls."""
def __init__(self, stream: str) -> None:
super().__init__()
self.set_stream(stream)
_PRINTF_TYPE_CAST = c_wrapper_generator.Logging._PRINTF_TYPE_CAST.copy()
_PRINTF_TYPE_CAST.update({
'mbedtls_svc_key_id_t': 'unsigned',
'psa_algorithm_t': 'unsigned',
'psa_drv_slot_number_t': 'unsigned long long',
'psa_key_derivation_step_t': 'int',
'psa_key_id_t': 'unsigned',
'psa_key_slot_number_t': 'unsigned long long',
'psa_key_lifetime_t': 'unsigned',
'psa_key_type_t': 'unsigned',
'psa_key_usage_flags_t': 'unsigned',
'psa_pake_role_t': 'int',
'psa_pake_step_t': 'int',
'psa_status_t': 'int',
})
def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
if typ.startswith('const '):
typ = typ[6:]
if typ == 'uint8_t *':
# Skip buffers
return '', []
if typ.endswith('operation_t *'):
return '', []
if typ in self._PAKE_STUFF:
return '', []
if typ == 'psa_key_attributes_t *':
return (var + '={id=%u, lifetime=0x%08x, type=0x%08x, bits=%u, alg=%08x, usage=%08x}',
['(unsigned) psa_get_key_{}({})'.format(field, var)
for field in ['id', 'lifetime', 'type', 'bits', 'algorithm', 'usage_flags']])
return super()._printf_parameters(typ, var)
DEFAULT_C_OUTPUT_FILE_NAME = 'tests/src/psa_test_wrappers.c'
DEFAULT_H_OUTPUT_FILE_NAME = 'tests/include/test/psa_test_wrappers.h'
def main() -> None:
parser = argparse.ArgumentParser(description=globals()['__doc__'])
parser.add_argument('--log',
help='Stream to log to (default: no logging code)')
parser.add_argument('--output-c',
metavar='FILENAME',
default=DEFAULT_C_OUTPUT_FILE_NAME,
help=('Output .c file path (default: {}; skip .c output if empty)'
.format(DEFAULT_C_OUTPUT_FILE_NAME)))
parser.add_argument('--output-h',
metavar='FILENAME',
default=DEFAULT_H_OUTPUT_FILE_NAME,
help=('Output .h file path (default: {}; skip .h output if empty)'
.format(DEFAULT_H_OUTPUT_FILE_NAME)))
options = parser.parse_args()
if options.log:
generator = PSALoggingWrapperGenerator(options.log) #type: PSAWrapperGenerator
else:
generator = PSAWrapperGenerator()
generator.gather_data()
if options.output_h:
generator.write_h_file(options.output_h)
if options.output_c:
generator.write_c_file(options.output_c)
if __name__ == '__main__':
main()

View File

@ -1,95 +0,0 @@
#!/usr/bin/env python3
"""
Generate `tests/src/test_certs.h` which includes certficaties/keys/certificate list for testing.
"""
#
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import os
import sys
import argparse
import jinja2
class MacroDefineAction(argparse.Action):
#pylint: disable=signature-differs, too-few-public-methods
def __call__(self, parser, namespace, values, option_string):
if not hasattr(namespace, 'values'):
setattr(namespace, 'values', [])
macro_name, filename = values
if self.dest in ('string', 'binary') and not os.path.exists(filename):
raise argparse.ArgumentError(
None, '`{}`: Input file does not exist.'.format(filename))
namespace.values.append((self.dest, macro_name, filename))
def macro_define_type(value):
ret = value.split('=', 1)
if len(ret) != 2:
raise argparse.ArgumentTypeError(
'`{}` is not MACRO=value format'.format(value))
return ret
def build_argparser(parser):
parser.description = __doc__
parser.add_argument('--string', type=macro_define_type, action=MacroDefineAction,
metavar='MACRO_NAME=path/to/file', help='PEM to C string. ')
parser.add_argument('--binary', type=macro_define_type, action=MacroDefineAction,
metavar='MACRO_NAME=path/to/file',
help='DER to C arrary.')
parser.add_argument('--password', type=macro_define_type, action=MacroDefineAction,
metavar='MACRO_NAME=password', help='Password to C string.')
parser.add_argument('--output', type=str, required=True)
def main():
parser = argparse.ArgumentParser()
build_argparser(parser)
args = parser.parse_args()
return generate(**vars(args))
#pylint: disable=dangerous-default-value, unused-argument
def generate(values=[], output=None, **kwargs):
"""Generate C header file.
"""
this_dir = os.path.dirname(os.path.abspath(__file__))
template_loader = jinja2.FileSystemLoader(
searchpath=os.path.join(this_dir, '..', 'data_files'))
template_env = jinja2.Environment(
loader=template_loader, lstrip_blocks=True, trim_blocks=True)
def read_as_c_array(filename):
with open(filename, 'rb') as f:
data = f.read(12)
while data:
yield ', '.join(['{:#04x}'.format(b) for b in data])
data = f.read(12)
def read_lines(filename):
with open(filename) as f:
try:
for line in f:
yield line.strip()
except:
print(filename)
raise
def put_to_column(value, position=0):
return ' '*position + value
template_env.filters['read_as_c_array'] = read_as_c_array
template_env.filters['read_lines'] = read_lines
template_env.filters['put_to_column'] = put_to_column
template = template_env.get_template('test_certs.h.jinja2')
with open(output, 'w') as f:
f.write(template.render(macros=values))
if __name__ == '__main__':
sys.exit(main())

File diff suppressed because it is too large Load Diff

View File

@ -15,3 +15,6 @@ import sys
sys.path.append(os.path.join(os.path.dirname(__file__),
os.path.pardir, os.path.pardir,
'scripts'))
sys.path.append(os.path.join(os.path.dirname(__file__),
os.path.pardir, os.path.pardir,
'framework', 'scripts'))

View File

@ -17,32 +17,24 @@ use strict;
my %configs = (
'config-ccm-psk-tls1_2.h' => {
'compat' => '-m tls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
'test_again_with_use_psa' => 1
'compat' => '-m tls12 -f \'^TLS_PSK_WITH_AES_..._CCM_8\'',
},
'config-ccm-psk-dtls1_2.h' => {
'compat' => '-m dtls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
'compat' => '-m dtls12 -f \'^TLS_PSK_WITH_AES_..._CCM_8\'',
'opt' => ' ',
'opt_needs_debug' => 1,
'test_again_with_use_psa' => 1
},
'config-no-entropy.h' => {
},
'config-suite-b.h' => {
'compat' => "-m tls12 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
'test_again_with_use_psa' => 1,
'compat' => "-m tls12 -f 'ECDHE_ECDSA.*AES.*GCM' -p mbedTLS",
'opt' => ' ',
'opt_needs_debug' => 1,
},
'config-symmetric-only.h' => {
'test_again_with_use_psa' => 0, # Uses PSA by default, no need to test it twice
},
'config-tfm.h' => {
'test_again_with_use_psa' => 0, # Uses PSA by default, no need to test it twice
},
'config-thread.h' => {
'opt' => '-f ECJPAKE.*nolog',
'test_again_with_use_psa' => 1,
},
);
@ -148,7 +140,10 @@ sub perform_test {
}
foreach my $conf ( @configs_to_test ) {
my $test_with_psa = $configs{$conf}{'test_again_with_use_psa'};
system("grep '//#define MBEDTLS_USE_PSA_CRYPTO' configs/$conf > /dev/null");
die "grep ... configs/$conf: $!" if $? != 0 && $? != 0x100;
my $test_with_psa = $? == 0;
if ( $test_with_psa )
{
perform_test( $conf, $configs{$conf}, $test_with_psa );

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ from typing import List
#pylint: disable=unused-import
import scripts_path
from mbedtls_dev import build_tree
from mbedtls_framework import build_tree
# PSA Compliance tests we expect to fail due to known defects in Mbed TLS /
# TF-PSA-Crypto (or the test suite).
@ -73,8 +73,14 @@ def main(library_build_dir: str):
os.mkdir(build_dir)
os.chdir(build_dir)
extra_includes = (';{}/drivers/builtin/include'.format(root_dir)
if in_tf_psa_crypto_repo else '')
# Temporary while the PSA compliance test suite is still run as part
# of Mbed TLS testing. When it is not the case anymore, the second case
# can be removed.
if in_tf_psa_crypto_repo:
extra_includes = ';{}/drivers/builtin/include'.format(root_dir)
elif os.path.isdir(os.path.join(root_dir, 'tf-psa-crypto')):
extra_includes = ';{}/tf-psa-crypto/include'.format(root_dir) + \
(';{}/tf-psa-crypto/drivers/builtin/include'.format(root_dir))
#pylint: disable=bad-continuation
subprocess.check_call([

View File

@ -19,9 +19,9 @@ import sys
from typing import Iterable, List, Optional, Tuple
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import c_build_helper
from mbedtls_dev.macro_collector import InputsForTest, PSAMacroEnumerator
from mbedtls_dev import typing_util
from mbedtls_framework import c_build_helper
from mbedtls_framework.macro_collector import InputsForTest, PSAMacroEnumerator
from mbedtls_framework import typing_util
def gather_inputs(headers: Iterable[str],
test_suites: Iterable[str],
@ -161,7 +161,9 @@ TEST_SUITES = ['tests/suites/test_suite_psa_crypto_metadata.data']
def main():
parser = argparse.ArgumentParser(description=globals()['__doc__'])
parser.add_argument('--include', '-I',
action='append', default=['include'],
action='append', default=['tf-psa-crypto/include',
'tf-psa-crypto/drivers/builtin/include',
'include'],
help='Directory for header files')
parser.add_argument('--keep-c',
action='store_true', dest='keep_c', default=False,

View File

@ -20,7 +20,7 @@
#include <string.h>
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include "libtestdriver1/include/psa/crypto.h"
#include "libtestdriver1/tf-psa-crypto/include/psa/crypto.h"
#include "libtestdriver1/library/psa_crypto_ecp.h"
#include "libtestdriver1/library/psa_crypto_ffdh.h"
#endif

View File

@ -193,6 +193,7 @@ psa_status_t mbedtls_test_transparent_generate_key(
uint8_t *key, size_t key_size, size_t *key_length)
{
++mbedtls_test_driver_key_management_hooks.hits;
++mbedtls_test_driver_key_management_hooks.hits_generate_key;
if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_management_hooks.forced_status;

View File

@ -1,5 +1,5 @@
/*
* Test driver for MAC entry points.
* Test driver for PAKE entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later

View File

@ -11,7 +11,7 @@
#include <test/macros.h>
#include <test/psa_exercise_key.h>
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <mbedtls/asn1.h>
#include <psa/crypto.h>
@ -1332,4 +1332,4 @@ exit:
}
#endif /* MBEDTLS_PK_C */
#endif /* MBEDTLS_PSA_CRYPTO_C */
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */

View File

@ -465,6 +465,7 @@ psa_status_t mbedtls_test_wrap_psa_copy_key(
}
/* Wrapper for psa_crypto_driver_pake_get_cipher_suite */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
psa_pake_cipher_suite_t *arg1_cipher_suite)
@ -472,8 +473,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(
psa_status_t status = (psa_crypto_driver_pake_get_cipher_suite)(arg0_inputs, arg1_cipher_suite);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_password */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_buffer,
@ -483,8 +486,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
psa_status_t status = (psa_crypto_driver_pake_get_password)(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_password_len */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_password_len)
@ -492,8 +497,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(
psa_status_t status = (psa_crypto_driver_pake_get_password_len)(arg0_inputs, arg1_password_len);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_peer */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_peer_id,
@ -503,8 +510,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
psa_status_t status = (psa_crypto_driver_pake_get_peer)(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_peer_len */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_peer_len)
@ -512,8 +521,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(
psa_status_t status = (psa_crypto_driver_pake_get_peer_len)(arg0_inputs, arg1_peer_len);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_user */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
uint8_t *arg1_user_id,
@ -523,8 +534,10 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
psa_status_t status = (psa_crypto_driver_pake_get_user)(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_driver_pake_get_user_len */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(
const psa_crypto_driver_pake_inputs_t *arg0_inputs,
size_t *arg1_user_len)
@ -532,6 +545,7 @@ psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(
psa_status_t status = (psa_crypto_driver_pake_get_user_len)(arg0_inputs, arg1_user_len);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_crypto_init */
psa_status_t mbedtls_test_wrap_psa_crypto_init(void)
@ -1008,14 +1022,17 @@ psa_status_t mbedtls_test_wrap_psa_mac_verify_setup(
}
/* Wrapper for psa_pake_abort */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_abort(
psa_pake_operation_t *arg0_operation)
{
psa_status_t status = (psa_pake_abort)(arg0_operation);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_get_implicit_key */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_get_implicit_key(
psa_pake_operation_t *arg0_operation,
psa_key_derivation_operation_t *arg1_output)
@ -1023,8 +1040,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_get_implicit_key(
psa_status_t status = (psa_pake_get_implicit_key)(arg0_operation, arg1_output);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_input */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_input(
psa_pake_operation_t *arg0_operation,
psa_pake_step_t arg1_step,
@ -1040,8 +1059,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_input(
#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_output */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_output(
psa_pake_operation_t *arg0_operation,
psa_pake_step_t arg1_step,
@ -1058,8 +1079,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_output(
#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_set_password_key */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_password_key(
psa_pake_operation_t *arg0_operation,
mbedtls_svc_key_id_t arg1_password)
@ -1067,8 +1090,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_set_password_key(
psa_status_t status = (psa_pake_set_password_key)(arg0_operation, arg1_password);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_set_peer */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_peer(
psa_pake_operation_t *arg0_operation,
const uint8_t *arg1_peer_id,
@ -1083,8 +1108,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_set_peer(
#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_set_role */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_role(
psa_pake_operation_t *arg0_operation,
psa_pake_role_t arg1_role)
@ -1092,8 +1119,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_set_role(
psa_status_t status = (psa_pake_set_role)(arg0_operation, arg1_role);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_set_user */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_set_user(
psa_pake_operation_t *arg0_operation,
const uint8_t *arg1_user_id,
@ -1108,8 +1137,10 @@ psa_status_t mbedtls_test_wrap_psa_pake_set_user(
#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_pake_setup */
#if defined(PSA_WANT_ALG_SOME_PAKE)
psa_status_t mbedtls_test_wrap_psa_pake_setup(
psa_pake_operation_t *arg0_operation,
const psa_pake_cipher_suite_t *arg1_cipher_suite)
@ -1117,6 +1148,7 @@ psa_status_t mbedtls_test_wrap_psa_pake_setup(
psa_status_t status = (psa_pake_setup)(arg0_operation, arg1_cipher_suite);
return status;
}
#endif /* defined(PSA_WANT_ALG_SOME_PAKE) */
/* Wrapper for psa_purge_key */
psa_status_t mbedtls_test_wrap_psa_purge_key(

File diff suppressed because it is too large Load Diff

View File

@ -1791,30 +1791,33 @@ int mbedtls_test_ssl_tls13_populate_session(mbedtls_ssl_session *session,
session->endpoint = endpoint_type == MBEDTLS_SSL_IS_CLIENT ?
MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER;
session->ciphersuite = 0xabcd;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
session->ticket_age_add = 0x87654321;
session->ticket_flags = 0x7;
session->resumption_key_len = 32;
memset(session->resumption_key, 0x99, sizeof(session->resumption_key));
#if defined(MBEDTLS_SSL_EARLY_DATA)
session->max_early_data_size = 0x87654321;
#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)
int ret = mbedtls_ssl_session_set_ticket_alpn(session, "ALPNExample");
if (ret != 0) {
return -1;
}
#endif /* MBEDTLS_SSL_ALPN && MBEDTLS_SSL_SRV_C */
#endif /* MBEDTLS_SSL_EARLY_DATA */
#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
session->ticket_creation_time = mbedtls_ms_time() - 42;
}
#endif
#if defined(MBEDTLS_SSL_SRV_C)
if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
int ret = mbedtls_ssl_session_set_ticket_alpn(session, "ALPNExample");
if (ret != 0) {
return -1;
}
#endif
#if defined(MBEDTLS_HAVE_TIME)
session->ticket_creation_time = mbedtls_ms_time() - 42;
#endif
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
}
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
#if defined(MBEDTLS_HAVE_TIME)
session->ticket_reception_time = mbedtls_ms_time() - 40;
#endif
@ -1828,9 +1831,22 @@ int mbedtls_test_ssl_tls13_populate_session(mbedtls_ssl_session *session,
}
memset(session->ticket, 33, ticket_len);
}
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
char hostname[] = "hostname example";
session->hostname = mbedtls_calloc(1, sizeof(hostname));
if (session->hostname == NULL) {
return -1;
}
memcpy(session->hostname, hostname, sizeof(hostname));
#endif
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
}
#endif /* MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_EARLY_DATA)
session->max_early_data_size = 0x87654321;
#endif /* MBEDTLS_SSL_EARLY_DATA */
#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
session->record_size_limit = 2048;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -549,6 +549,10 @@ void enc_fail(int cipher_id, int pad_mode, int key_len, int length_val,
/* encode length number of bytes from inbuf */
TEST_ASSERT(0 == mbedtls_cipher_update(&ctx, inbuf, length, encbuf, &outlen));
TEST_ASSERT(ret == mbedtls_cipher_finish(&ctx, encbuf + outlen, &outlen));
if (0 != ret) {
/* Check output parameter is set to the least-harmful value on error */
TEST_ASSERT(0 == outlen);
}
/* done */
exit:
@ -826,6 +830,10 @@ void decrypt_test_vec(int cipher_id, int pad_mode, data_t *key,
total_len += outlen;
TEST_ASSERT(finish_result == mbedtls_cipher_finish(&ctx, output + outlen,
&outlen));
if (0 != finish_result) {
/* Check output parameter is set to the least-harmful value on error */
TEST_ASSERT(0 == outlen);
}
total_len += outlen;
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
int tag_expected = (ctx.cipher_info->mode == MBEDTLS_MODE_GCM ||

Some files were not shown because too many files have changed in this diff Show More