iPXE
Defines | Functions | Variables
x509.c File Reference

X.509 certificates. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/list.h>
#include <ipxe/base16.h>
#include <ipxe/asn1.h>
#include <ipxe/crypto.h>
#include <ipxe/md5.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/rsa.h>
#include <ipxe/rootcert.h>
#include <ipxe/certstore.h>
#include <ipxe/socket.h>
#include <ipxe/in.h>
#include <ipxe/image.h>
#include <ipxe/ocsp.h>
#include <ipxe/x509.h>
#include <config/crypto.h>

Go to the source code of this file.

Defines

#define ENOTSUP_ALGORITHM   __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
#define EINFO_ENOTSUP_ALGORITHM   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
#define ENOTSUP_EXTENSION   __einfo_error ( EINFO_ENOTSUP_EXTENSION )
#define EINFO_ENOTSUP_EXTENSION   __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
#define EINVAL_ALGORITHM   __einfo_error ( EINFO_EINVAL_ALGORITHM )
#define EINFO_EINVAL_ALGORITHM   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
#define EINVAL_ALGORITHM_MISMATCH   __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
#define EINFO_EINVAL_ALGORITHM_MISMATCH   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )
#define EINVAL_PATH_LEN   __einfo_error ( EINFO_EINVAL_PATH_LEN )
#define EINFO_EINVAL_PATH_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )
#define EINVAL_VERSION   __einfo_error ( EINFO_EINVAL_VERSION )
#define EINFO_EINVAL_VERSION   __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )
#define EACCES_WRONG_ISSUER   __einfo_error ( EINFO_EACCES_WRONG_ISSUER )
#define EINFO_EACCES_WRONG_ISSUER   __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )
#define EACCES_NOT_CA   __einfo_error ( EINFO_EACCES_NOT_CA )
#define EINFO_EACCES_NOT_CA   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )
#define EACCES_KEY_USAGE   __einfo_error ( EINFO_EACCES_KEY_USAGE )
#define EINFO_EACCES_KEY_USAGE   __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )
#define EACCES_EXPIRED   __einfo_error ( EINFO_EACCES_EXPIRED )
#define EINFO_EACCES_EXPIRED   __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )
#define EACCES_PATH_LEN   __einfo_error ( EINFO_EACCES_PATH_LEN )
#define EINFO_EACCES_PATH_LEN   __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )
#define EACCES_UNTRUSTED   __einfo_error ( EINFO_EACCES_UNTRUSTED )
#define EINFO_EACCES_UNTRUSTED   __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
#define EACCES_OUT_OF_ORDER   __einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
#define EINFO_EACCES_OUT_OF_ORDER   __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
#define EACCES_EMPTY   __einfo_error ( EINFO_EACCES_EMPTY )
#define EINFO_EACCES_EMPTY   __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
#define EACCES_OCSP_REQUIRED   __einfo_error ( EINFO_EACCES_OCSP_REQUIRED )
#define EINFO_EACCES_OCSP_REQUIRED   __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )
#define EACCES_WRONG_NAME   __einfo_error ( EINFO_EACCES_WRONG_NAME )
#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )
#define EACCES_USELESS   __einfo_error ( EINFO_EACCES_USELESS )
#define EINFO_EACCES_USELESS   __einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
const char * x509_name (struct x509_certificate *cert)
 Get X.509 certificate display name.
