Line data Source code
1 : #ifndef HEADER_fd_src_discof_failover_fd_failover_tls_h 2 : #define HEADER_fd_src_discof_failover_fd_failover_tls_h 3 : 4 : /* TLS 1.3 over TCP for one failover candidate, built on fd_tls, 5 : fd_tlsrec and fd_tlsrec_sock. Both ends present an Ed25519 cert for 6 : the identity they hand off. The channel admits a peer before TLS and 7 : checks its TLS key against the admitted HELLO. The caller owns the 8 : socket. */ 9 : 10 : #include "../../waltz/tlsrec/fd_tlsrec_sock.h" 11 : #include "../../ballet/chacha/fd_chacha_rng.h" 12 : 13 : /* Max ciphertext accepted from a candidate before it pairs */ 14 0 : #define FD_FAILOVER_TLS_PREPAIR_MAX (32768UL) 15 : 16 : /* Per-channel TLS config, the fd_tls template and its RNG. The sign 17 : tile signs our CertificateVerify, no private key is kept here. */ 18 : 19 : struct fd_failover_tls_ctx { 20 : fd_tls_t tls; 21 : fd_chacha_rng_t rng[ 1 ]; 22 : int ready; /* set by init and wiped by fini, fd_failover_tls_new fails without it */ 23 : }; 24 : typedef struct fd_failover_tls_ctx fd_failover_tls_ctx_t; 25 : 26 : /* One TLS connection. */ 27 : 28 : struct fd_failover_tls { 29 : fd_tlsrec_conn_t conn; 30 : fd_tlsrec_sock_t sock; 31 : int fd; 32 : int verified; /* handshake done, peer_pubkey is set */ 33 : int paired; /* set by the channel after HELLO */ 34 : int peer_closed; /* orderly EOF or close_notify */ 35 : uchar peer_pubkey[ 32 ]; /* the key the peer signed the handshake with */ 36 : ulong received; /* ciphertext bytes read before pairing */ 37 : }; 38 : typedef struct fd_failover_tls fd_failover_tls_t; 39 : 40 : FD_PROTOTYPES_BEGIN 41 : 42 : /* fd_failover_tls_ctx_init sets the public key of our cert and the 43 : signer for CertificateVerify and seeds the RNG. It and every new 44 : connection read entropy from getrandom. Returns 0 on success, -1 if 45 : entropy fails. */ 46 : 47 : int 48 : fd_failover_tls_ctx_init( fd_failover_tls_ctx_t * ctx, 49 : uchar const public_key[ 32 ], 50 : fd_tls_sign_t signer ); 51 : 52 : /* fd_failover_tls_ctx_fini wipes the context. */ 53 : 54 : void 55 : fd_failover_tls_ctx_fini( fd_failover_tls_ctx_t * ctx ); 56 : 57 : /* fd_failover_tls_new binds a fresh connection to fd. The listener 58 : requires a client cert. Returns 0 on success, -1 if ctx is not 59 : initialized or entropy fails. */ 60 : 61 : int 62 : fd_failover_tls_new( fd_failover_tls_t * tls, 63 : fd_failover_tls_ctx_t * ctx, 64 : int fd, 65 : int dial_peer ); 66 : 67 : /* Prepare the outbound ClientHello without sending it, or feed an 68 : admitted peer flight to the connection without socket I/O. The 69 : generated reply is left in sock.tx_buf for the caller to capture or 70 : flush with fd_tlsrec_sock_flush. No earlier output may be pending. */ 71 : int 72 : fd_failover_tls_client_hello( fd_failover_tls_t * tls, uchar * out, ulong * out_sz ); 73 : 74 : int 75 : fd_failover_tls_accept_flight( fd_failover_tls_t * tls, uchar const * data, ulong sz ); 76 : 77 : /* fd_failover_tls_fini sends close_notify if the connection is up and 78 : wipes the connection state. The caller closes fd. */ 79 : 80 : void 81 : fd_failover_tls_fini( fd_failover_tls_t * tls ); 82 : 83 : /* fd_failover_tls_handshake returns 1 once the handshake is done and 84 : the peer signed it with an Ed25519 key, which is then in peer_pubkey, 85 : 0 while pending, -1 on failure. fd_failover_tls_read and 86 : fd_failover_tls_write return bytes moved, 0 when pending, -1 on error 87 : or peer close. A write may take fewer bytes than offered (at most one 88 : record), callers are responsible for retrying to obtain the rest. */ 89 : 90 : int 91 : fd_failover_tls_handshake( fd_failover_tls_t * tls ); 92 : 93 : long 94 : fd_failover_tls_read( fd_failover_tls_t * tls, 95 : void * buf, 96 : ulong sz ); 97 : 98 : long 99 : fd_failover_tls_write( fd_failover_tls_t * tls, 100 : void const * buf, 101 : ulong sz ); 102 : 103 : FD_PROTOTYPES_END 104 : 105 : #endif /* HEADER_fd_src_discof_failover_fd_failover_tls_h */