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 */