LCOV - code coverage report
Current view: top level - ballet/x509 - fd_x509_verify.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 21 22 95.5 %
Date: 2026-09-17 04:28:31 Functions: 1 14 7.1 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_x509_fd_x509_verify_h
       2             : #define HEADER_fd_src_ballet_x509_fd_x509_verify_h
       3             : 
       4             : /* fd_x509_verify.h provides certificate chain verification.  Walks the
       5             :    chain from leaf cert through intermediates to a trusted root CA,
       6             :    verifying each signature.
       7             : 
       8             :    Ensures:
       9             :    - Each cert on the path is signed by an issuer found among the other
      10             :      presented certs (in any order, RFC 8446 Section 4.4.2) or by a
      11             :      trust anchor
      12             :    - Where a presented cert is the issuer, its subject matches and it
      13             :      has basicConstraints cA=TRUE
      14             :    - The path terminates at a trust anchor in the CA store (one whose
      15             :      extKeyUsage, if any, permits serverAuth; the store loader drops
      16             :      the rest)
      17             :    - Hostname: the leaf cert's SAN must match the expected hostname
      18             :    - Every cert on the path is within its validity period
      19             :    - Leaf/issuer key usage restrictions met
      20             :    - Intermediate CA and trust anchor path length constraints are
      21             :      respected
      22             :    - dNSName, iPAddress and directoryName nameConstraints on
      23             :      intermediate CAs and on the trust anchor are respected; a
      24             :      constraint of any other name form rejects certs that carry a SAN of
      25             :      that form, and a CA constraining rfc822Name does not parse at all
      26             : 
      27             :    We do NOT check:
      28             :    - Certificate revocation (CRL / OCSP) */
      29             : 
      30             : #include "fd_x509.h"
      31             : #include "../../util/log/fd_log.h"
      32             : #include "fd_x509_ca_store.h"
      33             : 
      34             : /* FD_X509_CERT_SZ_MAX bounds each DER-encoded certificate accepted by
      35             :    the verifier.  64 KiB is well above ordinary web PKI cert sizes.
      36             : 
      37             :    FD_X509_CHAIN_MAX bounds the number of certs in a presented path. */
      38             : 
      39           3 : #define FD_X509_CERT_SZ_MAX (64UL<<10)
      40        1521 : #define FD_X509_CHAIN_MAX   (8UL)
      41             : 
      42       15765 : #define FD_X509_VERIFY_OK                  (0)
      43          57 : #define FD_X509_VERIFY_ERR_PARSE           (1)  /* certificate parse failed */
      44          21 : #define FD_X509_VERIFY_ERR_CHAIN_BREAK     (2)  /* issuer/subject mismatch in chain */
      45          18 : #define FD_X509_VERIFY_ERR_SIG             (3)  /* signature verification failed */
      46           3 : #define FD_X509_VERIFY_ERR_CA_FLAG         (4)  /* intermediate missing CA flag */
      47          66 : #define FD_X509_VERIFY_ERR_NO_TRUST_ANCHOR (5)  /* root not found in CA store */
      48          48 : #define FD_X509_VERIFY_ERR_HOSTNAME        (6)  /* SAN doesn't match hostname */
      49           0 : #define FD_X509_VERIFY_ERR_UNSUPPORTED     (7)  /* unsupported signature algorithm or leaf key type */
      50           9 : #define FD_X509_VERIFY_ERR_CHAIN_TOO_LONG  (8)  /* chain exceeds FD_X509_CHAIN_MAX */
      51          12 : #define FD_X509_VERIFY_ERR_TIME_PARSE      (9)  /* malformed validity period */
      52          24 : #define FD_X509_VERIFY_ERR_NOT_YET_VALID  (10)  /* now_unix < notBefore */
      53          36 : #define FD_X509_VERIFY_ERR_EXPIRED        (11)  /* now_unix > notAfter */
      54          30 : #define FD_X509_VERIFY_ERR_KEY_USAGE      (12)  /* keyUsage forbids this role */
      55          27 : #define FD_X509_VERIFY_ERR_EXT_KEY_USAGE  (13)  /* extKeyUsage lacks serverAuth */
      56          33 : #define FD_X509_VERIFY_ERR_PATH_LEN       (14)  /* basicConstraints path length exceeded */
      57        1617 : #define FD_X509_VERIFY_ERR_CERT_TOO_LARGE (15)  /* cert exceeds FD_X509_CERT_SZ_MAX */
      58         150 : #define FD_X509_VERIFY_ERR_NAME_CONSTRAINT (16) /* CA nameConstraints rejected a name */
      59             : 
      60             : FD_PROTOTYPES_BEGIN
      61             : 
      62             : /* fd_x509_verify_chain verifies a TLS certificate chain.
      63             : 
      64             :    chain_der is an array of DER-encoded certificates, chain_der_sz is
      65             :    the corresponding array of sizes.  chain_cnt is the number of
      66             :    certificates.  The first entry is the leaf cert.
      67             : 
      68             :    ca_store is the trusted CA store to anchor the chain against.
      69             : 
      70             :    hostname/hostname_len is the expected server hostname for SAN
      71             :    matching. hostname may be NULL or hostname_len may be 0 to skip
      72             :    hostname verification.
      73             : 
      74             :    Returns FD_X509_VERIFY_OK on success, or a non-zero error code on
      75             :    failure. */
      76             : int
      77             : fd_x509_verify_chain( uchar const * const *        chain_der,
      78             :                       ulong const *                chain_der_sz,
      79             :                       ulong                        chain_cnt,
      80             :                       fd_x509_ca_store_t const *   ca_store,
      81             :                       char const *                 hostname,
      82             :                       ulong                        hostname_len,
      83             :                       long                         unix_seconds );
      84             : 
      85             : /* fd_x509_verify_tls_cert_msg verifies the server certificate chain
      86             :    carried in the body of a TLS 1.3 Certificate handshake message (RFC
      87             :    8446 Section 4.4.2), i.e. an empty certificate_request_context followed
      88             :    by a CertificateList.  Parses the chain, then verifies it with
      89             :    fd_x509_verify_chain.  ca_store, hostname and hostname_len are as
      90             :    documented there.
      91             : 
      92             :    Returns FD_X509_VERIFY_OK on success, or a non-zero error code on
      93             :    failure. */
      94             : 
      95             : int
      96             : fd_x509_verify_tls_cert_msg( uchar const *              cert_msg,
      97             :                              ulong                      cert_msg_sz,
      98             :                              fd_x509_ca_store_t const * ca_store,
      99             :                              char const *               hostname,
     100             :                              ulong                      hostname_len,
     101             :                              long                       unix_seconds );
     102             : 
     103             : /* fd_x509_unix_now_seconds returns the current wallclock time in
     104             :    seconds since the Unix epoch. */
     105             : 
     106             : FD_FN_UNUSED static inline long
     107        1092 : fd_x509_unix_now_seconds( void ) {
     108        1092 :   return fd_log_wallclock() / 1000000000L;
     109        1092 : }
     110             : 
     111             : FD_PROTOTYPES_END
     112             : 
     113             : #endif /* HEADER_fd_src_ballet_x509_fd_x509_verify_h */

Generated by: LCOV version 1.14