iPXE
Data Structures | Defines | Enumerations | Functions
x509.h File Reference

X.509 certificates. More...

#include <stdint.h>
#include <stddef.h>
#include <time.h>
#include <ipxe/asn1.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>

Go to the source code of this file.

Data Structures

struct  x509_serial
 An X.509 serial number. More...
struct  x509_issuer
 An X.509 issuer. More...
struct  x509_time
 An X.509 time. More...
struct  x509_validity
 An X.509 certificate validity period. More...
struct  x509_public_key
 An X.509 certificate public key. More...
struct  x509_subject
 An X.509 certificate subject. More...
struct  x509_signature
 An X.509 certificate signature. More...
struct  x509_basic_constraints
 An X.509 certificate basic constraints set. More...
struct  x509_key_usage
 An X.509 certificate key usage. More...
struct  x509_extended_key_usage
 An X.509 certificate extended key usage. More...
struct  x509_ocsp_responder
 X.509 certificate OCSP responder. More...
struct  x509_authority_info_access
 X.509 certificate authority information access. More...
struct  x509_subject_alt_name
 X.509 certificate subject alternative name. More...
struct  x509_extensions
 An X.509 certificate extensions set. More...
struct  x509_link
 A link in an X.509 certificate chain. More...
struct  x509_chain
 An X.509 certificate chain. More...
struct  x509_certificate
 An X.509 certificate. More...
struct  x509_extension
 An X.509 extension. More...
struct  x509_key_purpose
 An X.509 key purpose. More...
struct  x509_access_method
 An X.509 access method. More...
struct  x509_root
 An X.509 root certificate store. More...

Defines

#define X509_PATH_LEN_UNLIMITED   -2U
 Unlimited path length.

Enumerations

enum  x509_key_usage_bits {
  X509_DIGITAL_SIGNATURE = 0x0080, X509_NON_REPUDIATION = 0x0040, X509_KEY_ENCIPHERMENT = 0x0020, X509_DATA_ENCIPHERMENT = 0x0010,
  X509_KEY_AGREEMENT = 0x0008, X509_KEY_CERT_SIGN = 0x0004, X509_CRL_SIGN = 0x0002, X509_ENCIPHER_ONLY = 0x0001,
  X509_DECIPHER_ONLY = 0x8000
}
 X.509 certificate key usage bits. More...
enum  x509_extended_key_usage_bits { X509_CODE_SIGNING = 0x0001, X509_OCSP_SIGNING = 0x0002 }
 X.509 certificate extended key usage bits. More...
enum  x509_general_name_types { X509_GENERAL_NAME_DNS = ASN1_IMPLICIT_TAG ( 2 ), X509_GENERAL_NAME_URI = ASN1_IMPLICIT_TAG ( 6 ), X509_GENERAL_NAME_IP = ASN1_IMPLICIT_TAG ( 7 ) }
 X.509 certificate general name types. More...
enum  x509_flags { X509_FL_VALIDATED = 0x0001, X509_FL_PERMANENT = 0x0002, X509_FL_EXPLICIT = 0x0004 }
 X.509 certificate flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static struct x509_certificatex509_get (struct x509_certificate *cert)
 Get reference to X.509 certificate.
static void x509_put (struct x509_certificate *cert)
 Drop reference to X.509 certificate.
static struct x509_chainx509_chain_get (struct x509_chain *chain)
 Get reference to X.509 certificate chain.
static void x509_chain_put (struct x509_chain *chain)
 Drop reference to X.509 certificate chain.
static struct x509_certificatex509_first (struct x509_chain *chain)
 Get first certificate in X.509 certificate chain.
static struct x509_certificatex509_last (struct x509_chain *chain)
 Get last certificate in X.509 certificate chain.
const char * x509_name (struct x509_certificate *cert)
 Get X.509 certificate display name.
