diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h index d92944506f..b927e8d108 100644 --- a/include/mbedtls/x509.h +++ b/include/mbedtls/x509.h @@ -71,6 +71,7 @@ #define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ #define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ #define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_OCSP_RESPONSE_VERIFY_FAILED -0x2710 /**< OCSP response verification failed, e.g. signature check failed. */ #define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ #define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ diff --git a/include/mbedtls/x509_ocsp.h b/include/mbedtls/x509_ocsp.h index 9d0b7d1de7..fe0e9d91dd 100644 --- a/include/mbedtls/x509_ocsp.h +++ b/include/mbedtls/x509_ocsp.h @@ -53,6 +53,15 @@ #define MBEDTLS_X509_OCSP_CERT_STATUS_REVOKED 1 #define MBEDTLS_X509_OCSP_CERT_STATUS_UNKNOWN 2 +#define MBEDTLS_X509_BADOCSP_RESPONSE_FUTURE 0x1 +#define MBEDTLS_X509_BADOCSP_RESPONSE_BAD_RESPONSE_STATUS 0x2 +#define MBEDTLS_X509_BADOCSP_RESPONSE_ISSUER_NOT_TRUSTED 0x4 +#define MBEDTLS_X509_BADOCSP_RESPONSE_NOT_TRUSTED 0x8 +#define MBEDTLS_X509_BADOCSP_RESPONSE_INCOMPLETE 0x10 +#define MBEDTLS_X509_BADOCSP_RESPONSE_EXPIRED 0x20 +#define MBEDTLS_X509_BADOCSP_RESPONSE_REVOKED_CERT 0x40 +#define MBEDTLS_X509_BADOCSP_RESPONSE_UNKNOWN_CERT 0x80 + #if defined(MBEDTLS_X509_OCSP_PARSE_C) /** * \addtogroup x509_module @@ -171,6 +180,26 @@ int mbedtls_x509_ocsp_response_parse( mbedtls_x509_ocsp_response *resp, const unsigned char *buf, size_t buflen ); +/** + * \brief Verify an OCSP response + * + * \param resp parsed OCSP response + * \param req_chain chain of certificates whose status is to be verified + * \param chain chain of untrusted certificates. This will be searched + * to find the OCSP response signer and the parent of the + * signer when needed + * \param trust_ca chain of certificates fully trusted certificates + * \param flags the result of the OCSP response verification + * + * \return 0 if the OCSP response was verified successfully, otherwise + * a specific X.509 error + */ +int mbedtls_x509_ocsp_verify_response( mbedtls_x509_ocsp_response *resp, + mbedtls_x509_crt *req_chain, + mbedtls_x509_crt *chain, + mbedtls_x509_crt *trust_ca, + uint32_t *flags ); + #if defined(MBEDTLS_FS_IO) /** * \brief Load and parse a single OCSP response from a file encoded in diff --git a/library/x509_ocsp.c b/library/x509_ocsp.c index 29bc75693b..a566ed9aee 100644 --- a/library/x509_ocsp.c +++ b/library/x509_ocsp.c @@ -1173,6 +1173,67 @@ int mbedtls_x509_ocsp_response_parse( mbedtls_x509_ocsp_response *resp, return( 0 ); } +static int x509_ocsp_verify_response_status( mbedtls_x509_ocsp_response *resp, + uint32_t *flags ) +{ + switch( resp->resp_status ) + { + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_SUCCESSFUL: + return( 0 ); + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_MALFORMED_REQ: + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_INTERNAL_ERR: + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_TRY_LATER: + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_SIG_REQUIRED: + case MBEDTLS_X509_OCSP_RESPONSE_STATUS_UNAUTHORIZED: + *flags |= MBEDTLS_X509_BADOCSP_RESPONSE_BAD_RESPONSE_STATUS; + return( MBEDTLS_ERR_X509_OCSP_RESPONSE_VERIFY_FAILED ); + default: + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } +} + + +/* + * TODO: + * - We cannot accept a tolerance value for timestamps + */ +int mbedtls_x509_ocsp_verify_response( mbedtls_x509_ocsp_response *resp, + mbedtls_x509_crt *req_chain, + mbedtls_x509_crt *chain, + mbedtls_x509_crt *trust_ca, + uint32_t *flags ) +{ + int ret; + + *flags = 0; + + if( resp == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Check if the response has a definite status. If there is a failure here + * it means that either we did not get a definitive response or the input + * data was invalid. In both cases we cannot continue verifying the + * response + */ + if( ( ret = x509_ocsp_verify_response_status( resp, flags ) ) != 0 ) + return( ret ); + + /* + * Check if producedAt is in the past + * + * TODO: We might want to check this against some threshold + */ + if( mbedtls_x509_time_is_future( &resp->produced_at ) != 0 ) + *flags |= MBEDTLS_X509_BADOCSP_RESPONSE_FUTURE; + + /* Fail if something does not check out */ + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_OCSP_RESPONSE_VERIFY_FAILED ); + + return( 0 ); +} + static int x509_ocsp_response_status_info( char *buf, size_t size, uint8_t resp_status ) {