static int x509_parse_version (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate version.
static int x509_parse_serial (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate serial number.
static int x509_parse_issuer (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate issuer.
static int x509_parse_validity (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate validity.
static int x509_parse_common_name (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate common name.
static int x509_parse_subject (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate subject.
static int x509_parse_public_key (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate public key information.
static int x509_parse_basic_constraints (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate basic constraints.
static int x509_parse_key_usage (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate key usage.
static int x509_parse_key_purpose (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate key purpose identifier.
static int x509_parse_extended_key_usage (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate extended key usage.
static int x509_parse_ocsp (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate OCSP access method.
static struct x509_access_methodx509_find_access_method (const struct asn1_cursor *oid)
 Identify X.509 access method by OID.
static int x509_parse_access_description (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate access description.
static int x509_parse_authority_info_access (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate authority information access.
static int x509_parse_subject_alt_name (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate subject alternative name.
static struct x509_extensionx509_find_extension (const struct asn1_cursor *oid)
 Identify X.509 extension by OID.
static int x509_parse_extension (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate extension.
static int x509_parse_extensions (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate extensions, if present.
static int x509_parse_tbscertificate (struct x509_certificate *cert, const struct asn1_cursor *raw)
 Parse X.509 certificate tbsCertificate.
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.
static int x509_check_signature (struct x509_certificate *cert, struct x509_public_key *public_key)
 Check X.509 certificate signature.
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.
int x509_validate (struct x509_certificate *cert, struct x509_certificate *issuer, time_t time, struct x509_root *root)
 Validate X.509 certificate.
static int x509_check_dnsname (struct x509_certificate *cert, const struct asn1_cursor *raw, const char *name)
 Check X.509 certificate alternative dNSName.
static int x509_check_ipaddress (struct x509_certificate *cert, const struct asn1_cursor *raw, const char *name)
 Check X.509 certificate alternative iPAddress.
static int x509_check_alt_name (struct x509_certificate *cert, const struct asn1_cursor *raw, const char *name)
 Check X.509 certificate alternative name.
int x509_check_name (struct x509_certificate *cert, const char *name)
 Check X.509 certificate name.
static void x509_free_chain (struct refcnt *refcnt)
 Free X.509 certificate chain.
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.
static struct x509_certificatex509_find_subject (struct x509_chain *certs, const struct asn1_cursor *subject)
 Identify X.509 certificate by subject.
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.
 REQUIRING_SYMBOL (x509_validate)
 REQUIRE_OBJECT (certstore)
 REQUIRE_OBJECT (config_crypto)

Variables

static uint8_t oid_common_name [] = { ASN1_OID_COMMON_NAME }
 "commonName" object identifier
static struct asn1_cursor oid_common_name_cursor
 "commonName" object identifier cursor
static uint8_t oid_code_signing [] = { ASN1_OID_CODESIGNING }
 "id-kp-codeSigning" object identifier
static uint8_t oid_ocsp_signing [] = { ASN1_OID_OCSPSIGNING }
 "id-kp-OCSPSigning" object identifier
static struct x509_key_purpose x509_key_purposes []
 Supported key purposes.
static uint8_t oid_ad_ocsp [] = { ASN1_OID_OCSP }
 "id-ad-ocsp" object identifier
static struct x509_access_method x509_access_methods []
 Supported access methods.
static uint8_t oid_ce_basic_constraints []
 "id-ce-basicConstraints" object identifier
static uint8_t oid_ce_key_usage []
 "id-ce-keyUsage" object identifier
static uint8_t oid_ce_ext_key_usage []
 "id-ce-extKeyUsage" object identifier
static uint8_t oid_pe_authority_info_access []
 "id-pe-authorityInfoAccess" object identifier
static uint8_t oid_ce_subject_alt_name []
 "id-ce-subjectAltName" object identifier
static struct x509_extension x509_extensions []
 Supported certificate extensions.

Detailed Description

X.509 certificates.

The structure of X.509v3 certificates is documented in RFC 5280 section 4.1.

Definition in file x509.c.


Define Documentation

Definition at line 56 of file x509.c.

#define EINFO_ENOTSUP_ALGORITHM   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )

Definition at line 58 of file x509.c.

Definition at line 60 of file x509.c.

Referenced by x509_parse_extension().

#define EINFO_ENOTSUP_EXTENSION   __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )

Definition at line 62 of file x509.c.

Definition at line 64 of file x509.c.

#define EINFO_EINVAL_ALGORITHM   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )

Definition at line 66 of file x509.c.

Definition at line 68 of file x509.c.

Referenced by x509_check_signature(), and x509_parse().

#define EINFO_EINVAL_ALGORITHM_MISMATCH   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )

Definition at line 70 of file x509.c.

Definition at line 72 of file x509.c.

#define EINFO_EINVAL_PATH_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )

Definition at line 74 of file x509.c.

Definition at line 76 of file x509.c.

Referenced by x509_parse_version().

#define EINFO_EINVAL_VERSION   __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )

Definition at line 78 of file x509.c.

Definition at line 80 of file x509.c.

Referenced by x509_check_issuer().

#define EINFO_EACCES_WRONG_ISSUER   __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )

Definition at line 82 of file x509.c.

Definition at line 84 of file x509.c.

Referenced by x509_check_issuer().

#define EINFO_EACCES_NOT_CA   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )

Definition at line 86 of file x509.c.

Definition at line 88 of file x509.c.

Referenced by x509_check_issuer().

#define EINFO_EACCES_KEY_USAGE   __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )

Definition at line 90 of file x509.c.

Definition at line 92 of file x509.c.

Referenced by x509_check_time().

#define EINFO_EACCES_EXPIRED   __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )

Definition at line 94 of file x509.c.

Definition at line 96 of file x509.c.

Referenced by x509_validate().

#define EINFO_EACCES_PATH_LEN   __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )

Definition at line 98 of file x509.c.

Definition at line 100 of file x509.c.

Referenced by x509_validate().

#define EINFO_EACCES_UNTRUSTED   __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )

Definition at line 102 of file x509.c.

Definition at line 104 of file x509.c.

Referenced by x509_validate().

#define EINFO_EACCES_OUT_OF_ORDER   __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )

Definition at line 106 of file x509.c.

Definition at line 108 of file x509.c.

Referenced by x509_auto_append().

#define EINFO_EACCES_EMPTY   __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )

Definition at line 110 of file x509.c.

Definition at line 112 of file x509.c.

Referenced by x509_validate().

#define EINFO_EACCES_OCSP_REQUIRED   __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )

Definition at line 114 of file x509.c.

Definition at line 116 of file x509.c.

Referenced by x509_check_name().

#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )

Definition at line 118 of file x509.c.

Definition at line 120 of file x509.c.

Referenced by x509_validate_chain().

#define EINFO_EACCES_USELESS   __einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )

Definition at line 122 of file x509.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
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;
}
static int x509_parse_version ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate version.

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

Definition at line 168 of file x509.c.

References asn1_enter(), ASN1_EXPLICIT_TAG, asn1_integer(), asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, EINVAL_VERSION, asn1_cursor::len, memcpy(), rc, strerror(), x509_certificate::version, and version.

Referenced by x509_parse_tbscertificate().

                                                                {
        struct asn1_cursor cursor;
        int version;
        int rc;

        /* Enter version */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );

        /* Parse integer */
        if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) {
                DBGC ( cert, "X509 %p cannot parse version: %s\n",
                       cert, strerror ( rc ) );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return rc;
        }

        /* Sanity check */
        if ( version < 0 ) {
                DBGC ( cert, "X509 %p invalid version %d\n", cert, version );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return -EINVAL_VERSION;
        }

        /* Record version */
        cert->version = version;
        DBGC2 ( cert, "X509 %p is a version %d certificate\n",
                cert, ( cert->version + 1 ) );

        return 0;
}
static int x509_parse_serial ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate serial number.

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

Definition at line 208 of file x509.c.

References ASN1_INTEGER, asn1_shrink(), asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, asn1_cursor::len, memcpy(), x509_serial::raw, rc, serial, x509_certificate::serial, and strerror().

Referenced by x509_parse_tbscertificate().

                                                               {
        struct x509_serial *serial = &cert->serial;
        int rc;

        /* Record raw serial number */
        memcpy ( &serial->raw, raw, sizeof ( serial->raw ) );
        if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) {
                DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p issuer is:\n", cert );
        DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len );

        return 0;
}
static int x509_parse_issuer ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate issuer.

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

Definition at line 233 of file x509.c.

References ASN1_SEQUENCE, asn1_shrink(), asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, x509_certificate::issuer, asn1_cursor::len, memcpy(), x509_issuer::raw, rc, and strerror().

Referenced by x509_parse_tbscertificate().

                                                               {
        struct x509_issuer *issuer = &cert->issuer;
        int rc;

        /* Record raw issuer */
        memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) );
        if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) {
                DBGC ( cert, "X509 %p cannot shrink issuer: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p issuer is:\n", cert );
        DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len );

        return 0;
}
static int x509_parse_validity ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate validity.

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

Definition at line 258 of file x509.c.

References asn1_enter(), asn1_generalized_time(), ASN1_SEQUENCE, asn1_skip_any(), DBGC, DBGC2, memcpy(), x509_validity::not_after, x509_validity::not_before, rc, strerror(), x509_time::time, and x509_certificate::validity.

Referenced by x509_parse_tbscertificate().

                                                                 {
        struct x509_validity *validity = &cert->validity;
        struct x509_time *not_before = &validity->not_before;
        struct x509_time *not_after = &validity->not_after;
        struct asn1_cursor cursor;
        int rc;

        /* Enter validity */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse notBefore */
        if ( ( rc = asn1_generalized_time ( &cursor,
                                            &not_before->time ) ) != 0 ) {
                DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p valid from time %lld\n",
                cert, not_before->time );
        asn1_skip_any ( &cursor );

        /* Parse notAfter */
        if ( ( rc = asn1_generalized_time ( &cursor,
                                            &not_after->time ) ) != 0 ) {
                DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }
        DBGC2 ( cert, "X509 %p valid until time %lld\n",
                cert, not_after->time );

        return 0;
}
static int x509_parse_common_name ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate common name.

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

Definition at line 301 of file x509.c.

References asn1_compare(), asn1_enter(), asn1_enter_any(), ASN1_OID, ASN1_SEQUENCE, ASN1_SET, asn1_skip_any(), x509_subject::common_name, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, asn1_cursor::len, memcpy(), rc, and x509_certificate::subject.

Referenced by x509_parse_subject().

                                                                    {
        struct asn1_cursor cursor;
        struct asn1_cursor oid_cursor;
        struct asn1_cursor name_cursor;
        int rc;

        /* Enter name */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Scan through name list */
        for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {

                /* Check for "commonName" OID */
                memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
                asn1_enter ( &oid_cursor, ASN1_SET );
                asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
                memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) );
                asn1_enter ( &oid_cursor, ASN1_OID );
                if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0)
                        continue;
                asn1_skip_any ( &name_cursor );
                if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) {
                        DBGC ( cert, "X509 %p cannot locate name:\n", cert );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return rc;
                }

                /* Record common name */
                memcpy ( &cert->subject.common_name, &name_cursor,
                         sizeof ( cert->subject.common_name ) );

                return 0;
        }

        /* Certificates may not have a commonName */
        DBGC2 ( cert, "X509 %p no commonName found:\n", cert );
        return 0;
}
static int x509_parse_subject ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate subject.

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

Definition at line 349 of file x509.c.

References asn1_shrink_any(), asn1_cursor::data, DBGC2, DBGC2_HDA, asn1_cursor::len, memcpy(), x509_subject::raw, rc, x509_certificate::subject, x509_name(), and x509_parse_common_name().

Referenced by x509_parse_tbscertificate().

                                                                {
        struct x509_subject *subject = &cert->subject;
        int rc;

        /* Record raw subject */
        memcpy ( &subject->raw, raw, sizeof ( subject->raw ) );
        asn1_shrink_any ( &subject->raw );
        DBGC2 ( cert, "X509 %p subject is:\n", cert );
        DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );

        /* Parse common name */
        if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 )
                return rc;
        DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert,
                x509_name ( cert ) );

        return 0;
}
static int x509_parse_public_key ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate public key information.

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

Definition at line 376 of file x509.c.

References x509_public_key::algorithm, algorithm, asn1_enter(), asn1_pubkey_algorithm(), ASN1_SEQUENCE, asn1_shrink_any(), asn1_skip_any(), asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, asn1_cursor::len, memcpy(), x509_subject::public_key, x509_public_key::raw, x509_public_key::raw_bits, rc, strerror(), and x509_certificate::subject.

Referenced by x509_parse_tbscertificate().

                                                                   {
        struct x509_public_key *public_key = &cert->subject.public_key;
        struct asn1_algorithm **algorithm = &public_key->algorithm;
        struct asn1_bit_string *raw_bits = &public_key->raw_bits;
        struct asn1_cursor cursor;
        int rc;

        /* Record raw subjectPublicKeyInfo */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_shrink_any ( &cursor );
        memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) );
        DBGC2 ( cert, "X509 %p public key is:\n", cert );
        DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len );

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

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

        /* Parse bit string */
        if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
                DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int x509_parse_basic_constraints ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate basic constraints.

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

Definition at line 421 of file x509.c.

References ASN1_BOOLEAN, asn1_boolean(), asn1_enter(), ASN1_INTEGER, asn1_integer(), ASN1_SEQUENCE, asn1_skip_any(), asn1_type(), x509_extensions::basic, x509_basic_constraints::ca, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, EINVAL, x509_certificate::extensions, asn1_cursor::len, memcpy(), x509_basic_constraints::path_len, rc, strerror(), and X509_PATH_LEN_UNLIMITED.

                                                                          {
        struct x509_basic_constraints *basic = &cert->extensions.basic;
        struct asn1_cursor cursor;
        int ca = 0;
        int path_len;
        int rc;

        /* Enter basicConstraints */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse "cA", if present */
        if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
                ca = asn1_boolean ( &cursor );
                if ( ca < 0 ) {
                        rc = ca;
                        DBGC ( cert, "X509 %p cannot parse cA: %s\n",
                               cert, strerror ( rc ) );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return rc;
                }
                asn1_skip_any ( &cursor );
        }
        basic->ca = ca;
        DBGC2 ( cert, "X509 %p is %sa CA certificate\n",
                cert, ( basic->ca ? "" : "not " ) );

        /* Ignore everything else unless "cA" is true */
        if ( ! ca )
                return 0;

        /* Parse "pathLenConstraint", if present and applicable */
        basic->path_len = X509_PATH_LEN_UNLIMITED;
        if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
                if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
                        DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
                               "%s\n", cert, strerror ( rc ) );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return rc;
                }
                if ( path_len < 0 ) {
                        DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n",
                               cert, path_len );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return -EINVAL;
                }
                basic->path_len = path_len;
                DBGC2 ( cert, "X509 %p path length constraint is %d\n",
                        cert, basic->path_len );
        }

        return 0;
}
static int x509_parse_key_usage ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate key usage.

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