int x509_parse (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate from ASN.1 data.
int x509_certificate (const void *data, size_t len, struct x509_certificate **cert)
 Create X.509 certificate.
int x509_validate (struct x509_certificate *cert, struct x509_certificate *issuer, time_t time, struct x509_root *root)
 Validate X.509 certificate.
int x509_check_name (struct x509_certificate *cert, const char *name)
 Check X.509 certificate name.
struct x509_chainx509_alloc_chain (void)
 Allocate X.509 certificate chain.
int x509_append (struct x509_chain *chain, struct x509_certificate *cert)
 Append X.509 certificate to X.509 certificate chain.
int x509_append_raw (struct x509_chain *chain, const void *data, size_t len)
 Append X.509 certificate to X.509 certificate chain.
int x509_auto_append (struct x509_chain *chain, struct x509_chain *certs)
 Append X.509 certificates to X.509 certificate chain.
int x509_validate_chain (struct x509_chain *chain, time_t time, struct x509_chain *store, struct x509_root *root)
 Validate X.509 certificate chain.
int image_x509 (struct image *image, size_t offset, struct x509_certificate **cert)
 Extract X.509 certificate object from image.
int x509_check_issuer (struct x509_certificate *cert, struct x509_certificate *issuer)
 Check X.509 certificate against issuer certificate.
void x509_fingerprint (struct x509_certificate *cert, struct digest_algorithm *digest, void *fingerprint)
 Calculate X.509 certificate fingerprint.
int x509_check_root (struct x509_certificate *cert, struct x509_root *root)
 Check X.509 root certificate.
int x509_check_time (struct x509_certificate *cert, time_t time)
 Check X.509 certificate validity period.
static int x509_is_valid (struct x509_certificate *cert)
 Check if X.509 certificate is valid.
static void x509_invalidate (struct x509_certificate *cert)
 Invalidate X.509 certificate.
static void x509_invalidate_chain (struct x509_chain *chain)
 Invalidate X.509 certificate chain.

Detailed Description

X.509 certificates.

Definition in file x509.h.


Define Documentation

#define X509_PATH_LEN_UNLIMITED   -2U

Unlimited path length.

We use -2U, since this quantity represents one *fewer* than the maximum number of remaining certificates in a chain.

Definition at line 88 of file x509.h.

Referenced by x509_parse_basic_constraints().


Enumeration Type Documentation

X.509 certificate key usage bits.

Enumerator:
X509_DIGITAL_SIGNATURE 
X509_NON_REPUDIATION 
X509_KEY_ENCIPHERMENT 
X509_DATA_ENCIPHERMENT 
X509_KEY_AGREEMENT 
X509_KEY_CERT_SIGN 
X509_CRL_SIGN 
X509_ENCIPHER_ONLY 
X509_DECIPHER_ONLY 

Definition at line 99 of file x509.h.

X.509 certificate extended key usage bits.

Extended key usages are identified by OID; these bits are purely an internal definition.

Enumerator:
X509_CODE_SIGNING 
X509_OCSP_SIGNING 

Definition at line 122 of file x509.h.

                                  {
        X509_CODE_SIGNING = 0x0001,
        X509_OCSP_SIGNING = 0x0002,
};

X.509 certificate general name types.

Enumerator:
X509_GENERAL_NAME_DNS 
X509_GENERAL_NAME_URI 
X509_GENERAL_NAME_IP 

Definition at line 148 of file x509.h.

enum x509_flags

X.509 certificate flags.

Enumerator:
X509_FL_VALIDATED 

Certificate has been validated.

X509_FL_PERMANENT 

Certificate was added at build time.

X509_FL_EXPLICIT 

Certificate was added explicitly at run time.

Definition at line 220 of file x509.h.

                {
        /** Certificate has been validated */
        X509_FL_VALIDATED = 0x0001,
        /** Certificate was added at build time */
        X509_FL_PERMANENT = 0x0002,
        /** Certificate was added explicitly at run time */
        X509_FL_EXPLICIT = 0x0004,
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static struct x509_certificate* x509_get ( struct x509_certificate cert) [static, read]

Get reference to X.509 certificate.

Parameters:
certX.509 certificate
Return values:
certX.509 certificate

Definition at line 236 of file x509.h.

References ref_get.

Referenced by cert_exec(), certstore_add(), ocsp_check(), tls_new_certificate_request(), x509_append(), and x509_certificate().

                                           {
        ref_get ( &cert->refcnt );
        return cert;
}
static void x509_put ( struct x509_certificate cert) [inline, static]
static struct x509_chain* x509_chain_get ( struct x509_chain chain) [static, read]

Get reference to X.509 certificate chain.

Parameters:
chainX.509 certificate chain
Return values:
chainX.509 certificate chain

Definition at line 258 of file x509.h.

References ref_get.

Referenced by create_validator().

                                            {
        ref_get ( &chain->refcnt );
        return chain;
}
static void x509_chain_put ( struct x509_chain chain) [inline, static]

Drop reference to X.509 certificate chain.

Parameters:
chainX.509 certificate chain

Definition at line 269 of file x509.h.

References ref_put.

Referenced by cms_free(), free_tls(), tls_parse_chain(), validator_append(), validator_free(), and x509_test_exec().

                                            {
        ref_put ( &chain->refcnt );
}
static struct x509_certificate* x509_first ( struct x509_chain chain) [static, read]

Get first certificate in X.509 certificate chain.

Parameters:
chainX.509 certificate chain
Return values:
certX.509 certificate, or NULL

Definition at line 280 of file x509.h.

References x509_link::cert, link, x509_link::list, list_first_entry, and NULL.

Referenced by cms_verify(), cms_verify_signer_info(), tls_validator_done(), and x509_chain_okx().

                                        {
        struct x509_link *link;

        link = list_first_entry ( &chain->links, struct x509_link, list );
        return ( link ? link->cert : NULL );
}
static struct x509_certificate* x509_last ( struct x509_chain chain) [static, read]

Get last certificate in X.509 certificate chain.

Parameters:
chainX.509 certificate chain
Return values:
certX.509 certificate, or NULL

Definition at line 294 of file x509.h.

References x509_link::cert, link, x509_link::list, list_last_entry, and NULL.

Referenced by cms_parse_certificates(), tls_parse_chain(), validator_append(), validator_step(), and x509_auto_append().

                                       {
        struct x509_link *link;

        link = list_last_entry ( &chain->links, struct x509_link, list );
        return ( link ? link->cert : NULL );
}
const char* x509_name ( struct x509_certificate cert)

Get X.509 certificate display name.

Parameters:
certX.509 certificate
Return values:
nameDisplay name

Definition at line 131 of file x509.c.

References x509_subject::common_name, asn1_cursor::data, digest, digest_algorithm::digestsize, asn1_cursor::len, len, memcpy(), sha1_algorithm, x509_certificate::subject, and x509_fingerprint().

Referenced by certstat(), certstore_add(), certstore_apply_settings(), certstore_del(), certstore_found(), certstore_init(), cms_parse_certificates(), ocsp_check_signature(), ocsp_parse_basic_response(), ocsp_parse_cert_id(), ocsp_parse_certs(), ocsp_parse_responder_id(), ocsp_parse_response_status(), ocsp_parse_response_type(), ocsp_parse_responses(), ocsp_request(), ocsp_uri_string(), ocsp_validate(), tls_new_certificate_request(), tls_parse_chain(), validator_append(), x509_append(), x509_check_alt_name(), x509_check_dnsname(), x509_check_ipaddress(), x509_check_issuer(), x509_check_name(), x509_check_root(), x509_check_signature(), x509_check_time(), x509_parse_subject(), and x509_validate().

                                                         {
        struct asn1_cursor *common_name = &cert->subject.common_name;
        struct digest_algorithm *digest = &sha1_algorithm;
        static char buf[64];
        uint8_t fingerprint[ digest->digestsize ];
        size_t len;

        len = common_name->len;
        if ( len ) {
                /* Certificate has a commonName: use that */
                if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
                        len = ( sizeof ( buf ) - 1 /* NUL */ );
                memcpy ( buf, common_name->data, len );
                buf[len] = '\0';
        } else {
                /* Certificate has no commonName: use SHA-1 fingerprint */
                x509_fingerprint ( cert, digest, fingerprint );
                base16_encode ( fingerprint, sizeof ( fingerprint ),
                                buf, sizeof ( buf ) );
        }
        return buf;
}
int x509_parse ( struct x509_certificate cert,
const struct asn1_cursor raw 
)

Parse X.509 certificate from ASN.1 data.

Parameters:
certX.509 certificate
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 989 of file x509.c.

References x509_signature::algorithm, asn1_enter(), asn1_integral_bit_string(), ASN1_SEQUENCE, asn1_signature_algorithm(), asn1_skip_any(), asn1_bit_string::data, DBGC, DBGC2, DBGC2_HDA, EINVAL_ALGORITHM_MISMATCH, asn1_bit_string::len, memcpy(), asn1_algorithm::name, x509_certificate::raw, rc, x509_certificate::signature, signature, strerror(), x509_signature::value, and x509_parse_tbscertificate().

Referenced by certstore_init(), and x509_certificate().

                                                 {
        struct x509_signature *signature = &cert->signature;
        struct asn1_algorithm **signature_algorithm = &signature->algorithm;
        struct asn1_bit_string *signature_value = &signature->value;
        struct asn1_cursor cursor;
        int rc;

        /* Record raw certificate */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );

        /* Enter certificate */
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse tbsCertificate */
        if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );

        /* Parse signatureAlgorithm */
        if ( ( rc = asn1_signature_algorithm ( &cursor,
                                               signature_algorithm ) ) != 0 ) {
                DBGC ( cert, "X509 %p could not parse signature algorithm: "
                       "%s\n", cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n",
                cert, (*signature_algorithm)->name );
        asn1_skip_any ( &cursor );

        /* Parse signatureValue */
        if ( ( rc = asn1_integral_bit_string ( &cursor,
                                               signature_value ) ) != 0 ) {
                DBGC ( cert, "X509 %p could not parse signature value: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
        DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );

        /* Check that algorithm in tbsCertificate matches algorithm in
         * signature
         */
        if ( signature->algorithm != (*signature_algorithm) ) {
                DBGC ( cert, "X509 %p signature algorithm %s does not match "
                       "signatureAlgorithm %s\n",
                       cert, signature->algorithm->name,
                       (*signature_algorithm)->name );
                return -EINVAL_ALGORITHM_MISMATCH;
        }

        return 0;
}
int x509_certificate ( const void *  data,
size_t  len,
struct x509_certificate **  cert 
)

Create X.509 certificate.

Parameters:
dataRaw certificate data
lenLength of raw data
Return values:
certX.509 certificate
rcReturn status code

On success, the caller holds a reference to the X.509 certificate, and is responsible for ultimately calling x509_put().

Definition at line 1055 of file x509.c.

References asn1_shrink_any(), certstore_add(), certstore_find(), asn1_cursor::data, data, ENOMEM, asn1_cursor::len, len, memcpy(), NULL, raw, rc, ref_init, x509_get(), x509_parse(), x509_put(), and zalloc().

                                                        {
        struct asn1_cursor cursor;
        void *raw;
        int rc;

        /* Initialise cursor */
        cursor.data = data;
        cursor.len = len;
        asn1_shrink_any ( &cursor );

        /* Return stored certificate, if present */
        if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {

                /* Add caller's reference */
                x509_get ( *cert );
                return 0;
        }

        /* Allocate and initialise certificate */
        *cert = zalloc ( sizeof ( **cert ) + cursor.len );
        if ( ! *cert )
                return -ENOMEM;
        ref_init ( &(*cert)->refcnt, NULL );
        raw = ( *cert + 1 );

        /* Copy raw data */
        memcpy ( raw, cursor.data, cursor.len );
        cursor.data = raw;

        /* Parse certificate */
        if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
                x509_put ( *cert );
                *cert = NULL;
                return rc;
        }

        /* Add certificate to store */
        certstore_add ( *cert );

        return 0;
}
int x509_validate ( struct x509_certificate cert,
struct x509_certificate issuer,
time_t  time,
struct x509_root root 
)

Validate X.509 certificate.

Parameters:
certX.509 certificate
issuerIssuing X.509 certificate (or NULL)
timeTime at which to validate certificate
rootRoot certificate list, or NULL to use default
Return values:
rcReturn status code

The issuing certificate must have already been validated.

Validation results are cached: if a certificate has already been successfully validated then issuer, time, and root will be ignored.

Definition at line 1313 of file x509.c.

References x509_extensions::basic, DBGC, DBGC2, EACCES_OCSP_REQUIRED, EACCES_OUT_OF_ORDER, EACCES_PATH_LEN, EACCES_UNTRUSTED, x509_certificate::extensions, x509_certificate::flags, ocsp_required(), x509_basic_constraints::path_len, x509_certificate::path_remaining, rc, root_certificates, x509_check_issuer(), x509_check_root(), x509_check_time(), X509_FL_VALIDATED, x509_is_valid(), and x509_name().

Referenced by ocsp_validate(), and x509_validate_chain().

                                                          {
        unsigned int max_path_remaining;
        int rc;

        /* Use default root certificate store if none specified */
        if ( ! root )
                root = &root_certificates;

        /* Return success if certificate has already been validated */
        if ( x509_is_valid ( cert ) )
                return 0;

        /* Fail if certificate is invalid at specified time */
        if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
                return rc;

        /* Succeed if certificate is a trusted root certificate */
        if ( x509_check_root ( cert, root ) == 0 ) {
                cert->flags |= X509_FL_VALIDATED;
                cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
                return 0;
        }

        /* Fail unless we have an issuer */
        if ( ! issuer ) {
                DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
                        cert, x509_name ( cert ) );
                return -EACCES_UNTRUSTED;
        }

        /* Fail unless issuer has already been validated */
        if ( ! x509_is_valid ( issuer ) ) {
                DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
                DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n",
                       issuer, x509_name ( issuer ) );
                return -EACCES_OUT_OF_ORDER;
        }

        /* Fail if issuing certificate cannot validate this certificate */
        if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
                return rc;

        /* Fail if path length constraint is violated */
        if ( issuer->path_remaining == 0 ) {
                DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
                DBGC ( cert, "issuer %p \"%s\" path length exceeded\n",
                       issuer, x509_name ( issuer ) );
                return -EACCES_PATH_LEN;
        }

        /* Fail if OCSP is required */
        if ( ocsp_required ( cert ) ) {
                DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n",
                       cert, x509_name ( cert ) );
                return -EACCES_OCSP_REQUIRED;
        }

        /* Calculate effective path length */
        cert->path_remaining = ( issuer->path_remaining - 1 );
        max_path_remaining = ( cert->extensions.basic.path_len + 1 );
        if ( cert->path_remaining > max_path_remaining )
                cert->path_remaining = max_path_remaining;

        /* Mark certificate as valid */
        cert->flags |= X509_FL_VALIDATED;

        DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
               cert, x509_name ( cert ) );
        DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) );
        return 0;
}
int x509_check_name ( struct x509_certificate cert,
const char *  name 
)

