Merge pull request #6486 from xkqian/tls13_add_early_data_indication
The merge job of the internal CI ran successfully. This is good to go.
diff --git a/ChangeLog.d/fix_dh_genprime_error_reporting.txt b/ChangeLog.d/fix_dh_genprime_error_reporting.txt
new file mode 100644
index 0000000..1c98947
--- /dev/null
+++ b/ChangeLog.d/fix_dh_genprime_error_reporting.txt
@@ -0,0 +1,4 @@
+Bugfix
+ * Fix bug in error reporting in dh_genprime.c where upon failure,
+ the error code returned by mbedtls_mpi_write_file() is overwritten
+ and therefore not printed.
diff --git a/ChangeLog.d/negative-zero-from-add.txt b/ChangeLog.d/negative-zero-from-add.txt
new file mode 100644
index 0000000..107d858
--- /dev/null
+++ b/ChangeLog.d/negative-zero-from-add.txt
@@ -0,0 +1,6 @@
+Bugfix
+ * In the bignum module, operations of the form (-A) - (+A) or (-A) - (-A)
+ with A > 0 created an unintended representation of the value 0 which was
+ not processed correctly by some bignum operations. Fix this. This had no
+ consequence on cryptography code, but might affect applications that call
+ bignum directly and use negative numbers.
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 9d15955..3bd1ca0 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -188,9 +188,27 @@
*/
typedef struct mbedtls_mpi
{
- int MBEDTLS_PRIVATE(s); /*!< Sign: -1 if the mpi is negative, 1 otherwise */
- size_t MBEDTLS_PRIVATE(n); /*!< total # of limbs */
- mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); /*!< pointer to limbs */
+ /** Sign: -1 if the mpi is negative, 1 otherwise.
+ *
+ * The number 0 must be represented with `s = +1`. Although many library
+ * functions treat all-limbs-zero as equivalent to a valid representation
+ * of 0 regardless of the sign bit, there are exceptions, so bignum
+ * functions and external callers must always set \c s to +1 for the
+ * number zero.
+ *
+ * Note that this implies that calloc() or `... = {0}` does not create
+ * a valid MPI representation. You must call mbedtls_mpi_init().
+ */
+ int MBEDTLS_PRIVATE(s);
+
+ /** Total number of limbs in \c p. */
+ size_t MBEDTLS_PRIVATE(n);
+
+ /** Pointer to limbs.
+ *
+ * This may be \c NULL if \c n is 0.
+ */
+ mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);
}
mbedtls_mpi;
diff --git a/library/bignum.c b/library/bignum.c
index 521787d..42be815 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -972,10 +972,12 @@
return( ret );
}
-/*
- * Signed addition: X = A + B
+/* Common function for signed addition and subtraction.
+ * Calculate A + B * flip_B where flip_B is 1 or -1.
*/
-int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+static int add_sub_mpi( mbedtls_mpi *X,
+ const mbedtls_mpi *A, const mbedtls_mpi *B,
+ int flip_B )
{
int ret, s;
MPI_VALIDATE_RET( X != NULL );
@@ -983,16 +985,21 @@
MPI_VALIDATE_RET( B != NULL );
s = A->s;
- if( A->s * B->s < 0 )
+ if( A->s * B->s * flip_B < 0 )
{
- if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
+ int cmp = mbedtls_mpi_cmp_abs( A, B );
+ if( cmp >= 0 )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
- X->s = s;
+ /* If |A| = |B|, the result is 0 and we must set the sign bit
+ * to +1 regardless of which of A or B was negative. Otherwise,
+ * since |A| > |B|, the sign is the sign of A. */
+ X->s = cmp == 0 ? 1 : s;
}
else
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
+ /* Since |A| < |B|, the sign is the opposite of A. */
X->s = -s;
}
}
@@ -1008,38 +1015,19 @@
}
/*
+ * Signed addition: X = A + B
+ */
+int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+{
+ return( add_sub_mpi( X, A, B, 1 ) );
+}
+
+/*
* Signed subtraction: X = A - B
*/
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret, s;
- MPI_VALIDATE_RET( X != NULL );
- MPI_VALIDATE_RET( A != NULL );
- MPI_VALIDATE_RET( B != NULL );
-
- s = A->s;
- if( A->s * B->s > 0 )
- {
- if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
- X->s = s;
- }
- else
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
- X->s = -s;
- }
- }
- else
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
- X->s = s;
- }
-
-cleanup:
-
- return( ret );
+ return( add_sub_mpi( X, A, B, -1 ) );
}
/*
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index a329e86..b43add7 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -127,7 +127,40 @@
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
+int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *m )
+{
+ mbedtls_mpi_uint *T;
+ const size_t t_limbs = m->limbs * 2 + 1;
+ if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+ mbedtls_mpi_core_montmul( X, X, m->rep.mont.rr, m->limbs, m->p, m->limbs,
+ m->rep.mont.mm, T );
+
+ mbedtls_platform_zeroize( T, t_limbs * ciL );
+ mbedtls_free( T );
+ return( 0 );
+}
+
+int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *m )
+{
+ const mbedtls_mpi_uint one = 1;
+ const size_t t_limbs = m->limbs * 2 + 1;
+ mbedtls_mpi_uint *T;
+
+ if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+ mbedtls_mpi_core_montmul( X, X, &one, 1, m->p, m->limbs,
+ m->rep.mont.mm, T );
+
+ mbedtls_platform_zeroize( T, t_limbs * ciL );
+ mbedtls_free( T );
+ return( 0 );
+}
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index 30648d3..f738e91 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -163,7 +163,29 @@
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
+/** Convert an MPI into Montgomery form.
+ *
+ * \param X The address of the MPI.
+ * Must have the same number of limbs as \p m.
+ * \param m The address of the modulus, which gives the size of
+ * the base `R` = 2^(biL*m->limbs).
+ *
+ * \return \c 0 if successful.
+ */
+int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *m );
+/** Convert an MPI back from Montgomery representation.
+ *
+ * \param X The address of the MPI.
+ * Must have the same number of limbs as \p m.
+ * \param m The address of the modulus, which gives the size of
+ * the base `R`= 2^(biL*m->limbs).
+ *
+ * \return \c 0 if successful.
+ */
+int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
+ const mbedtls_mpi_mod_modulus *m );
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index 2e696e5..331838b 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -157,8 +157,8 @@
goto exit;
}
- if( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) != 0 ) ||
- ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) )
+ if( ( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) ) != 0 ) ||
+ ( ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) ) != 0 ) )
{
mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret );
fclose( fout );
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 279668f..8b11bc2 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -14,9 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import itertools
-import typing
-
from abc import abstractmethod
from typing import Iterator, List, Tuple, TypeVar
@@ -38,7 +35,13 @@
raise ValueError("Not invertible")
def hex_to_int(val: str) -> int:
- return int(val, 16) if val else 0
+ """Implement the syntax accepted by mbedtls_test_read_mpi().
+
+ This is a superset of what is accepted by mbedtls_test_read_mpi_core().
+ """
+ if val in ['', '-']:
+ return 0
+ return int(val, 16)
def quote_str(val) -> str:
return "\"{}\"".format(val)
@@ -57,15 +60,8 @@
return (val.bit_length() + bits_in_limb - 1) // bits_in_limb
def combination_pairs(values: List[T]) -> List[Tuple[T, T]]:
- """Return all pair combinations from input values.
-
- The return value is cast, as older versions of mypy are unable to derive
- the specific type returned by itertools.combinations_with_replacement.
- """
- return typing.cast(
- List[Tuple[T, T]],
- list(itertools.combinations_with_replacement(values, 2))
- )
+ """Return all pair combinations from input values."""
+ return [(x, y) for x in values for y in values]
class OperationCommon:
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index 1465e3e..bd694a6 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -122,7 +122,126 @@
# END MERGE SLOT 6
# BEGIN MERGE SLOT 7
+class BignumModRawConvertToMont(BignumModRawOperationArchSplit):
+ """ Test cases for mpi_mod_raw_to_mont_rep(). """
+ test_function = "mpi_mod_raw_to_mont_rep"
+ test_name = "Convert into Mont: "
+
+ test_data_moduli = ["b",
+ "fd",
+ "eeff99aa37",
+ "eeff99aa11",
+ "800000000005",
+ "7fffffffffffffff",
+ "80fe000a10000001",
+ "25a55a46e5da99c71c7",
+ "1058ad82120c3a10196bb36229c1",
+ "7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f"
+ "18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a"
+ "98df75154f8c914a282f8b",
+ "8335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63",
+ "ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f"
+ "2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a6"
+ "4d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2"
+ "deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d"
+ "6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a0"
+ "7e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d389"
+ "8c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6"
+ "bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3a"
+ "d4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181d"
+ "b8896f33bb12e6ef73f12ec5c5ea7a8a337"
+ ]
+
+ test_input_numbers = ["0",
+ "1",
+ "97",
+ "f5",
+ "6f5c3",
+ "745bfe50f7",
+ "ffa1f9924123",
+ "334a8b983c79bd",
+ "5b84f632b58f3461",
+ "19acd15bc38008e1",
+ "ffffffffffffffff",
+ "54ce6a6bb8247fa0427cfc75a6b0599",
+ "fecafe8eca052f154ce6a6bb8247fa019558bfeecce9bb9",
+ "a87d7a56fa4bfdc7da42ef798b9cf6843d4c54794698cb14d72"
+ "851dec9586a319f4bb6d5695acbd7c92e7a42a5ede6972adcbc"
+ "f68425265887f2d721f462b7f1b91531bac29fa648facb8e3c6"
+ "1bd5ae42d5a59ba1c89a95897bfe541a8ce1d633b98f379c481"
+ "6f25e21f6ac49286b261adb4b78274fe5f61c187581f213e84b"
+ "2a821e341ef956ecd5de89e6c1a35418cd74a549379d2d4594a"
+ "577543147f8e35b3514e62cf3e89d1156cdc91ab5f4c928fbd6"
+ "9148c35df5962fed381f4d8a62852a36823d5425f7487c13a12"
+ "523473fb823aa9d6ea5f42e794e15f2c1a8785cf6b7d51a4617"
+ "947fb3baf674f74a673cf1d38126983a19ed52c7439fab42c2185"
+ ]
+
+ descr_tpl = '{} #{} N: \"{}\" A: \"{}\".'
+
+ def result(self) -> List[str]:
+ return [self.hex_x]
+
+ def arguments(self) -> List[str]:
+ return [bignum_common.quote_str(n) for n in [self.hex_n,
+ self.hex_a,
+ self.hex_x]]
+
+ def description(self) -> str:
+ return self.descr_tpl.format(self.test_name,
+ self.count,
+ self.int_n,
+ self.int_a)
+
+ @classmethod
+ def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+ for bil in [32, 64]:
+ for n in cls.test_data_moduli:
+ for i in cls.test_input_numbers:
+ # Skip invalid combinations where A.limbs > N.limbs
+ if bignum_common.hex_to_int(i) > bignum_common.hex_to_int(n):
+ continue
+ yield cls(n, i, bits_in_limb=bil).create_test_case()
+
+ @property
+ def x(self) -> int: # pylint: disable=invalid-name
+ return (self.int_a * self.r) % self.int_n
+
+ @property
+ def hex_x(self) -> str:
+ return "{:x}".format(self.x).zfill(self.hex_digits)
+
+class BignumModRawConvertFromMont(BignumModRawConvertToMont):
+ """ Test cases for mpi_mod_raw_from_mont_rep(). """
+
+ test_function = "mpi_mod_raw_from_mont_rep"
+ test_name = "Convert from Mont: "
+
+ test_input_numbers = ["0",
+ "1",
+ "3ca",
+ "539ed428",
+ "7dfe5c6beb35a2d6",
+ "dca8de1c2adfc6d7aafb9b48e",
+ "a7d17b6c4be72f3d5c16bf9c1af6fc933",
+ "2fec97beec546f9553142ed52f147845463f579",
+ "378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f",
+ "b6415f2a1a8e48a518345db11f56db3829c8f2c6415ab4a395a"
+ "b3ac2ea4cbef4af86eb18a84eb6ded4c6ecbfc4b59c2879a675"
+ "487f687adea9d197a84a5242a5cf6125ce19a6ad2e7341f1c57"
+ "d43ea4f4c852a51cb63dabcd1c9de2b827a3146a3d175b35bea"
+ "41ae75d2a286a3e9d43623152ac513dcdea1d72a7da846a8ab3"
+ "58d9be4926c79cfb287cf1cf25b689de3b912176be5dcaf4d4c"
+ "6e7cb839a4a3243a6c47c1e2c99d65c59d6fa3672575c2f1ca8"
+ "de6a32e854ec9d8ec635c96af7679fce26d7d159e4a9da3bd74"
+ "e1272c376cd926d74fe3fb164a5935cff3d5cdb92b35fe2cea32"
+ "138a7e6bfbc319ebd1725dacb9a359cbf693f2ecb785efb9d627"
+ ]
+
+ @property
+ def x(self): # pylint: disable=invalid-name
+ return (self.int_a * self.r_inv) % self.int_n
# END MERGE SLOT 7
# BEGIN MERGE SLOT 8
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 09a0689..d4f2011 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -884,6 +884,11 @@
$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA256
all_final += server1.req.sha256
+server1.req.sha256.ext: server1.key
+ # Generating this with OpenSSL as a comparison point to test we're getting the same result
+ openssl req -new -out $@ -key $< -subj '/C=NL/O=PolarSSL/CN=PolarSSL Server 1' -sha256 -addext "extendedKeyUsage=serverAuth"
+all_final += server1.req.sha256.ext
+
server1.req.sha384: server1.key
$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA384
all_final += server1.req.sha384
diff --git a/tests/data_files/server1.req.sha256.ext b/tests/data_files/server1.req.sha256.ext
new file mode 100644
index 0000000..3f26f09
--- /dev/null
+++ b/tests/data_files/server1.req.sha256.ext
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICpzCCAY8CAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRow
+GAYDVQQDDBFQb2xhclNTTCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZ
+ZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZ
+HqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYF
+W+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQs
+FiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/
+DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEAAaAmMCQGCSqGSIb3DQEJDjEX
+MBUwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHi0yEGu
+Fh5tuLiLuT95UrRnly55+lTY9xchFiKtlcoEdSheybYxqk3JHuSSqojOFKZBlRdk
+oG6Azg56/aMHPWyvtCMSRQX4b+FgjeQsm9IfhYNMquQOxyPxm62vjuU3MfZIofXH
+hKdI6Ci2CDF4Fyvw50KBWniV38eE9+kjsvDLdXD3ESZJGhjjuFl8ReUiA2wdBTcP
+XEZaXUIc6B4tUnlPeqn/2zp4GBqqWzNZx6TXBpApASGG3BEJnM52FVPC7E9p+8YZ
+qIGuiF5Cz/rYZkpwffBWIfS2zZakHLm5TB8FgZkWlyReJU9Ihk2Tl/sZ1kllFdYa
+xLPnLCL82KFL1Co=
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index e0e6fd2..5f9bde6 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -295,13 +295,19 @@
/** Read an MPI from a hexadecimal string.
*
- * Like mbedtls_mpi_read_string(), but size the resulting bignum based
- * on the number of digits in the string. In particular, construct 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.
+ * Like mbedtls_mpi_read_string(), but with tighter guarantees around
+ * edge cases.
*
- * This is important so that the "0 (null)" and "0 (1 limb)" and
- * "leading zeros" test cases do what they claim.
+ * - 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.
@@ -309,6 +315,14 @@
* \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/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index a105203..eee2f65 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -78,11 +78,17 @@
#pylint: disable=abstract-method
"""Common features for bignum operations in legacy tests."""
input_values = [
- "", "0", "7b", "-7b",
+ "", "0", "-", "-0",
+ "7b", "-7b",
"0000000000000000123", "-0000000000000000123",
"1230000000000000000", "-1230000000000000000"
]
+ def description_suffix(self) -> str:
+ #pylint: disable=no-self-use # derived classes need self
+ """Text to add at the end of the test case description."""
+ return ""
+
def description(self) -> str:
"""Generate a description for the test case.
@@ -96,6 +102,9 @@
self.symbol,
self.value_description(self.arg_b)
)
+ description_suffix = self.description_suffix()
+ if description_suffix:
+ self.case_description += " " + description_suffix
return super().description()
@staticmethod
@@ -107,6 +116,8 @@
"""
if val == "":
return "0 (null)"
+ if val == "-":
+ return "negative 0 (null)"
if val == "0":
return "0 (1 limb)"
@@ -171,9 +182,21 @@
]
)
- def result(self) -> List[str]:
- return [bignum_common.quote_str("{:x}").format(self.int_a + self.int_b)]
+ def __init__(self, val_a: str, val_b: str) -> None:
+ super().__init__(val_a, val_b)
+ self._result = self.int_a + self.int_b
+ def description_suffix(self) -> str:
+ if (self.int_a >= 0 and self.int_b >= 0):
+ return "" # obviously positive result or 0
+ if (self.int_a <= 0 and self.int_b <= 0):
+ return "" # obviously negative result or 0
+ # The sign of the result is not obvious, so indicate it
+ return ", result{}0".format('>' if self._result > 0 else
+ '<' if self._result < 0 else '=')
+
+ def result(self) -> List[str]:
+ return [bignum_common.quote_str("{:x}".format(self._result))]
if __name__ == '__main__':
# Use the section of the docstring relevant to the CLI as description
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index cc23fd7..7c83714 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -89,6 +89,10 @@
mbedtls_test_info.step = step;
}
+#if defined(MBEDTLS_BIGNUM_C)
+unsigned mbedtls_test_case_uses_negative_0 = 0;
+#endif
+
void mbedtls_test_info_reset( void )
{
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SUCCESS;
@@ -98,6 +102,9 @@
mbedtls_test_info.filename = 0;
memset( mbedtls_test_info.line1, 0, sizeof( mbedtls_test_info.line1 ) );
memset( mbedtls_test_info.line2, 0, sizeof( mbedtls_test_info.line2 ) );
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_test_case_uses_negative_0 = 0;
+#endif
}
int mbedtls_test_equal( const char *test, int line_no, const char* filename,
@@ -396,6 +403,15 @@
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 )
@@ -403,7 +419,15 @@
mbedtls_mpi_free( X );
return( 0 );
}
- else
- return( mbedtls_mpi_read_string( X, 16, s ) );
+ 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/test_suite_bignum.function b/tests/suites/test_suite_bignum.function
index 4cec0a7..b75f534 100644
--- a/tests/suites/test_suite_bignum.function
+++ b/tests/suites/test_suite_bignum.function
@@ -13,10 +13,21 @@
* constructing the value. */
static int sign_is_valid( const mbedtls_mpi *X )
{
+ /* Only +1 and -1 are valid sign bits, not e.g. 0 */
if( X->s != 1 && X->s != -1 )
- return( 0 ); // invalid sign bit, e.g. 0
- if( mbedtls_mpi_bitlen( X ) == 0 && X->s != 1 )
- return( 0 ); // negative zero
+ return( 0 );
+
+ /* The value 0 must be represented with the sign +1. A "negative zero"
+ * with s=-1 is an invalid representation. Forbid that. As an exception,
+ * we sometimes test the robustness of library functions when given
+ * a negative zero input. If a test case has a negative zero as input,
+ * we don't mind if the function has a negative zero output. */
+ if( ! mbedtls_test_case_uses_negative_0 &&
+ mbedtls_mpi_bitlen( X ) == 0 && X->s != 1 )
+ {
+ return( 0 );
+ }
+
return( 1 );
}
@@ -959,24 +970,57 @@
/* END_CASE */
/* BEGIN_CASE */
-void mpi_mod_int( char * input_X, int input_Y,
- int input_A, int div_result )
+void mpi_mod_int( char * input_X, char * input_Y,
+ char * input_A, int mod_result )
{
mbedtls_mpi X;
+ mbedtls_mpi Y;
+ mbedtls_mpi A;
int res;
mbedtls_mpi_uint r;
- mbedtls_mpi_init( &X );
- TEST_ASSERT( mbedtls_test_read_mpi( &X, input_X ) == 0 );
- res = mbedtls_mpi_mod_int( &r, &X, input_Y );
- TEST_ASSERT( res == div_result );
+ mbedtls_mpi_init( &X );
+ mbedtls_mpi_init( &Y );
+ mbedtls_mpi_init( &A );
+
+ /* We use MPIs to read Y and A since the test framework limits us to
+ * ints, so we can't have 64-bit values */
+ TEST_EQUAL( mbedtls_test_read_mpi( &X, input_X ), 0 );
+ TEST_EQUAL( mbedtls_test_read_mpi( &Y, input_Y ), 0 );
+ TEST_EQUAL( mbedtls_test_read_mpi( &A, input_A ), 0 );
+
+ TEST_EQUAL( Y.n, 1 );
+ TEST_EQUAL( A.n, 1 );
+
+ /* Convert the MPIs for Y and A to (signed) mbedtls_mpi_sints */
+
+ /* Since we're converting sign+magnitude to two's complement, we lose one
+ * bit of value in the output. This means there are some values we can't
+ * represent, e.g. (hex) -A0000000 on 32-bit systems. These are technically
+ * invalid test cases, so could be considered "won't happen", but they are
+ * easy to test for, and this helps guard against human error. */
+
+ mbedtls_mpi_sint y = (mbedtls_mpi_sint) Y.p[0];
+ TEST_ASSERT( y >= 0 ); /* If y < 0 here, we can't make negative y */
+ if( Y.s == -1 )
+ y = -y;
+
+ mbedtls_mpi_sint a = (mbedtls_mpi_sint) A.p[0];
+ TEST_ASSERT( a >= 0 ); /* Same goes for a */
+ if( A.s == -1 )
+ a = -a;
+
+ res = mbedtls_mpi_mod_int( &r, &X, y );
+ TEST_EQUAL( res, mod_result );
if( res == 0 )
{
- TEST_ASSERT( r == (mbedtls_mpi_uint) input_A );
+ TEST_EQUAL( r, a );
}
exit:
mbedtls_mpi_free( &X );
+ mbedtls_mpi_free( &Y );
+ mbedtls_mpi_free( &A );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_bignum.misc.data b/tests/suites/test_suite_bignum.misc.data
index 29ba4ab..818f361 100644
--- a/tests/suites/test_suite_bignum.misc.data
+++ b/tests/suites/test_suite_bignum.misc.data
@@ -1144,6 +1144,18 @@
Test mbedtls_mpi_div_mpi: 0 (null) / -1
mpi_div_mpi:"":"-1":"":"":0
+Test mbedtls_mpi_div_mpi: -0 (null) / 1
+mpi_div_mpi:"-":"1":"":"":0
+
+Test mbedtls_mpi_div_mpi: -0 (null) / -1
+mpi_div_mpi:"-":"-1":"":"":0
+
+Test mbedtls_mpi_div_mpi: -0 (null) / 42
+mpi_div_mpi:"-":"2a":"":"":0
+
+Test mbedtls_mpi_div_mpi: -0 (null) / -42
+mpi_div_mpi:"-":"-2a":"":"":0
+
Test mbedtls_mpi_div_mpi #1
mpi_div_mpi:"9e22d6da18a33d1ef28d2a82242b3f6e9c9742f63e5d440f58a190bfaf23a7866e67589adb80":"22":"4a6abf75b13dc268ea9cc8b5b6aaf0ac85ecd437a4e0987fb13cf8d2acc57c0306c738c1583":"1a":0
@@ -1204,41 +1216,85 @@
Test mbedtls_mpi_mod_mpi: 0 (null) % -1
mpi_mod_mpi:"":"-1":"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+Test mbedtls_mpi_mod_mpi: -0 (null) % 1
+mpi_mod_mpi:"-":"1":"":0
+
+Test mbedtls_mpi_mod_mpi: -0 (null) % -1
+mpi_mod_mpi:"-":"-1":"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
+Test mbedtls_mpi_mod_mpi: -0 (null) % 42
+mpi_mod_mpi:"-":"2a":"":0
+
+Test mbedtls_mpi_mod_mpi: -0 (null) % -42
+mpi_mod_mpi:"-":"-2a":"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
Base test mbedtls_mpi_mod_int #1
-mpi_mod_int:"3e8":13:12:0
+mpi_mod_int:"3e8":"d":"c":0
Base test mbedtls_mpi_mod_int #2 (Divide by zero)
-mpi_mod_int:"3e8":0:0:MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+mpi_mod_int:"3e8":"0":"0":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
Base test mbedtls_mpi_mod_int #3
-mpi_mod_int:"-3e8":13:1:0
+mpi_mod_int:"-3e8":"d":"1":0
Base test mbedtls_mpi_mod_int #4 (Negative modulo)
-mpi_mod_int:"3e8":-13:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+mpi_mod_int:"3e8":"-d":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
Base test mbedtls_mpi_mod_int #5 (Negative modulo)
-mpi_mod_int:"-3e8":-13:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+mpi_mod_int:"-3e8":"-d":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
Base test mbedtls_mpi_mod_int #6 (By 1)
-mpi_mod_int:"3e8":1:0:0
+mpi_mod_int:"3e8":"1":"0":0
Base test mbedtls_mpi_mod_int #7 (By 2)
-mpi_mod_int:"3e9":2:1:0
+mpi_mod_int:"3e9":"2":"1":0
Base test mbedtls_mpi_mod_int #8 (By 2)
-mpi_mod_int:"3e8":2:0:0
+mpi_mod_int:"3e8":"2":"0":0
Test mbedtls_mpi_mod_int: 0 (null) % 1
-mpi_mod_int:"":1:0:0
+mpi_mod_int:"":"1":"0":0
Test mbedtls_mpi_mod_int: 0 (null) % 2
-mpi_mod_int:"":2:0:0
+mpi_mod_int:"":"2":"0":0
Test mbedtls_mpi_mod_int: 0 (null) % -1
-mpi_mod_int:"":-1:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+mpi_mod_int:"":"-1":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
Test mbedtls_mpi_mod_int: 0 (null) % -2
-mpi_mod_int:"":-2:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+mpi_mod_int:"":"-2":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
+# CURRENTLY FAILS - SEE GITHUB ISSUE #6540
+#Test mbedtls_mpi_mod_int: 230772460340063000000100500000300000010 % 5178236083361335880 -> 3386266129388798810
+#depends_on:MBEDTLS_HAVE_INT64
+#mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA4847DCCA48":"2EFE6F1A7D28035A":0
+
+Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000300000010 % 5178236083361335880 -> 3386266129388798810
+mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA4847DCCA48":"2EFE6F1A7D28035A":0
+
+# CURRENTLY FAILS - SEE GITHUB ISSUE #6540
+#Test mbedtls_mpi_mod_int: 230772460340062999996714233870911201200 % 5178236083361335880 -> 0
+#depends_on:MBEDTLS_HAVE_INT64
+#mpi_mod_int:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":"47DCCA4847DCCA48":"0":0
+
+Test mbedtls_mpi_mod_mpi: 230772460340062999996714233870911201200 % 5178236083361335880 -> 0
+mpi_mod_mpi:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":"47DCCA4847DCCA48":"0":0
+
+# CURRENTLY FAILS WHEN MPIS ARE 32-BIT (ISSUE #6450): WHEN FIXED, REMOVE "depends_on" LINE
+Test mbedtls_mpi_mod_int: 230772460340063000000100500000300000010 % 1205652040 -> 3644370
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA48":"379BD2":0
+
+Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000300000010 % 1205652040 -> 3644370
+mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA48":"379BD2":0
+
+# CURRENTLY FAILS WHEN MPIS ARE 32-BIT (ISSUE #6450): WHEN FIXED, REMOVE "depends_on" LINE
+Test mbedtls_mpi_mod_int: 230772460340063000000100500000296355640 % 1205652040 -> 0
+depends_on:MBEDTLS_HAVE_INT64
+mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980974738":"47DCCA48":"0":0
+
+Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000296355640 % 1205652040 -> 0
+mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980974738":"47DCCA48":"0":0
Base test mbedtls_mpi_exp_mod #1
mpi_exp_mod:"17":"d":"1d":"18":0
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 4b90675..ff766b9 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -294,7 +294,77 @@
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
+/* BEGIN_CASE */
+void mpi_mod_raw_to_mont_rep( char * input_N, char * input_A, char * input_X )
+{
+ mbedtls_mpi_uint *N = NULL;
+ mbedtls_mpi_uint *A = NULL;
+ mbedtls_mpi_uint *X = NULL;
+ size_t n_limbs, a_limbs, x_limbs, x_bytes;
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ /* Read inputs */
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+ 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 ) );
+ x_bytes = x_limbs * sizeof(mbedtls_mpi_uint);
+
+ /* Test that input does not require more limbs than modulo */
+ TEST_LE_U(a_limbs, n_limbs);
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+ MBEDTLS_MPI_MOD_EXT_REP_BE, MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+ /* Convert from cannonical into Montgomery representation */
+ TEST_EQUAL(0, mbedtls_mpi_mod_raw_to_mont_rep( A, &m ) );
+
+ /* The result matches expected value */
+ ASSERT_COMPARE( A, x_bytes, X, x_bytes );
+exit:
+ mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_free( N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_raw_from_mont_rep( char * input_N, char * input_A, char * input_X )
+{
+ mbedtls_mpi_uint *N = NULL;
+ mbedtls_mpi_uint *A = NULL;
+ mbedtls_mpi_uint *X = NULL;
+ size_t n_limbs, a_limbs, x_limbs, x_bytes;
+
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ /* Read inputs */
+ TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+ 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 ) );
+ x_bytes = x_limbs * sizeof(mbedtls_mpi_uint);
+
+ /* Test that input does not require more limbs than modulo */
+ TEST_LE_U(a_limbs, n_limbs);
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+ MBEDTLS_MPI_MOD_EXT_REP_BE, MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+ /* Convert from Montgomery into cannonical representation */
+ TEST_EQUAL(0, mbedtls_mpi_mod_raw_from_mont_rep( A, &m ) );
+
+ /* The result matches expected value */
+ ASSERT_COMPARE( A, x_bytes, X, x_bytes );
+exit:
+ mbedtls_mpi_mod_modulus_free( &m );
+ mbedtls_free( N );
+ mbedtls_free( A );
+ mbedtls_free( X );
+}
+/* END_CASE */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 8411557..c55c9d1 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -1,30 +1,30 @@
Certificate Request check Server1 SHA1
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha1":MBEDTLS_MD_SHA1:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha1":MBEDTLS_MD_SHA1:0:0:0:0:0
Certificate Request check Server1 SHA224
depends_on:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha224":MBEDTLS_MD_SHA224:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha224":MBEDTLS_MD_SHA224:0:0:0:0:0
Certificate Request check Server1 SHA256
depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha256":MBEDTLS_MD_SHA256:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha256":MBEDTLS_MD_SHA256:0:0:0:0:0
Certificate Request check Server1 SHA384
depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha384":MBEDTLS_MD_SHA384:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha384":MBEDTLS_MD_SHA384:0:0:0:0:0
Certificate Request check Server1 SHA512
depends_on:MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha512":MBEDTLS_MD_SHA512:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha512":MBEDTLS_MD_SHA512:0:0:0:0:0
Certificate Request check Server1 MD5
depends_on:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.md5":MBEDTLS_MD_MD5:0:0:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.md5":MBEDTLS_MD_MD5:0:0:0:0:0
Certificate Request check Server1 key_usage
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.key_usage":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.key_usage":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0
Certificate Request check opaque Server1 key_usage
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
@@ -32,23 +32,27 @@
Certificate Request check Server1 key_usage empty
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.key_usage_empty":MBEDTLS_MD_SHA1:0:1:0:0
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.key_usage_empty":MBEDTLS_MD_SHA1:0:1:0:0:0
Certificate Request check Server1 ns_cert_type
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.cert_type":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.cert_type":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0
Certificate Request check Server1 ns_cert_type empty
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.cert_type_empty":MBEDTLS_MD_SHA1:0:0:0:1
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.cert_type_empty":MBEDTLS_MD_SHA1:0:0:0:1:0
Certificate Request check Server1 key_usage + ns_cert_type
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_csr_check:"data_files/server1.key":"data_files/server1.req.ku-ct":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.ku-ct":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0
Certificate Request check Server5 ECDSA, key_usage
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-x509_csr_check:"data_files/server5.key":"data_files/server5.req.ku.sha1":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION:1:0:0
+x509_csr_check:"data_files/server5.key":"data_files/server5.req.ku.sha1":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION:1:0:0:0
+
+Certificate Request check Server1, set_extension
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha256.ext":MBEDTLS_MD_SHA256:0:0:0:0:1
Certificate Request check opaque Server5 ECDSA, key_usage
depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index aa54072..5bd814a 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -5,6 +5,7 @@
#include "mbedtls/pem.h"
#include "mbedtls/oid.h"
#include "mbedtls/rsa.h"
+#include "mbedtls/asn1write.h"
#include "hash_info.h"
#include "mbedtls/legacy_or_psa.h"
@@ -74,6 +75,56 @@
}
#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C && MBEDTLS_X509_CSR_WRITE_C */
+#if defined(MBEDTLS_X509_CSR_WRITE_C)
+
+/*
+ * The size of this temporary buffer is given by the sequence of functions
+ * called hereinafter:
+ * - mbedtls_asn1_write_oid()
+ * - 8 bytes for MBEDTLS_OID_EXTENDED_KEY_USAGE raw value
+ * - 1 byte for MBEDTLS_OID_EXTENDED_KEY_USAGE length
+ * - 1 byte for MBEDTLS_ASN1_OID tag
+ * - mbedtls_asn1_write_len()
+ * - 1 byte since we're dealing with sizes which are less than 0x80
+ * - mbedtls_asn1_write_tag()
+ * - 1 byte
+ *
+ * This length is fine as long as this function is called using the
+ * MBEDTLS_OID_SERVER_AUTH OID. If this is changed in the future, then this
+ * buffer's length should be adjusted accordingly.
+ * Unfortunately there's no predefined max size for OIDs which can be used
+ * to set an overall upper boundary which is always guaranteed.
+ */
+#define EXT_KEY_USAGE_TMP_BUF_MAX_LENGTH 12
+
+static int csr_set_extended_key_usage( mbedtls_x509write_csr *ctx,
+ const char *oid, size_t oid_len )
+{
+ unsigned char buf[EXT_KEY_USAGE_TMP_BUF_MAX_LENGTH] = { 0 };
+ unsigned char *p = buf + sizeof( buf );
+ int ret;
+ size_t len = 0;
+
+ /*
+ * Following functions fail anyway if the temporary buffer is not large,
+ * but we set an extra check here to emphasize a possible source of errors
+ */
+ if ( oid_len > EXT_KEY_USAGE_TMP_BUF_MAX_LENGTH )
+ {
+ return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+ }
+
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &p, buf, oid, oid_len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, ret ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+
+ ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_EXTENDED_KEY_USAGE,
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_EXTENDED_KEY_USAGE ), 0, p, len );
+
+ return ret;
+}
+#endif /* MBEDTLS_X509_CSR_WRITE_C */
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -84,7 +135,7 @@
/* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C:MBEDTLS_X509_CSR_WRITE_C */
void x509_csr_check( char * key_file, char * cert_req_check_file, int md_type,
int key_usage, int set_key_usage, int cert_type,
- int set_cert_type )
+ int set_cert_type, int set_extension )
{
mbedtls_pk_context key;
mbedtls_x509write_csr req;
@@ -117,6 +168,9 @@
TEST_ASSERT( mbedtls_x509write_csr_set_key_usage( &req, key_usage ) == 0 );
if( set_cert_type != 0 )
TEST_ASSERT( mbedtls_x509write_csr_set_ns_cert_type( &req, cert_type ) == 0 );
+ if ( set_extension != 0 )
+ TEST_ASSERT( csr_set_extended_key_usage( &req, MBEDTLS_OID_SERVER_AUTH,
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ) ) == 0 );
ret = mbedtls_x509write_csr_pem( &req, buf, sizeof( buf ),
mbedtls_test_rnd_pseudo_rand, &rnd_info );