Definition at line 483 of file x509.c.

References x509_key_usage::bits, bytes, asn1_bit_string::data, DBGC, DBGC2, x509_certificate::extensions, len, asn1_bit_string::len, x509_key_usage::present, rc, strerror(), and x509_extensions::usage.

                                                                  {
        struct x509_key_usage *usage = &cert->extensions.usage;
        struct asn1_bit_string bit_string;
        const uint8_t *bytes;
        size_t len;
        unsigned int i;
        int rc;

        /* Mark extension as present */
        usage->present = 1;

        /* Parse bit string */
        if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
                DBGC ( cert, "X509 %p could not parse key usage: %s\n",
                       cert, strerror ( rc ) );
                return rc;
        }

        /* Parse key usage bits */
        bytes = bit_string.data;
        len = bit_string.len;
        if ( len > sizeof ( usage->bits ) )
                len = sizeof ( usage->bits );
        for ( i = 0 ; i < len ; i++ ) {
                usage->bits |= ( *(bytes++) << ( 8 * i ) );
        }
        DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits );

        return 0;
}
static int x509_parse_key_purpose ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate key purpose identifier.

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

Definition at line 542 of file x509.c.

References asn1_compare(), asn1_enter(), ASN1_OID, x509_extended_key_usage::bits, x509_key_purpose::bits, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, x509_extensions::ext_usage, x509_certificate::extensions, asn1_cursor::len, memcpy(), x509_key_purpose::name, x509_key_purpose::oid, rc, and x509_key_purposes.

