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.
This commit is contained in:
Andres Amaya Garcia
2017-08-25 11:00:29 +01:00
committed by Andres Amaya Garcia
parent a86467b6b3
commit 4bbe7d548d
2 changed files with 81 additions and 0 deletions

View File

@@ -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;
/**

View File

@@ -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 );
}