Squashed commit upgrading to mbedtls-2.22.0
Squash merging branch import/mbedtls-2.22.0
5cab03377186 ("mk/clang.mk: define libgcc$(sm)")
3607a5386a72 ("core: mbedtls: enable MBEDTLS_ECDH_LEGACY_CONTEXT")
896c8845bbda ("mbedtls: remove file md_wrap.c from build")
400b2af54fa0 ("libmbedtls: mbedtls_mpi_exp_mod(): optimize mempool usage")
777827c7af3d ("libmbedtls: mbedtls_mpi_exp_mod(): reduce stack usage")
549e4600678e ("libmbedtls: preserve mempool usage on reinit")
02d636083fe2 ("libmbedtls: mbedtls_mpi_exp_mod() initialize W")
d2ac2b3c92bf ("libmbedtls: fix no CRT issue")
f550879d5be2 ("libmbedtls: add interfaces in mbedtls for context memory operation")
219173d807ce ("libmedtls: mpi_miller_rabin: increase count limit")
7930b0b6b5e4 ("libmbedtls: add mbedtls_mpi_init_mempool()")
78af9fdc120f ("libmbedtls: make mbedtls_mpi_mont*() available")
8f7357271cc2 ("libmbedtls: refine mbedtls license header")
c5993878881f ("mbedtls: configure mbedtls to reach for config")
6f9c587783af ("mbedtls: remove default include/mbedtls/config.h")
3d3bd3b12752 ("Import mbedtls-2.22.0")
Signed-off-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/library/asn1parse.c b/lib/libmbedtls/mbedtls/library/asn1parse.c
index 3ad77a1..cb15b97 100644
--- a/lib/libmbedtls/mbedtls/library/asn1parse.c
+++ b/lib/libmbedtls/mbedtls/library/asn1parse.c
@@ -29,6 +29,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -124,7 +125,7 @@
const unsigned char *end,
int *val )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
@@ -139,21 +140,41 @@
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;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
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 );
- if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+ /*
+ * 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. */
+ if( ( **p & 0x80 ) != 0 )
+ return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+ /* Skip leading zeros. */
+ while( len > 0 && **p == 0 )
+ {
+ ++( *p );
+ --len;
+ }
+
+ /* Reject integers that don't fit in an int. This code assumes that
+ * the int type has no padding bit. */
+ if( len > sizeof( int ) )
+ return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+ if( len == sizeof( int ) && ( **p & 0x80 ) != 0 )
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
*val = 0;
-
while( len-- > 0 )
{
*val = ( *val << 8 ) | **p;
@@ -163,12 +184,26 @@
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,
mbedtls_mpi *X )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
@@ -185,7 +220,7 @@
int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Certificate type is a single byte bitstring */
if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
@@ -213,23 +248,124 @@
}
/*
+ * Traverse an ASN.1 "SEQUENCE OF <tag>"
+ * and call a callback for each entry found.
+ */
+int mbedtls_asn1_traverse_sequence_of(
+ unsigned char **p,
+ const unsigned char *end,
+ unsigned char tag_must_mask, unsigned char tag_must_val,
+ unsigned char tag_may_mask, unsigned char tag_may_val,
+ int (*cb)( void *ctx, int tag,
+ unsigned char *start, size_t len ),
+ void *ctx )
+{
+ int ret;
+ size_t len;
+
+ /* Get main sequence tag */
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( *p + len != end )
+ return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ unsigned char const tag = *(*p)++;
+
+ if( ( tag & tag_must_mask ) != tag_must_val )
+ return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+
+ if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 )
+ return( ret );
+
+ if( ( tag & tag_may_mask ) == tag_may_val )
+ {
+ if( cb != NULL )
+ {
+ ret = cb( ctx, tag, *p, len );
+ if( ret != 0 )
+ return( ret );
+ }
+ }
+
+ *p += len;
+ }
+
+ return( 0 );
+}
+
+/*
* Get a bit string without unused bits
*/
int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
return( ret );
- if( (*len)-- < 2 || *(*p)++ != 0 )
+ if( *len == 0 )
return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+ --( *len );
+
+ if( **p != 0 )
+ return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+ ++( *p );
return( 0 );
}
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq )
+{
+ while( seq != NULL )
+ {
+ mbedtls_asn1_sequence *next = seq->next;
+ mbedtls_platform_zeroize( seq, sizeof( *seq ) );
+ mbedtls_free( seq );
+ seq = next;
+ }
+}
+typedef struct
+{
+ int tag;
+ mbedtls_asn1_sequence *cur;
+} asn1_get_sequence_of_cb_ctx_t;
+
+static int asn1_get_sequence_of_cb( void *ctx,
+ int tag,
+ unsigned char *start,
+ size_t len )
+{
+ asn1_get_sequence_of_cb_ctx_t *cb_ctx =
+ (asn1_get_sequence_of_cb_ctx_t *) ctx;
+ mbedtls_asn1_sequence *cur =
+ cb_ctx->cur;
+
+ if( cur->buf.p != NULL )
+ {
+ cur->next =
+ mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ cur = cur->next;
+ }
+
+ cur->buf.p = start;
+ cur->buf.len = len;
+ cur->buf.tag = tag;
+
+ cb_ctx->cur = cur;
+ return( 0 );
+}
/*
* Parses and splits an ASN.1 "SEQUENCE OF <tag>"
@@ -239,56 +375,18 @@
mbedtls_asn1_sequence *cur,
int tag)
{
- int ret;
- size_t len;
- mbedtls_asn1_buf *buf;
-
- /* Get main sequence tag */
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
- return( ret );
-
- if( *p + len != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- buf = &(cur->buf);
- buf->tag = **p;
-
- if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
- return( ret );
-
- buf->p = *p;
- *p += buf->len;
-
- /* Allocate and assign next pointer */
- if( *p < end )
- {
- cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
- sizeof( mbedtls_asn1_sequence ) );
-
- if( cur->next == NULL )
- return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
- cur = cur->next;
- }
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if( *p != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
+ asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
+ memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
+ return( mbedtls_asn1_traverse_sequence_of(
+ p, end, 0xFF, tag, 0, 0,
+ asn1_get_sequence_of_cb, &cb_ctx ) );
}
int mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -332,7 +430,7 @@
const unsigned char *end,
mbedtls_asn1_buf *alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf params;
memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) );