Referenced by x509_parse_extended_key_usage().

                                                                    {
        struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
        struct x509_key_purpose *purpose;
        struct asn1_cursor cursor;
        unsigned int i;
        int rc;

        /* Enter keyPurposeId */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
                DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return rc;
        }

        /* Identify key purpose */
        for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
                            sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
                purpose = &x509_key_purposes[i];
                if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
                        DBGC2 ( cert, "X509 %p has key purpose %s\n",
                                cert, purpose->name );
                        ext_usage->bits |= purpose->bits;
                        return 0;
                }
        }

        /* Ignore unrecognised key purposes */
        return 0;
}
static int x509_parse_extended_key_usage ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate extended key usage.

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

Definition at line 581 of file x509.c.

References asn1_enter(), ASN1_SEQUENCE, asn1_skip_any(), asn1_cursor::len, memcpy(), rc, and x509_parse_key_purpose().

                                                                           {
        struct asn1_cursor cursor;
        int rc;

        /* Enter extKeyUsage */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse each extended key usage in turn */
        while ( cursor.len ) {
                if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
                        return rc;
                asn1_skip_any ( &cursor );
        }

        return 0;
}
static int x509_parse_ocsp ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate OCSP access method.

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

Definition at line 607 of file x509.c.

References asn1_enter(), x509_extensions::auth_info, asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, x509_certificate::extensions, asn1_cursor::len, memcpy(), x509_authority_info_access::ocsp, rc, x509_ocsp_responder::uri, and X509_GENERAL_NAME_URI.

                                                             {
        struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
        struct asn1_cursor *uri = &ocsp->uri;
        int rc;

        /* Enter accessLocation */
        memcpy ( uri, raw, sizeof ( *uri ) );
        if ( ( rc = asn1_enter ( uri, X509_GENERAL_NAME_URI ) ) != 0 ) {
                DBGC ( cert, "X509 %p OCSP does not contain "
                       "uniformResourceIdentifier:\n", cert );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return rc;
        }
        DBGC2 ( cert, "X509 %p OCSP URI is:\n", cert );
        DBGC2_HDA ( cert, 0, uri->data, uri->len );

        return 0;
}
static struct x509_access_method* x509_find_access_method ( const struct asn1_cursor oid) [static, read]