Check X.509 certificate name.

Parameters:
certX.509 certificate
nameName
Return values:
rcReturn status code

Definition at line 1519 of file x509.c.

References x509_extensions::alt_name, asn1_skip_any(), x509_subject::common_name, DBGC, DBGC2, EACCES_WRONG_NAME, x509_certificate::extensions, asn1_cursor::len, memcpy(), x509_subject_alt_name::names, rc, x509_certificate::subject, x509_check_alt_name(), x509_check_dnsname(), and x509_name().

Referenced by cert_exec(), cms_verify(), tls_validator_done(), x509_check_name_fail_okx(), and x509_check_name_okx().

                                                                        {
        struct asn1_cursor *common_name = &cert->subject.common_name;
        struct asn1_cursor alt_name;
        int rc;

        /* Check commonName */
        if ( x509_check_dnsname ( cert, common_name, name ) == 0 ) {
                DBGC2 ( cert, "X509 %p \"%s\" commonName matches \"%s\"\n",
                        cert, x509_name ( cert ), name );
                return 0;
        }

        /* Check any subjectAlternativeNames */
        memcpy ( &alt_name, &cert->extensions.alt_name.names,
                 sizeof ( alt_name ) );
        for ( ; alt_name.len ; asn1_skip_any ( &alt_name ) ) {
                if ( ( rc = x509_check_alt_name ( cert, &alt_name,
                                                  name ) ) == 0 ) {
                        DBGC2 ( cert, "X509 %p \"%s\" subjectAltName matches "
                                "\"%s\"\n", cert, x509_name ( cert ), name );
                        return 0;
                }
        }

        DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n",
               cert, x509_name ( cert ), name );
        return -EACCES_WRONG_NAME;
}
struct x509_chain* x509_alloc_chain ( void  ) [read]

