]>
Commit | Line | Data |
---|---|---|
9da20db2 RG |
1 | #pragma once |
2 | ||
0898164e | 3 | #include <atomic> |
0ef9ab19 | 4 | #include <fstream> |
9da20db2 RG |
5 | #include <map> |
6 | #include <memory> | |
489caa9f | 7 | #include <optional> |
9da20db2 RG |
8 | #include <string> |
9 | #include <vector> | |
6de19ce2 | 10 | #include <optional> |
9da20db2 RG |
11 | |
12 | #include "config.h" | |
0ef9ab19 RG |
13 | #include "circular_buffer.hh" |
14 | #include "lock.hh" | |
931536a5 | 15 | #include "misc.hh" |
9da20db2 | 16 | |
bcf26e85 | 17 | enum class LibsslTLSVersion : uint8_t { Unknown, TLS10, TLS11, TLS12, TLS13 }; |
9da20db2 | 18 | |
6de19ce2 CHB |
19 | struct TLSCertKeyPair |
20 | { | |
21 | std::string d_cert; | |
22 | std::optional<std::string> d_key; | |
23 | std::optional<std::string> d_password; | |
24 | explicit TLSCertKeyPair(const std::string& cert, std::optional<std::string> key = std::nullopt, std::optional<std::string> password = std::nullopt): | |
c92e6020 | 25 | d_cert(cert), d_key(std::move(key)), d_password(std::move(password)) { |
6de19ce2 CHB |
26 | } |
27 | }; | |
28 | ||
b54e94dc RG |
29 | class TLSConfig |
30 | { | |
31 | public: | |
6de19ce2 | 32 | std::vector<TLSCertKeyPair> d_certKeyPairs; |
b54e94dc RG |
33 | std::vector<std::string> d_ocspFiles; |
34 | ||
35 | std::string d_ciphers; | |
36 | std::string d_ciphers13; | |
37 | std::string d_ticketKeyFile; | |
7f8a5a32 | 38 | std::string d_keyLogFile; |
b54e94dc RG |
39 | |
40 | size_t d_maxStoredSessions{20480}; | |
25426675 | 41 | time_t d_sessionTimeout{0}; |
b54e94dc RG |
42 | time_t d_ticketsKeyRotationDelay{43200}; |
43 | uint8_t d_numberOfTicketsKeys{5}; | |
44 | LibsslTLSVersion d_minTLSVersion{LibsslTLSVersion::TLS10}; | |
45 | ||
12543371 | 46 | bool d_preferServerCiphers{true}; |
b54e94dc | 47 | bool d_enableTickets{true}; |
08d3b723 RG |
48 | /* whether OpenSSL will release I/O buffers when the connection |
49 | becomes idle, saving memory */ | |
50 | bool d_releaseBuffers{true}; | |
c223b99b RG |
51 | /* whether so-called secure renegotiation should be allowed for TLS < 1.3 */ |
52 | bool d_enableRenegotiation{false}; | |
489caa9f RG |
53 | /* enable TLS async mode, if supported by any engine */ |
54 | bool d_asyncMode{false}; | |
5afc196c RG |
55 | /* enable kTLS mode, if supported */ |
56 | bool d_ktls{false}; | |
e80c3b09 | 57 | /* set read ahead mode, if supported */ |
65454336 | 58 | bool d_readAhead{true}; |
b54e94dc RG |
59 | }; |
60 | ||
f34fdcc5 RG |
61 | struct TLSErrorCounters |
62 | { | |
63 | std::atomic<uint64_t> d_dhKeyTooSmall{0}; /* the other side sent a DH value that is not large enough */ | |
64 | std::atomic<uint64_t> d_inappropriateFallBack{0}; /* SCSV indicates that the client previously tried a higher version, | |
65 | something bad is happening */ | |
66 | std::atomic<uint64_t> d_noSharedCipher{0}; /* we could not agree on a cipher to use */ | |
67 | std::atomic<uint64_t> d_unknownCipherType{0}; /* unknown cipher type */ | |
68 | std::atomic<uint64_t> d_unknownKeyExchangeType{0}; /* * unknown exchange type, weird */ | |
69 | std::atomic<uint64_t> d_unknownProtocol{0}; /* unknown protocol (SSLv2 or TLS 1.4, who knows? */ | |
70 | std::atomic<uint64_t> d_unsupportedEC{0}; /* unsupported elliptic curve */ | |
71 | std::atomic<uint64_t> d_unsupportedProtocol{0}; /* we don't accept this TLS version, sorry */ | |
72 | }; | |
73 | ||
9da20db2 RG |
74 | #ifdef HAVE_LIBSSL |
75 | #include <openssl/ssl.h> | |
76 | ||
77 | void registerOpenSSLUser(); | |
78 | void unregisterOpenSSLUser(); | |
79 | ||
0ef9ab19 RG |
80 | /* From rfc5077 Section 4. Recommended Ticket Construction */ |
81 | #define TLS_TICKETS_KEY_NAME_SIZE (16) | |
82 | ||
83 | /* AES-256 */ | |
84 | #define TLS_TICKETS_CIPHER_KEY_SIZE (32) | |
85 | #define TLS_TICKETS_CIPHER_ALGO (EVP_aes_256_cbc) | |
86 | ||
87 | /* HMAC SHA-256 */ | |
88 | #define TLS_TICKETS_MAC_KEY_SIZE (32) | |
89 | #define TLS_TICKETS_MAC_ALGO (EVP_sha256) | |
90 | ||
91 | class OpenSSLTLSTicketKey | |
92 | { | |
93 | public: | |
94 | OpenSSLTLSTicketKey(); | |
95 | OpenSSLTLSTicketKey(std::ifstream& file); | |
96 | ~OpenSSLTLSTicketKey(); | |
97 | ||
98 | bool nameMatches(const unsigned char name[TLS_TICKETS_KEY_NAME_SIZE]) const; | |
f5e1b85e FM |
99 | |
100 | #if OPENSSL_VERSION_MAJOR >= 3 | |
101 | int encrypt(unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx) const; | |
102 | bool decrypt(const unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx) const; | |
103 | #else | |
b9839ca5 FM |
104 | int encrypt(unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx) const; |
105 | bool decrypt(const unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx) const; | |
f5e1b85e | 106 | #endif |
0ef9ab19 RG |
107 | |
108 | private: | |
109 | unsigned char d_name[TLS_TICKETS_KEY_NAME_SIZE]; | |
110 | unsigned char d_cipherKey[TLS_TICKETS_CIPHER_KEY_SIZE]; | |
111 | unsigned char d_hmacKey[TLS_TICKETS_MAC_KEY_SIZE]; | |
112 | }; | |
113 | ||
114 | class OpenSSLTLSTicketKeysRing | |
115 | { | |
116 | public: | |
117 | OpenSSLTLSTicketKeysRing(size_t capacity); | |
118 | ~OpenSSLTLSTicketKeysRing(); | |
0ef9ab19 RG |
119 | std::shared_ptr<OpenSSLTLSTicketKey> getEncryptionKey(); |
120 | std::shared_ptr<OpenSSLTLSTicketKey> getDecryptionKey(unsigned char name[TLS_TICKETS_KEY_NAME_SIZE], bool& activeKey); | |
121 | size_t getKeysCount(); | |
122 | void loadTicketsKeys(const std::string& keyFile); | |
123 | void rotateTicketsKey(time_t now); | |
124 | ||
125 | private: | |
c92e6020 RG |
126 | void addKey(std::shared_ptr<OpenSSLTLSTicketKey>&& newKey); |
127 | ||
17e1699b | 128 | SharedLockGuarded<boost::circular_buffer<std::shared_ptr<OpenSSLTLSTicketKey> > > d_ticketKeys; |
0ef9ab19 RG |
129 | }; |
130 | ||
131 | void* libssl_get_ticket_key_callback_data(SSL* s); | |
132 | void libssl_set_ticket_key_callback_data(SSL_CTX* ctx, void* data); | |
f5e1b85e FM |
133 | |
134 | #if OPENSSL_VERSION_MAJOR >= 3 | |
135 | int libssl_ticket_key_callback(SSL* s, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx, int enc); | |
136 | #else | |
b9839ca5 | 137 | int libssl_ticket_key_callback(SSL* s, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx, int enc); |
f5e1b85e | 138 | #endif |
0ef9ab19 | 139 | |
2ba75ea7 | 140 | #ifndef DISABLE_OCSP_STAPLING |
9da20db2 | 141 | int libssl_ocsp_stapling_callback(SSL* ssl, const std::map<int, std::string>& ocspMap); |
9da20db2 RG |
142 | #ifdef HAVE_OCSP_BASIC_SIGN |
143 | bool libssl_generate_ocsp_response(const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin); | |
144 | #endif | |
2ba75ea7 | 145 | #endif /* DISABLE_OCSP_STAPLING */ |
9da20db2 | 146 | |
e99550b8 | 147 | void libssl_set_error_counters_callback(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, TLSErrorCounters* counters); |
f34fdcc5 | 148 | |
9da20db2 | 149 | LibsslTLSVersion libssl_tls_version_from_string(const std::string& str); |
656a5e55 | 150 | const std::string& libssl_tls_version_to_string(LibsslTLSVersion version); |
e99550b8 | 151 | bool libssl_set_min_tls_version(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, LibsslTLSVersion version); |
9da20db2 | 152 | |
d1ce3058 RG |
153 | /* return the created context, and a list of warning messages for issues not severe enough |
154 | to trigger raising an exception, like failing to load an OCSP response file */ | |
e99550b8 | 155 | std::pair<std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>, std::vector<std::string>> libssl_init_server_context(const TLSConfig& config, |
d1ce3058 | 156 | std::map<int, std::string>& ocspResponses); |
b54e94dc | 157 | |
931536a5 | 158 | pdns::UniqueFilePtr libssl_set_key_log_file(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, const std::string& logFile); |
cc1f4ed8 | 159 | |
e82bf80f | 160 | /* called in a client context, if the client advertised more than one ALPN values and the server returned more than one as well, to select the one to use. */ |
d6d8802b | 161 | #ifndef DISABLE_NPN |
70dd1aed | 162 | void libssl_set_npn_select_callback(SSL_CTX* ctx, int (*cb)(SSL* s, unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* arg), void* arg); |
d6d8802b RG |
163 | #endif /* DISABLE_NPN */ |
164 | ||
e82bf80f | 165 | /* called in a server context, to select an ALPN value advertised by the client if any */ |
70dd1aed | 166 | void libssl_set_alpn_select_callback(SSL_CTX* ctx, int (*cb)(SSL* s, const unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* arg), void* arg); |
e82bf80f | 167 | /* set the supported ALPN protos in client context */ |
70dd1aed | 168 | bool libssl_set_alpn_protos(SSL_CTX* ctx, const std::vector<std::vector<uint8_t>>& protos); |
e82bf80f | 169 | |
cc1f4ed8 O |
170 | std::string libssl_get_error_string(); |
171 | ||
b7664acd FM |
172 | #if defined(HAVE_LIBSSL) && OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS) |
173 | std::pair<bool, std::string> libssl_load_provider(const std::string& engineName); | |
174 | #endif /* HAVE_LIBSSL && OPENSSL_VERSION_MAJOR >= 3 && HAVE_TLS_PROVIDERS */ | |
175 | ||
176 | #if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS) | |
489caa9f | 177 | std::pair<bool, std::string> libssl_load_engine(const std::string& engineName, const std::optional<std::string>& defaultString); |
b7664acd | 178 | #endif /* HAVE_LIBSSL && !HAVE_TLS_PROVIDERS */ |
489caa9f | 179 | |
9da20db2 | 180 | #endif /* HAVE_LIBSSL */ |