Identify X.509 access method by OID.

Parameters:
oidOID
Return values:
methodAccess method, or NULL

Definition at line 646 of file x509.c.

References asn1_compare(), method, NULL, x509_access_method::oid, and x509_access_methods.

Referenced by x509_parse_access_description().

                                                          {
        struct x509_access_method *method;
        unsigned int i;

        for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
                            sizeof ( x509_access_methods[0] ) ) ; i++ ) {
                method = &x509_access_methods[i];
                if ( asn1_compare ( &method->oid, oid ) == 0 )
                        return method;
        }

        return NULL;
}
static int x509_parse_access_description ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate access description.

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

Definition at line 667 of file x509.c.

References asn1_enter(), ASN1_OID, ASN1_SEQUENCE, asn1_skip_any(), DBGC2, memcpy(), method, x509_access_method::name, x509_access_method::parse, rc, and x509_find_access_method().

Referenced by x509_parse_authority_info_access().

                                                                           {
        struct asn1_cursor cursor;
        struct asn1_cursor subcursor;
        struct x509_access_method *method;
        int rc;

        /* Enter keyPurposeId */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Try to identify access method */
        memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
        asn1_enter ( &subcursor, ASN1_OID );
        method = x509_find_access_method ( &subcursor );
        asn1_skip_any ( &cursor );
        DBGC2 ( cert, "X509 %p found access method %s\n",
                cert, ( method ? method->name : "<unknown>" ) );

        /* Parse access location, if applicable */
        if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
                return rc;

        return 0;
}
static int x509_parse_authority_info_access ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate authority information access.

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

Definition at line 700 of file x509.c.

References asn1_enter(), ASN1_SEQUENCE, asn1_skip_any(), asn1_cursor::len, memcpy(), rc, and x509_parse_access_description().

                                                                              {
        struct asn1_cursor cursor;
        int rc;

        /* Enter authorityInfoAccess */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse each access description in turn */
        while ( cursor.len ) {
                if ( ( rc = x509_parse_access_description ( cert,
                                                            &cursor ) ) != 0 )
                        return rc;
                asn1_skip_any ( &cursor );
        }

        return 0;
}
static int x509_parse_subject_alt_name ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate subject alternative name.

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

Definition at line 727 of file x509.c.

References x509_extensions::alt_name, asn1_enter(), ASN1_SEQUENCE, asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, x509_certificate::extensions, asn1_cursor::len, memcpy(), x509_subject_alt_name::names, rc, and strerror().

                                                                         {
        struct x509_subject_alt_name *alt_name = &cert->extensions.alt_name;
        struct asn1_cursor *names = &alt_name->names;
        int rc;

        /* Enter subjectAltName */
        memcpy ( names, raw, sizeof ( *names ) );
        if ( ( rc = asn1_enter ( names, ASN1_SEQUENCE ) ) != 0 ) {
                DBGC ( cert, "X509 %p invalid subjectAltName: %s\n",
                       cert, strerror ( rc ) );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return rc;
        }
        DBGC2 ( cert, "X509 %p has subjectAltName:\n", cert );
        DBGC2_HDA ( cert, 0, names->data, names->len );

        return 0;
}
static struct x509_extension* x509_find_extension ( const struct asn1_cursor oid) [static, read]