Allocate X.509 certificate chain.

Return values:
chainX.509 certificate chain, or NULL

Definition at line 1577 of file x509.c.

References DBGC2, INIT_LIST_HEAD, x509_chain::links, NULL, ref_init, x509_chain::refcnt, x509_free_chain(), and zalloc().

Referenced by cms_parse(), cms_signature(), tls_parse_chain(), validator_append(), and x509_chain_okx().

                                              {
        struct x509_chain *chain;

        /* Allocate chain */
        chain = zalloc ( sizeof ( *chain ) );
        if ( ! chain )
                return NULL;

        /* Initialise chain */
        ref_init ( &chain->refcnt, x509_free_chain );
        INIT_LIST_HEAD ( &chain->links );

        DBGC2 ( chain, "X509 chain %p allocated\n", chain );
        return chain;
}
int x509_append ( struct x509_chain chain,
struct x509_certificate cert 
)

Append X.509 certificate to X.509 certificate chain.

Parameters:
chainX.509 certificate chain
certX.509 certificate
Return values:
rcReturn status code

Definition at line 1600 of file x509.c.

References x509_link::cert, DBGC, ENOMEM, link, x509_chain::links, x509_link::list, list_add_tail, x509_get(), x509_name(), and zalloc().

Referenced by cms_parse_signer_identifier(), x509_append_raw(), x509_auto_append(), and x509_chain_okx().

                                                                            {
        struct x509_link *link;

        /* Allocate link */
        link = zalloc ( sizeof ( *link ) );
        if ( ! link )
                return -ENOMEM;

        /* Add link to chain */
        link->cert = x509_get ( cert );
        list_add_tail ( &link->list, &chain->links );
        DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
               chain, cert, x509_name ( cert ) );

        return 0;
}
int x509_append_raw ( struct x509_chain chain,
const void *  data,
size_t  len 
)

