Merge pull request #6632 from yanesca/refactor_bignum_test_framework
Refactor bignum test framework
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/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/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 fdbb310..6220527 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 ),