Provide direct way of setting up a CRT frame from legacy CRT struct

Previously, `mbedtls_x509_crt_cache_provide_frame()` provided the requested
CRT frame by always parsing the raw data underlying the CRT. That's inefficient
in legacy mode, where the CRTs fields are permanently accessible through the
legacy `mbedtls_x509_crt` structure.

This commit modifies `mbedtls_x509_crt_cache_provide_frame()` in legacy mode
(that is, !MBEDTLS_X509_ON_DEMAND_PARSING) to setup the CRT frame by copying
fields from the legacy CRT structure.
This commit is contained in:
Hanno Becker 2019-03-04 11:52:23 +00:00
parent bfabd1dfae
commit ea32d8ba2a

View file

@ -90,6 +90,7 @@ static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
mbedtls_x509_sequence *ext_key_usage );
static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame );
int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
{
mbedtls_x509_crt_cache *cache = crt->cache;
@ -100,9 +101,57 @@ int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
cache->frame = frame;
#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
/* This would work with !MBEDTLS_X509_ON_DEMAND_PARSING, too,
* but is inefficient compared to copying the respective fields
* from the legacy mbedtls_x509_crt. */
return( x509_crt_parse_frame( crt->raw.p,
crt->raw.p + crt->raw.len,
frame ) );
#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
/* Make sure all extension related fields are properly initialized. */
frame->ca_istrue = 0;
frame->max_pathlen = 0;
frame->ext_types = 0;
frame->version = crt->version;
frame->sig_md = crt->sig_md;
frame->sig_pk = crt->sig_pk;
frame->valid_from = crt->valid_from;
frame->valid_to = crt->valid_to;
frame->raw.p = crt->raw.p;
frame->raw.len = crt->raw.len;
frame->tbs.p = crt->tbs.p;
frame->tbs.len = crt->tbs.len;
frame->serial.p = crt->serial.p;
frame->serial.len = crt->serial.len;
frame->pubkey_raw.p = crt->pk_raw.p;
frame->pubkey_raw.len = crt->pk_raw.len;
frame->issuer_raw = crt->issuer_raw_no_hdr;
frame->subject_raw = crt->subject_raw_no_hdr;
frame->issuer_id.p = crt->issuer_id.p;
frame->issuer_id.len = crt->issuer_id.len;
frame->subject_id.p = crt->subject_id.p;
frame->subject_id.len = crt->subject_id.len;
frame->sig.p = crt->sig.p;
frame->sig.len = crt->sig.len;
frame->v3_ext.p = crt->v3_ext.p;
frame->v3_ext.len = crt->v3_ext.len;
frame->subject_alt_raw = crt->subject_alt_raw;
frame->ext_key_usage_raw = crt->ext_key_usage_raw;
frame->issuer_raw_with_hdr.p = crt->issuer_raw.p;
frame->issuer_raw_with_hdr.len = crt->issuer_raw.len;
frame->subject_raw_with_hdr.p = crt->subject_raw.p;
frame->subject_raw_with_hdr.len = crt->subject_raw.len;
/* The legacy CRT structure doesn't explicitly contain
* the `AlgorithmIdentifier` bounds; however, those can
* be inferred from the surrounding (mandatory) `SerialNumber`
* and `Issuer` fields. */
frame->sig_alg.p = crt->serial.p + crt->serial.len;
frame->sig_alg.len = crt->issuer_raw.p - frame->sig_alg.p;
return( x509_crt_frame_parse_ext( frame ) );
#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
}
int mbedtls_x509_crt_cache_provide_pk( mbedtls_x509_crt const *crt )
@ -1376,24 +1425,30 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
crt->cache = cache;
x509_crt_cache_init( cache );
#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
ret = mbedtls_x509_crt_cache_provide_frame( crt );
if( ret != 0 )
goto exit;
frame = mbedtls_x509_crt_cache_get_frame( crt->cache );
/* Currently, we accept DER encoded CRTs with trailing garbage
* and promise to not account for the garbage in the `raw` field.
*
* Note that this means that `crt->raw.len` is not necessarily the
* full size of the heap buffer allocated at `crt->raw.p` in case
* of copy-mode, but this is not a problem: freeing the buffer doesn't
* need the size, and the garbage data doesn't need zeroization. */
crt->raw.len = frame->raw.len;
#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
cache->pk_raw = frame->pubkey_raw;
frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
if( frame == NULL )
{
ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
goto exit;
}
cache->frame = frame;
ret = x509_crt_parse_frame( crt->raw.p,
crt->raw.p + crt->raw.len,
frame );
if( ret != 0 )
goto exit;
#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
/* Copy frame to legacy CRT structure -- that's inefficient, but if
* memory matters, the new CRT structure should be used anyway. */
crt->tbs.p = frame->tbs.p;
@ -1484,6 +1539,17 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
goto exit;
#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
/* Currently, we accept DER encoded CRTs with trailing garbage
* and promise to not account for the garbage in the `raw` field.
*
* Note that this means that `crt->raw.len` is not necessarily the
* full size of the heap buffer allocated at `crt->raw.p` in case
* of copy-mode, but this is not a problem: freeing the buffer doesn't
* need the size, and the garbage data doesn't need zeroization. */
crt->raw.len = frame->raw.len;
cache->pk_raw = frame->pubkey_raw;
/* Free the frame before parsing the public key to
* keep peak RAM usage low. This is slightly inefficient
* because the frame will need to be parsed again on the