iPXE
Data Structures | Defines | Functions
ocsp.h File Reference

Online Certificate Status Protocol. More...

#include <stdarg.h>
#include <time.h>
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
#include <ipxe/refcnt.h>
#include <config/crypto.h>

Go to the source code of this file.

Data Structures

struct  ocsp_request
 An OCSP request. More...
struct  ocsp_responder
 An OCSP responder. More...
struct  ocsp_response
 An OCSP response. More...
struct  ocsp_check
 An OCSP check. More...

Defines

#define OCSP_ENABLED   0
#define OCSP_ALGORITHM_IDENTIFIER(...)
 OCSP algorithm identifier.
#define OCSP_STATUS_SUCCESSFUL   0x00
#define OCSP_STATUS_MALFORMED_REQUEST   0x01
#define OCSP_STATUS_INTERNAL_ERROR   0x02
#define OCSP_STATUS_TRY_LATER   0x03
#define OCSP_STATUS_SIG_REQUIRED   0x05
#define OCSP_STATUS_UNAUTHORIZED   0x06

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static struct ocsp_checkocsp_get (struct ocsp_check *ocsp)
 Get reference to OCSP check.
static void ocsp_put (struct ocsp_check *ocsp)
 Drop reference to OCSP check.
static int ocsp_required (struct x509_certificate *cert)
 Check if X.509 certificate requires an OCSP check.
int ocsp_check (struct x509_certificate *cert, struct x509_certificate *issuer, struct ocsp_check **ocsp)
 Create OCSP check.
int ocsp_response (struct ocsp_check *ocsp, const void *data, size_t len)
 Receive OCSP response.
int ocsp_validate (struct ocsp_check *check, time_t time)
 Validate OCSP response.

Detailed Description

Online Certificate Status Protocol.

Definition in file ocsp.h.


Define Documentation

#define OCSP_ENABLED   0

Definition at line 23 of file ocsp.h.

Referenced by ocsp_required().

#define OCSP_ALGORITHM_IDENTIFIER (   ...)
Value:
ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__,            \
        ASN1_NULL, 0x00

OCSP algorithm identifier.

Definition at line 27 of file ocsp.h.

#define OCSP_STATUS_SUCCESSFUL   0x00

Definition at line 32 of file ocsp.h.

Referenced by ocsp_parse_response_status().

#define OCSP_STATUS_MALFORMED_REQUEST   0x01

Definition at line 33 of file ocsp.h.

#define OCSP_STATUS_INTERNAL_ERROR   0x02

Definition at line 34 of file ocsp.h.

#define OCSP_STATUS_TRY_LATER   0x03

Definition at line 35 of file ocsp.h.

#define OCSP_STATUS_SIG_REQUIRED   0x05

Definition at line 36 of file ocsp.h.

#define OCSP_STATUS_UNAUTHORIZED   0x06

Definition at line 37 of file ocsp.h.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static struct ocsp_check* ocsp_get ( struct ocsp_check ocsp) [static, read]

Get reference to OCSP check.

Parameters:
ocspOCSP check
Return values:
ocspOCSP check

Definition at line 107 of file ocsp.h.

References ref_get.

                                     {
        ref_get ( &ocsp->refcnt );
        return ocsp;
}
static void ocsp_put ( struct ocsp_check ocsp) [inline, static]

Drop reference to OCSP check.

Parameters:
ocspOCSP check

Definition at line 118 of file ocsp.h.

References ref_put.

Referenced by ocsp_check(), ocsp_test_exec(), validator_free(), and validator_ocsp_validate().

                                     {
        ref_put ( &ocsp->refcnt );
}
static int ocsp_required ( struct x509_certificate cert) [inline, static]

Check if X.509 certificate requires an OCSP check.

Parameters:
certX.509 certificate
Return values:
ocsp_requiredAn OCSP check is required

Definition at line 128 of file ocsp.h.

References x509_extensions::auth_info, x509_certificate::extensions, x509_ocsp_responder::good, asn1_cursor::len, x509_authority_info_access::ocsp, OCSP_ENABLED, and x509_ocsp_responder::uri.

Referenced by validator_step(), and x509_validate().

                                                                  {

        /* An OCSP check is never required if OCSP checks are disabled */
        if ( ! OCSP_ENABLED )
                return 0;

        /* An OCSP check is required if an OCSP URI exists but the
         * OCSP status is not (yet) good.
         */
        return ( cert->extensions.auth_info.ocsp.uri.len &&
                 ( ! cert->extensions.auth_info.ocsp.good ) );
}
int ocsp_check ( struct x509_certificate cert,
struct x509_certificate issuer,
struct ocsp_check **  ocsp 
)

Create OCSP check.

Parameters:
certCertificate to check
issuerIssuing certificate
Return values:
ocspOCSP check
rcReturn status code

Definition at line 277 of file ocsp.c.