Append X.509 certificate to X.509 certificate chain.

Parameters:
chainX.509 certificate chain
dataRaw certificate data
lenLength of raw data
Return values:
rcReturn status code

Definition at line 1625 of file x509.c.

References rc, x509_append(), and x509_put().

Referenced by cms_parse_certificates(), tls_parse_chain(), and validator_append().

                                   {
        struct x509_certificate *cert;
        int rc;

        /* Parse certificate */
        if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 )
                goto err_parse;

        /* Append certificate to chain */
        if ( ( rc = x509_append ( chain, cert ) ) != 0 )
                goto err_append;

        /* Drop reference to certificate */
        x509_put ( cert );

        return 0;

 err_append:
        x509_put ( cert );
 err_parse:
        return rc;
}
int x509_auto_append ( struct x509_chain chain,
struct x509_chain certs 
)

Append X.509 certificates to X.509 certificate chain.

Parameters:
chainX.509 certificate chain
certsX.509 certificate list
Return values:
rcReturn status code

Certificates will be automatically appended to the chain based upon the subject and issuer names.

Definition at line 1684 of file x509.c.

References DBGC, EACCES_EMPTY, x509_certificate::issuer, x509_issuer::raw, rc, x509_append(), x509_find_subject(), and x509_last().

Referenced by cms_parse_signer_identifier(), validator_append(), and x509_validate_chain().

                                                                            {
        struct x509_certificate *cert;
        struct x509_certificate *previous;
        int rc;

        /* Get current certificate */
        cert = x509_last ( chain );
        if ( ! cert ) {
                DBGC ( chain, "X509 chain %p has no certificates\n", chain );
                return -EACCES_EMPTY;
        }

        /* Append certificates, in order */
        while ( 1 ) {

                /* Find issuing certificate */
                previous = cert;
                cert = x509_find_subject ( certs, &cert->issuer.raw );
                if ( ! cert )
                        break;
                if ( cert == previous )
                        break;

                /* Append certificate to chain */
                if ( ( rc = x509_append ( chain, cert ) ) != 0 )
                        return rc;
        }

        return 0;
}
int x509_validate_chain ( struct x509_chain chain,
time_t  time,
struct x509_chain store,
struct x509_root root 
)

