Merge pull request #325 from gilles-peskine-arm/psa-sign_hash
Rename psa_asymmetric_{sign_verify} to psa_{sign,verify}_hash
diff --git a/README.md b/README.md
index 9d34c55..a954a16 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
## PSA cryptography API
-Arm's Platform Security Architecture (PSA) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
+Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
-The PSA cryptography API provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.
+The [PSA cryptography API](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.
The design goals of the PSA cryptography API include:
@@ -24,17 +24,17 @@
## Documentation
-The Mbed Crypto library is a reference implementation of the PSA cryptography API. Please refer to the PSA Cryptography API documents for an overview of the library's interfaces and a detailed description of the types, macros and functions that it provides.
+The Mbed Crypto library implements both the legacy Mbed TLS interfaces to cryptographic primitives (`mbedtls_xxx`) and the new PSA Cryptography interfaces (`psa_xxx`).
+
+Documentation for the Mbed TLS interfaces in the default library configuration is available as part of the [Mbed TLS documentation](https://tls.mbed.org/api/).
+
+For the PSA interfaces, please refer to the PSA Cryptography API documents linked from the [PSA cryptography interfaces documentation portal](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) for an overview of the library's interfaces and a detailed description of the types, macros and functions that it provides. The API reference is available in [PDF](https://armmbed.github.io/mbed-crypto/PSA_Cryptography_API_Specification.pdf) and [HTML](https://armmbed.github.io/mbed-crypto/html/index.html) formats.
There are currently a few deviations where the library does not yet implement the latest version of the specification. Please refer to the [compliance issues on Github](https://github.com/ARMmbed/mbed-crypto/labels/compliance) for an up-to-date list.
-### PSA Cryptography API
-
-You can read the [complete PSA cryptography API specification as a PDF document](https://github.com/ARMmbed/mbed-crypto/raw/psa-crypto-api/docs/PSA_Cryptography_API_Specification.pdf). The API reference is also available in [HTML format](https://armmbed.github.io/mbed-crypto/html/index.html).
-
### Browsable library documentation
-To generate a local copy of the library documentation in HTML format:
+To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:
1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. We use version 1.8.11 but slightly older or more recent versions should work.
1. Run `make apidoc`.
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index 1a76111..1c6683f 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -75,6 +75,7 @@
#define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06
+#define MBEDTLS_ASN1_ENUMERATED 0x0A
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11
@@ -254,14 +255,33 @@
* a valid ASN.1 INTEGER.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
- * \return An ASN.1 error code if the input does not start with
- * a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val );
/**
+ * \brief Retrieve an enumerated ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param val On success, the parsed value.
+ *
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 ENUMERATED.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ * not fit in an \c int.
+ */
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
@@ -367,8 +387,6 @@
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
* \return An MPI error code if the parsed value is too large.
- * \return An ASN.1 error code if the input does not start with
- * a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h
index 9824146..0bce28e 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -193,6 +193,21 @@
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/**
+ * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param val The integer value to write.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
+
+/**
* \brief Write a string in ASN.1 format using a specific
* string encoding tag.
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 62b4c2e..31e339c 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -371,7 +371,7 @@
#define PSA_ALG_DSA(hash_alg) \
(PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000)
-#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)
+#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG
/** Deterministic DSA signature with hashing.
*
* This is the deterministic variant defined by RFC 6979 of
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index a18def5..d0008a9 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1197,11 +1197,12 @@
*/
#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \
(PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)
#define PSA_ALG_IS_ECDSA(alg) \
- (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \
+ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \
PSA_ALG_ECDSA_BASE)
#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \
- (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+ (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0)
#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \
(PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 412259e..87e7aa9 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -139,17 +139,20 @@
return( 0 );
}
-int mbedtls_asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val )
+static int asn1_get_tagged_int( unsigned char **p,
+ const unsigned char *end,
+ int tag, int *val )
{
int ret;
size_t len;
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
return( ret );
- /* len==0 is malformed (0 must be represented as 020100). */
+ /*
+ * len==0 is malformed (0 must be represented as 020100 for INTEGER,
+ * or 0A0100 for ENUMERATED tags
+ */
if( len == 0 )
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
/* This is a cryptography library. Reject negative integers. */
@@ -180,6 +183,20 @@
return( 0 );
}
+int mbedtls_asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
+}
+
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
+}
+
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
diff --git a/library/asn1write.c b/library/asn1write.c
index a138d0b..b3a3ad5 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -231,7 +231,7 @@
return( (int) len );
}
-int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
{
int ret;
size_t len = 0;
@@ -255,11 +255,21 @@
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
+}
+
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
+}
+
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len )
{
diff --git a/library/entropy.c b/library/entropy.c
index d7091cb..a40ce80 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -327,7 +327,8 @@
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
{
- int ret, count = 0, i, done;
+ int ret, count = 0, i, thresholds_reached;
+ size_t strong_size;
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
@@ -365,12 +366,17 @@
if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
goto exit;
- done = 1;
+ thresholds_reached = 1;
+ strong_size = 0;
for( i = 0; i < ctx->source_count; i++ )
+ {
if( ctx->source[i].size < ctx->source[i].threshold )
- done = 0;
+ thresholds_reached = 0;
+ if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+ strong_size += ctx->source[i].size;
+ }
}
- while( ! done );
+ while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
diff --git a/tests/suites/test_suite_asn1parse.data b/tests/suites/test_suite_asn1parse.data
index 4abae0b..e26f93a 100644
--- a/tests/suites/test_suite_asn1parse.data
+++ b/tests/suites/test_suite_asn1parse.data
@@ -286,6 +286,90 @@
INTEGER too large for mpi
get_mpi_too_large:
+ENUMERATED 0
+get_enum:"0A0100":"0":0
+
+ENUMERATED 0, extra leading 0
+get_enum:"0A020000":"0":0
+
+ENUMERATED 1
+get_enum:"0A0101":"1":0
+
+ENUMERATED 1, extra leading 0
+get_enum:"0A020001":"1":0
+
+ENUMERATED 0x7f
+get_enum:"0A017f":"7f":0
+
+ENUMERATED 0x80
+get_enum:"0A020080":"80":0
+
+ENUMERATED 0x80, extra leading 0
+get_enum:"0A03000080":"80":0
+
+ENUMERATED 0xff
+get_enum:"0A0200ff":"ff":0
+
+ENUMERATED 0x7fff
+get_enum:"0A027fff":"7fff":0
+
+ENUMERATED 0x12345678
+get_enum:"0A0412345678":"12345678":0
+
+ENUMERATED 0x12345678, extra leading 0
+get_enum:"0A050012345678":"12345678":0
+
+ENUMERATED 0x7fffffff
+get_enum:"0A047fffffff":"7fffffff":0
+
+ENUMERATED 0x7fffffff, extra leading 0
+get_enum:"0A05007fffffff":"7fffffff":0
+
+ENUMERATED 0x80000000
+get_enum:"0A050080000000":"80000000":0
+
+ENUMERATED 0xffffffff
+get_enum:"0A0500ffffffff":"ffffffff":0
+
+ENUMERATED 0x100000000
+get_enum:"0A050100000000":"0100000000":0
+
+ENUMERATED -1
+get_enum:"0A01ff":"-1":0
+
+ENUMERATED -1, extra leading ff
+get_enum:"0A02ffff":"-1":0
+
+ENUMERATED -0x7f
+get_enum:"0A0181":"-7f":0
+
+ENUMERATED -0x80
+get_enum:"0A0180":"-80":0
+
+ENUMERATED -0x81
+get_enum:"0A02ff7f":"-81":0
+
+ENUMERATED -0xff
+get_enum:"0A02ff01":"-ff":0
+
+ENUMERATED -0x100
+get_enum:"0A02ff00":"-100":0
+
+ENUMERATED -0x7fffffff
+get_enum:"0A0480000001":"-7fffffff":0
+
+ENUMERATED -0x80000000
+get_enum:"0A0480000000":"-80000000":0
+
+ENUMERATED -0x80000001
+get_enum:"0A05ff7fffffff":"-80000001":0
+
+ENUMERATED -0xffffffff
+get_enum:"0A05ff00000001":"-ffffffff":0
+
+ENUMERATED -0x100000000
+get_enum:"0A05ff00000000":"-100000000":0
+
BIT STRING: empty
get_bitstring:"0300":0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA:MBEDTLS_ERR_ASN1_INVALID_DATA
diff --git a/tests/suites/test_suite_asn1parse.function b/tests/suites/test_suite_asn1parse.function
index defbd01..d747cc2 100644
--- a/tests/suites/test_suite_asn1parse.function
+++ b/tests/suites/test_suite_asn1parse.function
@@ -393,6 +393,49 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void get_enum( const data_t *input,
+ const char *expected_hex, int expected_result )
+{
+ unsigned char *p;
+ long expected_value;
+ int expected_result_for_enum = expected_result;
+ int val;
+ int ret;
+
+ errno = 0;
+ expected_value = strtol( expected_hex, NULL, 16 );
+ if( expected_result == 0 &&
+ ( errno == ERANGE
+#if LONG_MAX > INT_MAX
+ || expected_value > INT_MAX || expected_value < INT_MIN
+#endif
+ ) )
+ {
+ /* The library returns the dubious error code INVALID_LENGTH
+ * for integers that are out of range. */
+ expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+ if( expected_result == 0 && expected_value < 0 )
+ {
+ /* The library does not support negative INTEGERs and
+ * returns the dubious error code INVALID_LENGTH.
+ * Test that we preserve the historical behavior. If we
+ * decide to change the behavior, we'll also change this test. */
+ expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+
+ p = input->x;
+ ret = mbedtls_asn1_get_enum( &p, input->x + input->len, &val );
+ TEST_EQUAL( ret, expected_result_for_enum );
+ if( ret == 0 )
+ {
+ TEST_EQUAL( val, expected_value );
+ TEST_ASSERT( p == input->x + input->len );
+ }
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
void get_mpi_too_large( )
{
diff --git a/tests/suites/test_suite_asn1write.data b/tests/suites/test_suite_asn1write.data
index fd589fb..7f5f536 100644
--- a/tests/suites/test_suite_asn1write.data
+++ b/tests/suites/test_suite_asn1write.data
@@ -49,6 +49,48 @@
ASN.1 Write int 2147483647
mbedtls_asn1_write_int:0x7fffffff:"02047fffffff"
+ASN.1 Write enum 0
+mbedtls_asn1_write_enum:0:"0A0100"
+
+ASN.1 Write enum 1
+mbedtls_asn1_write_enum:1:"0A0101"
+
+ASN.1 Write enum 127
+mbedtls_asn1_write_enum:0x7f:"0A017f"
+
+ASN.1 Write enum 128
+mbedtls_asn1_write_enum:0x80:"0A020080"
+
+ASN.1 Write enum 255
+mbedtls_asn1_write_enum:0xff:"0A0200ff"
+
+ASN.1 Write enum 256
+mbedtls_asn1_write_enum:0x100:"0A020100"
+
+ASN.1 Write enum 32767
+mbedtls_asn1_write_enum:0x7fff:"0A027fff"
+
+ASN.1 Write enum 32768
+mbedtls_asn1_write_enum:0x8000:"0A03008000"
+
+ASN.1 Write enum 65535
+mbedtls_asn1_write_enum:0xffff:"0A0300ffff"
+
+ASN.1 Write enum 65536
+mbedtls_asn1_write_enum:0x10000:"0A03010000"
+
+ASN.1 Write enum 8388607
+mbedtls_asn1_write_enum:0x7fffff:"0A037fffff"
+
+ASN.1 Write enum 8388608
+mbedtls_asn1_write_enum:0x800000:"0A0400800000"
+
+ASN.1 Write enum 0x12345678
+mbedtls_asn1_write_enum:0x12345678:"0A0412345678"
+
+ASN.1 Write enum 2147483647
+mbedtls_asn1_write_enum:0x7fffffff:"0A047fffffff"
+
#ASN.1 Write mpi 0
#mbedtls_asn1_write_mpi:"00":"020100"
diff --git a/tests/suites/test_suite_asn1write.function b/tests/suites/test_suite_asn1write.function
index b69f6b5..21465c7 100644
--- a/tests/suites/test_suite_asn1write.function
+++ b/tests/suites/test_suite_asn1write.function
@@ -117,6 +117,27 @@
}
/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_asn1_write_enum( int val, data_t *expected )
+{
+ generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
+ int ret;
+
+ for( data.size = 0; data.size < expected->len + 1; data.size++ )
+ {
+ if( ! generic_write_start_step( &data ) )
+ goto exit;
+ ret = mbedtls_asn1_write_enum( &data.p, data.start, val );
+ if( ! generic_write_finish_step( &data, expected, ret ) )
+ goto exit;
+ }
+
+exit:
+ mbedtls_free( data.output );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
{
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
index 11ced64..b2d20b4 100644
--- a/tests/suites/test_suite_entropy.data
+++ b/tests/suites/test_suite_entropy.data
@@ -1,45 +1,66 @@
Create NV seed_file
nv_seed_file_create:
-Entropy write/update seed file [#1]
+Entropy write/update seed file: good
entropy_seed_file:"data_files/entropy_seed":0
-Entropy write/update seed file [#2]
+Entropy write/update seed file: nonexistent
entropy_seed_file:"no_such_dir/file":MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
+Entropy no sources
+entropy_no_sources:
+
Entropy too many sources
entropy_too_many_sources:
-Entropy output length #1
+Entropy output length: 0
entropy_func_len:0:0
-Entropy output length #2
+Entropy output length: 1
entropy_func_len:1:0
-Entropy output length #3
+Entropy output length: 2
entropy_func_len:2:0
-Entropy output length #4
+Entropy output length: 31
entropy_func_len:31:0
-Entropy output length #5
+Entropy output length: 65 > BLOCK_SIZE
entropy_func_len:65:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
Entropy failing source
entropy_source_fail:"data_files/entropy_seed"
-Entropy threshold #1
+Entropy threshold: 16=2*8
entropy_threshold:16:2:8
-Entropy threshold #2
+Entropy threshold: 32=1*32
entropy_threshold:32:1:32
-Entropy threshold #3
+Entropy threshold: 0* never reaches the threshold
entropy_threshold:16:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
-Entropy threshold #4
+Entropy threshold: 1024 never reached
entropy_threshold:1024:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+Entropy calls: no strong
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_WEAK:MBEDTLS_ENTROPY_SOURCE_WEAK:1:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE
+
+Entropy calls: 1 strong, 1*BLOCK_SIZE
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:MBEDTLS_ENTROPY_BLOCK_SIZE:1
+
+Entropy calls: 1 strong, 2*(BLOCK_SIZE/2)
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:2
+
+Entropy calls: 1 strong, BLOCK_SIZE*1
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:1:MBEDTLS_ENTROPY_BLOCK_SIZE
+
+Entropy calls: 1 strong, 2*BLOCK_SIZE to reach threshold
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:MBEDTLS_ENTROPY_BLOCK_SIZE+1:MBEDTLS_ENTROPY_BLOCK_SIZE:2
+
+Entropy calls: 2 strong, BLOCK_SIZE/2 each
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:2
+
Check NV seed standard IO
entropy_nv_seed_std_io:
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 0d86ead..9f10a90 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -3,10 +3,19 @@
#include "mbedtls/entropy_poll.h"
#include "string.h"
-/*
- * Number of calls made to entropy_dummy_source()
- */
-static size_t entropy_dummy_calls;
+typedef enum
+{
+ DUMMY_CONSTANT_LENGTH, /* Output context->length bytes */
+ DUMMY_REQUESTED_LENGTH, /* Output whatever length was requested */
+ DUMMY_FAIL, /* Return an error code */
+} entropy_dummy_instruction;
+
+typedef struct
+{
+ entropy_dummy_instruction instruction;
+ size_t length; /* Length to return for DUMMY_CONSTANT_LENGTH */
+ size_t calls; /* Incremented at each call */
+} entropy_dummy_context;
/*
* Dummy entropy source
@@ -14,29 +23,28 @@
* If data is NULL, write exactly the requested length.
* Otherwise, write the length indicated by data or error if negative
*/
-static int entropy_dummy_source( void *data, unsigned char *output,
+static int entropy_dummy_source( void *arg, unsigned char *output,
size_t len, size_t *olen )
{
- entropy_dummy_calls++;
+ entropy_dummy_context *context = arg;
+ ++context->calls;
- if( data == NULL )
- *olen = len;
- else
+ switch( context->instruction )
{
- int *d = (int *) data;
-
- if( *d < 0 )
+ case DUMMY_CONSTANT_LENGTH:
+ *olen = context->length;
+ break;
+ case DUMMY_REQUESTED_LENGTH:
+ *olen = len;
+ break;
+ case DUMMY_FAIL:
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
- else
- *olen = *d;
}
memset( output, 0x2a, *olen );
-
return( 0 );
}
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
/*
* Ability to clear entropy sources to allow testing with just predefined
* entropy sources. This function or tests depending on it might break if there
@@ -48,11 +56,12 @@
* This might break memory checks in the future if sources need 'free-ing' then
* as well.
*/
-void entropy_clear_sources( mbedtls_entropy_context *ctx )
+static void entropy_clear_sources( mbedtls_entropy_context *ctx )
{
ctx->source_count = 0;
}
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
/*
* NV seed read/write functions that use a buffer instead of a file
*/
@@ -140,10 +149,27 @@
/* END_CASE */
/* BEGIN_CASE */
+void entropy_no_sources( )
+{
+ mbedtls_entropy_context ctx;
+ unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+ mbedtls_entropy_init( &ctx );
+ entropy_clear_sources( &ctx );
+ TEST_EQUAL( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ),
+ MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+exit:
+ mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void entropy_too_many_sources( )
{
mbedtls_entropy_context ctx;
size_t i;
+ entropy_dummy_context dummy = {DUMMY_REQUESTED_LENGTH, 0, 0};
mbedtls_entropy_init( &ctx );
@@ -152,10 +178,10 @@
* since we don't know how many sources were automatically added.
*/
for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ )
- (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
+ (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, &dummy,
16, MBEDTLS_ENTROPY_SOURCE_WEAK );
- TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
+ TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, &dummy,
16, MBEDTLS_ENTROPY_SOURCE_WEAK )
== MBEDTLS_ERR_ENTROPY_MAX_SOURCES );
@@ -197,13 +223,13 @@
void entropy_source_fail( char * path )
{
mbedtls_entropy_context ctx;
- int fail = -1;
unsigned char buf[16];
+ entropy_dummy_context dummy = {DUMMY_FAIL, 0, 0};
mbedtls_entropy_init( &ctx );
TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
- &fail, 16,
+ &dummy, 16,
MBEDTLS_ENTROPY_SOURCE_WEAK )
== 0 );
@@ -225,30 +251,87 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
+/* BEGIN_CASE */
void entropy_threshold( int threshold, int chunk_size, int result )
{
mbedtls_entropy_context ctx;
+ entropy_dummy_context strong =
+ {DUMMY_CONSTANT_LENGTH, MBEDTLS_ENTROPY_BLOCK_SIZE, 0};
+ entropy_dummy_context weak = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
int ret;
mbedtls_entropy_init( &ctx );
+ entropy_clear_sources( &ctx );
+ /* Set strong source that reaches its threshold immediately and
+ * a weak source whose threshold is a test parameter. */
TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
- &chunk_size, threshold,
+ &strong, 1,
+ MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
+ TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+ &weak, threshold,
MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 );
- entropy_dummy_calls = 0;
ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
if( result >= 0 )
{
TEST_ASSERT( ret == 0 );
#if defined(MBEDTLS_ENTROPY_NV_SEED)
- // Two times as much calls due to the NV seed update
+ /* If the NV seed functionality is enabled, there are two entropy
+ * updates: before and after updating the NV seed. */
result *= 2;
#endif
- TEST_ASSERT( entropy_dummy_calls == (size_t) result );
+ TEST_ASSERT( weak.calls == (size_t) result );
+ }
+ else
+ {
+ TEST_ASSERT( ret == result );
+ }
+
+exit:
+ mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_calls( int strength1, int strength2,
+ int threshold, int chunk_size,
+ int result )
+{
+ /*
+ * if result >= 0: result = expected number of calls to source 1
+ * if result < 0: result = expected return code from mbedtls_entropy_func()
+ */
+
+ mbedtls_entropy_context ctx;
+ entropy_dummy_context dummy1 = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
+ entropy_dummy_context dummy2 = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
+ unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
+ int ret;
+
+ mbedtls_entropy_init( &ctx );
+ entropy_clear_sources( &ctx );
+
+ TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+ &dummy1, threshold,
+ strength1 ) == 0 );
+ TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+ &dummy2, threshold,
+ strength2 ) == 0 );
+
+ ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
+
+ if( result >= 0 )
+ {
+ TEST_ASSERT( ret == 0 );
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ /* If the NV seed functionality is enabled, there are two entropy
+ * updates: before and after updating the NV seed. */
+ result *= 2;
+#endif
+ TEST_ASSERT( dummy1.calls == (size_t) result );
}
else
{
diff --git a/tests/suites/test_suite_memory_buffer_alloc.data b/tests/suites/test_suite_memory_buffer_alloc.data
index d59f113..d780fd4 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.data
+++ b/tests/suites/test_suite_memory_buffer_alloc.data
@@ -16,8 +16,8 @@
Memory buffer alloc - Out of Memory test
memory_buffer_alloc_oom_test:
-Memory buffer small buffer
-memory_buffer_small_buffer:
+Memory buffer: heap too small (header verification should fail)
+memory_buffer_heap_too_small:
-Memory buffer underalloc
+Memory buffer: attempt to allocate SIZE_MAX
memory_buffer_underalloc:
diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function
index bc03436..cc884c2 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.function
+++ b/tests/suites/test_suite_memory_buffer_alloc.function
@@ -29,7 +29,7 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes,
int d_bytes, int free_a, int free_b,
int free_c, int free_d, int e_bytes,
@@ -39,8 +39,11 @@
unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_d = NULL,
*ptr_e = NULL, *ptr_f = NULL;
+#if defined(MBEDTLS_MEMORY_DEBUG)
size_t reported_blocks;
- size_t allocated_bytes = 0, reported_bytes;
+ size_t reported_bytes;
+#endif
+ size_t allocated_bytes = 0;
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
@@ -78,8 +81,10 @@
allocated_bytes += d_bytes * sizeof(char);
}
+#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
if( free_a )
{
@@ -117,8 +122,10 @@
allocated_bytes -= d_bytes * sizeof(char);
}
+#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
if( e_bytes > 0 )
{
@@ -178,8 +185,10 @@
ptr_f = NULL;
}
+#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == 0 );
+#endif
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
@@ -188,12 +197,14 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
void memory_buffer_alloc_oom_test( )
{
unsigned char buf[1024];
unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL;
+#if defined(MBEDTLS_MEMORY_DEBUG)
size_t reported_blocks, reported_bytes;
+#endif
(void)ptr_c;
@@ -210,8 +221,10 @@
ptr_c = mbedtls_calloc( 431, sizeof(char) );
TEST_ASSERT( ptr_c == NULL );
+#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes >= 864 && reported_bytes <= sizeof(buf) );
+#endif
mbedtls_free( ptr_a );
ptr_a = NULL;
@@ -221,8 +234,10 @@
ptr_b = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
+#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == 0 );
+#endif
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
@@ -231,17 +246,20 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
-void memory_buffer_small_buffer( )
+/* BEGIN_CASE */
+void memory_buffer_heap_too_small( )
{
unsigned char buf[1];
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+ /* With MBEDTLS_MEMORY_DEBUG enabled, this prints a message
+ * "FATAL: verification of first header failed".
+ */
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() != 0 );
}
/* END_CASE */
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
void memory_buffer_underalloc( )
{
unsigned char buf[100];