References assert, ENOMEM, NULL, ocsp_free(), ocsp_put(), ocsp_uri_string(), rc, ref_init, x509_get(), x509_is_valid(), and zalloc().

                                            {
        int rc;

        /* Sanity checks */
        assert ( cert != NULL );
        assert ( issuer != NULL );
        assert ( x509_is_valid ( issuer ) );

        /* Allocate and initialise check */
        *ocsp = zalloc ( sizeof ( **ocsp ) );
        if ( ! *ocsp ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &(*ocsp)->refcnt, ocsp_free );
        (*ocsp)->cert = x509_get ( cert );
        (*ocsp)->issuer = x509_get ( issuer );

        /* Build request */
        if ( ( rc = ocsp_request ( *ocsp ) ) != 0 )
                goto err_request;

        /* Build URI string */
        if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 )
                goto err_uri_string;

        return 0;

 err_uri_string:
 err_request:
        ocsp_put ( *ocsp );
 err_alloc:
        *ocsp = NULL;
        return rc;
}
int ocsp_response ( struct ocsp_check ocsp,
const void *  data,
size_t  len 
)

Receive OCSP response.

Parameters:
ocspOCSP check
dataResponse data
lenLength of response data
Return values:
rcReturn status code

Definition at line 784 of file ocsp.c.

References asn1_cursor::data, ocsp_response::data, ENOMEM, free, asn1_cursor::len, len, malloc(), memcpy(), NULL, ocsp_parse_response(), rc, ocsp_check::response, ocsp_response::signer, and x509_put().

                                                                            {
        struct ocsp_response *response = &ocsp->response;
        struct asn1_cursor cursor;
        int rc;

        /* Duplicate data */
        x509_put ( response->signer );
        response->signer = NULL;
        free ( response->data );
        response->data = malloc ( len );
        if ( ! response->data )
                return -ENOMEM;
        memcpy ( response->data, data, len );
        cursor.data = response->data;
        cursor.len = len;

        /* Parse response */
        if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 )
                return rc;

        return 0;
}
int ocsp_validate ( struct ocsp_check ocsp,
time_t  time 
)

Validate OCSP response.

Parameters:
ocspOCSP check
timeTime at which to validate response
Return values:
rcReturn status code

Definition at line 876 of file ocsp.c.

References assert, x509_extensions::auth_info, x509_extended_key_usage::bits, ocsp_check::cert, ocsp_response::data, DBGC, DBGC2, EACCES_NON_OCSP_SIGNING, EACCES_STALE, x509_extensions::ext_usage, x509_certificate::extensions, x509_ocsp_responder::good, ocsp_check::issuer, ocsp_response::next_update, NULL, x509_authority_info_access::ocsp, ocsp_check_signature(), rc, ocsp_check::response, ocsp_response::signer, strerror(), ocsp_response::this_update, TIMESTAMP_ERROR_MARGIN, x509_invalidate(), x509_name(), X509_OCSP_SIGNING, and x509_validate().

Referenced by validator_ocsp_validate().

                                                           {
        struct ocsp_response *response = &ocsp->response;
        struct x509_certificate *signer;
        int rc;

        /* Sanity checks */
        assert ( response->data != NULL );

        /* The response may include a signer certificate; if this is
         * not present then the response must have been signed
         * directly by the issuer.
         */
        signer = ( response->signer ? response->signer : ocsp->issuer );

        /* Validate signer, if applicable.  If the signer is not the
         * issuer, then it must be signed directly by the issuer.
         */
        if ( signer != ocsp->issuer ) {
                /* Forcibly invalidate the signer, since we need to
                 * ensure that it was signed by our issuer (and not
                 * some other issuer).  This prevents a sub-CA's OCSP
                 * certificate from fraudulently signing OCSP
                 * responses from the parent CA.
                 */
                x509_invalidate ( signer );
                if ( ( rc = x509_validate ( signer, ocsp->issuer, time,
                                            &ocsp_root ) ) != 0 ) {
                        DBGC ( ocsp, "OCSP %p \"%s\" could not validate ",
                               ocsp, x509_name ( ocsp->cert ) );
                        DBGC ( ocsp, "signer \"%s\": %s\n",
                               x509_name ( signer ), strerror ( rc ) );
                        return rc;
                }

                /* If signer is not the issuer, then it must have the
                 * extendedKeyUsage id-kp-OCSPSigning.
                 */
                if ( ! ( signer->extensions.ext_usage.bits &
                         X509_OCSP_SIGNING ) ) {
                        DBGC ( ocsp, "OCSP %p \"%s\" ",
                               ocsp, x509_name ( ocsp->cert ) );
                        DBGC ( ocsp, "signer \"%s\" is not an OCSP-signing "
                               "certificate\n", x509_name ( signer ) );
                        return -EACCES_NON_OCSP_SIGNING;
                }
        }

        /* Check OCSP response signature */
        if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 )
                return rc;

        /* Check OCSP response is valid at the specified time
         * (allowing for some margin of error).
         */
        if ( response->this_update > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at "
                       "time %lld)\n", ocsp, x509_name ( ocsp->cert ), time );
                return -EACCES_STALE;
        }
        if ( response->next_update < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time "
                       "%lld)\n", ocsp, x509_name ( ocsp->cert ), time );
                return -EACCES_STALE;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n",
                ocsp, x509_name ( ocsp->cert ), time );

        /* Mark certificate as passing OCSP verification */
        ocsp->cert->extensions.auth_info.ocsp.good = 1;

        /* Validate certificate against issuer */
        if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time,
                                    &ocsp_root ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: "
                       "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
                return rc;
        }
        DBGC ( ocsp, "OCSP %p \"%s\" successfully validated ",
               ocsp, x509_name ( ocsp->cert ) );
        DBGC ( ocsp, "using \"%s\"\n", x509_name ( signer ) );

        return 0;
}