Validate X.509 certificate chain.

Parameters:
chainX.509 certificate chain
timeTime at which to validate certificates
storeCertificate store, or NULL to use default
rootRoot certificate list, or NULL to use default
Return values:
rcReturn status code

Definition at line 1724 of file x509.c.

References x509_link::cert, certstore, DBGC, EACCES_USELESS, x509_certificate::issuer, link, x509_chain::links, x509_link::list, list_for_each_entry, list_for_each_entry_continue_reverse, NULL, rc, x509_auto_append(), and x509_validate().

Referenced by cms_verify_signer_info(), validator_step(), x509_validate_chain_fail_okx(), and x509_validate_chain_okx().

                                                                             {
        struct x509_certificate *issuer = NULL;
        struct x509_link *link;
        int rc;

        /* Use default certificate store if none specified */
        if ( ! store )
                store = &certstore;

        /* Append any applicable certificates from the certificate store */
        if ( ( rc = x509_auto_append ( chain, store ) ) != 0 )
                return rc;

        /* Find first certificate that can be validated as a
         * standalone (i.e.  is already valid, or can be validated as
         * a trusted root certificate).
         */
        list_for_each_entry ( link, &chain->links, list ) {

                /* Try validating this certificate as a standalone */
                if ( ( rc = x509_validate ( link->cert, NULL, time,
                                            root ) ) != 0 )
                        continue;

                /* Work back up to start of chain, performing pairwise
                 * validation.
                 */
                issuer = link->cert;
                list_for_each_entry_continue_reverse ( link, &chain->links,
                                                       list ) {

                        /* Validate this certificate against its issuer */
                        if ( ( rc = x509_validate ( link->cert, issuer, time,
                                                    root ) ) != 0 )
                                return rc;
                        issuer = link->cert;
                }

                return 0;
        }

        DBGC ( chain, "X509 chain %p found no usable certificates\n", chain );
        return -EACCES_USELESS;
}
int image_x509 ( struct image image,
size_t  offset,
struct x509_certificate **  cert 
)