Identify X.509 extension by OID.

Parameters:
oidOID
Return values:
extensionExtension, or NULL

Definition at line 803 of file x509.c.

References asn1_compare(), NULL, x509_extension::oid, and x509_extensions.

Referenced by x509_parse_extension().

                                                      {
        struct x509_extension *extension;
        unsigned int i;

        for ( i = 0 ; i < ( sizeof ( x509_extensions ) /
                            sizeof ( x509_extensions[0] ) ) ; i++ ) {
                extension = &x509_extensions[i];
                if ( asn1_compare ( &extension->oid, oid ) == 0 )
                        return extension;
        }

        return NULL;
}
static int x509_parse_extension ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate extension.

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

Definition at line 824 of file x509.c.

References ASN1_BOOLEAN, asn1_boolean(), asn1_enter(), ASN1_OCTET_STRING, ASN1_OID, ASN1_SEQUENCE, asn1_skip_any(), asn1_type(), asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, ENOTSUP_EXTENSION, asn1_cursor::len, memcpy(), x509_extension::name, x509_extension::parse, rc, strerror(), and x509_find_extension().

Referenced by x509_parse_extensions().

                                                                  {
        struct asn1_cursor cursor;
        struct asn1_cursor subcursor;
        struct x509_extension *extension;
        int is_critical = 0;
        int rc;

        /* Enter extension */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Try to identify extension */
        memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
        asn1_enter ( &subcursor, ASN1_OID );
        extension = x509_find_extension ( &subcursor );
        asn1_skip_any ( &cursor );
        DBGC2 ( cert, "X509 %p found extension %s\n",
                cert, ( extension ? extension->name : "<unknown>" ) );

        /* Identify criticality */
        if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
                is_critical = asn1_boolean ( &cursor );
                if ( is_critical < 0 ) {
                        rc = is_critical;
                        DBGC ( cert, "X509 %p cannot parse extension "
                               "criticality: %s\n", cert, strerror ( rc ) );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return rc;
                }
                asn1_skip_any ( &cursor );
        }

        /* Handle unknown extensions */
        if ( ! extension ) {
                if ( is_critical ) {
                        /* Fail if we cannot handle a critical extension */
                        DBGC ( cert, "X509 %p cannot handle critical "
                               "extension:\n", cert );
                        DBGC_HDA ( cert, 0, raw->data, raw->len );
                        return -ENOTSUP_EXTENSION;
                } else {
                        /* Ignore unknown non-critical extensions */
                        return 0;
                }
        };

        /* Extract extnValue */
        if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
                DBGC ( cert, "X509 %p extension missing extnValue:\n", cert );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return rc;
        }

        /* Parse extension */
        if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 )
                return rc;

        return 0;
}
static int x509_parse_extensions ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate extensions, if present.

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

Definition at line 892 of file x509.c.

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_skip_any(), asn1_cursor::len, memcpy(), rc, and x509_parse_extension().

Referenced by x509_parse_tbscertificate().

                                                                   {
        struct asn1_cursor cursor;
        int rc;

        /* Enter extensions, if present */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse each extension in turn */
        while ( cursor.len ) {
                if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 )
                        return rc;
                asn1_skip_any ( &cursor );
        }

        return 0;
}
static int x509_parse_tbscertificate ( struct x509_certificate cert,
const struct asn1_cursor raw 
) [static]

Parse X.509 certificate tbsCertificate.

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

Definition at line 919 of file x509.c.

References algorithm, asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_shrink_any(), asn1_signature_algorithm(), asn1_skip_any(), asn1_type(), DBGC, DBGC2, memcpy(), rc, x509_certificate::signature_algorithm, strerror(), x509_certificate::tbs, x509_parse_extensions(), x509_parse_issuer(), x509_parse_public_key(), x509_parse_serial(), x509_parse_subject(), x509_parse_validity(), and x509_parse_version().

Referenced by x509_parse().

                                                                       {
        struct asn1_algorithm **algorithm = &cert->signature_algorithm;
        struct asn1_cursor cursor;
        int rc;

        /* Record raw tbsCertificate */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_shrink_any ( &cursor );
        memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) );

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

        /* Parse version, if present */
        if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
                if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 )
                        return rc;
                asn1_skip_any ( &cursor );
        }

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

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

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

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

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

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

        /* Parse extensions, if present */
        if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 )
                return rc;

        return 0;
}
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;
}
static int x509_check_signature ( struct x509_certificate cert,
struct x509_public_key public_key 
) [static]

Check X.509 certificate signature.

Parameters:
certX.509 certificate
public_keyX.509 public key
Return values:
rcReturn status code

Definition at line 1105 of file x509.c.

References x509_public_key::algorithm, x509_signature::algorithm, algorithm, assert, digest_algorithm::ctxsize, pubkey_algorithm::ctxsize, asn1_cursor::data, asn1_bit_string::data, DBGC, DBGC2, DBGC2_HDA, digest, asn1_algorithm::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, EINVAL_ALGORITHM_MISMATCH, asn1_cursor::len, asn1_bit_string::len, asn1_algorithm::name, asn1_algorithm::pubkey, pubkey_final(), pubkey_init(), pubkey_verify(), x509_public_key::raw, rc, x509_certificate::signature, signature, x509_certificate::signature_algorithm, strerror(), x509_certificate::tbs, x509_signature::value, and x509_name().

