From b5bba497fe95383edda7dcc8f786893f5d64bc19 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Fri, 20 Jan 2023 10:58:12 +0100 Subject: [PATCH 01/15] Extract Secp192r1 from the prototype Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 727283f73a..787a700032 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -4570,6 +4570,7 @@ static int ecp_group_load(mbedtls_ecp_group *grp, /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); +static int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); @@ -4884,10 +4885,12 @@ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) } #define WIDTH 8 / sizeof(mbedtls_mpi_uint) -#define A(i) N->p + (i) * WIDTH -#define ADD(i) add64(p, A(i), &c) +#define A(i) Np + (i) * WIDTH +#define ADD(i) add64(p, A(i), &c) #define NEXT p += WIDTH; carry64(p, &c) #define LAST p += WIDTH; *p = c; while (++p < end) *p = 0 +#define RESET last_carry[0] = c; c = 0; p = Np +#define ADD_LAST add64(p, last_carry, &c) /* * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) @@ -4895,28 +4898,47 @@ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) static int ecp_mod_p192(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi_uint c = 0; - mbedtls_mpi_uint *p, *end; - - /* Make sure we have enough blocks so that A(5) is legal */ - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, 6 * WIDTH)); - - p = N->p; - end = p + N->n; - - ADD(3); ADD(5); NEXT; // A0 += A3 + A5 - ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 - ADD(4); ADD(5); LAST; // A2 += A4 + A5 + size_t expected_width = 2 * ((192 + biL - 1) / biL); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = ecp_mod_p192_raw(N->p, expected_width); cleanup: return ret; } +static int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) +{ + mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; + mbedtls_mpi_uint *p, *end; + + if (Nn != 2*((192 + biL - 1)/biL)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + p = Np; + end = p + Nn; + + ADD(3); ADD(5); NEXT; // A0 += A3 + A5 + ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 + ADD(4); ADD(5); // A2 += A4 + A5 + + RESET; + + ADD_LAST; NEXT; + ADD_LAST; NEXT; + + LAST; + + return 0; +} + #undef WIDTH #undef A #undef ADD #undef NEXT #undef LAST +#undef RESET +#undef ADD_LAST #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ From deece2bb650f47ff17319841ef664bd395c0b743 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Wed, 25 Jan 2023 17:57:36 +0100 Subject: [PATCH 02/15] Change the ecp_mod_p192_raw to be testable Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 6 ++++-- library/ecp_invasive.h | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 787a700032..817dc9be46 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -4570,7 +4570,8 @@ static int ecp_group_load(mbedtls_ecp_group *grp, /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); -static int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); +MBEDTLS_STATIC_TESTABLE +int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); @@ -4906,7 +4907,8 @@ cleanup: return ret; } -static int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) +MBEDTLS_STATIC_TESTABLE +int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) { mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; mbedtls_mpi_uint *p, *end; diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index 18815be089..a0c678dfa9 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -76,6 +76,13 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + +MBEDTLS_STATIC_TESTABLE +int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); + +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_INVASIVE_H */ From 51ec06aa51e5422d1facc91acb25404c6f19a2f5 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Wed, 25 Jan 2023 18:05:44 +0100 Subject: [PATCH 03/15] Add test function for ecp_mod_p192_raw Signed-off-by: Gabor Mezei --- tests/suites/test_suite_ecp.function | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 394253de53..5b7a1d1416 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -4,6 +4,7 @@ #include "mbedtls/ecdh.h" #include "ecp_invasive.h" +#include "bignum_mod_raw_invasive.h" #if defined(MBEDTLS_TEST_HOOKS) && \ (defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ @@ -1295,3 +1296,45 @@ exit: mbedtls_mpi_free(&expected_n); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ +void ecp_mod_p192_raw(char *input_N, + char *input_X, + char *result) +{ + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *N = NULL; + mbedtls_mpi_uint *res = NULL; + size_t limbs_X; + size_t limbs_N; + size_t limbs_res; + + mbedtls_mpi_mod_modulus m; + mbedtls_mpi_mod_modulus_init(&m); + + TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs_X, input_X), 0); + TEST_EQUAL(mbedtls_test_read_mpi_core(&N, &limbs_N, input_N), 0); + TEST_EQUAL(mbedtls_test_read_mpi_core(&res, &limbs_res, result), 0); + + size_t limbs = limbs_N; + size_t bytes = limbs * sizeof(mbedtls_mpi_uint); + + TEST_EQUAL(limbs_X, 2 * limbs); + TEST_EQUAL(limbs_res, limbs); + + TEST_EQUAL(mbedtls_mpi_mod_modulus_setup( + &m, N, limbs, + MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0); + + TEST_EQUAL(ecp_mod_p192_raw(X, limbs_X), 0); + mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m); + ASSERT_COMPARE(X, bytes, res, bytes); + +exit: + mbedtls_free(X); + mbedtls_free(res); + + mbedtls_mpi_mod_modulus_free(&m); + mbedtls_free(N); +} +/* END_CASE */ From 95ecaaf56d90bc3af8e4867ef1541c263a7a0d84 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 16 Jan 2023 16:53:29 +0100 Subject: [PATCH 04/15] Add test generation support for the ecp module Signed-off-by: Gabor Mezei --- scripts/mbedtls_dev/ecp.py | 25 ++++++++++ tests/CMakeLists.txt | 51 +++++++++++++++++++- tests/Makefile | 21 +++++++- tests/scripts/check-generated-files.sh | 1 + tests/scripts/generate_ecp_tests.py | 67 ++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 scripts/mbedtls_dev/ecp.py create mode 100755 tests/scripts/generate_ecp_tests.py diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py new file mode 100644 index 0000000000..77381cfd30 --- /dev/null +++ b/scripts/mbedtls_dev/ecp.py @@ -0,0 +1,25 @@ +"""Framework classes for generation of ecp test cases.""" +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import List + +from . import test_case +from . import test_data_generation + +class EcpTarget(test_data_generation.BaseTarget): + #pylint: disable=abstract-method, too-few-public-methods + """Target for ecp test case generation.""" + target_basename = 'test_suite_ecp.generated' diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4a7de820aa..4549a7a2b6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,18 @@ execute_process( string(REGEX REPLACE "[^;]*/" "" base_bignum_generated_data_files "${base_bignum_generated_data_files}") +execute_process( + COMMAND + ${MBEDTLS_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py + --list-for-cmake + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR}/.. + OUTPUT_VARIABLE + base_ecp_generated_data_files) +string(REGEX REPLACE "[^;]*/" "" + base_ecp_generated_data_files "${base_ecp_generated_data_files}") + execute_process( COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} @@ -44,14 +56,18 @@ string(REGEX REPLACE "[^;]*/" "" # Derive generated file paths in the build directory. The generated data # files go into the suites/ subdirectory. set(base_generated_data_files - ${base_bignum_generated_data_files} ${base_psa_generated_data_files}) + ${base_bignum_generated_data_files} ${base_ecp_generated_data_files} ${base_psa_generated_data_files}) string(REGEX REPLACE "([^;]+)" "suites/\\1" all_generated_data_files "${base_generated_data_files}") set(bignum_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_ecp_generated_data_files}) + list(APPEND ecp_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file}) +endforeach() foreach(file ${base_psa_generated_data_files}) list(APPEND psa_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file}) endforeach() @@ -75,6 +91,22 @@ if(GEN_FILES) ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py ) + add_custom_command( + OUTPUT + ${ecp_generated_data_files} + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR}/.. + COMMAND + ${MBEDTLS_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../tests/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 + ) add_custom_command( OUTPUT ${psa_generated_data_files} @@ -107,6 +139,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_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. if((NOT DEFINED SKIP_TEST_SUITES) AND (DEFINED ENV{SKIP_TEST_SUITES})) @@ -129,6 +162,7 @@ function(add_test_suite suite_name) # Get the test names of the tests with generated .data files # from the generated_data_files list in parent scope. set(bignum_generated_data_names "") + set(ecp_generated_data_names "") set(psa_generated_data_names "") foreach(generated_data_file ${bignum_generated_data_files}) # Get the plain filename @@ -139,6 +173,15 @@ function(add_test_suite suite_name) string(SUBSTRING ${generated_data_name} 11 -1 generated_data_name) list(APPEND bignum_generated_data_names ${generated_data_name}) endforeach() + foreach(generated_data_file ${ecp_generated_data_files}) + # Get the plain filename + get_filename_component(generated_data_name ${generated_data_file} NAME) + # Remove the ".data" extension + get_name_without_last_ext(generated_data_name ${generated_data_name}) + # Remove leading "test_suite_" + string(SUBSTRING ${generated_data_name} 11 -1 generated_data_name) + list(APPEND ecp_generated_data_names ${generated_data_name}) + endforeach() foreach(generated_data_file ${psa_generated_data_files}) # Get the plain filename get_filename_component(generated_data_name ${generated_data_file} NAME) @@ -153,6 +196,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(";${ecp_generated_data_names};" MATCHES ";${data_name};") + set(data_file + ${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data) + set(dependency test_suite_ecp_generated_data) elseif(";${psa_generated_data_names};" MATCHES ";${data_name};") set(data_file ${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data) @@ -160,7 +207,7 @@ 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_psa_generated_data) + set(dependency test_suite_bignum_generated_data test_suite_ecp_generated_data test_suite_psa_generated_data) endif() add_custom_command( diff --git a/tests/Makefile b/tests/Makefile index 312607ee30..c9283c984f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -73,6 +73,13 @@ GENERATED_BIGNUM_DATA_FILES := $(patsubst tests/%,%,$(shell \ ifeq ($(GENERATED_BIGNUM_DATA_FILES),FAILED) $(error "$(PYTHON) scripts/generate_bignum_tests.py --list" failed) endif +GENERATED_ECP_DATA_FILES := $(patsubst tests/%,%,$(shell \ + $(PYTHON) scripts/generate_ecp_tests.py --list || \ + echo FAILED \ +)) +ifeq ($(GENERATED_ECP_DATA_FILES),FAILED) +$(error "$(PYTHON) scripts/generate_ecp_tests.py --list" failed) +endif GENERATED_PSA_DATA_FILES := $(patsubst tests/%,%,$(shell \ $(PYTHON) scripts/generate_psa_tests.py --list || \ echo FAILED \ @@ -80,7 +87,7 @@ GENERATED_PSA_DATA_FILES := $(patsubst tests/%,%,$(shell \ ifeq ($(GENERATED_PSA_DATA_FILES),FAILED) $(error "$(PYTHON) scripts/generate_psa_tests.py --list" failed) endif -GENERATED_FILES := $(GENERATED_PSA_DATA_FILES) $(GENERATED_BIGNUM_DATA_FILES) +GENERATED_FILES := $(GENERATED_PSA_DATA_FILES) $(GENERATED_ECP_DATA_FILES) $(GENERATED_BIGNUM_DATA_FILES) generated_files: $(GENERATED_FILES) # generate_bignum_tests.py and generate_psa_tests.py spend more time analyzing @@ -89,7 +96,7 @@ 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_psa_test_data +.SECONDARY: generated_bignum_test_data generated_ecp_test_data generated_psa_test_data $(GENERATED_BIGNUM_DATA_FILES): generated_bignum_test_data generated_bignum_test_data: scripts/generate_bignum_tests.py generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_common.py @@ -102,6 +109,16 @@ generated_bignum_test_data: echo " Gen $(GENERATED_BIGNUM_DATA_FILES)" $(PYTHON) scripts/generate_bignum_tests.py +$(GENERATED_ECP_DATA_FILES): 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: + echo " Gen $(GENERATED_ECP_DATA_FILES)" + $(PYTHON) scripts/generate_ecp_tests.py + $(GENERATED_PSA_DATA_FILES): generated_psa_test_data generated_psa_test_data: scripts/generate_psa_tests.py generated_psa_test_data: ../scripts/mbedtls_dev/crypto_knowledge.py diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh index 2bb9fea7ce..4d6f93079c 100755 --- a/tests/scripts/check-generated-files.sh +++ b/tests/scripts/check-generated-files.sh @@ -137,4 +137,5 @@ check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated. check scripts/generate_visualc_files.pl visualc/VS2013 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) diff --git a/tests/scripts/generate_ecp_tests.py b/tests/scripts/generate_ecp_tests.py new file mode 100755 index 0000000000..b3c1d10cfc --- /dev/null +++ b/tests/scripts/generate_ecp_tests.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Generate test data for ecp 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. + +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 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +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])) From bd23f3b2b88b48c4b34615d48e3c93c2f4261735 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Wed, 25 Jan 2023 18:09:49 +0100 Subject: [PATCH 05/15] Add test generation for ecp_mod_p192_raw Signed-off-by: Gabor Mezei --- scripts/mbedtls_dev/ecp.py | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py index 77381cfd30..7e1dafce48 100644 --- a/scripts/mbedtls_dev/ecp.py +++ b/scripts/mbedtls_dev/ecp.py @@ -18,8 +18,58 @@ from typing import List from . import test_case from . import test_data_generation +from . import bignum_common class EcpTarget(test_data_generation.BaseTarget): #pylint: disable=abstract-method, too-few-public-methods """Target for ecp test case generation.""" target_basename = 'test_suite_ecp.generated' + +class EcpP192R1Raw(bignum_common.ModOperationCommon, + EcpTarget): + """Test cases for ecp quasi_reduction().""" + symbol = "-" + test_function = "ecp_mod_p192_raw" + test_name = "ecp_mod_p192_raw" + input_style = "fixed" + arity = 1 + + moduli = [ "fffffffffffffffffffffffffffffffeffffffffffffffff" ] # type: List[str] + + input_values = [ + "0", "1", + + # First 8 number generated by random.getrandbits(384) - seed(2,2) + ("cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd" + "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"), + ("ffed9235288bc781ae66267594c9c9500925e4749b575bd1" + "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"), + ("ef8acd128b4f2fc15f3f57ebf30b94fa82523e86feac7eb7" + "dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"), + ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045" + "defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2"), + ("2d3d854e061b90303b08c6e33c7295782d6c797f8f7d9b78" + "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"), + ("fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f1" + "5c14bc4a829e07b0829a48d422fe99a22c70501e533c9135"), + ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561" + "867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"), + ("bd143fa9b714210c665d7435c1066932f4767f26294365b2" + "721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"), + + # Next 2 number generated by random.getrandbits(192) + "47733e847d718d733ff98ff387c56473a7a83ee0761ebfd2", + "cbd4d3e2d4dec9ef83f0be4e80371eb97f81375eecc1cb63" + ] + + @property + def arg_a(self) -> str: + return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits) + + def result(self) -> List[str]: + result = self.int_a % self.int_n + return [self.format_result(result)] + + @property + def is_valid(self) -> bool: + return True From 9b290b33e4a0ccc1efe63e3056b9b0b0d18c149b Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Fri, 27 Jan 2023 11:00:51 +0100 Subject: [PATCH 06/15] Add documentation Signed-off-by: Gabor Mezei --- library/ecp_invasive.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index a0c678dfa9..0844c49c2c 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -78,6 +78,12 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + * + * \param[in,out] Np The address of the MPI to be converted. + * Must have the double the limbs than \p Nn. + * \param[in] Nn The address of the modulus. + */ MBEDTLS_STATIC_TESTABLE int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); From 4721bb95fbc8ab634c55b74641b8072ea1112b38 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 30 Jan 2023 18:08:12 +0100 Subject: [PATCH 07/15] Fix test file generation on windows Signed-off-by: Gabor Mezei --- scripts/make_generated_files.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_generated_files.bat b/scripts/make_generated_files.bat index e9d92758a6..9cf34f6fd2 100644 --- a/scripts/make_generated_files.bat +++ b/scripts/make_generated_files.bat @@ -11,4 +11,5 @@ python scripts\generate_ssl_debug_helpers.py || exit /b 1 perl scripts\generate_visualc_files.pl || exit /b 1 python scripts\generate_psa_constants.py || exit /b 1 python tests\scripts\generate_bignum_tests.py || exit /b 1 +python tests\scripts\generate_ecp_tests.py || exit /b 1 python tests\scripts\generate_psa_tests.py || exit /b 1 From 2038ce976e21b4956f8280d241d88cc2c18d681b Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Tue, 31 Jan 2023 14:33:12 +0100 Subject: [PATCH 08/15] Rename function to follow naming convention Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 6 +++--- library/ecp_invasive.h | 2 +- tests/suites/test_suite_ecp.function | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 817dc9be46..f3ae509449 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -4571,7 +4571,7 @@ static int ecp_group_load(mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE -int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); @@ -4901,14 +4901,14 @@ static int ecp_mod_p192(mbedtls_mpi *N) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = 2 * ((192 + biL - 1) / biL); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); - ret = ecp_mod_p192_raw(N->p, expected_width); + ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE -int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) { mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; mbedtls_mpi_uint *p, *end; diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index 0844c49c2c..13f39cd302 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -85,7 +85,7 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, * \param[in] Nn The address of the modulus. */ MBEDTLS_STATIC_TESTABLE -int ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 5b7a1d1416..f22c5714ca 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -1326,7 +1326,7 @@ void ecp_mod_p192_raw(char *input_N, &m, N, limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0); - TEST_EQUAL(ecp_mod_p192_raw(X, limbs_X), 0); + TEST_EQUAL(mbedtls_ecp_mod_p192_raw(X, limbs_X), 0); mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m); ASSERT_COMPARE(X, bytes, res, bytes); From b6875086e6ae1b2599005c78eeaf602df76d2cbc Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Tue, 31 Jan 2023 14:35:17 +0100 Subject: [PATCH 09/15] Fix pylint issues Signed-off-by: Gabor Mezei --- scripts/mbedtls_dev/ecp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py index 7e1dafce48..bcb6bfb95b 100644 --- a/scripts/mbedtls_dev/ecp.py +++ b/scripts/mbedtls_dev/ecp.py @@ -16,7 +16,6 @@ from typing import List -from . import test_case from . import test_data_generation from . import bignum_common @@ -34,7 +33,7 @@ class EcpP192R1Raw(bignum_common.ModOperationCommon, input_style = "fixed" arity = 1 - moduli = [ "fffffffffffffffffffffffffffffffeffffffffffffffff" ] # type: List[str] + moduli = ["fffffffffffffffffffffffffffffffeffffffffffffffff"] # type: List[str] input_values = [ "0", "1", From 63aae68b8f1d7d923487f6e1e3297bc03c87d269 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 6 Feb 2023 16:24:08 +0100 Subject: [PATCH 10/15] Fix documentation Signed-off-by: Gabor Mezei --- library/ecp_invasive.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index 13f39cd302..752fceb143 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -81,8 +81,8 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, /** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) * * \param[in,out] Np The address of the MPI to be converted. - * Must have the double the limbs than \p Nn. - * \param[in] Nn The address of the modulus. + * Must have twice as many limbs as \p Nn. + * \param[in] Nn The length of \p Np in limbs. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); From a9d82dd0a2f512ae6e0ede67238b7ad7cce54522 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 13 Feb 2023 14:10:23 +0100 Subject: [PATCH 11/15] Keep the description in one place, just refer it Delete the duplicated file description and refer to the original one in generate_bignum_tests.py. Signed-off-by: Gabor Mezei --- tests/scripts/generate_ecp_tests.py | 37 ++--------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/tests/scripts/generate_ecp_tests.py b/tests/scripts/generate_ecp_tests.py index b3c1d10cfc..abbfda55f1 100755 --- a/tests/scripts/generate_ecp_tests.py +++ b/tests/scripts/generate_ecp_tests.py @@ -1,41 +1,8 @@ #!/usr/bin/env python3 """Generate test data for ecp 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. - -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. +The command line usage, class structure and available methods are the same +as in generate_bignum_tests.py. """ # Copyright The Mbed TLS Contributors From 23d4b8baee8fc2694ad1332913f140e95fab3dbb Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 13 Feb 2023 14:13:33 +0100 Subject: [PATCH 12/15] Add check for test Check the bit length of the output of p192_raw. Signed-off-by: Gabor Mezei --- tests/suites/test_suite_ecp.function | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index f22c5714ca..052d238c1b 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -3,8 +3,9 @@ #include "mbedtls/ecdsa.h" #include "mbedtls/ecdh.h" -#include "ecp_invasive.h" +#include "bignum_core.h" #include "bignum_mod_raw_invasive.h" +#include "ecp_invasive.h" #if defined(MBEDTLS_TEST_HOOKS) && \ (defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ @@ -1327,6 +1328,7 @@ void ecp_mod_p192_raw(char *input_N, MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0); TEST_EQUAL(mbedtls_ecp_mod_p192_raw(X, limbs_X), 0); + TEST_LE_U(mbedtls_mpi_core_bitlen(X, limbs_X), 192); mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m); ASSERT_COMPARE(X, bytes, res, bytes); From 5c9f401e4759d3f798ce4899241bff766fefefe7 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 13 Feb 2023 14:15:08 +0100 Subject: [PATCH 13/15] Add more test cases Signed-off-by: Gabor Mezei --- scripts/mbedtls_dev/ecp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py index bcb6bfb95b..93cd2123ff 100644 --- a/scripts/mbedtls_dev/ecp.py +++ b/scripts/mbedtls_dev/ecp.py @@ -38,6 +38,9 @@ class EcpP192R1Raw(bignum_common.ModOperationCommon, input_values = [ "0", "1", + # Modulus - 1 + "fffffffffffffffffffffffffffffffefffffffffffffffe", + # First 8 number generated by random.getrandbits(384) - seed(2,2) ("cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd" "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"), From a264831cffe3ffe279dd1283d18703be7596a97b Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 13 Feb 2023 16:29:05 +0100 Subject: [PATCH 14/15] Update documentation and add comments Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 9 ++++++--- library/ecp_invasive.h | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index f3ae509449..ae82cb7855 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -4926,10 +4926,13 @@ int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) RESET; - ADD_LAST; NEXT; - ADD_LAST; NEXT; + /* Use the reduction for the carry as well: + * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 + */ + ADD_LAST; NEXT; // A0 += last_carry + ADD_LAST; NEXT; // A1 += last_carry - LAST; + LAST; // A2 += carry return 0; } diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index 752fceb143..bf31f0c1d5 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -79,9 +79,13 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + * + * This operation expects a 384 bit MPI and the result of the reduction + * is a 192 bit MPI. * * \param[in,out] Np The address of the MPI to be converted. - * Must have twice as many limbs as \p Nn. + * Must have twice as many limbs as the modulus so + * 384 bits in length. * \param[in] Nn The length of \p Np in limbs. */ MBEDTLS_STATIC_TESTABLE From 0b4b8e3c5e63499982de15acf8febc8048ce95ec Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Tue, 14 Feb 2023 16:36:38 +0100 Subject: [PATCH 15/15] Update documentation Signed-off-by: Gabor Mezei --- library/ecp_invasive.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h index bf31f0c1d5..3ee238ee53 100644 --- a/library/ecp_invasive.h +++ b/library/ecp_invasive.h @@ -84,8 +84,10 @@ int mbedtls_ecp_gen_privkey_mx(size_t n_bits, * is a 192 bit MPI. * * \param[in,out] Np The address of the MPI to be converted. - * Must have twice as many limbs as the modulus so - * 384 bits in length. + * Must have twice as many limbs as the modulus. + * Upon return this holds the reduced value. The bitlength + * of the reduced value is the same as that of the modulus + * (192 bits). * \param[in] Nn The length of \p Np in limbs. */ MBEDTLS_STATIC_TESTABLE