Parse sequence of SingleResponse(s) in OCSP

Populate the function x509_ocsp_get_responses() that parses the
SEQUENCE OF tag in a BasicOCSPResponse. The function also calls its
helper function x509_ocsp_get_single_response() for each of the
SingleResponse(s) contained. Note that for each SingleResponse,
x509_ocsp_get_responses() must allocate a new internal struct
mbedtls_x509_ocsp_single_response where the parsed data will be
stored.

This change also populates the mbedtls_x509_ocsp_single_response
with the necessary values as specified by RFC 6960 Section 4.1.1.
This commit is contained in:
Andres Amaya Garcia
2017-08-25 11:42:50 +01:00
committed by Andres Amaya Garcia
parent 2a135bb259
commit eb106496f5
2 changed files with 70 additions and 0 deletions

View File

@@ -81,6 +81,23 @@ typedef struct mbedtls_x509_ocsp_responder_id {
* Container for an X.509 OCSP SingleResponse.
*/
typedef struct mbedtls_x509_ocsp_single_response {
mbedtls_x509_buf md_oid; /**< Hash algorithm used to generate issuerHashName and issuesKeyHash */
mbedtls_md_type_t md_alg; /**< Internal representation of the MD algorithm of the hash algorithm, e.g. MBEDTLS_MD_SHA256 */
mbedtls_x509_buf issuer_name_hash; /**< Hash of the issues's distinduished name (DN) */
mbedtls_x509_buf issues_key_hash; /**< Hash of issuer's public key */
mbedtls_x509_buf serial; /**< The serial of the certificate that this SingleResponse corresponds to */
uint8_t cert_status; /**< The revocation status of the certificate with CertID, e.g. good, revoked, unknown */
uint8_t revocation_reason; /**< Optional value that identifies the reason for the certificate revocation, e.g. keyCompromise, cACompromise, etc */
int has_revocation_reason; /**< Whether the revocationReason value is present in the OCSP resposne */
mbedtls_x509_time revocation_time; /**< The time at which the certificate was revoked or placed on hold */
mbedtls_x509_time this_update; /**< The most recent time at which the status is known to the responder to have been correct */
mbedtls_x509_time next_update; /**< The time at or before which newer information will be available about the status of the certificate */
int has_next_update; /**< Whether the nextUpdate value is present in the OCSP response */
struct mbedtls_x509_ocsp_single_response *next; /**< Next SingleResponse in the list */
} mbedtls_x509_ocsp_single_response;
/**

View File

@@ -251,10 +251,63 @@ static int x509_ocsp_get_generalized_time( unsigned char **p,
return( 0 );
}
static int x509_ocsp_get_single_response( unsigned char **p,
const unsigned char *end,
mbedtls_x509_ocsp_single_response *cur )
{
return( 0 );
}
static int x509_ocsp_get_responses( unsigned char **p,
const unsigned char *end,
mbedtls_x509_ocsp_single_response *single_resp )
{
int ret;
size_t len;
mbedtls_x509_ocsp_single_response *cur = single_resp;
/*
* responses SEQUENCE OF SingleResponse
*
* Note: the standard allows an OCSPResponse that has no responses
*/
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;
while( *p < end )
{
/* Allocate space for the next SingleResponse if necessary */
if( cur->md_oid.p != NULL )
{
/*
* This check prevents errors when populating an already used
* mbedtls_x509_ocsp_single_response
*/
if( cur->next != NULL )
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
cur->next = mbedtls_calloc( 1,
sizeof( mbedtls_x509_ocsp_single_response ) );
if( cur->next == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
cur = cur->next;
}
/* Parse SingleResponse and populate cur */
if( ( ret = x509_ocsp_get_single_response( p, end, cur ) ) != 0 )
return( ret );
}
if( *p != end )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}