Referenced by x509_check_issuer().

                                                                       {
        struct x509_signature *signature = &cert->signature;
        struct asn1_algorithm *algorithm = signature->algorithm;
        struct digest_algorithm *digest = algorithm->digest;
        struct pubkey_algorithm *pubkey = algorithm->pubkey;
        uint8_t digest_ctx[ digest->ctxsize ];
        uint8_t digest_out[ digest->digestsize ];
        uint8_t pubkey_ctx[ pubkey->ctxsize ];
        int rc;

        /* Sanity check */
        assert ( cert->signature_algorithm == cert->signature.algorithm );

        /* Calculate certificate digest */
        digest_init ( digest, digest_ctx );
        digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
        digest_final ( digest, digest_ctx, digest_out );
        DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) );
        DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );

        /* Check that signature public key algorithm matches signer */
        if ( public_key->algorithm->pubkey != pubkey ) {
                DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
                       "match signer's algorithm %s\n",
                       cert, x509_name ( cert ), algorithm->name,
                       public_key->algorithm->name );
                rc = -EINVAL_ALGORITHM_MISMATCH;
                goto err_mismatch;
        }

        /* Verify signature using signer's public key */
        if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
                                  public_key->raw.len ) ) != 0 ) {
                DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
                       "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
                goto err_pubkey_init;
        }
        if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
                                    signature->value.data,
                                    signature->value.len ) ) != 0 ) {
                DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
                       "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
                goto err_pubkey_verify;
        }

        /* Success */
        rc = 0;

 err_pubkey_verify:
        pubkey_final ( pubkey, pubkey_ctx );
 err_pubkey_init:
 err_mismatch:
        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;
}
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;
}
static int x509_check_dnsname ( struct x509_certificate cert,
const struct asn1_cursor raw,
const char *  name 
) [static]

Check X.509 certificate alternative dNSName.

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

Definition at line 1395 of file x509.c.

References asn1_cursor::data, DBGC2, ENOENT, asn1_cursor::len, len, memcmp(), name, strchr(), strlen(), and x509_name().

Referenced by x509_check_alt_name(), and x509_check_name().

                                                   {
        const char *fullname = name;
        const char *dnsname = raw->data;
        size_t len = raw->len;

        /* Check for wildcards */
        if ( ( len >= 2 ) && ( dnsname[0] == '*' ) && ( dnsname[1] == '.' ) ) {

                /* Skip initial "*." */
                dnsname += 2;
                len -= 2;

                /* Skip initial portion of name to be tested */
                name = strchr ( name, '.' );
                if ( ! name )
                        return -ENOENT;
                name++;
        }

        /* Compare names */
        if ( ! ( ( strlen ( name ) == len ) &&
                 ( memcmp ( name, dnsname, len ) == 0 ) ) )
                return -ENOENT;

        if ( name != fullname ) {
                DBGC2 ( cert, "X509 %p \"%s\" found wildcard match for "
                        "\"*.%s\"\n", cert, x509_name ( cert ), name );
        }
        return 0;
}
static int x509_check_ipaddress ( struct x509_certificate cert,
const struct asn1_cursor raw,
const char *  name 
) [static]

Check X.509 certificate alternative iPAddress.

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

Definition at line 1436 of file x509.c.

References address, AF_INET, AF_INET6, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, EINVAL, ENOENT, asn1_cursor::len, memcmp(), rc, sockaddr::sa_family, sin, sin6, sockaddr_in6::sin6_addr, sockaddr_in::sin_addr, sock_aton(), sock_ntoa(), strerror(), and x509_name().

Referenced by x509_check_alt_name().

                                                     {
        struct sockaddr sa;
        sa_family_t family;
        const void *address;
        int rc;

        /* Determine address family */
        if ( raw->len == sizeof ( struct in_addr ) ) {
                struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa );
                family = AF_INET;
                address = &sin->sin_addr;
        } else if ( raw->len == sizeof ( struct in6_addr ) ) {
                struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa );
                family = AF_INET6;
                address = &sin6->sin6_addr;
        } else {
                DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected "
                       "length %zd\n", cert, x509_name ( cert ), raw->len );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
                return -EINVAL;
        }

        /* Attempt to convert name to a socket address */
        if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) {
                DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as "
                        "iPAddress: %s\n", cert, x509_name ( cert ), name,
                        strerror ( rc ) );
                return rc;
        }
        if ( sa.sa_family != family )
                return -ENOENT;

        /* Compare addresses */
        if ( memcmp ( address, raw->data, raw->len ) != 0 )
                return -ENOENT;

        DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n",
                cert, x509_name ( cert ), sock_ntoa ( &sa ) );
        return 0;
}
static int x509_check_alt_name ( struct x509_certificate cert,
const struct asn1_cursor raw,
const char *  name 
) [static]

Check X.509 certificate alternative name.

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

Definition at line 1487 of file x509.c.