Extract X.509 certificate object from image.

Parameters:
imageImage
offsetOffset within image
Return values:
certX.509 certificate
nextOffset to next image, or negative error

On success, the caller holds a reference to the X.509 certificate, and is responsible for ultimately calling x509_put().

Definition at line 1781 of file x509.c.

References asn1_cursor::data, free, image_asn1(), asn1_cursor::len, next, rc, and x509_put().

Referenced by cert_exec().

                                                  {
        struct asn1_cursor *cursor;
        int next;
        int rc;

        /* Get ASN.1 object */
        next = image_asn1 ( image, offset, &cursor );
        if ( next < 0 ) {
                rc = next;
                goto err_asn1;
        }

        /* Parse certificate */
        if ( ( rc = x509_certificate ( cursor->data, cursor->len,
                                       cert ) ) != 0 )
                goto err_certificate;

        /* Free ASN.1 object */
        free ( cursor );

        return next;

        x509_put ( *cert );
 err_certificate:
        free ( cursor );
 err_asn1:
        return rc;
}
int x509_check_issuer ( struct x509_certificate cert,
struct x509_certificate issuer 
)

Check X.509 certificate against issuer certificate.

Parameters:
certX.509 certificate
issuerX.509 issuer certificate
Return values:
rcReturn status code

Definition at line 1168 of file x509.c.

References asn1_compare(), x509_extensions::basic, x509_key_usage::bits, x509_basic_constraints::ca, asn1_cursor::data, DBGC, DBGC_HDA, EACCES_KEY_USAGE, EACCES_NOT_CA, EACCES_WRONG_ISSUER, x509_certificate::extensions, x509_certificate::issuer, asn1_cursor::len, x509_key_usage::present, x509_subject::public_key, x509_issuer::raw, x509_subject::raw, rc, x509_certificate::subject, x509_extensions::usage, x509_check_signature(), X509_KEY_CERT_SIGN, and x509_name().

Referenced by x509_check_issuer_fail_okx(), x509_check_issuer_okx(), and x509_validate().

                                                          {
        struct x509_public_key *public_key = &issuer->subject.public_key;
        int rc;

        /* Check issuer.  In theory, this should be a full X.500 DN
         * comparison, which would require support for a plethora of
         * abominations such as TeletexString (which allows the
         * character set to be changed mid-string using escape codes).
         * In practice, we assume that anyone who deliberately changes
         * the encoding of the issuer DN is probably a masochist who
         * will rather enjoy the process of figuring out exactly why
         * their certificate doesn't work.
         *
         * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
         * for some enjoyable ranting on this subject.
         */
        if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
                DBGC ( cert, "X509 %p \"%s\" issuer does not match ",
                       cert, x509_name ( cert ) );
                DBGC ( cert, "X509 %p \"%s\" subject\n",
                       issuer, x509_name ( issuer ) );
                DBGC_HDA ( cert, 0, cert->issuer.raw.data,
                           cert->issuer.raw.len );
                DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
                           issuer->subject.raw.len );
                return -EACCES_WRONG_ISSUER;
        }

        /* Check that issuer is allowed to sign certificates */
        if ( ! issuer->extensions.basic.ca ) {
                DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
                       issuer, x509_name ( issuer ) );
                DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n",
                       cert, x509_name ( cert ) );
                return -EACCES_NOT_CA;
        }
        if ( issuer->extensions.usage.present &&
             ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
                DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
                       issuer, x509_name ( issuer ) );
                DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n",
                       cert, x509_name ( cert ) );
                return -EACCES_KEY_USAGE;
        }

        /* Check signature */
        if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
                return rc;

        return 0;
}
void x509_fingerprint ( struct x509_certificate cert,
struct digest_algorithm digest,
void *  fingerprint 
)

Calculate X.509 certificate fingerprint.

Parameters:
certX.509 certificate
digestDigest algorithm
fingerprintFingerprint buffer

Definition at line 1228 of file x509.c.

