From 4775cd3827f084a78cbbcb5ff3fccbb680747ab8 Mon Sep 17 00:00:00 2001 From: Andres Amaya Garcia Date: Fri, 25 Aug 2017 10:46:38 +0100 Subject: [PATCH] Parse top-level OCSP ResponseData Populate the function x509_ocsp_get_response_data() with code that parses the following ASN.1 structure: ResponseData ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, responderID ResponderID, producedAt GeneralizedTime, responses SEQUENCE OF SingleResponse, responseExtensions [1] EXPLICIT Extensions OPTIONAL } x509_ocsp_get_response_data() will parse the top-level SEQUENCE and the two EXPLICIT tags. It delegates the parsing of the individual subcomponents to x509_ocsp_get_version(), x509_ocsp_get_responder_id(), x509_ocsp_get_generalized_time(), x509_ocsp_get_responses() and x509_ocsp_get_extensions(). --- include/mbedtls/x509_ocsp.h | 37 +++++++++--- library/x509_ocsp.c | 116 ++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/x509_ocsp.h b/include/mbedtls/x509_ocsp.h index 67e934f5b1..0861a30763 100644 --- a/include/mbedtls/x509_ocsp.h +++ b/include/mbedtls/x509_ocsp.h @@ -47,6 +47,8 @@ #define MBEDTLS_X509_OCSP_RESPONSE_STATUS_SIG_REQUIRED 5 #define MBEDTLS_X509_OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 +#define MBEDTLS_X509_OCSP_VERSION_1 0 + /** * \addtogroup x509_module * \{ @@ -61,24 +63,41 @@ extern "C" { * \{ */ +/** + * Container for an X.509 OCSP ResponderID. + */ +typedef struct mbedtls_x509_ocsp_responder_id { +} mbedtls_x509_ocsp_responder_id; + +/** + * Container for an X.509 OCSP SingleResponse. + */ +typedef struct mbedtls_x509_ocsp_single_response { +} mbedtls_x509_ocsp_single_response; + /** * Container for an X.509 OCSP response. */ typedef struct mbedtls_x509_ocsp_response { - mbedtls_x509_buf raw; /**< The raw response data (DER). */ + mbedtls_x509_buf raw; /**< The raw response data (DER). */ - mbedtls_x509_buf resp_type; /**< The type of response e.g. OCSP or BASIC */ + uint8_t resp_status; /**< The OCSP response status */ - uint8_t resp_status; /**< The OCSP response status */ + mbedtls_x509_buf resp_type; /**< The type of response e.g. OCSP or BASIC */ - mbedtls_x509_buf sig; /**< Signature computed on the hash of the ResponseData */ + int version; /**< The OCSP response version. (0=v1) */ + mbedtls_x509_ocsp_responder_id responder_id; /**< Internal representation of the ResponderID */ + mbedtls_x509_time produced_at; /**< The time at which the OCSP responder signed this response */ + mbedtls_x509_ocsp_single_response single_resp; /**< List of SingleResponse containers each containing the revocation status of a certificate */ - mbedtls_x509_buf sig_oid; /**< Signature algorithm OID, e.g. sha1RSA */ - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + mbedtls_x509_buf sig; /**< Signature computed on the hash of the ResponseData */ - mbedtls_x509_crt certs; /**< List of certificates included in the OCSP response */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm OID, e.g. sha1RSA */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + mbedtls_x509_crt certs; /**< List of certificates included in the OCSP response */ } mbedtls_x509_ocsp_response; /** diff --git a/library/x509_ocsp.c b/library/x509_ocsp.c index dc2ed64bc9..f9be67b82c 100644 --- a/library/x509_ocsp.c +++ b/library/x509_ocsp.c @@ -44,6 +44,11 @@ #include #include +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + void mbedtls_x509_ocsp_response_init( mbedtls_x509_ocsp_response *resp ) { } @@ -113,9 +118,120 @@ static int x509_ocsp_get_response_type( unsigned char **p, return( 0 ); } +static int x509_ocsp_get_extensions( unsigned char **p, + const unsigned char *end ) +{ + return( 0 ); +} + +static int x509_ocsp_get_response_version( unsigned char **p, + const unsigned char *end, + int *version ) +{ + return( 0 ); +} + +static int x509_ocsp_get_responder_id( unsigned char **p, + const unsigned char *end, + mbedtls_x509_ocsp_responder_id *responder_id ) +{ + return( 0 ); +} + +static int x509_ocsp_get_generalized_time( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *t ) +{ + return( 0 ); +} + +static int x509_ocsp_get_responses( unsigned char **p, + const unsigned char *end, + mbedtls_x509_ocsp_single_response *single_resp ) +{ + return( 0 ); +} + static int x509_ocsp_get_response_data( mbedtls_x509_ocsp_response *resp, unsigned char **p, const unsigned char *end ) { + int ret; + size_t len; + + /* + * ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = *p + len; + + /* Get the subcomponent [0] EXPLICIT ... DEFAULT v1 */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + /* + * Note that DEFAULT means that the version might not be present, in + * which case the value defaults to v1 + */ + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + resp->version = MBEDTLS_X509_OCSP_VERSION_1; + else + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + /* Parse version */ + else if( ( ret = x509_ocsp_get_response_version( p, *p + len, + &resp->version ) ) != 0 ) + { + return( ret ); + } + + /* Parse responderID */ + if( ( ret = x509_ocsp_get_responder_id( p, end, + &resp->responder_id ) ) != 0 ) + { + return( ret ); + } + + /* Parse producedAt */ + if( ( ret = x509_ocsp_get_generalized_time( p, end, + &resp->produced_at ) ) != 0 ) + { + return( ret ); + } + + /* Parse responses */ + if( ( ret = x509_ocsp_get_responses( p, end, &resp->single_resp ) ) != 0 ) + return( ret ); + + /* responseExtensions is optional, so find out if there is more data */ + if( *p == end ) + return( 0 ); + + /* Get the [1] EXPLICIT tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1 ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + /* Parse responseExtensions */ + if( ( ret = x509_ocsp_get_extensions( p, *p + len ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + return( 0 ); }