1 /* Copyright (C) 2016 American Civil Liberties Union (ACLU) 2 * SPDX-License-Identifier: GPL-3.0-or-later 3 */ 4 5 #pragma once 6 7 #include <uv.h> 8 #include <gnutls/gnutls.h> 9 #include <libknot/packet/pkt.h> 10 #include "lib/defines.h" 11 #include "lib/generic/array.h" 12 #include "lib/generic/trie.h" 13 #include "lib/utils.h" 14 15 #define MAX_TLS_PADDING KR_EDNS_PAYLOAD 16 #define TLS_MAX_UNCORK_RETRIES 100 17 18 /* rfc 5476, 7.3 - handshake Protocol overview 19 * https://tools.ietf.org/html/rfc5246#page-33 20 * Message flow for a full handshake (only mandatory messages) 21 * ClientHello --------> 22 ServerHello 23 <-------- ServerHelloDone 24 ClientKeyExchange 25 Finished --------> 26 <-------- Finished 27 * 28 * See also https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/ 29 * So it takes 2 RTT. 30 * As we use session tickets, there are additional messages, add one RTT mode. 31 */ 32 #define TLS_MAX_HANDSHAKE_TIME (KR_CONN_RTT_MAX * 3) 33 34 /** Transport session (opaque). */ 35 struct session; 36 37 struct tls_ctx; 38 struct tls_client_ctx; 39 struct tls_credentials { 40 int count; 41 char *tls_cert; 42 char *tls_key; 43 gnutls_certificate_credentials_t credentials; 44 time_t valid_until; 45 char *ephemeral_servicename; 46 }; 47 48 49 #define TLS_SHA256_RAW_LEN 32 /* gnutls_hash_get_len(GNUTLS_DIG_SHA256) */ 50 /** Required buffer length for pin_sha256, including the zero terminator. */ 51 #define TLS_SHA256_BASE64_BUFLEN (((TLS_SHA256_RAW_LEN * 8 + 4) / 6) + 3 + 1) 52 53 #if GNUTLS_VERSION_NUMBER >= 0x030400 54 #define TLS_CAN_USE_PINS 1 55 #else 56 #define TLS_CAN_USE_PINS 0 57 #endif 58 59 60 /** TLS authentication parameters for a single address-port pair. */ 61 typedef struct { 62 uint32_t refs; /**< Reference count; consider TLS sessions in progress. */ 63 bool insecure; /**< Use no authentication. */ 64 const char *hostname; /**< Server name for SNI and certificate check, lowercased. */ 65 array_t(const char *) ca_files; /**< Paths to certificate files; not really used. */ 66 array_t(const uint8_t *) pins; /**< Certificate pins as raw unterminated strings.*/ 67 gnutls_certificate_credentials_t credentials; /**< CA creds. in gnutls format. */ 68 gnutls_datum_t session_data; /**< Session-resumption data gets stored here. */ 69 } tls_client_param_t; 70 /** Holds configuration for TLS authentication for all potential servers. 71 * Special case: NULL pointer also means empty. */ 72 typedef trie_t tls_client_params_t; 73 74 /** Get a pointer-to-pointer to TLS auth params. 75 * If it didn't exist, it returns NULL (if !do_insert) or pointer to NULL. */ 76 tls_client_param_t ** tls_client_param_getptr(tls_client_params_t **params, 77 const struct sockaddr *addr, bool do_insert); 78 79 /** Get a pointer to TLS auth params or NULL. */ 80 static inline tls_client_param_t * tls_client_param_get(tls_client_params_t * params,const struct sockaddr * addr)81 tls_client_param_get(tls_client_params_t *params, const struct sockaddr *addr) 82 { 83 tls_client_param_t **pe = tls_client_param_getptr(¶ms, addr, false); 84 return pe ? *pe : NULL; 85 } 86 87 /** Allocate and initialize the structure (with ->ref = 1). */ 88 tls_client_param_t * tls_client_param_new(); 89 /** Reference-counted free(); any inside data is freed alongside. */ 90 void tls_client_param_unref(tls_client_param_t *entry); 91 92 int tls_client_param_remove(tls_client_params_t *params, const struct sockaddr *addr); 93 /** Free TLS authentication parameters. */ 94 void tls_client_params_free(tls_client_params_t *params); 95 96 97 struct worker_ctx; 98 struct qr_task; 99 struct network; 100 struct engine; 101 102 typedef enum tls_client_hs_state { 103 TLS_HS_NOT_STARTED = 0, 104 TLS_HS_IN_PROGRESS, 105 TLS_HS_DONE, 106 TLS_HS_CLOSING, 107 TLS_HS_LAST 108 } tls_hs_state_t; 109 110 typedef int (*tls_handshake_cb) (struct session *session, int status); 111 112 113 struct tls_common_ctx { 114 bool client_side; 115 gnutls_session_t tls_session; 116 tls_hs_state_t handshake_state; 117 struct session *session; 118 /* for reading from the network */ 119 const uint8_t *buf; 120 ssize_t nread; 121 ssize_t consumed; 122 uint8_t recv_buf[16384]; 123 tls_handshake_cb handshake_cb; 124 struct worker_ctx *worker; 125 size_t write_queue_size; 126 }; 127 128 struct tls_ctx { 129 /* 130 * Since pointer to tls_ctx needs to be casted 131 * to tls_ctx_common in some functions, 132 * this field must be always at first position 133 */ 134 struct tls_common_ctx c; 135 struct tls_credentials *credentials; 136 }; 137 138 struct tls_client_ctx { 139 /* 140 * Since pointer to tls_client_ctx needs to be casted 141 * to tls_ctx_common in some functions, 142 * this field must be always at first position 143 */ 144 struct tls_common_ctx c; 145 tls_client_param_t *params; /**< It's reference-counted. */ 146 }; 147 148 /*! Create an empty TLS context in query context */ 149 struct tls_ctx* tls_new(struct worker_ctx *worker); 150 151 /*! Close a TLS context (call gnutls_bye()) */ 152 void tls_close(struct tls_common_ctx *ctx); 153 154 /*! Release a TLS context */ 155 void tls_free(struct tls_ctx* tls); 156 157 /*! Push new data to TLS context for sending */ 158 int tls_write(uv_write_t *req, uv_handle_t* handle, knot_pkt_t * pkt, uv_write_cb cb); 159 160 /*! Unwrap incoming data from a TLS stream and pass them to TCP session. 161 * @return the number of newly-completed requests (>=0) or an error code 162 */ 163 ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nread); 164 165 /*! Set TLS certificate and key from files. */ 166 int tls_certificate_set(struct network *net, const char *tls_cert, const char *tls_key); 167 168 /*! Borrow TLS credentials for context. */ 169 struct tls_credentials *tls_credentials_reserve(struct tls_credentials *tls_credentials); 170 171 /*! Release TLS credentials for context (decrements refcount or frees). */ 172 int tls_credentials_release(struct tls_credentials *tls_credentials); 173 174 /*! Free TLS credentials, must not be called if it holds positive refcount. */ 175 void tls_credentials_free(struct tls_credentials *tls_credentials); 176 177 /*! Log DNS-over-TLS OOB key-pin form of current credentials: 178 * https://tools.ietf.org/html/rfc7858#appendix-A */ 179 void tls_credentials_log_pins(struct tls_credentials *tls_credentials); 180 181 /*! Generate new ephemeral TLS credentials. */ 182 struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine); 183 184 /*! Get TLS handshake state. */ 185 tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx); 186 187 /*! Set TLS handshake state. */ 188 int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state); 189 190 191 /*! Allocate new client TLS context */ 192 struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry, 193 struct worker_ctx *worker); 194 195 /*! Free client TLS context */ 196 void tls_client_ctx_free(struct tls_client_ctx *ctx); 197 198 int tls_client_connect_start(struct tls_client_ctx *client_ctx, 199 struct session *session, 200 tls_handshake_cb handshake_cb); 201 202 int tls_client_ctx_set_session(struct tls_client_ctx *ctx, struct session *session); 203 204 205 /* Session tickets, server side. Implementation in ./tls_session_ticket-srv.c */ 206 207 /*! Opaque struct used by tls_session_ticket_* functions. */ 208 struct tls_session_ticket_ctx; 209 210 /*! Suggested maximum reasonable secret length. */ 211 #define TLS_SESSION_TICKET_SECRET_MAX_LEN 1024 212 213 /*! Create a session ticket context and initialize it (secret gets copied inside). 214 * 215 * Passing zero-length secret implies using a random key, i.e. not synchronized 216 * between multiple instances. 217 * 218 * Beware that knowledge of the secret (if nonempty) breaks forward secrecy, 219 * so you should rotate the secret regularly and securely erase all past secrets. 220 * With TLS < 1.3 it's probably too risky to set nonempty secret. 221 */ 222 struct tls_session_ticket_ctx * tls_session_ticket_ctx_create( 223 uv_loop_t *loop, const char *secret, size_t secret_len); 224 225 /*! Try to enable session tickets for a server session. */ 226 void tls_session_ticket_enable(struct tls_session_ticket_ctx *ctx, gnutls_session_t session); 227 228 /*! Free all resources of the session ticket context. NULL is accepted as well. */ 229 void tls_session_ticket_ctx_destroy(struct tls_session_ticket_ctx *ctx); 230 231