Merge pull request #6836 from gilles-peskine-arm/code-style-more-kr-20221222
Tweak code style to be more like K&R
diff --git a/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
new file mode 100644
index 0000000..44253dd
--- /dev/null
+++ b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
@@ -0,0 +1,6 @@
+Features
+ * Add support for reading points in compressed format
+ (MBEDTLS_ECP_PF_COMPRESSED) with mbedtls_ecp_point_read_binary()
+ (and callers) for Short Weierstrass curves with prime p where p = 3 mod 4
+ (all mbedtls MBEDTLS_ECP_DP_SECP* and MBEDTLS_ECP_DP_BP* curves
+ except MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1)
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index 31e18e7..bd67241 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -176,6 +176,28 @@
/* BEGIN MERGE SLOT 2 */
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ if( N->limbs == 0 )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ mbedtls_mpi_uint *T = mbedtls_calloc( N->limbs * 2 + 1, ciL );
+ if( T == NULL )
+ return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+
+ mbedtls_mpi_mod_raw_mul( X->p, A->p, B->p, N, T );
+
+ mbedtls_free( T );
+
+ return( 0 );
+}
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -303,6 +325,17 @@
/* BEGIN MERGE SLOT 6 */
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ if( X->limbs != N->limbs )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ return( mbedtls_mpi_mod_raw_random( X->p, min, N, f_rng, p_rng ) );
+}
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
@@ -326,8 +359,7 @@
r->limbs = m->limbs;
- if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
- ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
+ ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep( r->p, m );
cleanup:
return ( ret );
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index 95aaacc..1b1e920 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -87,12 +87,23 @@
#include "mbedtls/bignum.h"
#endif
-/* Skip 1 as it is slightly easier to accidentally pass to functions. */
+/** How residues associated with a modulus are represented.
+ *
+ * This also determines which fields of the modulus structure are valid and
+ * what their contents are (see #mbedtls_mpi_mod_modulus).
+ */
typedef enum
{
+ /** Representation not chosen (makes the modulus structure invalid). */
MBEDTLS_MPI_MOD_REP_INVALID = 0,
+ /* Skip 1 as it is slightly easier to accidentally pass to functions. */
+ /** Montgomery representation. */
MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
- MBEDTLS_MPI_MOD_REP_OPT_RED
+ /** TODO: document this.
+ *
+ * Residues are in canonical representation.
+ */
+ MBEDTLS_MPI_MOD_REP_OPT_RED,
} mbedtls_mpi_mod_rep_selector;
/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
@@ -124,7 +135,9 @@
mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union
union rep
{
+ /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
mbedtls_mpi_mont_struct mont;
+ /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
mbedtls_mpi_opt_red_struct ored;
} rep;
} mbedtls_mpi_mod_modulus;
@@ -217,6 +230,40 @@
/* BEGIN MERGE SLOT 2 */
+/** \brief Multiply two residues, returning the residue modulo the specified
+ * modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X The address of the result MPI. Must have the same
+ * number of limbs as \p N.
+ * On successful completion, \p X contains the result of
+ * the multiplication `A * B * R^-1` mod N where
+ * `R = 2^(biL * N->limbs)`.
+ * \param[in] A The address of the first MPI.
+ * \param[in] B The address of the second MPI.
+ * \param[in] N The address of the modulus. Used to perform a modulo
+ * operation on the result of the multiplication.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
+ * have the same number of limbs or \p N is invalid.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N );
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
@@ -319,6 +366,39 @@
/* BEGIN MERGE SLOT 6 */
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note There are `N - min` possible outputs. The lower bound
+ * \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X The destination residue.
+ * \param min The minimum value to return. It must be strictly smaller
+ * than \b N.
+ * \param N The modulus.
+ * This is the upper bound of the output range, exclusive.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ * unable to find a suitable value within a limited number
+ * of attempts. This has a negligible probability if \p N
+ * is significantly larger than \p min, which is the case
+ * for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index 5950ff6..18599c3 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -186,6 +186,48 @@
/* BEGIN MERGE SLOT 6 */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ switch( N->int_rep )
+ {
+ case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+ return( mbedtls_mpi_mod_raw_to_mont_rep( X, N ) );
+ case MBEDTLS_MPI_MOD_REP_OPT_RED:
+ return( 0 );
+ default:
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ }
+}
+
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ switch( N->int_rep )
+ {
+ case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+ return( mbedtls_mpi_mod_raw_from_mont_rep( X, N ) );
+ case MBEDTLS_MPI_MOD_REP_OPT_RED:
+ return( 0 );
+ default:
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ }
+}
+
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret = mbedtls_mpi_core_random( X, min, N->p, N->limbs, f_rng, p_rng );
+ if( ret != 0 )
+ return( ret );
+ return( mbedtls_mpi_mod_raw_canonical_to_modulus_rep( X, N ) );
+}
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index 0fac6f8..ea3207f 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -336,6 +336,74 @@
/* BEGIN MERGE SLOT 6 */
+/** Convert an MPI from canonical representation (little-endian limb array)
+ * to the representation associated with the modulus.
+ *
+ * \param[in,out] X The limb array to convert.
+ * It must have as many limbs as \p N.
+ * It is converted in place.
+ * If this function returns an error, the content of \p X
+ * is unspecified.
+ * \param[in] N The modulus structure.
+ *
+ *\ return \c 0 if successful.
+ * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N );
+
+/** Convert an MPI from the representation associated with the modulus
+ * to canonical representation (little-endian limb array).
+ *
+ * \param[in,out] X The limb array to convert.
+ * It must have as many limbs as \p N.
+ * It is converted in place.
+ * If this function returns an error, the content of \p X
+ * is unspecified.
+ * \param[in] N The modulus structure.
+ *
+ *\ return \c 0 if successful.
+ * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+ mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *N );
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note There are `N - min` possible outputs. The lower bound
+ * \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X The destination MPI, in canonical representation modulo \p N.
+ * It must not be aliased with \p N or otherwise overlap it.
+ * \param min The minimum value to return. It must be strictly smaller
+ * than \b N.
+ * \param N The modulus.
+ * This is the upper bound of the output range, exclusive.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ * unable to find a suitable value within a limited number
+ * of attempts. This has a negligible probability if \p N
+ * is significantly larger than \p min, which is the case
+ * for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+ mbedtls_mpi_uint min,
+ const mbedtls_mpi_mod_modulus *N,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/library/ecp.c b/library/ecp.c
index cd7d554..b6ed60a 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -754,6 +754,13 @@
return( ret );
}
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *X,
+ mbedtls_mpi *Y,
+ int parity_bit );
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
/*
* Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
*/
@@ -795,16 +802,29 @@
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
- if( buf[0] != 0x04 )
- return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
-
- if( ilen != 2 * plen + 1 )
+ if( ilen < 1 + plen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
- buf + 1 + plen, plen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+
+ if( buf[0] == 0x04 )
+ {
+ /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */
+ if( ilen != 1 + plen * 2 )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ return( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
+ }
+ else if( buf[0] == 0x02 || buf[0] == 0x03 )
+ {
+ /* format == MBEDTLS_ECP_PF_COMPRESSED */
+ if( ilen != 1 + plen )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ return( mbedtls_ecp_sw_derive_y( grp, &pt->X, &pt->Y,
+ ( buf[0] & 1 ) ) );
+ }
+ else
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
#endif
@@ -1191,6 +1211,86 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( (X), (Y), (cond) ) )
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+
+/*
+ * Computes the right-hand side of the Short Weierstrass equation
+ * RHS = X^3 + A X + B
+ */
+static int ecp_sw_rhs( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *rhs,
+ const mbedtls_mpi *X )
+{
+ int ret;
+
+ /* Compute X^3 + A X + B as X (X^2 + A) + B */
+ MPI_ECP_SQR( rhs, X );
+
+ /* Special case for A = -3 */
+ if( grp->A.p == NULL )
+ {
+ MPI_ECP_SUB_INT( rhs, rhs, 3 );
+ }
+ else
+ {
+ MPI_ECP_ADD( rhs, rhs, &grp->A );
+ }
+
+ MPI_ECP_MUL( rhs, rhs, X );
+ MPI_ECP_ADD( rhs, rhs, &grp->B );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Derive Y from X and a parity bit
+ */
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *X,
+ mbedtls_mpi *Y,
+ int parity_bit )
+{
+ /* w = y^2 = x^3 + ax + b
+ * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4)
+ *
+ * Note: this method for extracting square root does not validate that w
+ * was indeed a square so this function will return garbage in Y if X
+ * does not correspond to a point on the curve.
+ */
+
+ /* Check prerequisite p = 3 mod 4 */
+ if( mbedtls_mpi_get_bit( &grp->P, 0 ) != 1 ||
+ mbedtls_mpi_get_bit( &grp->P, 1 ) != 1 )
+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ int ret;
+ mbedtls_mpi exp;
+ mbedtls_mpi_init( &exp );
+
+ /* use Y to store intermediate result, actually w above */
+ MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, Y, X ) );
+
+ /* w = y^2 */ /* Y contains y^2 intermediate result */
+ /* exp = ((p+1)/4) */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &exp, &grp->P, 1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &exp, 2 ) );
+ /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( Y, Y /*y^2*/, &exp, &grp->P, NULL ) );
+
+ /* check parity bit match or else invert Y */
+ /* This quick inversion implementation is valid because Y != 0 for all
+ * Short Weierstrass curves supported by mbedtls, as each supported curve
+ * has an order that is a large prime, so each supported curve does not
+ * have any point of order 2, and a point with Y == 0 would be of order 2 */
+ if( mbedtls_mpi_get_bit( Y, 0 ) != parity_bit )
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( Y, &grp->P, Y ) );
+
+cleanup:
+
+ mbedtls_mpi_free( &exp );
+ return( ret );
+}
+
/*
* For curves in short Weierstrass form, we do all the internal operations in
* Jacobian coordinates.
@@ -2611,23 +2711,10 @@
/*
* YY = Y^2
- * RHS = X (X^2 + A) + B = X^3 + A X + B
+ * RHS = X^3 + A X + B
*/
MPI_ECP_SQR( &YY, &pt->Y );
- MPI_ECP_SQR( &RHS, &pt->X );
-
- /* Special case for A = -3 */
- if( grp->A.p == NULL )
- {
- MPI_ECP_SUB_INT( &RHS, &RHS, 3 );
- }
- else
- {
- MPI_ECP_ADD( &RHS, &RHS, &grp->A );
- }
-
- MPI_ECP_MUL( &RHS, &RHS, &pt->X );
- MPI_ECP_ADD( &RHS, &RHS, &grp->B );
+ MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, &RHS, &pt->X ) );
if( MPI_ECP_CMP( &YY, &RHS ) != 0 )
ret = MBEDTLS_ERR_ECP_INVALID_KEY;
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index c4efabf..2422175 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -15,6 +15,7 @@
# limitations under the License.
from abc import abstractmethod
+import enum
from typing import Iterator, List, Tuple, TypeVar, Any
from itertools import chain
@@ -53,7 +54,7 @@
return 0
return int(val, 16)
-def quote_str(val) -> str:
+def quote_str(val: str) -> str:
return "\"{}\"".format(val)
def bound_mpi(val: int, bits_in_limb: int) -> int:
@@ -139,7 +140,7 @@
def hex_digits(self) -> int:
return 2 * (self.limbs * self.bits_in_limb // 8)
- def format_arg(self, val) -> str:
+ def format_arg(self, val: str) -> str:
if self.input_style not in self.input_styles:
raise ValueError("Unknown input style!")
if self.input_style == "variable":
@@ -147,7 +148,7 @@
else:
return val.zfill(self.hex_digits)
- def format_result(self, res) -> str:
+ def format_result(self, res: int) -> str:
res_str = '{:x}'.format(res)
return quote_str(self.format_arg(res_str))
@@ -245,6 +246,23 @@
)
+class ModulusRepresentation(enum.Enum):
+ """Representation selector of a modulus."""
+ # Numerical values aligned with the type mbedtls_mpi_mod_rep_selector
+ INVALID = 0
+ MONTGOMERY = 2
+ OPT_RED = 3
+
+ def symbol(self) -> str:
+ """The C symbol for this representation selector."""
+ return 'MBEDTLS_MPI_MOD_REP_' + self.name
+
+ @classmethod
+ def supported_representations(cls) -> List['ModulusRepresentation']:
+ """Return all representations that are supported in positive test cases."""
+ return [cls.MONTGOMERY, cls.OPT_RED]
+
+
class ModOperationCommon(OperationCommon):
#pylint: disable=abstract-method
"""Target for bignum mod_raw test case generation."""
@@ -266,6 +284,17 @@
def from_montgomery(self, val: int) -> int:
return (val * self.r_inv) % self.int_n
+ def convert_from_canonical(self, canonical: int,
+ rep: ModulusRepresentation) -> int:
+ """Convert values from canonical representation to the given representation."""
+ if rep is ModulusRepresentation.MONTGOMERY:
+ return self.to_montgomery(canonical)
+ elif rep is ModulusRepresentation.OPT_RED:
+ return canonical
+ else:
+ raise ValueError('Modulus representation not supported: {}'
+ .format(rep.name))
+
@property
def boundary(self) -> int:
return self.int_n
@@ -282,6 +311,9 @@
def arg_n(self) -> str:
return self.format_arg(self.val_n)
+ def format_arg(self, val: str) -> str:
+ return super().format_arg(val).zfill(self.hex_digits)
+
def arguments(self) -> List[str]:
return [quote_str(self.arg_n)] + super().arguments()
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index 25afe30..a83e136 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -31,6 +31,26 @@
# BEGIN MERGE SLOT 2
+class BignumModMul(bignum_common.ModOperationCommon,
+ BignumModTarget):
+ # pylint:disable=duplicate-code
+ """Test cases for bignum mpi_mod_mul()."""
+ symbol = "*"
+ test_function = "mpi_mod_mul"
+ test_name = "mbedtls_mpi_mod_mul"
+ input_style = "arch_split"
+ arity = 2
+
+ def arguments(self) -> List[str]:
+ return [self.format_result(self.to_montgomery(self.int_a)),
+ self.format_result(self.to_montgomery(self.int_b)),
+ bignum_common.quote_str(self.arg_n)
+ ] + self.result()
+
+ def result(self) -> List[str]:
+ result = (self.int_a * self.int_b) % self.int_n
+ return [self.format_result(self.to_montgomery(result))]
+
# END MERGE SLOT 2
# BEGIN MERGE SLOT 3
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index 09bbbee..f9d9899 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -14,8 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import Dict, List
+from typing import Iterator, List
+from . import test_case
from . import test_data_generation
from . import bignum_common
from .bignum_data import ONLY_PRIME_MODULI
@@ -116,6 +117,88 @@
# BEGIN MERGE SLOT 6
+class BignumModRawConvertRep(bignum_common.ModOperationCommon,
+ BignumModRawTarget):
+ # This is an abstract class, it's ok to have unimplemented methods.
+ #pylint: disable=abstract-method
+ """Test cases for representation conversion."""
+ symbol = ""
+ input_style = "arch_split"
+ arity = 1
+ rep = bignum_common.ModulusRepresentation.INVALID
+
+ def set_representation(self, r: bignum_common.ModulusRepresentation) -> None:
+ self.rep = r
+
+ def arguments(self) -> List[str]:
+ return ([bignum_common.quote_str(self.arg_n), self.rep.symbol(),
+ bignum_common.quote_str(self.arg_a)] +
+ self.result())
+
+ def description(self) -> str:
+ base = super().description()
+ mod_with_rep = 'mod({})'.format(self.rep.name)
+ return base.replace('mod', mod_with_rep, 1)
+
+ @classmethod
+ def test_cases_for_values(cls, rep: bignum_common.ModulusRepresentation,
+ n: str, a: str) -> Iterator[test_case.TestCase]:
+ """Emit test cases for the given values (if any).
+
+ This may emit no test cases if a isn't valid for the modulus n,
+ or multiple test cases if rep requires different data depending
+ on the limb size.
+ """
+ for bil in cls.limb_sizes:
+ test_object = cls(n, a, bits_in_limb=bil)
+ test_object.set_representation(rep)
+ # The class is set to having separate test cases for each limb
+ # size, because the Montgomery representation requires it.
+ # But other representations don't require it. So for other
+ # representations, emit a single test case with no dependency
+ # on the limb size.
+ if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+ test_object.dependencies = \
+ [dep for dep in test_object.dependencies
+ if not dep.startswith('MBEDTLS_HAVE_INT')]
+ if test_object.is_valid:
+ yield test_object.create_test_case()
+ if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+ # A single test case (emitted, or skipped due to invalidity)
+ # is enough, since this test case doesn't depend on the
+ # limb size.
+ break
+
+ # The parent class doesn't support non-bignum parameters. So we override
+ # test generation, in order to have the representation as a parameter.
+ @classmethod
+ def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+
+ for rep in bignum_common.ModulusRepresentation.supported_representations():
+ for n in cls.moduli:
+ for a in cls.input_values:
+ yield from cls.test_cases_for_values(rep, n, a)
+
+class BignumModRawCanonicalToModulusRep(BignumModRawConvertRep):
+ """Test cases for mpi_mod_raw_canonical_to_modulus_rep."""
+ test_function = "mpi_mod_raw_canonical_to_modulus_rep"
+ test_name = "Rep canon->mod"
+
+ def result(self) -> List[str]:
+ return [self.format_result(self.convert_from_canonical(self.int_a, self.rep))]
+
+class BignumModRawModulusToCanonicalRep(BignumModRawConvertRep):
+ """Test cases for mpi_mod_raw_modulus_to_canonical_rep."""
+ test_function = "mpi_mod_raw_modulus_to_canonical_rep"
+ test_name = "Rep mod->canon"
+
+ @property
+ def arg_a(self) -> str:
+ return self.format_arg("{:x}".format(self.convert_from_canonical(self.int_a, self.rep)))
+
+ def result(self) -> List[str]:
+ return [self.format_result(self.int_a)]
+
# END MERGE SLOT 6
# BEGIN MERGE SLOT 7
diff --git a/tests/include/test/bignum_helpers.h b/tests/include/test/bignum_helpers.h
new file mode 100644
index 0000000..164017e
--- /dev/null
+++ b/tests/include/test/bignum_helpers.h
@@ -0,0 +1,118 @@
+/**
+ * \file bignum_helpers.h
+ *
+ * \brief This file contains the prototypes of helper functions for
+ * bignum-related testing.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef TEST_BIGNUM_HELPERS_H
+#define TEST_BIGNUM_HELPERS_H
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <mbedtls/bignum.h>
+#include <bignum_mod.h>
+
+/** Allocate and populate a core MPI from a test case argument.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free().
+ *
+ * \param[in,out] pX The address where a pointer to the allocated limb
+ * array will be stored.
+ * \c *pX must be null on entry.
+ * On exit, \c *pX is null on error or if the number
+ * of limbs is 0.
+ * \param[out] plimbs The address where the number of limbs will be stored.
+ * \param[in] input The test argument to read.
+ * It is interpreted as a hexadecimal representation
+ * of a non-negative integer.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+ const char *input );
+
+/** Read a modulus from a hexadecimal string.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free(). You can do that by calling
+ * mbedtls_test_mpi_mod_modulus_free_with_limbs().
+ *
+ * \param[in,out] N A modulus structure. It must be initialized, but
+ * not set up.
+ * \param[in] s The null-terminated hexadecimal string to read from.
+ * \param int_rep The desired representation of residues.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+ const char *s,
+ mbedtls_mpi_mod_rep_selector int_rep );
+
+/** Free a modulus and its limbs.
+ *
+ * \param[in] N A modulus structure such that there is no other
+ * reference to `N->p`.
+ */
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N );
+
+/** Read an MPI from a hexadecimal string.
+ *
+ * Like mbedtls_mpi_read_string(), but with tighter guarantees around
+ * edge cases.
+ *
+ * - This function guarantees that if \p s begins with '-' then the sign
+ * bit of the result will be negative, even if the value is 0.
+ * When this function encounters such a "negative 0", it
+ * increments #mbedtls_test_case_uses_negative_0.
+ * - The size of the result is exactly the minimum number of limbs needed
+ * to fit the digits in the input. In particular, this function constructs
+ * a bignum with 0 limbs for an empty string, and a bignum with leading 0
+ * limbs if the string has sufficiently many leading 0 digits.
+ * This is important so that the "0 (null)" and "0 (1 limb)" and
+ * "leading zeros" test cases do what they claim.
+ *
+ * \param[out] X The MPI object to populate. It must be initialized.
+ * \param[in] s The null-terminated hexadecimal string to read from.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
+
+/** Nonzero if the current test case had an input parsed with
+ * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
+ * constructing a result with the sign bit set to -1 and the value being
+ * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
+ * tested for robustness).
+ */
+extern unsigned mbedtls_test_case_uses_negative_0;
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#endif /* TEST_BIGNUM_HELPERS_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 5f9bde6..b64bfcb 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -216,6 +216,17 @@
int len );
/**
+ * \brief Convert hexadecimal digit to an integer.
+ *
+ * \param c The digit to convert (`'0'` to `'9'`, `'A'` to `'F'` or
+ * `'a'` to `'f'`).
+ * \param[out] uc On success, the value of the digit (0 to 15).
+ *
+ * \return 0 on success, -1 if \p c is not a hexadecimal digit.
+ */
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc);
+
+/**
* Allocate and zeroize a buffer.
*
* If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
@@ -269,60 +280,4 @@
const char *file, int line);
#endif
-#if defined(MBEDTLS_BIGNUM_C)
-/** Allocate and populate a core MPI from a test case argument.
- *
- * This function allocates exactly as many limbs as necessary to fit
- * the length of the input. In other words, it preserves leading zeros.
- *
- * The limb array is allocated with mbedtls_calloc() and must later be
- * freed with mbedtls_free().
- *
- * \param[in,out] pX The address where a pointer to the allocated limb
- * array will be stored.
- * \c *pX must be null on entry.
- * On exit, \c *pX is null on error or if the number
- * of limbs is 0.
- * \param[out] plimbs The address where the number of limbs will be stored.
- * \param[in] input The test argument to read.
- * It is interpreted as a hexadecimal representation
- * of a non-negative integer.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
- const char *input );
-
-/** Read an MPI from a hexadecimal string.
- *
- * Like mbedtls_mpi_read_string(), but with tighter guarantees around
- * edge cases.
- *
- * - This function guarantees that if \p s begins with '-' then the sign
- * bit of the result will be negative, even if the value is 0.
- * When this function encounters such a "negative 0", it
- * increments #mbedtls_test_case_uses_negative_0.
- * - The size of the result is exactly the minimum number of limbs needed
- * to fit the digits in the input. In particular, this function constructs
- * a bignum with 0 limbs for an empty string, and a bignum with leading 0
- * limbs if the string has sufficiently many leading 0 digits.
- * This is important so that the "0 (null)" and "0 (1 limb)" and
- * "leading zeros" test cases do what they claim.
- *
- * \param[out] X The MPI object to populate. It must be initialized.
- * \param[in] s The null-terminated hexadecimal string to read from.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
-
-/** Nonzero if the current test case had an input parsed with
- * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
- * constructing a result with the sign bit set to -1 and the value being
- * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
- * tested for robustness).
- */
-extern unsigned mbedtls_test_case_uses_negative_0;
-#endif /* MBEDTLS_BIGNUM_C */
-
#endif /* TEST_HELPERS_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 584906a..18dc8a6 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -870,7 +870,7 @@
else
opt=''
fi
- tests/scripts/check_test_cases.py $opt
+ tests/scripts/check_test_cases.py -q $opt
unset opt
}
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index 0b84711..6ee6ab3 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -60,7 +60,6 @@
from typing import List
import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import test_case
from mbedtls_dev import test_data_generation
from mbedtls_dev import bignum_common
# Import modules containing additional test classes
diff --git a/tests/src/bignum_helpers.c b/tests/src/bignum_helpers.c
new file mode 100644
index 0000000..d6ec9bd
--- /dev/null
+++ b/tests/src/bignum_helpers.c
@@ -0,0 +1,142 @@
+/**
+ * \file bignum_helpers.c
+ *
+ * \brief This file contains the prototypes of helper functions for
+ * bignum-related testing.
+ */
+
+/*
+ * 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.
+ */
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include <test/bignum_helpers.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbedtls/bignum.h>
+#include <bignum_core.h>
+#include <bignum_mod.h>
+#include <bignum_mod_raw.h>
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+ const char *input )
+{
+ /* Sanity check */
+ if( *pX != NULL )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ size_t hex_len = strlen( input );
+ size_t byte_len = ( hex_len + 1 ) / 2;
+ *plimbs = CHARS_TO_LIMBS( byte_len );
+
+ /* A core bignum is not allowed to be empty. Forbid it as test data,
+ * this way static analyzers have a chance of knowing we don't expect
+ * the bignum functions to support empty inputs. */
+ if( *plimbs == 0 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+ *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
+ if( *pX == NULL )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+ unsigned char *byte_start = ( unsigned char * ) *pX;
+ if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
+ {
+ byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
+ }
+ if( ( hex_len & 1 ) != 0 )
+ {
+ /* mbedtls_test_unhexify wants an even number of hex digits */
+ TEST_ASSERT( mbedtls_test_ascii2uc( *input, byte_start ) == 0 );
+ ++byte_start;
+ ++input;
+ --byte_len;
+ }
+ TEST_ASSERT( mbedtls_test_unhexify( byte_start,
+ byte_len,
+ input,
+ &byte_len ) == 0 );
+
+ mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
+ return( 0 );
+
+exit:
+ mbedtls_free( *pX );
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+}
+
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+ const char *s,
+ mbedtls_mpi_mod_rep_selector int_rep )
+{
+ mbedtls_mpi_uint *p = NULL;
+ size_t limbs = 0;
+ if( N->limbs != 0 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ int ret = mbedtls_test_read_mpi_core( &p, &limbs, s );
+ if( ret != 0 )
+ return( ret );
+ ret = mbedtls_mpi_mod_modulus_setup( N, p, limbs, int_rep );
+ if( ret != 0 )
+ mbedtls_free( p );
+ return( ret );
+}
+
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N )
+{
+ mbedtls_free( (mbedtls_mpi_uint*) N->p );
+ mbedtls_mpi_mod_modulus_free( N );
+}
+
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
+{
+ int negative = 0;
+ /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
+ * This creates an invalid representation, which mbedtls_mpi_read_string()
+ * avoids but we want to be able to create that in test data. */
+ if( s[0] == '-' )
+ {
+ ++s;
+ negative = 1;
+ }
+ /* mbedtls_mpi_read_string() currently retains leading zeros.
+ * It always allocates at least one limb for the value 0. */
+ if( s[0] == 0 )
+ {
+ mbedtls_mpi_free( X );
+ return( 0 );
+ }
+ int ret = mbedtls_mpi_read_string( X, 16, s );
+ if( ret != 0 )
+ return( ret );
+ if( negative )
+ {
+ if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+ ++mbedtls_test_case_uses_negative_0;
+ X->s = -1;
+ }
+ return( 0 );
+}
+
+#endif /* MBEDTLS_BIGNUM_C */
+
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 7c83714..be5c465 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -48,7 +48,7 @@
#endif /* MBEDTLS_PLATFORM_C */
}
-static int ascii2uc(const char c, unsigned char *uc)
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc)
{
if( ( c >= '0' ) && ( c <= '9' ) )
*uc = c - '0';
@@ -207,10 +207,10 @@
while( *ibuf != 0 )
{
- if ( ascii2uc( *(ibuf++), &uc ) != 0 )
+ if ( mbedtls_test_ascii2uc( *(ibuf++), &uc ) != 0 )
return( -1 );
- if ( ascii2uc( *(ibuf++), &uc2 ) != 0 )
+ if ( mbedtls_test_ascii2uc( *(ibuf++), &uc2 ) != 0 )
return( -1 );
*(obuf++) = ( uc << 4 ) | uc2;
@@ -350,84 +350,3 @@
}
}
#endif /* MBEDTLS_TEST_HOOKS */
-
-#if defined(MBEDTLS_BIGNUM_C)
-#include "bignum_core.h"
-
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
- const char *input )
-{
- /* Sanity check */
- if( *pX != NULL )
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
- size_t hex_len = strlen( input );
- size_t byte_len = ( hex_len + 1 ) / 2;
- *plimbs = CHARS_TO_LIMBS( byte_len );
-
- /* A core bignum is not allowed to be empty. Forbid it as test data,
- * this way static analyzers have a chance of knowing we don't expect
- * the bignum functions to support empty inputs. */
- if( *plimbs == 0 )
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
- *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
- if( *pX == NULL )
- return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
- unsigned char *byte_start = ( unsigned char * ) *pX;
- if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
- {
- byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
- }
- if( ( hex_len & 1 ) != 0 )
- {
- /* mbedtls_test_unhexify wants an even number of hex digits */
- TEST_ASSERT( ascii2uc( *input, byte_start ) == 0 );
- ++byte_start;
- ++input;
- --byte_len;
- }
- TEST_ASSERT( mbedtls_test_unhexify( byte_start,
- byte_len,
- input,
- &byte_len ) == 0 );
-
- mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
- return( 0 );
-
-exit:
- mbedtls_free( *pX );
- return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-}
-
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
-{
- int negative = 0;
- /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
- * This creates an invalid representation, which mbedtls_mpi_read_string()
- * avoids but we want to be able to create that in test data. */
- if( s[0] == '-' )
- {
- ++s;
- negative = 1;
- }
- /* mbedtls_mpi_read_string() currently retains leading zeros.
- * It always allocates at least one limb for the value 0. */
- if( s[0] == 0 )
- {
- mbedtls_mpi_free( X );
- return( 0 );
- }
- int ret = mbedtls_mpi_read_string( X, 16, s );
- if( ret != 0 )
- return( ret );
- if( negative )
- {
- if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
- ++mbedtls_test_case_uses_negative_0;
- X->s = -1;
- }
- return( 0 );
-}
-#endif
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index fe33f9b..8249564 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,6 +5,7 @@
#include <test/helpers.h>
#include <test/macros.h>
#include <test/random.h>
+#include <test/bignum_helpers.h>
#include <test/psa_crypto_helpers.h>
#include <stdlib.h>
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 79f5134..8ab8ccf 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -2,6 +2,7 @@
#include "mbedtls/bignum.h"
#include "mbedtls/entropy.h"
#include "bignum_mod.h"
+#include "bignum_mod_raw.h"
#include "constant_time_internal.h"
#include "test/constant_flow.h"
@@ -102,6 +103,145 @@
/* BEGIN MERGE SLOT 2 */
+/* BEGIN_CASE */
+void mpi_mod_mul( char * input_A,
+ char * input_B,
+ char * input_N,
+ char * result )
+{
+ mbedtls_mpi_uint *X = NULL;
+
+ mbedtls_mpi_mod_residue rA = { NULL, 0 };
+ mbedtls_mpi_mod_residue rB = { NULL, 0 };
+ mbedtls_mpi_mod_residue rR = { NULL, 0 };
+ mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+ 0 );
+
+ TEST_EQUAL( test_read_residue( &rA, &m, input_A, 0 ), 0 );
+ TEST_EQUAL( test_read_residue( &rB, &m, input_B, 0 ), 0 );
+ TEST_EQUAL( test_read_residue( &rR, &m, result, 0 ), 0 );
+
+ const size_t limbs = m.limbs;
+ const size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
+
+ TEST_EQUAL( rA.limbs, limbs );
+ TEST_EQUAL( rB.limbs, limbs );
+ TEST_EQUAL( rR.limbs, limbs );
+
+ ASSERT_ALLOC( X, limbs );
+
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* alias X to A */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rB, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* alias X to B */
+ memcpy( rX.p, rB.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rX, &m ), 0);
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* A == B: alias A and B */
+ if( memcmp( rA.p, rB.p, bytes ) == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* X, A, B all aliased together */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rX, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+ }
+
+ /* A != B: test B * A */
+ else
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* B * A: alias X to A */
+ memcpy( rX.p, rA.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rX, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+ /* B + A: alias X to B */
+ memcpy( rX.p, rB.p, bytes );
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rA, &m ), 0 );
+ ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+ }
+
+exit:
+ mbedtls_free( rA.p );
+ mbedtls_free( rB.p );
+ mbedtls_free( rR.p );
+ mbedtls_free( X );
+ mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+ mbedtls_mpi_mod_modulus_free( &m );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_mul_neg( char * input_A,
+ char * input_B,
+ char * input_N,
+ char * result,
+ int exp_ret )
+{
+ mbedtls_mpi_uint *X = NULL;
+
+ mbedtls_mpi_mod_residue rA = { NULL, 0 };
+ mbedtls_mpi_mod_residue rB = { NULL, 0 };
+ mbedtls_mpi_mod_residue rR = { NULL, 0 };
+ mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ mbedtls_mpi_mod_modulus fake_m;
+ mbedtls_mpi_mod_modulus_init( &fake_m );
+
+ TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+ 0 );
+
+ TEST_EQUAL( test_read_residue( &rA, &m, input_A, 1 ), 0 );
+ TEST_EQUAL( test_read_residue( &rB, &m, input_B, 1 ), 0 );
+ TEST_EQUAL( test_read_residue( &rR, &m, result, 1 ), 0 );
+
+ const size_t limbs = m.limbs;
+
+ ASSERT_ALLOC( X, limbs );
+
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+ rX.limbs = rR.limbs;
+
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), exp_ret );
+
+ /* Check when m is not initialized */
+ TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &fake_m ),
+ MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+exit:
+ mbedtls_free( rA.p );
+ mbedtls_free( rB.p );
+ mbedtls_free( rR.p );
+ mbedtls_free( X );
+ mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+ mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_mpi_mod_modulus_free( &fake_m );
+}
+/* END_CASE */
+
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
diff --git a/tests/suites/test_suite_bignum_mod.misc.data b/tests/suites/test_suite_bignum_mod.misc.data
index 6240e21..e369211 100644
--- a/tests/suites/test_suite_bignum_mod.misc.data
+++ b/tests/suites/test_suite_bignum_mod.misc.data
@@ -12,7 +12,14 @@
# END MERGE SLOT 1
# BEGIN MERGE SLOT 2
+Test mpi_mod_mul #1 N->limbs != A->limbs
+mpi_mod_mul_neg:"1":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Test mpi_mod_mul #2 N->limbs != B->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"0":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mpi_mod_mul #3 N->limbs != X->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
# END MERGE SLOT 2
# BEGIN MERGE SLOT 3
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 461a18e..4a658e1 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -619,7 +619,59 @@
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
+/* BEGIN_CASE */
+void mpi_mod_raw_canonical_to_modulus_rep( const char *input_N, int rep,
+ const char *input_A,
+ const char *input_X )
+{
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+ mbedtls_mpi_uint *A = NULL;
+ size_t A_limbs = 0;;
+ mbedtls_mpi_uint *X = NULL;
+ size_t X_limbs = 0;
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_raw_canonical_to_modulus_rep( A, &N ) );
+ ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+ X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_raw_modulus_to_canonical_rep( const char *input_N, int rep,
+ const char *input_A,
+ const char *input_X )
+{
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+ mbedtls_mpi_uint *A = NULL;
+ size_t A_limbs = 0;
+ mbedtls_mpi_uint *X = NULL;
+ size_t X_limbs = 0;
+
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_raw_modulus_to_canonical_rep( A, &N ) );
+ ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+ X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
diff --git a/tests/suites/test_suite_bignum_random.data b/tests/suites/test_suite_bignum_random.data
index fe29053..ee5e397 100644
--- a/tests/suites/test_suite_bignum_random.data
+++ b/tests/suites/test_suite_bignum_random.data
@@ -17,31 +17,55 @@
mpi_core_random_basic:0x40000000:"0200000000000000000000000000000000":0
# Use the same data values for mpi_core_random_basic->NOT_ACCEPTABLE
-# and for mpi_random_values where we want to return NOT_ACCEPTABLE but
-# this isn't checked at runtime.
-MPI core random basic: 2^28-1..2^28 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x0fffffff:"10000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+# and for mpi_XXX_random_values where we want to return NOT_ACCEPTABLE
+# but this isn't checked at runtime.
+MPI core random basic: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x0fffffff:"10000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
-MPI random legacy=core: 2^28-1..2^28 (NOT_ACCEPTABLE)
-mpi_random_values:0x0fffffff:"10000000"
+MPI random legacy=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x0fffffff:"10000001"
-MPI core random basic: 2^29-1..2^29 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x1fffffff:"20000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
-MPI random legacy=core: 2^29-1..2^29 (NOT_ACCEPTABLE)
-mpi_random_values:0x1fffffff:"20000000"
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_OPT_RED
-MPI core random basic: 2^30-1..2^30 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x3fffffff:"40000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI core random basic: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x1fffffff:"20000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
-MPI random legacy=core: 2^30-1..2^30 (NOT_ACCEPTABLE)
-mpi_random_values:0x3fffffff:"40000000"
+MPI random legacy=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x1fffffff:"20000001"
-MPI core random basic: 2^31-1..2^31 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x7fffffff:"80000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
-MPI random legacy=core: 2^31-1..2^31 (NOT_ACCEPTABLE)
-mpi_random_values:0x7fffffff:"80000000"
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x3fffffff:"40000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x3fffffff:"40000001"
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x7fffffff:"80000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x7fffffff:"80000001"
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_OPT_RED
MPI random in range: 1..2
mpi_random_many:1:"02":1000
@@ -214,22 +238,103 @@
mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
MPI random legacy=core: 0..1
-mpi_random_values:0:"01"
+mpi_legacy_random_values:0:"01"
MPI random legacy=core: 0..2
-mpi_random_values:0:"02"
+mpi_legacy_random_values:0:"02"
MPI random legacy=core: 1..2
-mpi_random_values:1:"02"
+mpi_legacy_random_values:1:"02"
MPI random legacy=core: 2^30..2^31
-mpi_random_values:0x40000000:"80000000"
+mpi_legacy_random_values:0x40000000:"80000000"
MPI random legacy=core: 2^31-1..2^32-1
-mpi_random_values:0x7fffffff:"ffffffff"
+mpi_legacy_random_values:0x7fffffff:"ffffffff"
MPI random legacy=core: 0..2^256
-mpi_random_values:0:"010000000000000000000000000000000000000000000000000000000000000000"
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000000"
MPI random legacy=core: 0..2^256+1
-mpi_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001"
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001"
+
+MPI random mod=core: 0..1 (Mont)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..1 (canon)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..3 (Mont)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..3 (canon)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 1..3 (Mont)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 1..3 (canon)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^30..2^31-1 (Mont)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30..2^31-1 (canon)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^31-1..2^32-1 (Mont)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^32-1 (canon)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..2^256+1 (Mont)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..2^256+1 (canon)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod validation: 1 limb, good, 0..1
+mpi_mod_random_validation:0:"1":0:0
+
+MPI random mod validation: 1 limb, good, 1..3
+mpi_mod_random_validation:1:"3":0:0
+
+MPI random mod validation: 1 limb, good, 2..3
+mpi_mod_random_validation:2:"3":0:0
+
+MPI random mod validation: 1 limb, good, 3..5
+mpi_mod_random_validation:3:"5":0:0
+
+MPI random mod validation: 1 limb, good, 4..5
+mpi_mod_random_validation:4:"5":0:0
+
+MPI random mod validation: 1 limb, good, 5..7
+mpi_mod_random_validation:5:"7":0:0
+
+MPI random mod validation: 1 limb, good, 6..7
+mpi_mod_random_validation:6:"7":0:0
+
+MPI random mod validation: 1 limb, good, 0..0x123
+mpi_mod_random_validation:0:"123":0:0
+
+MPI random mod validation: 2+ limbs, good
+mpi_mod_random_validation:0:"01234567890123456789":0:0
+
+MPI random mod validation: 1 limb, output null
+mpi_mod_random_validation:0:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 1 limb, output too large
+mpi_mod_random_validation:0:"123":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too small
+mpi_mod_random_validation:0:"01234567890123456789":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too large
+mpi_mod_random_validation:0:"01234567890123456789":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min == upper bound
+mpi_mod_random_validation:0x123:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min > upper bound
+mpi_mod_random_validation:0x124:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_bignum_random.function b/tests/suites/test_suite_bignum_random.function
index 184de5a..4709148 100644
--- a/tests/suites/test_suite_bignum_random.function
+++ b/tests/suites/test_suite_bignum_random.function
@@ -3,11 +3,44 @@
* functions. Due to the complexity of how these functions are tested,
* we test all the layers in a single test suite, unlike the way other
* functions are tested with each layer in its own test suite.
+ *
+ * Test strategy
+ * =============
+ *
+ * There are three main goals for testing random() functions:
+ * - Parameter validation.
+ * - Correctness of outputs (well-formed, in range).
+ * - Distribution of outputs.
+ *
+ * We test parameter validation in a standard way, with unit tests with
+ * positive and negative cases:
+ * - mbedtls_mpi_core_random(): negative cases for mpi_core_random_basic.
+ * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): negative
+ * cases for mpi_mod_random_validation.
+ * - mbedtls_mpi_random(): mpi_random_fail.
+ *
+ * We test the correctness of outputs in positive tests:
+ * - mbedtls_mpi_core_random(): positive cases for mpi_core_random_basic,
+ * and mpi_random_many.
+ * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): tested indirectly
+ * via mpi_mod_random_values.
+ * - mbedtls_mpi_random(): mpi_random_sizes, plus indirectly via
+ * mpi_random_values.
+ *
+ * We test the distribution of outputs only for mbedtls_mpi_core_random(),
+ * in mpi_random_many, which runs the function multiple times. This also
+ * helps in validating the output range, through test cases with a small
+ * range where any output out of range would be very likely to lead to a
+ * test failure. For the other functions, we validate the distribution
+ * indirectly by testing that these functions consume the random generator
+ * in the same way as mbedtls_mpi_core_random(). This is done in
+ * mpi_mod_random_values and mpi_legacy_random_values.
*/
#include "mbedtls/bignum.h"
#include "mbedtls/entropy.h"
#include "bignum_core.h"
+#include "bignum_mod_raw.h"
#include "constant_time_internal.h"
/* This test suite only manipulates non-negative bignums. */
@@ -110,7 +143,7 @@
/* END_CASE */
/* BEGIN_CASE */
-void mpi_random_values( int min, char *max_hex )
+void mpi_legacy_random_values( int min, char *max_hex )
{
/* Same RNG as in mpi_core_random_basic */
mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
@@ -159,6 +192,77 @@
/* END_CASE */
/* BEGIN_CASE */
+void mpi_mod_random_values( int min, char *max_hex, int rep )
+{
+ /* Same RNG as in mpi_core_random_basic */
+ mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
+ mbedtls_test_rnd_pseudo_info rnd_mod_raw;
+ memcpy( &rnd_mod_raw, &rnd_core, sizeof( rnd_core ) );
+ mbedtls_test_rnd_pseudo_info rnd_mod;
+ memcpy( &rnd_mod, &rnd_core, sizeof( rnd_core ) );
+ mbedtls_mpi_uint *R_core = NULL;
+ mbedtls_mpi_uint *R_mod_raw = NULL;
+ mbedtls_mpi_uint *R_mod_digits = NULL;
+ mbedtls_mpi_mod_residue R_mod;
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, max_hex, rep ), 0 );
+ ASSERT_ALLOC( R_core, N.limbs );
+ ASSERT_ALLOC( R_mod_raw, N.limbs );
+ ASSERT_ALLOC( R_mod_digits, N.limbs );
+ TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &R_mod, &N,
+ R_mod_digits, N.limbs ),
+ 0 );
+
+ /* Call the core and mod random() functions with the same random stream. */
+ int core_ret = mbedtls_mpi_core_random( R_core,
+ min, N.p, N.limbs,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_core );
+ int mod_raw_ret = mbedtls_mpi_mod_raw_random( R_mod_raw,
+ min, &N,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_mod_raw );
+ int mod_ret = mbedtls_mpi_mod_random( &R_mod,
+ min, &N,
+ mbedtls_test_rnd_pseudo_rand,
+ &rnd_mod );
+
+ /* They must return the same status, and, on success, output the
+ * same number, with the same limb count. */
+ TEST_EQUAL( core_ret, mod_raw_ret );
+ TEST_EQUAL( core_ret, mod_ret );
+ if( core_ret == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_raw, &N ),
+ 0 );
+ ASSERT_COMPARE( R_core, N.limbs * ciL,
+ R_mod_raw, N.limbs * ciL );
+ TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_digits, &N ),
+ 0 );
+ ASSERT_COMPARE( R_core, N.limbs * ciL,
+ R_mod_digits, N.limbs * ciL );
+ }
+
+ /* Also check that they have consumed the RNG in the same way. */
+ /* This may theoretically fail on rare platforms with padding in
+ * the structure! If this is a problem in practice, change to a
+ * field-by-field comparison. */
+ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+ &rnd_mod_raw, sizeof( rnd_mod_raw ) );
+ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+ &rnd_mod, sizeof( rnd_mod ) );
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( R_core );
+ mbedtls_free( R_mod_raw );
+ mbedtls_free( R_mod_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void mpi_random_many( int min, char *bound_hex, int iterations )
{
/* Generate numbers in the range 1..bound-1. Do it iterations times.
@@ -312,6 +416,64 @@
/* END_CASE */
/* BEGIN_CASE */
+void mpi_mod_random_validation( int min, char *bound_hex,
+ int result_limbs_delta,
+ int expected_ret )
+{
+ mbedtls_mpi_uint *result_digits = NULL;
+ mbedtls_mpi_mod_modulus N;
+ mbedtls_mpi_mod_modulus_init( &N );
+
+ TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, bound_hex,
+ MBEDTLS_MPI_MOD_REP_OPT_RED ),
+ 0 );
+ size_t result_limbs = N.limbs + result_limbs_delta;
+ ASSERT_ALLOC( result_digits, result_limbs );
+ /* Build a reside that might not match the modulus, to test that
+ * the library function rejects that as expected. */
+ mbedtls_mpi_mod_residue result = {result_digits, result_limbs};
+
+ TEST_EQUAL( mbedtls_mpi_mod_random( &result, min, &N,
+ mbedtls_test_rnd_std_rand, NULL ),
+ expected_ret );
+ if( expected_ret == 0 )
+ {
+ /* Success should only be expected when the result has the same
+ * size as the modulus, otherwise it's a mistake in the test data. */
+ TEST_EQUAL( result_limbs, N.limbs );
+ /* Sanity check: check that the result is in range */
+ TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+ 1 );
+ /* Check result >= min (changes result) */
+ TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result_digits, min,
+ result_limbs ),
+ 0 );
+ }
+
+ /* When the result has the right number of limbs, also test mod_raw
+ * (for which this is an unchecked precondition). */
+ if( result_limbs_delta == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_mod_raw_random( result_digits, min, &N,
+ mbedtls_test_rnd_std_rand, NULL ),
+ expected_ret );
+ if( expected_ret == 0 )
+ {
+ TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+ 1 );
+ TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result.p, min,
+ result_limbs ),
+ 0 );
+ }
+ }
+
+exit:
+ mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+ mbedtls_free( result_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void mpi_random_fail( int min, data_t *bound_bytes, int expected_ret )
{
mbedtls_mpi upper_bound;
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 73808c9..c2ec782 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -35,7 +35,7 @@
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round one: KKP1: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: nothing after first point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -50,7 +50,7 @@
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP1: nothing after second point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -83,7 +83,7 @@
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb120100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round one: KKP2: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: nothing after first point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -98,7 +98,7 @@
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round one: KKP2: nothing after second point
read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -149,7 +149,7 @@
read_round_two_cli:"0300170100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round two client: unknown first point format
-read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: nothing after first point
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -164,7 +164,7 @@
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a60104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: unknown second point format
-read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two client: nothing after second point
read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -203,7 +203,7 @@
read_round_two_srv:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
ECJPAKE round two server: unknown first point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: nothing after first point
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -218,7 +218,7 @@
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: unknown second point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECJPAKE round two server: nothing after second point
read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 4c0ed1c..9311200 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -227,19 +227,51 @@
ECP read binary #2 (zero, invalid first byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECP read binary #3 (zero, OK)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"00":"01":"01":"00":0
-ECP read binary #4 (non-zero, invalid ilen)
+ECP read binary #4 (non-zero, invalid ilen, too short)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"04001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+ECP read binary #4a (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"03001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4b (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"02001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4c (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"040011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4d (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"030011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4e (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"020011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
ECP read binary #5 (non-zero, invalid first byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5a (non-zero, compressed format, invalid first byte)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5b (non-zero, compressed format, parity 0, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0
+
+ECP read binary #5c (non-zero, compressed format, parity 1, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":0
ECP read binary #6 (non-zero, OK)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
@@ -285,6 +317,14 @@
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"0":"1":0
+ECP read binary #17 (non-zero, compressed format, p != 3 mod 4, secp224r1)
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224R1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
+ECP read binary #17a (non-zero, compressed format, p != 3 mod 4, secp224k1)
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224K1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
ECP tls read point #1 (zero, invalid length byte)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
mbedtls_ecp_tls_read_point:MBEDTLS_ECP_DP_SECP192R1:"0200":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 2971c57..96b9f40 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -642,6 +642,19 @@
{
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Z, &Z ) == 0 );
+
+ if( buf->x[0] == 0x04 &&
+ /* (reading compressed format supported only for
+ * Short Weierstrass curves with prime p where p = 3 mod 4) */
+ id != MBEDTLS_ECP_DP_SECP224R1 &&
+ id != MBEDTLS_ECP_DP_SECP224K1 )
+ {
+ /* re-encode in compressed format and test read again */
+ mbedtls_mpi_free( &P.Y );
+ buf->x[0] = 0x02 + mbedtls_mpi_get_bit( &Y, 0 );
+ TEST_ASSERT( mbedtls_ecp_point_read_binary( &grp, &P, buf->x, buf->len/2+1 ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
+ }
}
}
@@ -703,8 +716,10 @@
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
TEST_ASSERT( mbedtls_ecp_tls_write_point( &grp, &grp.G,
MBEDTLS_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 );
- TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen )
- == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+ TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 );
TEST_ASSERT( vbuf == buf + olen );
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;