References asn1_enter_any(), asn1_type(), asn1_cursor::data, DBGC2, DBGC2_HDA, ENOTSUP, asn1_cursor::len, memcpy(), type, x509_check_dnsname(), x509_check_ipaddress(), X509_GENERAL_NAME_DNS, X509_GENERAL_NAME_IP, and x509_name().

Referenced by x509_check_name().

                                                    {
        struct asn1_cursor alt_name;
        unsigned int type;

        /* Enter generalName */
        memcpy ( &alt_name, raw, sizeof ( alt_name ) );
        type = asn1_type ( &alt_name );
        asn1_enter_any ( &alt_name );

        /* Check this name */
        switch ( type ) {
        case X509_GENERAL_NAME_DNS :
                return x509_check_dnsname ( cert, &alt_name, name );
        case X509_GENERAL_NAME_IP :
                return x509_check_ipaddress ( cert, &alt_name, name );
        default:
                DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n",
                        cert, x509_name ( cert ), type );
                DBGC2_HDA ( cert, 0, alt_name.data, alt_name.len );
                return -ENOTSUP;
        }
}
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;
}
static void x509_free_chain ( struct refcnt refcnt) [static]

Free X.509 certificate chain.

Parameters:
refcntReference count

Definition at line 1553 of file x509.c.

References x509_link::cert, container_of, DBGC2, free, link, x509_chain::links, x509_link::list, list_del, list_for_each_entry_safe, and x509_put().

Referenced by x509_alloc_chain().

                                                      {
        struct x509_chain *chain =
                container_of ( refcnt, struct x509_chain, refcnt );
        struct x509_link *link;
        struct x509_link *tmp;

        DBGC2 ( chain, "X509 chain %p freed\n", chain );

        /* Free each link in the chain */
        list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
                x509_put ( link->cert );
                list_del ( &link->list );
                free ( link );
        }

        /* Free chain */
        free ( chain );
}
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;
}
static struct x509_certificate* x509_find_subject ( struct x509_chain certs,
const struct asn1_cursor subject 
) [static, read]

Identify X.509 certificate by subject.

Parameters:
certsX.509 certificate list
subjectSubject
Return values:
certX.509 certificate, or NULL if not found

Definition at line 1657 of file x509.c.

References asn1_compare(), x509_link::cert, link, x509_chain::links, list_for_each_entry, NULL, x509_subject::raw, and x509_certificate::subject.

Referenced by x509_auto_append().

                                                        {
        struct x509_link *link;
        struct x509_certificate *cert;

        /* Scan through certificate list */
        list_for_each_entry ( link, &certs->links, list ) {

                /* Check subject */
                cert = link->cert;
                if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
                        return cert;
        }

        return NULL;
}
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;
}
REQUIRE_OBJECT ( config_crypto  )

Variable Documentation

"commonName" object identifier

Definition at line 155 of file x509.c.

Initial value:

"commonName" object identifier cursor

Definition at line 158 of file x509.c.

"id-kp-codeSigning" object identifier

Definition at line 516 of file x509.c.

"id-kp-OCSPSigning" object identifier

Definition at line 519 of file x509.c.

Initial value:
 {
        {
                .name = "codeSigning",
                .bits = X509_CODE_SIGNING,
                .oid = ASN1_OID_CURSOR ( oid_code_signing ),
        },
        {
                .name = "ocspSigning",
                .bits = X509_OCSP_SIGNING,
                .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ),
        },
}

Supported key purposes.

Definition at line 522 of file x509.c.

Referenced by x509_parse_key_purpose().

uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP } [static]

"id-ad-ocsp" object identifier

Definition at line 628 of file x509.c.

Initial value:
 {
        {
                .name = "OCSP",
                .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
                .parse = x509_parse_ocsp,
        },
}

Supported access methods.

Definition at line 631 of file x509.c.

Referenced by x509_find_access_method().

Initial value:

"id-ce-basicConstraints" object identifier

Definition at line 748 of file x509.c.

Initial value:

"id-ce-keyUsage" object identifier

Definition at line 752 of file x509.c.

Initial value:

"id-ce-extKeyUsage" object identifier

Definition at line 756 of file x509.c.

Initial value:

"id-pe-authorityInfoAccess" object identifier

Definition at line 760 of file x509.c.

Initial value:

"id-ce-subjectAltName" object identifier

Definition at line 764 of file x509.c.

struct x509_extension x509_extensions[] [static]
Initial value:
 {
        {
                .name = "basicConstraints",
                .oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ),
                .parse = x509_parse_basic_constraints,
        },
        {
                .name = "keyUsage",
                .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
                .parse = x509_parse_key_usage,
        },
        {
                .name = "extKeyUsage",
                .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
                .parse = x509_parse_extended_key_usage,
        },
        {
                .name = "authorityInfoAccess",
                .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
                .parse = x509_parse_authority_info_access,
        },
        {
                .name = "subjectAltName",
                .oid = ASN1_OID_CURSOR ( oid_ce_subject_alt_name ),
                .parse = x509_parse_subject_alt_name,
        },
}

Supported certificate extensions.

Definition at line 768 of file x509.c.

Referenced by x509_find_extension().