References ctx, digest_algorithm::ctxsize, asn1_cursor::data, digest_final(), digest_init(), digest_update(), asn1_cursor::len, and x509_certificate::raw.

Referenced by certstat(), x509_check_root(), x509_fingerprint_okx(), and x509_name().

                                            {
        uint8_t ctx[ digest->ctxsize ];

        /* Calculate fingerprint */
        digest_init ( digest, ctx );
        digest_update ( digest, ctx, cert->raw.data, cert->raw.len );
        digest_final ( digest, ctx, fingerprint );
}
int x509_check_root ( struct x509_certificate cert,
struct x509_root root 
)

Check X.509 root certificate.

Parameters:
certX.509 certificate
rootX.509 root certificate list
Return values:
rcReturn status code

Definition at line 1246 of file x509.c.

References x509_root::count, DBGC, DBGC2, digest, x509_root::digest, digest_algorithm::digestsize, ENOENT, x509_root::fingerprints, memcmp(), x509_fingerprint(), and x509_name().

Referenced by x509_check_root_fail_okx(), x509_check_root_okx(), and x509_validate().

                                                                              {
        struct digest_algorithm *digest = root->digest;
        uint8_t fingerprint[ digest->digestsize ];
        const uint8_t *root_fingerprint = root->fingerprints;
        unsigned int i;

        /* Calculate certificate fingerprint */
        x509_fingerprint ( cert, digest, fingerprint );

        /* Check fingerprint against all root certificates */
        for ( i = 0 ; i < root->count ; i++ ) {
                if ( memcmp ( fingerprint, root_fingerprint,
                              sizeof ( fingerprint ) ) == 0 ) {
                        DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
                               cert, x509_name ( cert ) );
                        return 0;
                }
                root_fingerprint += sizeof ( fingerprint );
        }

        DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
                cert, x509_name ( cert ) );
        return -ENOENT;
}
int x509_check_time ( struct x509_certificate cert,
time_t  time 
)

Check X.509 certificate validity period.

Parameters:
certX.509 certificate
timeTime at which to check certificate
Return values:
rcReturn status code

Definition at line 1278 of file x509.c.

References DBGC, DBGC2, EACCES_EXPIRED, x509_validity::not_after, x509_validity::not_before, x509_time::time, TIMESTAMP_ERROR_MARGIN, x509_certificate::validity, and x509_name().

Referenced by x509_check_time_fail_okx(), x509_check_time_okx(), and x509_validate().

                                                                   {
        struct x509_validity *validity = &cert->validity;

        /* Check validity period */
        if ( validity->not_before.time > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
                DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
                       cert, x509_name ( cert ), time );
                return -EACCES_EXPIRED;
        }
        if ( validity->not_after.time < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
                DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
                       cert, x509_name ( cert ), time );
                return -EACCES_EXPIRED;
        }

        DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
                cert, x509_name ( cert ), time );
        return 0;
}
static int x509_is_valid ( struct x509_certificate cert) [inline, static]

Check if X.509 certificate is valid.

Parameters:
certX.509 certificate

Definition at line 391 of file x509.h.

References x509_certificate::flags, and X509_FL_VALIDATED.

Referenced by certstat(), ocsp_check(), validator_step(), and x509_validate().

                                                                  {
        return ( cert->flags & X509_FL_VALIDATED );
}
static void x509_invalidate ( struct x509_certificate cert) [inline, static]

Invalidate X.509 certificate.

Parameters:
certX.509 certificate

Definition at line 400 of file x509.h.

References x509_certificate::flags, x509_certificate::path_remaining, and X509_FL_VALIDATED.

Referenced by ocsp_prepare_test(), ocsp_validate(), and x509_invalidate_chain().

                                                                     {
        cert->flags &= ~X509_FL_VALIDATED;
        cert->path_remaining = 0;
}
static void x509_invalidate_chain ( struct x509_chain chain) [inline, static]

Invalidate X.509 certificate chain.

Parameters:
chainX.509 certificate chain

Definition at line 410 of file x509.h.

References x509_link::cert, link, x509_chain::links, x509_link::list, list_for_each_entry, and x509_invalidate().

Referenced by cms_verify_fail_okx(), cms_verify_okx(), x509_validate_chain_fail_okx(), and x509_validate_chain_okx().

                                                                      {
        struct x509_link *link;

        list_for_each_entry ( link, &chain->links, list )
                x509_invalidate ( link->cert );
}