]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/libssl.hh
Merge pull request #14032 from rgacogne/ddist-192-changelog-secpoll
[thirdparty/pdns.git] / pdns / libssl.hh
1 #pragma once
2
3 #include <atomic>
4 #include <fstream>
5 #include <map>
6 #include <memory>
7 #include <optional>
8 #include <string>
9 #include <vector>
10 #include <optional>
11
12 #include "config.h"
13 #include "circular_buffer.hh"
14 #include "lock.hh"
15 #include "misc.hh"
16
17 enum class LibsslTLSVersion : uint8_t { Unknown, TLS10, TLS11, TLS12, TLS13 };
18
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):
25 d_cert(cert), d_key(std::move(key)), d_password(std::move(password)) {
26 }
27 };
28
29 class TLSConfig
30 {
31 public:
32 std::vector<TLSCertKeyPair> d_certKeyPairs;
33 std::vector<std::string> d_ocspFiles;
34
35 std::string d_ciphers;
36 std::string d_ciphers13;
37 std::string d_ticketKeyFile;
38 std::string d_keyLogFile;
39
40 size_t d_maxStoredSessions{20480};
41 time_t d_sessionTimeout{0};
42 time_t d_ticketsKeyRotationDelay{43200};
43 uint8_t d_numberOfTicketsKeys{5};
44 LibsslTLSVersion d_minTLSVersion{LibsslTLSVersion::TLS10};
45
46 bool d_preferServerCiphers{true};
47 bool d_enableTickets{true};
48 /* whether OpenSSL will release I/O buffers when the connection
49 becomes idle, saving memory */
50 bool d_releaseBuffers{true};
51 /* whether so-called secure renegotiation should be allowed for TLS < 1.3 */
52 bool d_enableRenegotiation{false};
53 /* enable TLS async mode, if supported by any engine */
54 bool d_asyncMode{false};
55 /* enable kTLS mode, if supported */
56 bool d_ktls{false};
57 /* set read ahead mode, if supported */
58 bool d_readAhead{true};
59 };
60
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
74 #ifdef HAVE_LIBSSL
75 #include <openssl/ssl.h>
76
77 void registerOpenSSLUser();
78 void unregisterOpenSSLUser();
79
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;
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
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;
106 #endif
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();
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:
126 void addKey(std::shared_ptr<OpenSSLTLSTicketKey>&& newKey);
127
128 SharedLockGuarded<boost::circular_buffer<std::shared_ptr<OpenSSLTLSTicketKey> > > d_ticketKeys;
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);
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
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);
138 #endif
139
140 #ifndef DISABLE_OCSP_STAPLING
141 int libssl_ocsp_stapling_callback(SSL* ssl, const std::map<int, std::string>& ocspMap);
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
145 #endif /* DISABLE_OCSP_STAPLING */
146
147 void libssl_set_error_counters_callback(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, TLSErrorCounters* counters);
148
149 LibsslTLSVersion libssl_tls_version_from_string(const std::string& str);
150 const std::string& libssl_tls_version_to_string(LibsslTLSVersion version);
151 bool libssl_set_min_tls_version(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, LibsslTLSVersion version);
152
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 */
155 std::pair<std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>, std::vector<std::string>> libssl_init_server_context(const TLSConfig& config,
156 std::map<int, std::string>& ocspResponses);
157
158 pdns::UniqueFilePtr libssl_set_key_log_file(std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>& ctx, const std::string& logFile);
159
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. */
161 #ifndef DISABLE_NPN
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);
163 #endif /* DISABLE_NPN */
164
165 /* called in a server context, to select an ALPN value advertised by the client if any */
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);
167 /* set the supported ALPN protos in client context */
168 bool libssl_set_alpn_protos(SSL_CTX* ctx, const std::vector<std::vector<uint8_t>>& protos);
169
170 std::string libssl_get_error_string();
171
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)
177 std::pair<bool, std::string> libssl_load_engine(const std::string& engineName, const std::optional<std::string>& defaultString);
178 #endif /* HAVE_LIBSSL && !HAVE_TLS_PROVIDERS */
179
180 #endif /* HAVE_LIBSSL */