// SPDX-FileCopyrightText: © 2022—2026 Vladimir Zorin // SPDX-License-Identifier: LicenseRef-OWL-1.0-or-later // Licensed under OWL v1.0+. See LICENSE. /* * LITLS -- TLS 1.3 Client Implementation * Internal structures and prototypes for the TLS 1.3 record layer, * key schedule, handshake parser/builder, and client state machine. */ #ifndef LITLS_TLS13_H #define LITLS_TLS13_H #include "../litls.h" #include #include /* ── TLS 1.3 constants ────────────────────────────────────────────── */ #define TLS13_VERSION_12 0x0303 /* legacy in record layer */ #define TLS13_VERSION_13 0x0304 #define TLS13_MAX_RECORD 16384 #define TLS13_RECORD_HDR 5 #define TLS13_TAG_LEN 16 /* AEAD tag */ #define TLS13_MAX_CIPHERTEXT (TLS13_MAX_RECORD + 256) /* with padding + tag + content type */ /* Content types */ #define TLS13_CT_CHANGE_CIPHER_SPEC 0x14 #define TLS13_CT_ALERT 0x15 #define TLS13_CT_HANDSHAKE 0x16 #define TLS13_CT_APPLICATION_DATA 0x17 /* Handshake types */ #define TLS13_HT_CLIENT_HELLO 1 #define TLS13_HT_SERVER_HELLO 2 #define TLS13_HT_NEW_SESSION_TICKET 4 #define TLS13_HT_ENCRYPTED_EXTENSIONS 8 #define TLS13_HT_CERTIFICATE 11 #define TLS13_HT_CERTIFICATE_REQUEST 13 #define TLS13_HT_CERTIFICATE_VERIFY 15 #define TLS13_HT_FINISHED 20 #define TLS13_HT_KEY_UPDATE 24 /* Alert descriptions */ #define TLS13_ALERT_CLOSE_NOTIFY 0 #define TLS13_ALERT_UNEXPECTED_MESSAGE 10 #define TLS13_ALERT_BAD_RECORD_MAC 20 #define TLS13_ALERT_HANDSHAKE_FAILURE 40 #define TLS13_ALERT_CERTIFICATE_UNKNOWN 46 #define TLS13_ALERT_DECODE_ERROR 50 #define TLS13_ALERT_DECRYPT_ERROR 51 #define TLS13_ALERT_PROTOCOL_VERSION 70 #define TLS13_ALERT_INTERNAL_ERROR 80 /* Cipher suite IDs */ #define TLS13_AES_128_GCM_SHA256 0x1301 #define TLS13_AES_256_GCM_SHA384 0x1302 #define TLS13_CHACHA20_POLY1305_SHA256 0x1303 /* Signature algorithms */ #define TLS13_SIG_ECDSA_SECP256R1_SHA256 0x0403 #define TLS13_SIG_RSA_PSS_RSAE_SHA256 0x0804 #define TLS13_SIG_ED25519 0x0807 #define TLS13_SIG_RSA_PKCS1_SHA256 0x0401 /* Named groups */ #define TLS13_GROUP_X25519 0x001D /* Extensions */ #define TLS13_EXT_SERVER_NAME 0x0000 #define TLS13_EXT_SUPPORTED_GROUPS 0x000A #define TLS13_EXT_SIGNATURE_ALGORITHMS 0x000D #define TLS13_EXT_SUPPORTED_VERSIONS 0x002B #define TLS13_EXT_COOKIE 0x002C #define TLS13_EXT_KEY_SHARE 0x0033 /* HelloRetryRequest magic (SHA-256 of "HelloRetryRequest") */ extern const uint8_t TLS13_HRR_RANDOM[32]; /* ── I/O signaling ────────────────────────────────────────────────── */ typedef enum { LITLS_WANT_READ = 1, LITLS_WANT_WRITE = 2, LITLS_DONE = 3, LITLS_ERROR = -1, LITLS_CLOSED = -2 } litls_io_want; /* ── Handshake states ─────────────────────────────────────────────── */ typedef enum { /* Client states */ TLS13_HS_SEND_CLIENT_HELLO, TLS13_HS_RECV_SERVER_HELLO, TLS13_HS_RECV_ENCRYPTED_EXTENSIONS, TLS13_HS_RECV_CERTIFICATE, TLS13_HS_RECV_CERTIFICATE_VERIFY, TLS13_HS_RECV_FINISHED, TLS13_HS_SEND_CLIENT_CERTIFICATE, TLS13_HS_SEND_CLIENT_CERTIFICATE_VERIFY, TLS13_HS_SEND_FINISHED, /* Server states */ TLS13_HS_SRV_RECV_CLIENT_HELLO, TLS13_HS_SRV_SEND_SERVER_HELLO, TLS13_HS_SRV_SEND_ENCRYPTED_EXTENSIONS, TLS13_HS_SRV_SEND_CERTIFICATE, TLS13_HS_SRV_SEND_CERTIFICATE_VERIFY, TLS13_HS_SRV_SEND_FINISHED, TLS13_HS_SRV_RECV_FINISHED, /* Shared terminal state */ TLS13_HS_DONE } litls_hs_state; /* ── Cipher suite dispatch ────────────────────────────────────────── */ typedef int (*litls_aead_encrypt_fn)(const uint8_t *key, const uint8_t *nonce, const uint8_t *aad, size_t aad_len, const uint8_t *pt, size_t pt_len, uint8_t *ct, uint8_t tag[16]); typedef int (*litls_aead_decrypt_fn)(const uint8_t *key, const uint8_t *nonce, const uint8_t *aad, size_t aad_len, const uint8_t *ct, size_t ct_len, const uint8_t tag[16], uint8_t *pt); typedef struct { uint16_t id; int hash_len; /* 32 for SHA-256, 48 for SHA-384 */ int key_len; int iv_len; litls_aead_encrypt_fn encrypt; litls_aead_decrypt_fn decrypt; } litls_cipher_suite; /* ── Traffic keys (per direction) ─────────────────────────────────── */ typedef struct { uint8_t key[32]; uint8_t iv[12]; uint64_t seq; } litls_traffic_keys; /* ── I/O buffer ───────────────────────────────────────────────────── */ typedef struct { uint8_t data[TLS13_MAX_CIPHERTEXT + TLS13_RECORD_HDR + 256]; size_t len; /* bytes in buffer */ size_t pos; /* bytes consumed / written */ } litls_iobuf; /* ── Transcript hash ──────────────────────────────────────────────── */ typedef struct { litls_sha256_ctx sha256; litls_sha384_ctx sha384; int use_384; /* 0 = SHA-256, 1 = SHA-384, -1 = both (before suite selected) */ } litls_transcript; /* ── Server identity (pre-parsed cert + key) ─────────────────────── */ #define LITLS_MAX_CERT_CHAIN_DER 16384 typedef struct { char hostname[256]; uint8_t cert_chain_der[LITLS_MAX_CERT_CHAIN_DER]; size_t cert_der_offsets[LITLS_X509_MAX_CHAIN]; size_t cert_der_lens[LITLS_X509_MAX_CHAIN]; int cert_count; int key_type; /* LITLS_KEY_ECDSA_P256 or LITLS_KEY_ED25519 */ uint8_t private_key[64]; /* 32 for P-256, 64 for Ed25519 secret_key */ size_t private_key_len; uint8_t public_key[65]; /* 65 for P-256 uncompressed, 32 for Ed25519 */ size_t public_key_len; } litls_server_identity; /* ── Main TLS 1.3 connection context ──────────────────────────────── */ #define TLS13_HS_BUF_SIZE 65536 #define TLS13_APP_BUF_SIZE 16384 #define TLS13_MAX_SNI_LEN 256 typedef struct { /* Socket */ int fd; /* Handshake state */ litls_hs_state hs_state; /* Selected cipher suite */ litls_cipher_suite suite; /* Key exchange material */ uint8_t x25519_priv[32]; uint8_t x25519_pub[32]; uint8_t shared_secret[32]; /* Traffic keys */ litls_traffic_keys hs_read; litls_traffic_keys hs_write; litls_traffic_keys app_read; litls_traffic_keys app_write; int encrypting; /* handshake keys installed for writing */ int decrypting; /* handshake keys installed for reading */ /* I/O buffers */ litls_iobuf rbuf; litls_iobuf wbuf; /* Handshake reassembly */ uint8_t hs_buf[TLS13_HS_BUF_SIZE]; size_t hs_buf_len; size_t hs_msg_expected; /* total expected handshake message length (0 = unknown) */ /* Application plaintext buffer (decrypted data ready for read) */ uint8_t app_buf[TLS13_APP_BUF_SIZE]; size_t app_buf_len; size_t app_buf_pos; /* Transcript hash */ litls_transcript transcript; /* Handshake secrets for Finished verify */ uint8_t server_hs_secret[48]; /* max hash_len */ uint8_t client_hs_secret[48]; uint8_t master_secret[48]; /* Certificate verification config */ int verify; const litls_x509_trust_anchor *anchors; int anchor_count; /* SNI */ char sni[TLS13_MAX_SNI_LEN]; /* HelloRetryRequest state */ int hrr_seen; /* current ServerHello message is an HRR */ int hrr_done; /* an HRR has already been processed this handshake */ uint16_t hrr_suite; /* cipher suite committed in the HRR */ uint8_t hrr_cookie[512]; size_t hrr_cookie_len; /* Error */ char error[256]; /* close_notify received */ int peer_closed; /* Server-specific fields */ int is_server; litls_server_identity *identity; /* selected identity (default or SNI match), not owned */ litls_server_identity *sni_hosts; /* SNI table, not owned */ int sni_host_count; uint16_t peer_sig_algos[8]; int peer_sig_algo_count; int peer_sent_sig_algos; /* 1 if client sent signature_algorithms extension */ uint8_t session_id[32]; /* client's session_id for echo in ServerHello */ uint8_t session_id_len; /* Per-connection leaf cert info (client only, used across handshake states) */ litls_x509_cert_info leaf_cert; /* Client identity for mTLS (caller-owned, not freed by ctx) */ litls_server_identity *client_identity; int cert_requested; /* 1 if server sent CertificateRequest */ uint8_t cert_request_ctx[256]; /* certificate_request_context echo */ size_t cert_request_ctx_len; /* Per-connection decrypt buffer (avoids static shared across coroutines) */ uint8_t decrypt_buf[TLS13_MAX_CIPHERTEXT + 256]; } litls_tls13_ctx; /* ── Record layer (record.c) ──────────────────────────────────────── */ litls_io_want litls_record_fill(litls_tls13_ctx *ctx); litls_io_want litls_record_flush(litls_tls13_ctx *ctx); /* Write a record into wbuf. Encrypts if keys are installed. */ int litls_record_write(litls_tls13_ctx *ctx, uint8_t content_type, const uint8_t *data, size_t len); /* Read and decrypt a complete record from rbuf. * Returns content type via *ct, data via *out and *out_len. * *out points into ctx internal buffer. * Returns 0 on success, 1 if incomplete (need more data), -1 on error. */ int litls_record_read(litls_tls13_ctx *ctx, uint8_t *ct, uint8_t **out, size_t *out_len); /* Build per-record nonce: iv XOR seq */ void litls_record_nonce(const litls_traffic_keys *keys, uint8_t nonce[12]); /* ── Key schedule (keys.c) ────────────────────────────────────────── */ int litls_tls13_expand_label_256(const uint8_t secret[32], const char *label, const uint8_t *context, size_t context_len, uint8_t *out, size_t out_len); int litls_tls13_expand_label_384(const uint8_t secret[48], const char *label, const uint8_t *context, size_t context_len, uint8_t *out, size_t out_len); int litls_tls13_derive_secret_256(const uint8_t secret[32], const char *label, const uint8_t transcript_hash[32], uint8_t out[32]); int litls_tls13_derive_secret_384(const uint8_t secret[48], const char *label, const uint8_t transcript_hash[48], uint8_t out[48]); int litls_tls13_derive_handshake_keys(litls_tls13_ctx *ctx); int litls_tls13_derive_app_keys(litls_tls13_ctx *ctx); void litls_tls13_traffic_keys_256(const uint8_t traffic_secret[32], uint8_t *key, size_t key_len, uint8_t iv[12]); void litls_tls13_traffic_keys_384(const uint8_t traffic_secret[48], uint8_t *key, size_t key_len, uint8_t iv[12]); /* ── Handshake messages (handshake.c) ─────────────────────────────── */ int litls_build_client_hello(litls_tls13_ctx *ctx, uint8_t *out, size_t cap, size_t *out_len); int litls_parse_server_hello(litls_tls13_ctx *ctx, const uint8_t *data, size_t len); int litls_parse_encrypted_extensions(litls_tls13_ctx *ctx, const uint8_t *data, size_t len); int litls_parse_certificate(litls_tls13_ctx *ctx, const uint8_t *data, size_t len, const uint8_t **chain_ders, size_t *chain_lens, int *chain_count, int max_chain); int litls_parse_certificate_verify(litls_tls13_ctx *ctx, const uint8_t *data, size_t len, uint16_t *sig_algo, const uint8_t **sig_out, size_t *sig_len_out); int litls_parse_finished(litls_tls13_ctx *ctx, const uint8_t *data, size_t len, const uint8_t **verify_data, size_t *verify_len); /* Transcript hash management */ void litls_transcript_init(litls_transcript *t); void litls_transcript_update(litls_transcript *t, const uint8_t *data, size_t len); void litls_transcript_hash(const litls_transcript *t, uint8_t *out); int litls_transcript_hash_len(const litls_transcript *t); /* Handshake reassembly: feed record data, get complete messages. * Returns number of complete bytes available, or -1 on error. * When a complete message is available, *msg_type, *msg, *msg_len are set. */ int litls_hs_reassemble(litls_tls13_ctx *ctx, const uint8_t *data, size_t data_len, uint8_t *msg_type, const uint8_t **msg, size_t *msg_len); /* ── Shared handshake helpers (handshake.c) ───────────────────────── */ /* Initialize cipher suite fields on ctx from a suite ID. Returns 0 or -1. */ int litls_init_cipher_suite(litls_tls13_ctx *ctx, uint16_t suite_id); /* Get the next complete handshake message (from hs_buf or by reading a record). * Returns 1 if ready, 0 if need more data, -1 error, -2 closed. */ int litls_get_hs_message(litls_tls13_ctx *ctx, uint8_t *msg_type, const uint8_t **msg, size_t *msg_len); /* Consume the processed handshake message from hs_buf. */ void litls_consume_hs_message(litls_tls13_ctx *ctx, size_t msg_len); /* Build a Finished message using the given handshake secret. * out must be at least 4 + 48 bytes. */ int litls_build_finished(litls_tls13_ctx *ctx, const uint8_t *hs_secret, uint8_t *out, size_t *out_len); /* Server-side handshake message parsers/builders (handshake.c) */ int litls_parse_client_hello(litls_tls13_ctx *ctx, const uint8_t *data, size_t len); int litls_build_server_hello(litls_tls13_ctx *ctx, uint8_t *out, size_t cap, size_t *out_len); int litls_build_encrypted_extensions(uint8_t *out, size_t cap, size_t *out_len); int litls_build_certificate(const litls_server_identity *id, const uint8_t *cert_req_ctx, size_t cert_req_ctx_len, uint8_t *out, size_t cap, size_t *out_len); int litls_build_certificate_verify(litls_tls13_ctx *ctx, const litls_server_identity *id, int is_server, uint8_t *out, size_t cap, size_t *out_len); int litls_parse_certificate_request(litls_tls13_ctx *ctx, const uint8_t *data, size_t len); /* ── Client state machine (client.c) ──────────────────────────────── */ int litls_tls13_client_init(litls_tls13_ctx *ctx, int fd, int verify, const char *sni, const litls_x509_trust_anchor *anchors, int anchor_count, litls_server_identity *client_identity); litls_io_want litls_tls13_handshake_step(litls_tls13_ctx *ctx); int litls_tls13_write(litls_tls13_ctx *ctx, const uint8_t *data, size_t len); int litls_tls13_read(litls_tls13_ctx *ctx, uint8_t *buf, size_t cap); int litls_tls13_shutdown(litls_tls13_ctx *ctx); /* ── Server state machine (server.c) ─────────────────────────────── */ int litls_tls13_server_init(litls_tls13_ctx *ctx, int fd, litls_server_identity *default_identity, litls_server_identity *sni_hosts, int sni_host_count); litls_io_want litls_tls13_server_handshake_step(litls_tls13_ctx *ctx); #endif /* LITLS_TLS13_H */