From 4bbe7d548d7658a860c9772c54dd09ac3080c18c Mon Sep 17 00:00:00 2001 From: Andres Amaya Garcia Date: Fri, 25 Aug 2017 11:00:29 +0100 Subject: [PATCH] Parse ResponderID structure in OCSP response Populate the function x509_ocsp_get_responder_id() with code that parses the following X.509 structure: ResponderID ::= CHOICE { byName [1] Name, byKey [2] KeyHash } KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key (excluding the tag and length fields) Note that here the name is parsed by the helper function mbedtls_x509_get_name() and the KeyHash's bounds are checked but we do not ensure that the hash is of the correct length. --- include/mbedtls/x509_ocsp.h | 8 ++++ library/x509_ocsp.c | 73 +++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/include/mbedtls/x509_ocsp.h b/include/mbedtls/x509_ocsp.h index 0861a30763..f1fe2b7ab6 100644 --- a/include/mbedtls/x509_ocsp.h +++ b/include/mbedtls/x509_ocsp.h @@ -49,6 +49,9 @@ #define MBEDTLS_X509_OCSP_VERSION_1 0 +#define MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_NAME 1 +#define MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_KEY_HASH 2 + /** * \addtogroup x509_module * \{ @@ -67,6 +70,11 @@ extern "C" { * Container for an X.509 OCSP ResponderID. */ typedef struct mbedtls_x509_ocsp_responder_id { + int type; /**< Flag that indicates whether the ID is a X.509 Name or a KeyHash */ + union { + mbedtls_x509_name name; /**< Internal representation of the ResponderID as an X.509 Name */ + mbedtls_x509_buf key; /**< The ResponderID as the SHA1 hash of the responder's public key */ + } id; /**< Internal representation of the ResponderID, which is an X.509 CHOICE component */ } mbedtls_x509_ocsp_responder_id; /** diff --git a/library/x509_ocsp.c b/library/x509_ocsp.c index e4a783fbb8..cfdd67dfe6 100644 --- a/library/x509_ocsp.c +++ b/library/x509_ocsp.c @@ -146,6 +146,79 @@ static int x509_ocsp_get_responder_id( unsigned char **p, const unsigned char *end, mbedtls_x509_ocsp_responder_id *responder_id ) { + int ret; + size_t len; + unsigned char tag; + unsigned char base_tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED; + + /* + * RespoderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + */ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + ( *p )++; + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + end = *p + len; + + if( tag == ( base_tag | MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_NAME ) ) + { + /* + * mbedtls_x509_get_name() cannot handle the following ASN1 + * constructs at the beginning of the Name, so we must remove it + * manually + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = mbedtls_x509_get_name( p, end, + &responder_id->id.name ) ) != 0 ) + { + return( ret ); + } + + responder_id->type = MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_NAME; + } + else if( tag == ( base_tag | + MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_KEY_HASH ) ) + { + /* KeyHash ::= OCTET STRING */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + responder_id->type = MBEDTLS_X509_OCSP_RESPONDER_ID_TYPE_KEY_HASH; + responder_id->id.key.len = len; + responder_id->id.key.p = *p; + responder_id->id.key.tag = MBEDTLS_ASN1_OCTET_STRING; + + *p = *p + len; + } + else + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + return( 0 ); }