Merge pull request #6476 from yuhaoth/pr/fix-tls13-mbedtls_ssl_is_handshake_over
TLS 1.3: Fix tls13 mbedtls ssl is handshake over
diff --git a/ChangeLog.d/fix-tls12server-sent-sigalgs.txt b/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
new file mode 100644
index 0000000..9abde2b
--- /dev/null
+++ b/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
@@ -0,0 +1,5 @@
+Bugfix
+ * Fix a bug whereby the the list of signature algorithms sent as part of the
+ TLS 1.2 server certificate request would get corrupted, meaning the first
+ algorithm would not get sent and an entry consisting of two random bytes
+ would be sent instead. Found by Serban Bejan and Dudek Sebastian.
diff --git a/ChangeLog.d/mpi-add-0-ub.txt b/ChangeLog.d/mpi-add-0-ub.txt
new file mode 100644
index 0000000..9f131a4
--- /dev/null
+++ b/ChangeLog.d/mpi-add-0-ub.txt
@@ -0,0 +1,4 @@
+Bugfix
+ * Fix undefined behavior (typically harmless in practice) of
+ mbedtls_mpi_add_mpi(), mbedtls_mpi_add_abs() and mbedtls_mpi_add_int()
+ when both operands are 0 and the left operand is represented with 0 limbs.
diff --git a/ChangeLog.d/mpi-most-negative-sint.txt b/ChangeLog.d/mpi-most-negative-sint.txt
new file mode 100644
index 0000000..5e775c4
--- /dev/null
+++ b/ChangeLog.d/mpi-most-negative-sint.txt
@@ -0,0 +1,4 @@
+Bugfix
+ * Fix undefined behavior (typically harmless in practice) when some bignum
+ functions receive the most negative value of mbedtls_mpi_sint. Credit
+ to OSS-Fuzz. Fixes #6597.
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 3bd1ca0..877fbc7 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -179,6 +179,20 @@
#endif /* !MBEDTLS_NO_UDBL_DIVISION */
#endif /* !MBEDTLS_HAVE_INT64 */
+/** \typedef mbedtls_mpi_uint
+ * \brief The type of machine digits in a bignum, called _limbs_.
+ *
+ * This is always an unsigned integer type with no padding bits. The size
+ * is platform-dependent.
+ */
+
+/** \typedef mbedtls_mpi_sint
+ * \brief The signed type corresponding to #mbedtls_mpi_uint.
+ *
+ * This is always an signed integer type with no padding bits. The size
+ * is platform-dependent.
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 3f869b9..12d503e 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -1648,7 +1648,7 @@
* production.
*
*/
-#define MBEDTLS_SSL_EARLY_DATA
+//#define MBEDTLS_SSL_EARLY_DATA
/**
* \def MBEDTLS_SSL_PROTO_DTLS
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index afb634e..8fec3c6 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -96,7 +96,10 @@
/* Error space gap */
/** Processing of the Certificate handshake message failed. */
#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00
-/** Received NewSessionTicket Post Handshake Message */
+/**
+ * Received NewSessionTicket Post Handshake Message.
+ * This error code is experimental and may be changed or removed without notice.
+ */
#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00
/* Error space gap */
/* Error space gap */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 4f65398..33e2e77 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -1829,7 +1829,7 @@
*/
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
#define PSA_PAKE_OPERATION_INIT {PSA_ALG_NONE, 0, 0, 0, 0, \
- MBEDTLS_SVC_KEY_ID_INIT, \
+ NULL, 0 , \
PSA_PAKE_ROLE_NONE, {0}, 0, 0, \
{.dummy = 0}}
#else
@@ -1920,7 +1920,8 @@
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
unsigned int MBEDTLS_PRIVATE(input_step);
unsigned int MBEDTLS_PRIVATE(output_step);
- mbedtls_svc_key_id_t MBEDTLS_PRIVATE(password);
+ uint8_t* MBEDTLS_PRIVATE(password);
+ size_t MBEDTLS_PRIVATE(password_len);
psa_pake_role_t MBEDTLS_PRIVATE(role);
uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_PAKE_BUFFER_SIZE]);
size_t MBEDTLS_PRIVATE(buffer_length);
diff --git a/library/bignum.c b/library/bignum.c
index 42be815..ba03988 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -252,6 +252,17 @@
memcpy( Y, &T, sizeof( mbedtls_mpi ) );
}
+static inline mbedtls_mpi_uint mpi_sint_abs( mbedtls_mpi_sint z )
+{
+ if( z >= 0 )
+ return( z );
+ /* Take care to handle the most negative value (-2^(biL-1)) correctly.
+ * A naive -z would have undefined behavior.
+ * Write this in a way that makes popular compilers happy (GCC, Clang,
+ * MSVC). */
+ return( (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z );
+}
+
/*
* Set value from integer
*/
@@ -263,7 +274,7 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
memset( X->p, 0, X->n * ciL );
- X->p[0] = ( z < 0 ) ? -z : z;
+ X->p[0] = mpi_sint_abs( z );
X->s = ( z < 0 ) ? -1 : 1;
cleanup:
@@ -853,7 +864,7 @@
mbedtls_mpi_uint p[1];
MPI_VALIDATE_RET( X != NULL );
- *p = ( z < 0 ) ? -z : z;
+ *p = mpi_sint_abs( z );
Y.s = ( z < 0 ) ? -1 : 1;
Y.n = 1;
Y.p = p;
@@ -889,6 +900,11 @@
if( B->p[j - 1] != 0 )
break;
+ /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
+ * and B is 0 (of any size). */
+ if( j == 0 )
+ return( 0 );
+
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
/* j is the number of non-zero limbs of B. Add those to X. */
@@ -1040,7 +1056,7 @@
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
@@ -1058,7 +1074,7 @@
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
@@ -1396,7 +1412,7 @@
mbedtls_mpi_uint p[1];
MPI_VALIDATE_RET( A != NULL );
- p[0] = ( b < 0 ) ? -b : b;
+ p[0] = mpi_sint_abs( b );
B.s = ( b < 0 ) ? -1 : 1;
B.n = 1;
B.p = p;
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 2ce5e43..8c9deff 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -877,20 +877,7 @@
return( PSA_SUCCESS );
}
-/** Get the description of a key given its identifier and policy constraints
- * and lock it.
- *
- * The key must have allow all the usage flags set in \p usage. If \p alg is
- * nonzero, the key must allow operations with this algorithm. If \p alg is
- * zero, the algorithm is not checked.
- *
- * In case of a persistent key, the function loads the description of the key
- * into a key slot if not already done.
- *
- * On success, the returned key slot is locked. It is the responsibility of
- * the caller to unlock the key slot when it does not access it anymore.
- */
-static psa_status_t psa_get_and_lock_key_slot_with_policy(
+psa_status_t psa_get_and_lock_key_slot_with_policy(
mbedtls_svc_key_id_t key,
psa_key_slot_t **p_slot,
psa_key_usage_t usage,
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 9863848..5cefa27 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -183,6 +183,24 @@
}
#endif
+/** Get the description of a key given its identifier and policy constraints
+ * and lock it.
+ *
+ * The key must have allow all the usage flags set in \p usage. If \p alg is
+ * nonzero, the key must allow operations with this algorithm. If \p alg is
+ * zero, the algorithm is not checked.
+ *
+ * In case of a persistent key, the function loads the description of the key
+ * into a key slot if not already done.
+ *
+ * On success, the returned key slot is locked. It is the responsibility of
+ * the caller to unlock the key slot when it does not access it anymore.
+ */
+psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key,
+ psa_key_slot_t **p_slot,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg );
+
/** Completely wipe a slot in memory, including its policy.
*
* Persistent storage is not affected.
diff --git a/library/psa_crypto_pake.c b/library/psa_crypto_pake.c
index 870b5b5..659b712 100644
--- a/library/psa_crypto_pake.c
+++ b/library/psa_crypto_pake.c
@@ -248,6 +248,7 @@
psa_key_attributes_t attributes = psa_key_attributes_init();
psa_key_type_t type;
psa_key_usage_t usage;
+ psa_key_slot_t *slot = NULL;
if( operation->alg == PSA_ALG_NONE ||
operation->state != PSA_PAKE_STATE_SETUP )
@@ -273,7 +274,27 @@
if( ( usage & PSA_KEY_USAGE_DERIVE ) == 0 )
return( PSA_ERROR_NOT_PERMITTED );
- operation->password = password;
+ if( operation->password != NULL )
+ return( PSA_ERROR_BAD_STATE );
+
+ status = psa_get_and_lock_key_slot_with_policy( password, &slot,
+ PSA_KEY_USAGE_DERIVE,
+ PSA_ALG_JPAKE );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ operation->password = mbedtls_calloc( 1, slot->key.bytes );
+ if( operation->password == NULL )
+ {
+ psa_unlock_key_slot( slot );
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ }
+ memcpy( operation->password, slot->key.data, slot->key.bytes );
+ operation->password_len = slot->key.bytes;
+
+ status = psa_unlock_key_slot( slot );
+ if( status != PSA_SUCCESS )
+ return( status );
return( PSA_SUCCESS );
}
@@ -348,9 +369,7 @@
static psa_status_t psa_pake_ecjpake_setup( psa_pake_operation_t *operation )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecjpake_role role;
- psa_key_slot_t *slot = NULL;
if( operation->role == PSA_PAKE_ROLE_CLIENT )
role = MBEDTLS_ECJPAKE_CLIENT;
@@ -359,22 +378,20 @@
else
return( PSA_ERROR_BAD_STATE );
- if( psa_is_valid_key_id( operation->password, 1 ) == 0 )
+ if( operation->password_len == 0 )
return( PSA_ERROR_BAD_STATE );
- status = psa_get_and_lock_key_slot( operation->password, &slot );
- if( status != PSA_SUCCESS )
- return( status );
-
-
ret = mbedtls_ecjpake_setup( &operation->ctx.ecjpake,
role,
MBEDTLS_MD_SHA256,
MBEDTLS_ECP_DP_SECP256R1,
- slot->key.data, slot->key.bytes );
+ operation->password,
+ operation->password_len );
- psa_unlock_key_slot( slot );
- slot = NULL;
+ mbedtls_platform_zeroize( operation->password, operation->password_len );
+ mbedtls_free( operation->password );
+ operation->password = NULL;
+ operation->password_len = 0;
if( ret != 0 )
return( mbedtls_ecjpake_to_psa_error( ret ) );
@@ -840,7 +857,11 @@
{
operation->input_step = PSA_PAKE_STEP_INVALID;
operation->output_step = PSA_PAKE_STEP_INVALID;
- operation->password = MBEDTLS_SVC_KEY_ID_INIT;
+ if( operation->password_len > 0 )
+ mbedtls_platform_zeroize( operation->password, operation->password_len );
+ mbedtls_free( operation->password );
+ operation->password = NULL;
+ operation->password_len = 0;
operation->role = PSA_PAKE_ROLE_NONE;
mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE );
operation->buffer_length = 0;
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 1c53a09..21b3ba6 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -2654,7 +2654,7 @@
for( size_t i = 0; i < sig_alg_len; i += 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 3,
- ( "Supported Signature Algorithm found: %d,%d",
+ ( "Supported Signature Algorithm found: %02x %02x",
sig_alg[i], sig_alg[i + 1] ) );
}
#endif
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 71f703c..3dab246 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -2531,10 +2531,15 @@
if( ! mbedtls_ssl_sig_alg_is_supported( ssl, *sig_alg ) )
continue;
- MBEDTLS_PUT_UINT16_BE( *sig_alg, p, sa_len );
+ /* Write elements at offsets starting from 1 (offset 0 is for the
+ * length). Thus the offset of each element is the length of the
+ * partial list including that element. */
sa_len += 2;
+ MBEDTLS_PUT_UINT16_BE( *sig_alg, p, sa_len );
+
}
+ /* Fill in list length. */
MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 );
sa_len += 2;
p += sa_len;
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 8b11bc2..67ea78d 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -15,7 +15,12 @@
# limitations under the License.
from abc import abstractmethod
-from typing import Iterator, List, Tuple, TypeVar
+from typing import Iterator, List, Tuple, TypeVar, Any
+from itertools import chain
+
+from . import test_case
+from . import test_data_generation
+from .bignum_data import INPUTS_DEFAULT, MODULI_DEFAULT
T = TypeVar('T') #pylint: disable=invalid-name
@@ -63,8 +68,7 @@
"""Return all pair combinations from input values."""
return [(x, y) for x in values for y in values]
-
-class OperationCommon:
+class OperationCommon(test_data_generation.BaseTest):
"""Common features for bignum binary operations.
This adds functionality common in binary operation tests.
@@ -78,22 +82,106 @@
unique_combinations_only: Boolean to select if test case combinations
must be unique. If True, only A,B or B,A would be included as a test
case. If False, both A,B and B,A would be included.
+ input_style: Controls the way how test data is passed to the functions
+ in the generated test cases. "variable" passes them as they are
+ defined in the python source. "arch_split" pads the values with
+ zeroes depending on the architecture/limb size. If this is set,
+ test cases are generated for all architectures.
+ arity: the number of operands for the operation. Currently supported
+ values are 1 and 2.
"""
symbol = ""
- input_values = [] # type: List[str]
- input_cases = [] # type: List[Tuple[str, str]]
- unique_combinations_only = True
+ input_values = INPUTS_DEFAULT # type: List[str]
+ input_cases = [] # type: List[Any]
+ unique_combinations_only = False
+ input_styles = ["variable", "fixed", "arch_split"] # type: List[str]
+ input_style = "variable" # type: str
+ limb_sizes = [32, 64] # type: List[int]
+ arities = [1, 2]
+ arity = 2
- def __init__(self, val_a: str, val_b: str) -> None:
- self.arg_a = val_a
- self.arg_b = val_b
+ def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None:
+ self.val_a = val_a
+ self.val_b = val_b
+ # Setting the int versions here as opposed to making them @properties
+ # provides earlier/more robust input validation.
self.int_a = hex_to_int(val_a)
self.int_b = hex_to_int(val_b)
+ if bits_in_limb not in self.limb_sizes:
+ raise ValueError("Invalid number of bits in limb!")
+ if self.input_style == "arch_split":
+ self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)]
+ self.bits_in_limb = bits_in_limb
+
+ @property
+ def boundary(self) -> int:
+ if self.arity == 1:
+ return self.int_a
+ elif self.arity == 2:
+ return max(self.int_a, self.int_b)
+ raise ValueError("Unsupported number of operands!")
+
+ @property
+ def limb_boundary(self) -> int:
+ return bound_mpi(self.boundary, self.bits_in_limb)
+
+ @property
+ def limbs(self) -> int:
+ return limbs_mpi(self.boundary, self.bits_in_limb)
+
+ @property
+ def hex_digits(self) -> int:
+ return 2 * (self.limbs * self.bits_in_limb // 8)
+
+ def format_arg(self, val) -> str:
+ if self.input_style not in self.input_styles:
+ raise ValueError("Unknown input style!")
+ if self.input_style == "variable":
+ return val
+ else:
+ return val.zfill(self.hex_digits)
+
+ def format_result(self, res) -> str:
+ res_str = '{:x}'.format(res)
+ return quote_str(self.format_arg(res_str))
+
+ @property
+ def arg_a(self) -> str:
+ return self.format_arg(self.val_a)
+
+ @property
+ def arg_b(self) -> str:
+ if self.arity == 1:
+ raise AttributeError("Operation is unary and doesn't have arg_b!")
+ return self.format_arg(self.val_b)
def arguments(self) -> List[str]:
- return [
- quote_str(self.arg_a), quote_str(self.arg_b)
- ] + self.result()
+ args = [quote_str(self.arg_a)]
+ if self.arity == 2:
+ args.append(quote_str(self.arg_b))
+ return args + self.result()
+
+ 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:
+ if self.arity == 1:
+ self.case_description = "{} {:x}".format(
+ self.symbol, self.int_a
+ )
+ elif self.arity == 2:
+ self.case_description = "{:x} {} {:x}".format(
+ self.int_a, self.symbol, self.int_b
+ )
+ return super().description()
+
+ @property
+ def is_valid(self) -> bool:
+ return True
@abstractmethod
def result(self) -> List[str]:
@@ -111,15 +199,134 @@
Combinations are first generated from all input values, and then
specific cases provided.
"""
- if cls.unique_combinations_only:
- yield from combination_pairs(cls.input_values)
+ if cls.arity == 1:
+ yield from ((a, "0") for a in cls.input_values)
+ elif cls.arity == 2:
+ if cls.unique_combinations_only:
+ yield from combination_pairs(cls.input_values)
+ else:
+ yield from (
+ (a, b)
+ for a in cls.input_values
+ for b in cls.input_values
+ )
else:
- yield from (
- (a, b)
- for a in cls.input_values
- for b in cls.input_values
- )
- yield from cls.input_cases
+ raise ValueError("Unsupported number of operands!")
+
+ @classmethod
+ def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+ if cls.input_style not in cls.input_styles:
+ raise ValueError("Unknown input style!")
+ if cls.arity not in cls.arities:
+ raise ValueError("Unsupported number of operands!")
+ if cls.input_style == "arch_split":
+ test_objects = (cls(a, b, bits_in_limb=bil)
+ for a, b in cls.get_value_pairs()
+ for bil in cls.limb_sizes)
+ special_cases = (cls(*args, bits_in_limb=bil) # type: ignore
+ for args in cls.input_cases
+ for bil in cls.limb_sizes)
+ else:
+ test_objects = (cls(a, b)
+ for a, b in cls.get_value_pairs())
+ special_cases = (cls(*args) for args in cls.input_cases)
+ yield from (valid_test_object.create_test_case()
+ for valid_test_object in filter(
+ lambda test_object: test_object.is_valid,
+ chain(test_objects, special_cases)
+ )
+ )
+
+
+class ModOperationCommon(OperationCommon):
+ #pylint: disable=abstract-method
+ """Target for bignum mod_raw test case generation."""
+ moduli = MODULI_DEFAULT # type: List[str]
+
+ def __init__(self, val_n: str, val_a: str, val_b: str = "0",
+ bits_in_limb: int = 64) -> None:
+ super().__init__(val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb)
+ self.val_n = val_n
+ # Setting the int versions here as opposed to making them @properties
+ # provides earlier/more robust input validation.
+ self.int_n = hex_to_int(val_n)
+
+ @property
+ def boundary(self) -> int:
+ return self.int_n
+
+ @property
+ def arg_n(self) -> str:
+ return self.format_arg(self.val_n)
+
+ def arguments(self) -> List[str]:
+ return [quote_str(self.arg_n)] + super().arguments()
+
+ @property
+ def r(self) -> int: # pylint: disable=invalid-name
+ l = limbs_mpi(self.int_n, self.bits_in_limb)
+ return bound_mpi_limbs(l, self.bits_in_limb)
+
+ @property
+ def r_inv(self) -> int:
+ return invmod(self.r, self.int_n)
+
+ @property
+ def r2(self) -> int: # pylint: disable=invalid-name
+ return pow(self.r, 2)
+
+ @property
+ def is_valid(self) -> bool:
+ if self.int_a >= self.int_n:
+ return False
+ if self.arity == 2 and self.int_b >= self.int_n:
+ return False
+ return True
+
+ def description(self) -> str:
+ """Generate a description for the test case.
+
+ It uses the form A `symbol` B mod N, where symbol is used to represent
+ the operation.
+ """
+
+ if not self.case_description:
+ return super().description() + " mod {:x}".format(self.int_n)
+ return super().description()
+
+ @classmethod
+ def input_cases_args(cls) -> Iterator[Tuple[Any, Any, Any]]:
+ if cls.arity == 1:
+ yield from ((n, a, "0") for a, n in cls.input_cases)
+ elif cls.arity == 2:
+ yield from ((n, a, b) for a, b, n in cls.input_cases)
+ else:
+ raise ValueError("Unsupported number of operands!")
+
+ @classmethod
+ def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+ if cls.input_style not in cls.input_styles:
+ raise ValueError("Unknown input style!")
+ if cls.arity not in cls.arities:
+ raise ValueError("Unsupported number of operands!")
+ if cls.input_style == "arch_split":
+ test_objects = (cls(n, a, b, bits_in_limb=bil)
+ for n in cls.moduli
+ for a, b in cls.get_value_pairs()
+ for bil in cls.limb_sizes)
+ special_cases = (cls(*args, bits_in_limb=bil)
+ for args in cls.input_cases_args()
+ for bil in cls.limb_sizes)
+ else:
+ test_objects = (cls(n, a, b)
+ for n in cls.moduli
+ for a, b in cls.get_value_pairs())
+ special_cases = (cls(*args) for args in cls.input_cases_args())
+ yield from (valid_test_object.create_test_case()
+ for valid_test_object in filter(
+ lambda test_object: test_object.is_valid,
+ chain(test_objects, special_cases)
+ ))
# BEGIN MERGE SLOT 1
diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py
index 0cc86b8..4910dae 100644
--- a/scripts/mbedtls_dev/bignum_core.py
+++ b/scripts/mbedtls_dev/bignum_core.py
@@ -16,20 +16,19 @@
import random
-from abc import ABCMeta
from typing import Dict, Iterator, List, Tuple
from . import test_case
from . import test_data_generation
from . import bignum_common
-class BignumCoreTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
+class BignumCoreTarget(test_data_generation.BaseTarget):
+ #pylint: disable=abstract-method, too-few-public-methods
"""Target for bignum core test case generation."""
target_basename = 'test_suite_bignum_core.generated'
-class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta):
+class BignumCoreShiftR(BignumCoreTarget, test_data_generation.BaseTest):
"""Test cases for mbedtls_bignum_core_shift_r()."""
count = 0
test_function = "mpi_core_shift_r"
@@ -69,7 +68,7 @@
for count in counts:
yield cls(input_hex, descr, count).create_test_case()
-class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta):
+class BignumCoreCTLookup(BignumCoreTarget, test_data_generation.BaseTest):
"""Test cases for mbedtls_mpi_core_ct_uint_table_lookup()."""
test_function = "mpi_core_ct_uint_table_lookup"
test_name = "Constant time MPI table lookup"
@@ -107,104 +106,33 @@
yield (cls(bitsize, bitsize_description, window_size)
.create_test_case())
-class BignumCoreOperation(bignum_common.OperationCommon, BignumCoreTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
- """Common features for bignum core operations."""
- input_values = [
- "0", "1", "3", "f", "fe", "ff", "100", "ff00", "fffe", "ffff", "10000",
- "fffffffe", "ffffffff", "100000000", "1f7f7f7f7f7f7f",
- "8000000000000000", "fefefefefefefefe", "fffffffffffffffe",
- "ffffffffffffffff", "10000000000000000", "1234567890abcdef0",
- "fffffffffffffffffefefefefefefefe", "fffffffffffffffffffffffffffffffe",
- "ffffffffffffffffffffffffffffffff", "100000000000000000000000000000000",
- "1234567890abcdef01234567890abcdef0",
- "fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe",
- "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
- "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- "10000000000000000000000000000000000000000000000000000000000000000",
- "1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0",
- (
- "4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f34029"
- "643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf179298bd9947"
- "c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38edf0c5889eca4a0"
- "cfa99b45fbdeee4c696b328ddceae4723945901ec025076b12b"
- )
- ]
- 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 = "{:x} {} {:x}".format(
- self.int_a, self.symbol, self.int_b
- )
- return super().description()
-
- @classmethod
- def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
- for a_value, b_value in cls.get_value_pairs():
- yield cls(a_value, b_value).create_test_case()
-
-
-class BignumCoreOperationArchSplit(BignumCoreOperation):
- #pylint: disable=abstract-method
- """Common features for bignum core operations where the result depends on
- the limb size."""
-
- def __init__(self, val_a: str, val_b: str, bits_in_limb: int) -> None:
- super().__init__(val_a, val_b)
- bound_val = max(self.int_a, self.int_b)
- self.bits_in_limb = bits_in_limb
- self.bound = bignum_common.bound_mpi(bound_val, self.bits_in_limb)
- limbs = bignum_common.limbs_mpi(bound_val, self.bits_in_limb)
- byte_len = limbs * self.bits_in_limb // 8
- self.hex_digits = 2 * byte_len
- if self.bits_in_limb == 32:
- self.dependencies = ["MBEDTLS_HAVE_INT32"]
- elif self.bits_in_limb == 64:
- self.dependencies = ["MBEDTLS_HAVE_INT64"]
- else:
- raise ValueError("Invalid number of bits in limb!")
- self.arg_a = self.arg_a.zfill(self.hex_digits)
- self.arg_b = self.arg_b.zfill(self.hex_digits)
-
- def pad_to_limbs(self, val) -> str:
- return "{:x}".format(val).zfill(self.hex_digits)
-
- @classmethod
- def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
- for a_value, b_value in cls.get_value_pairs():
- yield cls(a_value, b_value, 32).create_test_case()
- yield cls(a_value, b_value, 64).create_test_case()
-
-class BignumCoreAddAndAddIf(BignumCoreOperationArchSplit):
+class BignumCoreAddAndAddIf(BignumCoreTarget, bignum_common.OperationCommon):
"""Test cases for bignum core add and add-if."""
count = 0
symbol = "+"
test_function = "mpi_core_add_and_add_if"
test_name = "mpi_core_add_and_add_if"
+ input_style = "arch_split"
+ unique_combinations_only = True
def result(self) -> List[str]:
result = self.int_a + self.int_b
- carry, result = divmod(result, self.bound)
+ carry, result = divmod(result, self.limb_boundary)
return [
- bignum_common.quote_str(self.pad_to_limbs(result)),
+ self.format_result(result),
str(carry)
]
-class BignumCoreSub(BignumCoreOperation):
+
+class BignumCoreSub(BignumCoreTarget, bignum_common.OperationCommon):
"""Test cases for bignum core sub."""
count = 0
symbol = "-"
test_function = "mpi_core_sub"
test_name = "mbedtls_mpi_core_sub"
- unique_combinations_only = False
def result(self) -> List[str]:
if self.int_a >= self.int_b:
@@ -224,12 +152,11 @@
]
-class BignumCoreMLA(BignumCoreOperation):
+class BignumCoreMLA(BignumCoreTarget, bignum_common.OperationCommon):
"""Test cases for fixed-size multiply accumulate."""
count = 0
test_function = "mpi_core_mla"
test_name = "mbedtls_mpi_core_mla"
- unique_combinations_only = False
input_values = [
"0", "1", "fffe", "ffffffff", "100000000", "20000000000000",
@@ -289,6 +216,16 @@
]
@classmethod
+ def get_value_pairs(cls) -> Iterator[Tuple[str, str]]:
+ """Generator to yield pairs of inputs.
+
+ Combinations are first generated from all input values, and then
+ specific cases provided.
+ """
+ yield from super().get_value_pairs()
+ yield from cls.input_cases
+
+ @classmethod
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
"""Override for additional scalar input."""
for a_value, b_value in cls.get_value_pairs():
@@ -297,7 +234,7 @@
yield cur_op.create_test_case()
-class BignumCoreMontmul(BignumCoreTarget):
+class BignumCoreMontmul(BignumCoreTarget, test_data_generation.BaseTest):
"""Test cases for Montgomery multiplication."""
count = 0
test_function = "mpi_core_montmul"
diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py
new file mode 100644
index 0000000..74d21d0
--- /dev/null
+++ b/scripts/mbedtls_dev/bignum_data.py
@@ -0,0 +1,136 @@
+"""Base values and datasets for bignum generated tests and helper functions that
+produced them."""
+# 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 random
+
+# Functions calling these were used to produce test data and are here only for
+# reproducability, they are not used by the test generation framework/classes
+try:
+ from Cryptodome.Util.number import isPrime, getPrime #type: ignore #pylint: disable=import-error
+except ImportError:
+ pass
+
+# Generated by bignum_common.gen_safe_prime(192,1)
+SAFE_PRIME_192_BIT_SEED_1 = "d1c127a667786703830500038ebaef20e5a3e2dc378fb75b"
+
+# First number generated by random.getrandbits(192) - seed(2,2), not a prime
+RANDOM_192_BIT_SEED_2_NO1 = "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"
+
+# Second number generated by random.getrandbits(192) - seed(2,2), not a prime
+RANDOM_192_BIT_SEED_2_NO2 = "cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
+
+# Third number generated by random.getrandbits(192) - seed(2,2), not a prime
+RANDOM_192_BIT_SEED_2_NO3 = "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"
+
+# Fourth number generated by random.getrandbits(192) - seed(2,2), not a prime
+RANDOM_192_BIT_SEED_2_NO4 = "ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
+
+# Ninth number generated by random.getrandbits(192) - seed(2,2), not a prime
+RANDOM_192_BIT_SEED_2_NO9 = "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"
+
+# Generated by bignum_common.gen_safe_prime(1024,3)
+SAFE_PRIME_1024_BIT_SEED_3 = ("c93ba7ec74d96f411ba008bdb78e63ff11bb5df46a51e16b"
+ "2c9d156f8e4e18abf5e052cb01f47d0d1925a77f60991577"
+ "e128fb6f52f34a27950a594baadd3d8057abeb222cf3cca9"
+ "62db16abf79f2ada5bd29ab2f51244bf295eff9f6aaba130"
+ "2efc449b128be75eeaca04bc3c1a155d11d14e8be32a2c82"
+ "87b3996cf6ad5223")
+
+# First number generated by random.getrandbits(1024) - seed(4,2), not a prime
+RANDOM_1024_BIT_SEED_4_NO1 = ("6905269ed6f0b09f165c8ce36e2f24b43000de01b2ed40ed"
+ "3addccb2c33be0ac79d679346d4ac7a5c3902b38963dc6e8"
+ "534f45738d048ec0f1099c6c3e1b258fd724452ccea71ff4"
+ "a14876aeaff1a098ca5996666ceab360512bd13110722311"
+ "710cf5327ac435a7a97c643656412a9b8a1abcd1a6916c74"
+ "da4f9fc3c6da5d7")
+
+# Second number generated by random.getrandbits(1024) - seed(4,2), not a prime
+RANDOM_1024_BIT_SEED_4_NO2 = ("f1cfd99216df648647adec26793d0e453f5082492d83a823"
+ "3fb62d2c81862fc9634f806fabf4a07c566002249b191bf4"
+ "d8441b5616332aca5f552773e14b0190d93936e1daca3c06"
+ "f5ff0c03bb5d7385de08caa1a08179104a25e4664f5253a0"
+ "2a3187853184ff27459142deccea264542a00403ce80c4b0"
+ "a4042bb3d4341aad")
+
+# Third number generated by random.getrandbits(1024) - seed(4,2), not a prime
+RANDOM_1024_BIT_SEED_4_NO3 = ("14c15c910b11ad28cc21ce88d0060cc54278c2614e1bcb38"
+ "3bb4a570294c4ea3738d243a6e58d5ca49c7b59b995253fd"
+ "6c79a3de69f85e3131f3b9238224b122c3e4a892d9196ada"
+ "4fcfa583e1df8af9b474c7e89286a1754abcb06ae8abb93f"
+ "01d89a024cdce7a6d7288ff68c320f89f1347e0cdd905ecf"
+ "d160c5d0ef412ed6")
+
+# Fourth number generated by random.getrandbits(1024) - seed(4,2), not a prime
+RANDOM_1024_BIT_SEED_4_NO4 = ("32decd6b8efbc170a26a25c852175b7a96b98b5fbf37a2be"
+ "6f98bca35b17b9662f0733c846bbe9e870ef55b1a1f65507"
+ "a2909cb633e238b4e9dd38b869ace91311021c9e32111ac1"
+ "ac7cc4a4ff4dab102522d53857c49391b36cc9aa78a330a1"
+ "a5e333cb88dcf94384d4cd1f47ca7883ff5a52f1a05885ac"
+ "7671863c0bdbc23a")
+
+# Fifth number generated by random.getrandbits(1024) - seed(4,2), not a prime
+RANDOM_1024_BIT_SEED_4_NO5 = ("53be4721f5b9e1f5acdac615bc20f6264922b9ccf469aef8"
+ "f6e7d078e55b85dd1525f363b281b8885b69dc230af5ac87"
+ "0692b534758240df4a7a03052d733dcdef40af2e54c0ce68"
+ "1f44ebd13cc75f3edcb285f89d8cf4d4950b16ffc3e1ac3b"
+ "4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc"
+ "52d32377e78131c1")
+
+# Adding 192 bit and 1024 bit numbers because these are the shortest required
+# for ECC and RSA respectively.
+INPUTS_DEFAULT = [
+ "0", "1", # corner cases
+ "2", "3", # small primes
+ "4", # non-prime even
+ "38", # small random
+ SAFE_PRIME_192_BIT_SEED_1, # prime
+ RANDOM_192_BIT_SEED_2_NO1, # not a prime
+ RANDOM_192_BIT_SEED_2_NO2, # not a prime
+ SAFE_PRIME_1024_BIT_SEED_3, # prime
+ RANDOM_1024_BIT_SEED_4_NO1, # not a prime
+ RANDOM_1024_BIT_SEED_4_NO3, # not a prime
+ RANDOM_1024_BIT_SEED_4_NO2, # largest (not a prime)
+ ]
+
+# Only odd moduli are present as in the new bignum code only odd moduli are
+# supported for now.
+MODULI_DEFAULT = [
+ "53", # safe prime
+ "45", # non-prime
+ SAFE_PRIME_192_BIT_SEED_1, # safe prime
+ RANDOM_192_BIT_SEED_2_NO4, # not a prime
+ SAFE_PRIME_1024_BIT_SEED_3, # safe prime
+ RANDOM_1024_BIT_SEED_4_NO5, # not a prime
+ ]
+
+def __gen_safe_prime(bits, seed):
+ '''
+ Generate a safe prime.
+
+ This function is intended for generating constants offline and shouldn't be
+ used in test generation classes.
+
+ Requires pycryptodomex for getPrime and isPrime and python 3.9 or later for
+ randbytes.
+ '''
+ rng = random.Random()
+ # We want reproducability across python versions
+ rng.seed(seed, version=2)
+ while True:
+ prime = 2*getPrime(bits-1, rng.randbytes)+1 #pylint: disable=no-member
+ if isPrime(prime, 1e-30):
+ return prime
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index 2bd7fbb..a604cc0 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -14,12 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from abc import ABCMeta
-
from . import test_data_generation
-class BignumModTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
+class BignumModTarget(test_data_generation.BaseTarget):
+ #pylint: disable=abstract-method, too-few-public-methods
"""Target for bignum mod test case generation."""
target_basename = 'test_suite_bignum_mod.generated'
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index bd694a6..60f2fed 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -14,89 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from abc import ABCMeta
-from typing import Dict, Iterator, List
+from typing import Dict, List
-from . import test_case
from . import test_data_generation
from . import bignum_common
-class BignumModRawTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
+class BignumModRawTarget(test_data_generation.BaseTarget):
+ #pylint: disable=abstract-method, too-few-public-methods
"""Target for bignum mod_raw test case generation."""
target_basename = 'test_suite_bignum_mod_raw.generated'
-class BignumModRawOperation(bignum_common.OperationCommon, BignumModRawTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
- """Target for bignum mod_raw test case generation."""
-
- def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None:
- super().__init__(val_a=val_a, val_b=val_b)
- self.val_n = val_n
- self.bits_in_limb = bits_in_limb
-
- @property
- def int_n(self) -> int:
- return bignum_common.hex_to_int(self.val_n)
-
- @property
- def boundary(self) -> int:
- data_in = [self.int_a, self.int_b, self.int_n]
- return max([n for n in data_in if n is not None])
-
- @property
- def limbs(self) -> int:
- return bignum_common.limbs_mpi(self.boundary, self.bits_in_limb)
-
- @property
- def hex_digits(self) -> int:
- return 2 * (self.limbs * self.bits_in_limb // 8)
-
- @property
- def hex_n(self) -> str:
- return "{:x}".format(self.int_n).zfill(self.hex_digits)
-
- @property
- def hex_a(self) -> str:
- return "{:x}".format(self.int_a).zfill(self.hex_digits)
-
- @property
- def hex_b(self) -> str:
- return "{:x}".format(self.int_b).zfill(self.hex_digits)
-
- @property
- def r(self) -> int: # pylint: disable=invalid-name
- l = bignum_common.limbs_mpi(self.int_n, self.bits_in_limb)
- return bignum_common.bound_mpi_limbs(l, self.bits_in_limb)
-
- @property
- def r_inv(self) -> int:
- return bignum_common.invmod(self.r, self.int_n)
-
- @property
- def r2(self) -> int: # pylint: disable=invalid-name
- return pow(self.r, 2)
-
-class BignumModRawOperationArchSplit(BignumModRawOperation):
- #pylint: disable=abstract-method
- """Common features for bignum mod raw operations where the result depends on
- the limb size."""
-
- limb_sizes = [32, 64] # type: List[int]
-
- def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None:
- super().__init__(val_n=val_n, val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb)
-
- if bits_in_limb not in self.limb_sizes:
- raise ValueError("Invalid number of bits in limb!")
-
- self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)]
-
- @classmethod
- def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
- for a_value, b_value in cls.get_value_pairs():
- for bil in cls.limb_sizes:
- yield cls(a_value, b_value, bits_in_limb=bil).create_test_case()
# BEGIN MERGE SLOT 1
# END MERGE SLOT 1
@@ -122,126 +49,35 @@
# END MERGE SLOT 6
# BEGIN MERGE SLOT 7
-class BignumModRawConvertToMont(BignumModRawOperationArchSplit):
- """ Test cases for mpi_mod_raw_to_mont_rep(). """
+class BignumModRawConvertToMont(bignum_common.ModOperationCommon,
+ BignumModRawTarget):
+ """ Test cases for mpi_mod_raw_to_mont_rep(). """
test_function = "mpi_mod_raw_to_mont_rep"
test_name = "Convert into Mont: "
-
- test_data_moduli = ["b",
- "fd",
- "eeff99aa37",
- "eeff99aa11",
- "800000000005",
- "7fffffffffffffff",
- "80fe000a10000001",
- "25a55a46e5da99c71c7",
- "1058ad82120c3a10196bb36229c1",
- "7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f"
- "18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a"
- "98df75154f8c914a282f8b",
- "8335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63",
- "ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f"
- "2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a6"
- "4d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2"
- "deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d"
- "6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a0"
- "7e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d389"
- "8c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6"
- "bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3a"
- "d4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181d"
- "b8896f33bb12e6ef73f12ec5c5ea7a8a337"
- ]
-
- test_input_numbers = ["0",
- "1",
- "97",
- "f5",
- "6f5c3",
- "745bfe50f7",
- "ffa1f9924123",
- "334a8b983c79bd",
- "5b84f632b58f3461",
- "19acd15bc38008e1",
- "ffffffffffffffff",
- "54ce6a6bb8247fa0427cfc75a6b0599",
- "fecafe8eca052f154ce6a6bb8247fa019558bfeecce9bb9",
- "a87d7a56fa4bfdc7da42ef798b9cf6843d4c54794698cb14d72"
- "851dec9586a319f4bb6d5695acbd7c92e7a42a5ede6972adcbc"
- "f68425265887f2d721f462b7f1b91531bac29fa648facb8e3c6"
- "1bd5ae42d5a59ba1c89a95897bfe541a8ce1d633b98f379c481"
- "6f25e21f6ac49286b261adb4b78274fe5f61c187581f213e84b"
- "2a821e341ef956ecd5de89e6c1a35418cd74a549379d2d4594a"
- "577543147f8e35b3514e62cf3e89d1156cdc91ab5f4c928fbd6"
- "9148c35df5962fed381f4d8a62852a36823d5425f7487c13a12"
- "523473fb823aa9d6ea5f42e794e15f2c1a8785cf6b7d51a4617"
- "947fb3baf674f74a673cf1d38126983a19ed52c7439fab42c2185"
- ]
-
- descr_tpl = '{} #{} N: \"{}\" A: \"{}\".'
+ symbol = "R *"
+ input_style = "arch_split"
+ arity = 1
def result(self) -> List[str]:
- return [self.hex_x]
+ result = (self.int_a * self.r) % self.int_n
+ return [self.format_result(result)]
- def arguments(self) -> List[str]:
- return [bignum_common.quote_str(n) for n in [self.hex_n,
- self.hex_a,
- self.hex_x]]
- def description(self) -> str:
- return self.descr_tpl.format(self.test_name,
- self.count,
- self.int_n,
- self.int_a)
-
- @classmethod
- def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
- for bil in [32, 64]:
- for n in cls.test_data_moduli:
- for i in cls.test_input_numbers:
- # Skip invalid combinations where A.limbs > N.limbs
- if bignum_common.hex_to_int(i) > bignum_common.hex_to_int(n):
- continue
- yield cls(n, i, bits_in_limb=bil).create_test_case()
-
- @property
- def x(self) -> int: # pylint: disable=invalid-name
- return (self.int_a * self.r) % self.int_n
-
- @property
- def hex_x(self) -> str:
- return "{:x}".format(self.x).zfill(self.hex_digits)
-
-class BignumModRawConvertFromMont(BignumModRawConvertToMont):
+class BignumModRawConvertFromMont(bignum_common.ModOperationCommon,
+ BignumModRawTarget):
""" Test cases for mpi_mod_raw_from_mont_rep(). """
-
test_function = "mpi_mod_raw_from_mont_rep"
test_name = "Convert from Mont: "
+ symbol = "1/R *"
+ input_style = "arch_split"
+ arity = 1
- test_input_numbers = ["0",
- "1",
- "3ca",
- "539ed428",
- "7dfe5c6beb35a2d6",
- "dca8de1c2adfc6d7aafb9b48e",
- "a7d17b6c4be72f3d5c16bf9c1af6fc933",
- "2fec97beec546f9553142ed52f147845463f579",
- "378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f",
- "b6415f2a1a8e48a518345db11f56db3829c8f2c6415ab4a395a"
- "b3ac2ea4cbef4af86eb18a84eb6ded4c6ecbfc4b59c2879a675"
- "487f687adea9d197a84a5242a5cf6125ce19a6ad2e7341f1c57"
- "d43ea4f4c852a51cb63dabcd1c9de2b827a3146a3d175b35bea"
- "41ae75d2a286a3e9d43623152ac513dcdea1d72a7da846a8ab3"
- "58d9be4926c79cfb287cf1cf25b689de3b912176be5dcaf4d4c"
- "6e7cb839a4a3243a6c47c1e2c99d65c59d6fa3672575c2f1ca8"
- "de6a32e854ec9d8ec635c96af7679fce26d7d159e4a9da3bd74"
- "e1272c376cd926d74fe3fb164a5935cff3d5cdb92b35fe2cea32"
- "138a7e6bfbc319ebd1725dacb9a359cbf693f2ecb785efb9d627"
- ]
+ def result(self) -> List[str]:
+ result = (self.int_a * self.r_inv) % self.int_n
+ return [self.format_result(result)]
- @property
- def x(self): # pylint: disable=invalid-name
- return (self.int_a * self.r_inv) % self.int_n
+
# END MERGE SLOT 7
# BEGIN MERGE SLOT 8
diff --git a/scripts/mbedtls_dev/test_data_generation.py b/scripts/mbedtls_dev/test_data_generation.py
index eec0f9d..02aa510 100644
--- a/scripts/mbedtls_dev/test_data_generation.py
+++ b/scripts/mbedtls_dev/test_data_generation.py
@@ -25,6 +25,7 @@
import os
import posixpath
import re
+import inspect
from abc import ABCMeta, abstractmethod
from typing import Callable, Dict, Iterable, Iterator, List, Type, TypeVar
@@ -35,12 +36,8 @@
T = TypeVar('T') #pylint: disable=invalid-name
-class BaseTarget(metaclass=ABCMeta):
- """Base target for test case generation.
-
- Child classes of this class represent an output file, and can be referred
- to as file targets. These indicate where test cases will be written to for
- all subclasses of the file target, which is set by `target_basename`.
+class BaseTest(metaclass=ABCMeta):
+ """Base class for test case generation.
Attributes:
count: Counter for test cases from this class.
@@ -48,8 +45,6 @@
automatically generated using the class, or manually set.
dependencies: A list of dependencies required for the test case.
show_test_count: Toggle for inclusion of `count` in the test description.
- target_basename: Basename of file to write generated tests to. This
- should be specified in a child class of BaseTarget.
test_function: Test function which the class generates cases for.
test_name: A common name or description of the test function. This can
be `test_function`, a clearer equivalent, or a short summary of the
@@ -59,7 +54,6 @@
case_description = ""
dependencies = [] # type: List[str]
show_test_count = True
- target_basename = ""
test_function = ""
test_name = ""
@@ -121,6 +115,21 @@
"""
raise NotImplementedError
+
+class BaseTarget:
+ #pylint: disable=too-few-public-methods
+ """Base target for test case generation.
+
+ Child classes of this class represent an output file, and can be referred
+ to as file targets. These indicate where test cases will be written to for
+ all subclasses of the file target, which is set by `target_basename`.
+
+ Attributes:
+ target_basename: Basename of file to write generated tests to. This
+ should be specified in a child class of BaseTarget.
+ """
+ target_basename = ""
+
@classmethod
def generate_tests(cls) -> Iterator[test_case.TestCase]:
"""Generate test cases for the class and its subclasses.
@@ -132,7 +141,8 @@
yield from `generate_tests()` in each. Calling this method on a class X
will yield test cases from all classes derived from X.
"""
- if cls.test_function:
+ if issubclass(cls, BaseTest) and not inspect.isabstract(cls):
+ #pylint: disable=no-member
yield from cls.generate_function_tests()
for subclass in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
yield from subclass.generate_tests()
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 8272dcc..3a69fd7 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -3250,6 +3250,7 @@
component_test_tls13_only () {
msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3, without MBEDTLS_SSL_PROTO_TLS1_2"
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
msg "test: TLS 1.3 only, all key exchange modes enabled"
@@ -3269,6 +3270,7 @@
scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION
scripts/config.py unset MBEDTLS_ECDSA_C
scripts/config.py unset MBEDTLS_PKCS1_V21
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
msg "test_suite_ssl: TLS 1.3 only, only PSK key exchange mode enabled"
@@ -3301,6 +3303,7 @@
scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION
scripts/config.py unset MBEDTLS_ECDSA_C
scripts/config.py unset MBEDTLS_PKCS1_V21
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
msg "test_suite_ssl: TLS 1.3 only, only PSK ephemeral key exchange mode"
@@ -3318,6 +3321,7 @@
scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION
scripts/config.py unset MBEDTLS_ECDSA_C
scripts/config.py unset MBEDTLS_PKCS1_V21
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
msg "test_suite_ssl: TLS 1.3 only, PSK and PSK ephemeral key exchange modes"
@@ -3330,6 +3334,7 @@
component_test_tls13_only_ephemeral_all () {
msg "build: TLS 1.3 only from default, without PSK key exchange mode"
scripts/config.py unset MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
msg "test_suite_ssl: TLS 1.3 only, ephemeral and PSK ephemeral key exchange modes"
@@ -3344,6 +3349,7 @@
scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
scripts/config.py set MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
@@ -3357,6 +3363,7 @@
scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
scripts/config.py unset MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1
+ scripts/config.py set MBEDTLS_SSL_EARLY_DATA
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index eee2f65..c3058e9 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -57,7 +57,7 @@
import sys
from abc import ABCMeta
-from typing import Iterator, List
+from typing import List
import scripts_path # pylint: disable=unused-import
from mbedtls_dev import test_case
@@ -68,15 +68,17 @@
# the framework
from mbedtls_dev import bignum_core, bignum_mod_raw # pylint: disable=unused-import
-class BignumTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
- #pylint: disable=abstract-method
+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):
+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",
@@ -132,11 +134,6 @@
tmp = "large " + tmp
return tmp
- @classmethod
- def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
- for a_value, b_value in cls.get_value_pairs():
- yield cls(a_value, b_value).create_test_case()
-
class BignumCmp(BignumOperation):
"""Test cases for bignum value comparison."""
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 8a5bb93..cedc0bf 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -50,10 +50,10 @@
'verbose|v:1' => \$verbose,
) or die;
-# All test suites = executable files derived from a .data file.
+# All test suites = executable files with a .datax file.
my @suites = ();
-for my $data_file (glob 'suites/test_suite_*.data') {
- (my $base = $data_file) =~ s#^suites/(.*)\.data$#$1#;
+for my $data_file (glob 'test_suite_*.datax') {
+ (my $base = $data_file) =~ s/\.datax$//;
push @suites, $base if -x $base;
push @suites, "$base.exe" if -e "$base.exe";
}
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index a4789db..b460c67 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2384,6 +2384,31 @@
-u "IV used" \
-U "IV used"
+# Test for correctness of sent single supported algorithm
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_hash_alg SHA_256
+run_test "Single supported algorithm sending: mbedtls client" \
+ "$P_SRV sig_algs=ecdsa_secp256r1_sha256 auth_mode=required" \
+ "$P_CLI sig_algs=ecdsa_secp256r1_sha256 debug_level=3" \
+ 0 \
+ -c "Supported Signature Algorithm found: 04 03"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_ECP_DP_SECP256R1_ENABLED
+requires_hash_alg SHA_256
+run_test "Single supported algorithm sending: openssl client" \
+ "$P_SRV sig_algs=ecdsa_secp256r1_sha256 auth_mode=required" \
+ "$O_CLI -cert data_files/server6.crt \
+ -key data_files/server6.key" \
+ 0
+
# Tests for certificate verification callback
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
run_test "Configuration-specific CRT verification callback" \
@@ -5287,8 +5312,8 @@
key_file=data_files/server6.key \
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \
0 \
- -c "Supported Signature Algorithm found: 4," \
- -c "Supported Signature Algorithm found: 5,"
+ -c "Supported Signature Algorithm found: 04 " \
+ -c "Supported Signature Algorithm found: 05 "
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
@@ -5298,8 +5323,8 @@
key_file=data_files/server6.key \
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" \
0 \
- -c "Supported Signature Algorithm found: 4," \
- -c "Supported Signature Algorithm found: 5,"
+ -c "Supported Signature Algorithm found: 04 " \
+ -c "Supported Signature Algorithm found: 05 "
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Authentication: client has no cert, server required (TLS)" \
@@ -5700,8 +5725,8 @@
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \
0 \
-s "use CA callback for X.509 CRT verification" \
- -c "Supported Signature Algorithm found: 4," \
- -c "Supported Signature Algorithm found: 5,"
+ -c "Supported Signature Algorithm found: 04 " \
+ -c "Supported Signature Algorithm found: 05 "
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -5713,8 +5738,8 @@
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" \
0 \
-s "use CA callback for X.509 CRT verification" \
- -c "Supported Signature Algorithm found: 4," \
- -c "Supported Signature Algorithm found: 5,"
+ -c "Supported Signature Algorithm found: 04 " \
+ -c "Supported Signature Algorithm found: 05 "
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
diff --git a/tests/suites/test_suite_bignum.function b/tests/suites/test_suite_bignum.function
index b75f534..55bb2f5 100644
--- a/tests/suites/test_suite_bignum.function
+++ b/tests/suites/test_suite_bignum.function
@@ -1458,6 +1458,150 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void most_negative_mpi_sint( )
+{
+ /* Ad hoc tests for n = -p = -2^(biL-1) as a mbedtls_mpi_sint. We
+ * guarantee that mbedtls_mpi_sint is a two's complement type, so this
+ * is a valid value. However, negating it (`-n`) has undefined behavior
+ * (although in practice `-n` evaluates to the value n).
+ *
+ * This function has ad hoc tests for this value. It's separated from other
+ * functions because the test framework makes it hard to pass this value
+ * into test cases.
+ *
+ * In the comments here:
+ * - biL = number of bits in limbs
+ * - p = 2^(biL-1) (smallest positive value not in mbedtls_mpi_sint range)
+ * - n = -2^(biL-1) (largest negative value in mbedtls_mpi_sint range)
+ */
+
+ mbedtls_mpi A, R, X;
+ mbedtls_mpi_init( &A );
+ mbedtls_mpi_init( &R );
+ mbedtls_mpi_init( &X );
+
+ const size_t biL = 8 * sizeof( mbedtls_mpi_sint );
+ mbedtls_mpi_uint most_positive_plus_1 = (mbedtls_mpi_uint) 1 << ( biL - 1 );
+ const mbedtls_mpi_sint most_positive = most_positive_plus_1 - 1;
+ const mbedtls_mpi_sint most_negative = - most_positive - 1;
+ TEST_EQUAL( (mbedtls_mpi_uint) most_negative,
+ (mbedtls_mpi_uint) 1 << ( biL - 1 ) );
+ TEST_EQUAL( (mbedtls_mpi_uint) most_negative << 1, 0 );
+
+ /* Test mbedtls_mpi_lset() */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_negative ), 0 );
+ TEST_EQUAL( A.s, -1 );
+ TEST_EQUAL( A.n, 1 );
+ TEST_EQUAL( A.p[0], most_positive_plus_1 );
+
+ /* Test mbedtls_mpi_cmp_int(): -p == -p */
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &A, most_negative ), 0 );
+
+ /* Test mbedtls_mpi_cmp_int(): -(p+1) < -p */
+ A.p[0] = most_positive_plus_1 + 1;
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &A, most_negative ), -1 );
+
+ /* Test mbedtls_mpi_cmp_int(): -(p-1) > -p */
+ A.p[0] = most_positive_plus_1 - 1;
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &A, most_negative ), 1 );
+
+ /* Test mbedtls_mpi_add_int(): (p-1) + (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_positive ), 0 );
+ TEST_EQUAL( mbedtls_mpi_add_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, -1 ), 0 );
+
+ /* Test mbedtls_mpi_add_int(): (0) + (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, 0 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_add_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, most_negative ), 0 );
+
+ /* Test mbedtls_mpi_add_int(): (-p) + (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_add_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( X.s, -1 );
+ TEST_EQUAL( X.n, 2 );
+ TEST_EQUAL( X.p[0], 0 );
+ TEST_EQUAL( X.p[1], 1 );
+
+ /* Test mbedtls_mpi_sub_int(): (p) - (-p) */
+ mbedtls_mpi_free( &X );
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_positive ), 0 );
+ TEST_EQUAL( mbedtls_mpi_sub_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( X.s, 1 );
+ TEST_EQUAL( X.n, 1 );
+ TEST_EQUAL( X.p[0], ~(mbedtls_mpi_uint)0 );
+
+ /* Test mbedtls_mpi_sub_int(): (0) - (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, 0 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_sub_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( X.s, 1 );
+ TEST_EQUAL( X.n, 1 );
+ TEST_EQUAL( X.p[0], most_positive_plus_1 );
+
+ /* Test mbedtls_mpi_sub_int(): (-p) - (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_sub_int( &X, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 0 ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (-p+1) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, -most_positive ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 0 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, -most_positive ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (-p) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, 0 ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (-2*p) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_shift_l( &A, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 2 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, 0 ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (-2*p+1) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_add_int( &A, &A, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, -most_positive ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (p-1) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_lset( &A, most_positive ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, 0 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, most_positive ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (p) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_add_int( &A, &A, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, -1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, 0 ), 0 );
+
+ /* Test mbedtls_mpi_div_int(): (2*p) / (-p) */
+ TEST_EQUAL( mbedtls_mpi_shift_l( &A, 1 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_div_int( &X, &R, &A, most_negative ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &X, -2 ), 0 );
+ TEST_EQUAL( mbedtls_mpi_cmp_int( &R, 0 ), 0 );
+
+ /* Test mbedtls_mpi_mod_int(): never valid */
+ TEST_EQUAL( mbedtls_mpi_mod_int( X.p, &A, most_negative ),
+ MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+
+ /* Test mbedtls_mpi_random(): never valid */
+ TEST_EQUAL( mbedtls_mpi_random( &X, most_negative, &A,
+ mbedtls_test_rnd_std_rand, NULL ),
+ MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+exit:
+ mbedtls_mpi_free( &A );
+ mbedtls_mpi_free( &R );
+ mbedtls_mpi_free( &X );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mpi_selftest( )
{
diff --git a/tests/suites/test_suite_bignum.misc.data b/tests/suites/test_suite_bignum.misc.data
index 818f361..dc6830e 100644
--- a/tests/suites/test_suite_bignum.misc.data
+++ b/tests/suites/test_suite_bignum.misc.data
@@ -1958,6 +1958,9 @@
MPI random bad arguments: min > N = 1, 0 limb in upper bound
mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Most negative mbedtls_mpi_sint
+most_negative_mpi_sint:
+
MPI Selftest
depends_on:MBEDTLS_SELF_TEST
mpi_selftest:
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index ff766b9..4adccce 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -117,10 +117,12 @@
mbedtls_mpi_uint *X = NULL;
mbedtls_mpi_uint *Y = NULL;
mbedtls_mpi_uint *buff_m = NULL;
- mbedtls_mpi_mod_modulus m;
size_t limbs_X;
size_t limbs_Y;
+ 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( &Y, &limbs_Y, input_Y ), 0 );
@@ -129,8 +131,6 @@
size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint );
- mbedtls_mpi_mod_modulus_init( &m );
-
TEST_EQUAL( limbs_X, limbs_Y );
TEST_ASSERT( copy_limbs <= limbs );
@@ -190,10 +190,12 @@
mbedtls_mpi_uint *X = NULL;
mbedtls_mpi_uint *Y = NULL;
mbedtls_mpi_uint *buff_m = NULL;
- mbedtls_mpi_mod_modulus m;
size_t limbs_X;
size_t limbs_Y;
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
TEST_EQUAL( mbedtls_test_read_mpi_core( &tmp_X, &limbs_X, input_X ), 0 );
TEST_EQUAL( mbedtls_test_read_mpi_core( &tmp_Y, &limbs_Y, input_Y ), 0 );
@@ -202,8 +204,6 @@
size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint );
- mbedtls_mpi_mod_modulus_init( &m );
-
TEST_EQUAL( limbs_X, limbs_Y );
TEST_ASSERT( copy_limbs <= limbs );
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index cce3fd0..659205d 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -6549,11 +6549,16 @@
PSA PAKE: ecjpake rounds
depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
-ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0
PSA PAKE: ecjpake rounds, client input first
depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
-ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1:0
+
+# This test case relies on implementation (it may need to be adjusted in the future)
+PSA PAKE: ecjpake rounds - key is destroyed after being passed to set_password_key
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:1
PSA PAKE: ecjpake no input errors
depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 779f594..ca1614b 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -31,6 +31,27 @@
#define ASSERT_OPERATION_IS_ACTIVE( operation ) TEST_ASSERT( operation.id != 0 )
#define ASSERT_OPERATION_IS_INACTIVE( operation ) TEST_ASSERT( operation.id == 0 )
+#if defined(PSA_WANT_ALG_JPAKE)
+int ecjpake_operation_setup( psa_pake_operation_t *operation,
+ psa_pake_cipher_suite_t *cipher_suite,
+ psa_pake_role_t role,
+ mbedtls_svc_key_id_t key,
+ size_t key_available )
+{
+ PSA_ASSERT( psa_pake_abort( operation ) );
+
+ PSA_ASSERT( psa_pake_setup( operation, cipher_suite ) );
+
+ PSA_ASSERT( psa_pake_set_role( operation, role) );
+
+ if( key_available )
+ PSA_ASSERT( psa_pake_set_password_key( operation, key ) );
+ return 0;
+exit:
+ return 1;
+}
+#endif
+
/** An invalid export length that will never be set by psa_export_key(). */
static const size_t INVALID_EXPORT_LENGTH = ~0U;
@@ -8740,7 +8761,6 @@
{
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_pake_operation_t operation = psa_pake_operation_init();
- psa_pake_operation_t op_copy = psa_pake_operation_init();
psa_algorithm_t alg = alg_arg;
psa_pake_primitive_t primitive = primitive_arg;
psa_key_type_t key_type_pw = key_type_pw_arg;
@@ -8839,22 +8859,25 @@
if( input_first )
{
/* Invalid parameters (input) */
- op_copy = operation;
- TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF,
+ TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF,
NULL, 0 ),
PSA_ERROR_INVALID_ARGUMENT );
/* Invalid parameters (step) */
- op_copy = operation;
- TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF + 10,
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ) , 0 );
+ TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
output_buffer, size_zk_proof ),
PSA_ERROR_INVALID_ARGUMENT );
/* Invalid first step */
- op_copy = operation;
- TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF,
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ), 0 );
+ TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF,
output_buffer, size_zk_proof ),
PSA_ERROR_BAD_STATE );
/* Possibly valid */
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ), 0 );
TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE,
output_buffer, size_key_share ),
expected_status_input_output);
@@ -8875,22 +8898,25 @@
else
{
/* Invalid parameters (output) */
- op_copy = operation;
- TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF,
+ TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
NULL, 0, NULL ),
PSA_ERROR_INVALID_ARGUMENT );
- op_copy = operation;
/* Invalid parameters (step) */
- TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF + 10,
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ), 0 );
+ TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
output_buffer, buf_size, &output_len ),
PSA_ERROR_INVALID_ARGUMENT );
/* Invalid first step */
- op_copy = operation;
- TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF,
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ), 0 );
+ TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
output_buffer, buf_size, &output_len ),
PSA_ERROR_BAD_STATE );
/* Possibly valid */
+ TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
+ key, pw_data->len ), 0 );
TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
output_buffer, buf_size, &output_len ),
expected_status_input_output );
@@ -8974,7 +9000,7 @@
/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
void ecjpake_rounds( int alg_arg, int primitive_arg, int hash_arg,
int derive_alg_arg, data_t *pw_data,
- int client_input_first )
+ int client_input_first, int destroy_key )
{
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_pake_operation_t server = psa_pake_operation_init();
@@ -9025,6 +9051,9 @@
PSA_ASSERT( psa_pake_set_password_key( &server, key ) );
PSA_ASSERT( psa_pake_set_password_key( &client, key ) );
+ if( destroy_key == 1 )
+ psa_destroy_key( key );
+
TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
PSA_ERROR_BAD_STATE );
TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),