13 #include <openssl/conf.h>
14 #include <openssl/err.h>
15 #include <openssl/ocsp.h>
16 #include <openssl/rand.h>
17 #include <openssl/ssl.h>
21 #endif /* HAVE_LIBSODIUM */
23 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
24 /* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
27 static std::vector
<std::mutex
> openssllocks
;
30 static void openssl_pthreads_locking_callback(int mode
, int type
, const char *file
, int line
)
32 if (mode
& CRYPTO_LOCK
) {
33 openssllocks
.at(type
).lock();
36 openssllocks
.at(type
).unlock();
40 static unsigned long openssl_pthreads_id_callback()
42 return (unsigned long)pthread_self();
46 static void openssl_thread_setup()
48 openssllocks
= std::vector
<std::mutex
>(CRYPTO_num_locks());
49 CRYPTO_set_id_callback(&openssl_pthreads_id_callback
);
50 CRYPTO_set_locking_callback(&openssl_pthreads_locking_callback
);
53 static void openssl_thread_cleanup()
55 CRYPTO_set_locking_callback(nullptr);
59 #endif /* (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL) */
61 static std::atomic
<uint64_t> s_users
;
62 static int s_ticketsKeyIndex
{-1};
63 static int s_countersIndex
{-1};
64 static int s_keyLogIndex
{-1};
66 void registerOpenSSLUser()
68 if (s_users
.fetch_add(1) == 0) {
69 #ifdef HAVE_OPENSSL_INIT_CRYPTO
70 /* load the default configuration file (or one specified via OPENSSL_CONF),
71 which can then be used to load engines */
72 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG
, nullptr);
75 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x2090100fL))
76 SSL_load_error_strings();
77 OpenSSL_add_ssl_algorithms();
78 openssl_thread_setup();
80 s_ticketsKeyIndex
= SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
82 if (s_ticketsKeyIndex
== -1) {
83 throw std::runtime_error("Error getting an index for tickets key");
86 s_countersIndex
= SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
88 if (s_countersIndex
== -1) {
89 throw std::runtime_error("Error getting an index for counters");
92 s_keyLogIndex
= SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
94 if (s_keyLogIndex
== -1) {
95 throw std::runtime_error("Error getting an index for TLS key logging");
100 void unregisterOpenSSLUser()
102 if (s_users
.fetch_sub(1) == 1) {
103 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x2090100fL))
108 CONF_modules_finish();
110 CONF_modules_unload(1);
112 CRYPTO_cleanup_all_ex_data();
113 openssl_thread_cleanup();
118 void* libssl_get_ticket_key_callback_data(SSL
* s
)
120 SSL_CTX
* sslCtx
= SSL_get_SSL_CTX(s
);
121 if (sslCtx
== nullptr) {
125 return SSL_CTX_get_ex_data(sslCtx
, s_ticketsKeyIndex
);
128 void libssl_set_ticket_key_callback_data(SSL_CTX
* ctx
, void* data
)
130 SSL_CTX_set_ex_data(ctx
, s_ticketsKeyIndex
, data
);
133 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
)
136 const auto key
= keyring
.getEncryptionKey();
137 if (key
== nullptr) {
141 return key
->encrypt(keyName
, iv
, ectx
, hctx
);
144 bool activeEncryptionKey
= false;
146 const auto key
= keyring
.getDecryptionKey(keyName
, activeEncryptionKey
);
147 if (key
== nullptr) {
148 /* we don't know this key, just create a new ticket */
152 if (key
->decrypt(iv
, ectx
, hctx
) == false) {
156 if (!activeEncryptionKey
) {
157 /* this key is not active, please encrypt the ticket content with the currently active one */
164 static void libssl_info_callback(const SSL
*ssl
, int where
, int ret
)
166 SSL_CTX
* sslCtx
= SSL_get_SSL_CTX(ssl
);
167 if (sslCtx
== nullptr) {
171 TLSErrorCounters
* counters
= reinterpret_cast<TLSErrorCounters
*>(SSL_CTX_get_ex_data(sslCtx
, s_countersIndex
));
172 if (counters
== nullptr) {
176 if (where
& SSL_CB_ALERT
) {
177 const long lastError
= ERR_peek_last_error();
178 switch (ERR_GET_REASON(lastError
)) {
179 #ifdef SSL_R_DH_KEY_TOO_SMALL
180 case SSL_R_DH_KEY_TOO_SMALL
:
181 ++counters
->d_dhKeyTooSmall
;
183 #endif /* SSL_R_DH_KEY_TOO_SMALL */
184 case SSL_R_NO_SHARED_CIPHER
:
185 ++counters
->d_noSharedCipher
;
187 case SSL_R_UNKNOWN_PROTOCOL
:
188 ++counters
->d_unknownProtocol
;
190 case SSL_R_UNSUPPORTED_PROTOCOL
:
191 #ifdef SSL_R_VERSION_TOO_LOW
192 case SSL_R_VERSION_TOO_LOW
:
193 #endif /* SSL_R_VERSION_TOO_LOW */
194 ++counters
->d_unsupportedProtocol
;
196 case SSL_R_INAPPROPRIATE_FALLBACK
:
197 ++counters
->d_inappropriateFallBack
;
199 case SSL_R_UNKNOWN_CIPHER_TYPE
:
200 ++counters
->d_unknownCipherType
;
202 case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE
:
203 ++counters
->d_unknownKeyExchangeType
;
205 case SSL_R_UNSUPPORTED_ELLIPTIC_CURVE
:
206 ++counters
->d_unsupportedEC
;
214 void libssl_set_error_counters_callback(std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)>& ctx
, TLSErrorCounters
* counters
)
216 SSL_CTX_set_ex_data(ctx
.get(), s_countersIndex
, counters
);
217 SSL_CTX_set_info_callback(ctx
.get(), libssl_info_callback
);
220 int libssl_ocsp_stapling_callback(SSL
* ssl
, const std::map
<int, std::string
>& ocspMap
)
222 auto pkey
= SSL_get_privatekey(ssl
);
223 if (pkey
== nullptr) {
224 return SSL_TLSEXT_ERR_NOACK
;
227 /* look for an OCSP response for the corresponding private key type (RSA, ECDSA..) */
228 const auto& data
= ocspMap
.find(EVP_PKEY_base_id(pkey
));
229 if (data
== ocspMap
.end()) {
230 return SSL_TLSEXT_ERR_NOACK
;
233 /* we need to allocate a copy because OpenSSL will free the pointer passed to SSL_set_tlsext_status_ocsp_resp() */
234 void* copy
= OPENSSL_malloc(data
->second
.size());
235 if (copy
== nullptr) {
236 return SSL_TLSEXT_ERR_NOACK
;
239 memcpy(copy
, data
->second
.data(), data
->second
.size());
240 SSL_set_tlsext_status_ocsp_resp(ssl
, copy
, data
->second
.size());
241 return SSL_TLSEXT_ERR_OK
;
244 static bool libssl_validate_ocsp_response(const std::string
& response
)
246 auto responsePtr
= reinterpret_cast<const unsigned char *>(response
.data());
247 std::unique_ptr
<OCSP_RESPONSE
, void(*)(OCSP_RESPONSE
*)> resp(d2i_OCSP_RESPONSE(nullptr, &responsePtr
, response
.size()), OCSP_RESPONSE_free
);
248 if (resp
== nullptr) {
249 throw std::runtime_error("Unable to parse OCSP response");
252 int status
= OCSP_response_status(resp
.get());
253 if (status
!= OCSP_RESPONSE_STATUS_SUCCESSFUL
) {
254 throw std::runtime_error("OCSP response status is not successful: " + std::to_string(status
));
257 std::unique_ptr
<OCSP_BASICRESP
, void(*)(OCSP_BASICRESP
*)> basic(OCSP_response_get1_basic(resp
.get()), OCSP_BASICRESP_free
);
258 if (basic
== nullptr) {
259 throw std::runtime_error("Error getting a basic OCSP response");
262 if (OCSP_resp_count(basic
.get()) != 1) {
263 throw std::runtime_error("More than one single response in an OCSP basic response");
266 auto singleResponse
= OCSP_resp_get0(basic
.get(), 0);
267 if (singleResponse
== nullptr) {
268 throw std::runtime_error("Error getting a single response from the basic OCSP response");
272 ASN1_GENERALIZEDTIME
* revTime
= nullptr;
273 ASN1_GENERALIZEDTIME
* thisUpdate
= nullptr;
274 ASN1_GENERALIZEDTIME
* nextUpdate
= nullptr;
276 auto singleResponseStatus
= OCSP_single_get0_status(singleResponse
, &reason
, &revTime
, &thisUpdate
, &nextUpdate
);
277 if (singleResponseStatus
!= V_OCSP_CERTSTATUS_GOOD
) {
278 throw std::runtime_error("Invalid status for OCSP single response (" + std::to_string(singleResponseStatus
) + ")");
280 if (thisUpdate
== nullptr || nextUpdate
== nullptr) {
281 throw std::runtime_error("Error getting validity of OCSP single response");
284 auto validityResult
= OCSP_check_validity(thisUpdate
, nextUpdate
, /* 5 minutes of leeway */ 5 * 60, -1);
285 if (validityResult
== 0) {
286 throw std::runtime_error("OCSP single response is not yet, or no longer, valid");
292 std::map
<int, std::string
> libssl_load_ocsp_responses(const std::vector
<std::string
>& ocspFiles
, std::vector
<int> keyTypes
)
294 std::map
<int, std::string
> ocspResponses
;
296 if (ocspFiles
.size() > keyTypes
.size()) {
297 throw std::runtime_error("More OCSP files than certificates and keys loaded!");
301 for (const auto& filename
: ocspFiles
) {
302 std::ifstream
file(filename
, std::ios::binary
);
306 file
.read(buffer
, sizeof(buffer
));
309 throw std::runtime_error("Unable to load OCSP response from '" + filename
+ "'");
311 content
.append(buffer
, file
.gcount());
316 libssl_validate_ocsp_response(content
);
317 ocspResponses
.insert({keyTypes
.at(count
), std::move(content
)});
319 catch (const std::exception
& e
) {
320 throw std::runtime_error("Error checking the validity of OCSP response from '" + filename
+ "': " + e
.what());
325 return ocspResponses
;
328 int libssl_get_last_key_type(std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)>& ctx
)
330 #ifdef HAVE_SSL_CTX_GET0_PRIVATEKEY
331 auto pkey
= SSL_CTX_get0_privatekey(ctx
.get());
333 auto temp
= std::unique_ptr
<SSL
, void(*)(SSL
*)>(SSL_new(ctx
.get()), SSL_free
);
337 auto pkey
= SSL_get_privatekey(temp
.get());
344 return EVP_PKEY_base_id(pkey
);
347 #ifdef HAVE_OCSP_BASIC_SIGN
348 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
)
350 const EVP_MD
* rmd
= EVP_sha256();
352 auto fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(certFile
.c_str(), "r"), fclose
);
354 throw std::runtime_error("Unable to open '" + certFile
+ "' when loading the certificate to generate an OCSP response");
356 auto cert
= std::unique_ptr
<X509
, void(*)(X509
*)>(PEM_read_X509_AUX(fp
.get(), nullptr, nullptr, nullptr), X509_free
);
358 fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(caCert
.c_str(), "r"), fclose
);
360 throw std::runtime_error("Unable to open '" + caCert
+ "' when loading the issuer certificate to generate an OCSP response");
362 auto issuer
= std::unique_ptr
<X509
, void(*)(X509
*)>(PEM_read_X509_AUX(fp
.get(), nullptr, nullptr, nullptr), X509_free
);
363 fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(caKey
.c_str(), "r"), fclose
);
365 throw std::runtime_error("Unable to open '" + caKey
+ "' when loading the issuer key to generate an OCSP response");
367 auto issuerKey
= std::unique_ptr
<EVP_PKEY
, void(*)(EVP_PKEY
*)>(PEM_read_PrivateKey(fp
.get(), nullptr, nullptr, nullptr), EVP_PKEY_free
);
370 auto bs
= std::unique_ptr
<OCSP_BASICRESP
, void(*)(OCSP_BASICRESP
*)>(OCSP_BASICRESP_new(), OCSP_BASICRESP_free
);
371 auto thisupd
= std::unique_ptr
<ASN1_TIME
, void(*)(ASN1_TIME
*)>(X509_gmtime_adj(nullptr, 0), ASN1_TIME_free
);
372 auto nextupd
= std::unique_ptr
<ASN1_TIME
, void(*)(ASN1_TIME
*)>(X509_time_adj_ex(nullptr, ndays
, nmin
* 60, nullptr), ASN1_TIME_free
);
374 auto cid
= std::unique_ptr
<OCSP_CERTID
, void(*)(OCSP_CERTID
*)>(OCSP_cert_to_id(rmd
, cert
.get(), issuer
.get()), OCSP_CERTID_free
);
375 OCSP_basic_add1_status(bs
.get(), cid
.get(), V_OCSP_CERTSTATUS_GOOD
, 0, nullptr, thisupd
.get(), nextupd
.get());
377 if (OCSP_basic_sign(bs
.get(), issuer
.get(), issuerKey
.get(), rmd
, nullptr, OCSP_NOCERTS
) != 1) {
378 throw std::runtime_error("Error while signing the OCSP response");
381 auto resp
= std::unique_ptr
<OCSP_RESPONSE
, void(*)(OCSP_RESPONSE
*)>(OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL
, bs
.get()), OCSP_RESPONSE_free
);
382 auto bio
= std::unique_ptr
<BIO
, void(*)(BIO
*)>(BIO_new_file(outFile
.c_str(), "wb"), BIO_vfree
);
384 throw std::runtime_error("Error opening file for writing the OCSP response");
387 // i2d_OCSP_RESPONSE_bio(bio.get(), resp.get()) is unusable from C++ because of an invalid cast
388 ASN1_i2d_bio((i2d_of_void
*)i2d_OCSP_RESPONSE
, bio
.get(), (unsigned char*)resp
.get());
392 #endif /* HAVE_OCSP_BASIC_SIGN */
394 LibsslTLSVersion
libssl_tls_version_from_string(const std::string
& str
)
396 if (str
== "tls1.0") {
397 return LibsslTLSVersion::TLS10
;
399 if (str
== "tls1.1") {
400 return LibsslTLSVersion::TLS11
;
402 if (str
== "tls1.2") {
403 return LibsslTLSVersion::TLS12
;
405 if (str
== "tls1.3") {
406 return LibsslTLSVersion::TLS13
;
408 throw std::runtime_error("Unknown TLS version '" + str
);
411 const std::string
& libssl_tls_version_to_string(LibsslTLSVersion version
)
413 static const std::map
<LibsslTLSVersion
, std::string
> versions
= {
414 { LibsslTLSVersion::TLS10
, "tls1.0" },
415 { LibsslTLSVersion::TLS11
, "tls1.1" },
416 { LibsslTLSVersion::TLS12
, "tls1.2" },
417 { LibsslTLSVersion::TLS13
, "tls1.3" }
420 const auto& it
= versions
.find(version
);
421 if (it
== versions
.end()) {
422 throw std::runtime_error("Unknown TLS version (" + std::to_string((int)version
) + ")");
427 bool libssl_set_min_tls_version(std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)>& ctx
, LibsslTLSVersion version
)
429 #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) || defined(SSL_CTX_set_min_proto_version)
430 /* These functions have been introduced in 1.1.0, and the use of SSL_OP_NO_* is deprecated
431 Warning: SSL_CTX_set_min_proto_version is a function-like macro in OpenSSL */
434 case LibsslTLSVersion::TLS10
:
437 case LibsslTLSVersion::TLS11
:
438 vers
= TLS1_1_VERSION
;
440 case LibsslTLSVersion::TLS12
:
441 vers
= TLS1_2_VERSION
;
443 case LibsslTLSVersion::TLS13
:
444 #ifdef TLS1_3_VERSION
445 vers
= TLS1_3_VERSION
;
448 #endif /* TLS1_3_VERSION */
454 if (SSL_CTX_set_min_proto_version(ctx
.get(), vers
) != 1) {
459 long vers
= SSL_OP_NO_SSLv2
| SSL_OP_NO_SSLv3
;
461 case LibsslTLSVersion::TLS10
:
463 case LibsslTLSVersion::TLS11
:
464 vers
|= SSL_OP_NO_TLSv1
;
466 case LibsslTLSVersion::TLS12
:
467 vers
|= SSL_OP_NO_TLSv1
| SSL_OP_NO_TLSv1_1
;
469 case LibsslTLSVersion::TLS13
:
470 vers
|= SSL_OP_NO_TLSv1
| SSL_OP_NO_TLSv1_1
| SSL_OP_NO_TLSv1_2
;
476 long options
= SSL_CTX_get_options(ctx
.get());
477 SSL_CTX_set_options(ctx
.get(), options
| vers
);
482 OpenSSLTLSTicketKeysRing::OpenSSLTLSTicketKeysRing(size_t capacity
)
484 d_ticketKeys
.set_capacity(capacity
);
487 OpenSSLTLSTicketKeysRing::~OpenSSLTLSTicketKeysRing()
491 void OpenSSLTLSTicketKeysRing::addKey(std::shared_ptr
<OpenSSLTLSTicketKey
> newKey
)
493 WriteLock
wl(&d_lock
);
494 d_ticketKeys
.push_front(newKey
);
497 std::shared_ptr
<OpenSSLTLSTicketKey
> OpenSSLTLSTicketKeysRing::getEncryptionKey()
499 ReadLock
rl(&d_lock
);
500 return d_ticketKeys
.front();
503 std::shared_ptr
<OpenSSLTLSTicketKey
> OpenSSLTLSTicketKeysRing::getDecryptionKey(unsigned char name
[TLS_TICKETS_KEY_NAME_SIZE
], bool& activeKey
)
505 ReadLock
rl(&d_lock
);
506 for (auto& key
: d_ticketKeys
) {
507 if (key
->nameMatches(name
)) {
508 activeKey
= (key
== d_ticketKeys
.front());
515 size_t OpenSSLTLSTicketKeysRing::getKeysCount()
517 ReadLock
rl(&d_lock
);
518 return d_ticketKeys
.size();
521 void OpenSSLTLSTicketKeysRing::loadTicketsKeys(const std::string
& keyFile
)
523 bool keyLoaded
= false;
524 std::ifstream
file(keyFile
);
527 auto newKey
= std::make_shared
<OpenSSLTLSTicketKey
>(file
);
531 while (!file
.fail());
533 catch (const std::exception
& e
) {
534 /* if we haven't been able to load at least one key, fail */
543 void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t now
)
545 auto newKey
= std::make_shared
<OpenSSLTLSTicketKey
>();
549 OpenSSLTLSTicketKey::OpenSSLTLSTicketKey()
551 if (RAND_bytes(d_name
, sizeof(d_name
)) != 1) {
552 throw std::runtime_error("Error while generating the name of the OpenSSL TLS ticket key");
555 if (RAND_bytes(d_cipherKey
, sizeof(d_cipherKey
)) != 1) {
556 throw std::runtime_error("Error while generating the cipher key of the OpenSSL TLS ticket key");
559 if (RAND_bytes(d_hmacKey
, sizeof(d_hmacKey
)) != 1) {
560 throw std::runtime_error("Error while generating the HMAC key of the OpenSSL TLS ticket key");
562 #ifdef HAVE_LIBSODIUM
563 sodium_mlock(d_name
, sizeof(d_name
));
564 sodium_mlock(d_cipherKey
, sizeof(d_cipherKey
));
565 sodium_mlock(d_hmacKey
, sizeof(d_hmacKey
));
566 #endif /* HAVE_LIBSODIUM */
569 OpenSSLTLSTicketKey::OpenSSLTLSTicketKey(ifstream
& file
)
571 file
.read(reinterpret_cast<char*>(d_name
), sizeof(d_name
));
572 file
.read(reinterpret_cast<char*>(d_cipherKey
), sizeof(d_cipherKey
));
573 file
.read(reinterpret_cast<char*>(d_hmacKey
), sizeof(d_hmacKey
));
576 throw std::runtime_error("Unable to load a ticket key from the OpenSSL tickets key file");
578 #ifdef HAVE_LIBSODIUM
579 sodium_mlock(d_name
, sizeof(d_name
));
580 sodium_mlock(d_cipherKey
, sizeof(d_cipherKey
));
581 sodium_mlock(d_hmacKey
, sizeof(d_hmacKey
));
582 #endif /* HAVE_LIBSODIUM */
585 OpenSSLTLSTicketKey::~OpenSSLTLSTicketKey()
587 #ifdef HAVE_LIBSODIUM
588 sodium_munlock(d_name
, sizeof(d_name
));
589 sodium_munlock(d_cipherKey
, sizeof(d_cipherKey
));
590 sodium_munlock(d_hmacKey
, sizeof(d_hmacKey
));
592 OPENSSL_cleanse(d_name
, sizeof(d_name
));
593 OPENSSL_cleanse(d_cipherKey
, sizeof(d_cipherKey
));
594 OPENSSL_cleanse(d_hmacKey
, sizeof(d_hmacKey
));
595 #endif /* HAVE_LIBSODIUM */
598 bool OpenSSLTLSTicketKey::nameMatches(const unsigned char name
[TLS_TICKETS_KEY_NAME_SIZE
]) const
600 return (memcmp(d_name
, name
, sizeof(d_name
)) == 0);
603 int OpenSSLTLSTicketKey::encrypt(unsigned char keyName
[TLS_TICKETS_KEY_NAME_SIZE
], unsigned char *iv
, EVP_CIPHER_CTX
*ectx
, HMAC_CTX
*hctx
) const
605 memcpy(keyName
, d_name
, sizeof(d_name
));
607 if (RAND_bytes(iv
, EVP_MAX_IV_LENGTH
) != 1) {
611 if (EVP_EncryptInit_ex(ectx
, TLS_TICKETS_CIPHER_ALGO(), nullptr, d_cipherKey
, iv
) != 1) {
615 if (HMAC_Init_ex(hctx
, d_hmacKey
, sizeof(d_hmacKey
), TLS_TICKETS_MAC_ALGO(), nullptr) != 1) {
622 bool OpenSSLTLSTicketKey::decrypt(const unsigned char* iv
, EVP_CIPHER_CTX
*ectx
, HMAC_CTX
*hctx
) const
624 if (HMAC_Init_ex(hctx
, d_hmacKey
, sizeof(d_hmacKey
), TLS_TICKETS_MAC_ALGO(), nullptr) != 1) {
628 if (EVP_DecryptInit_ex(ectx
, TLS_TICKETS_CIPHER_ALGO(), nullptr, d_cipherKey
, iv
) != 1) {
635 std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)> libssl_init_server_context(const TLSConfig
& config
,
636 std::map
<int, std::string
>& ocspResponses
)
638 auto ctx
= std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)>(SSL_CTX_new(SSLv23_server_method()), SSL_CTX_free
);
643 SSL_OP_NO_COMPRESSION
|
644 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
645 SSL_OP_SINGLE_DH_USE
|
646 SSL_OP_SINGLE_ECDH_USE
;
648 if (!config
.d_enableTickets
|| config
.d_numberOfTicketsKeys
== 0) {
649 /* for TLS 1.3 this means no stateless tickets, but stateful tickets might still be issued,
650 which is something we don't want. */
651 sslOptions
|= SSL_OP_NO_TICKET
;
652 /* really disable all tickets */
653 #ifdef HAVE_SSL_CTX_SET_NUM_TICKETS
654 SSL_CTX_set_num_tickets(ctx
.get(), 0);
655 #endif /* HAVE_SSL_CTX_SET_NUM_TICKETS */
658 if (config
.d_sessionTimeout
> 0) {
659 SSL_CTX_set_timeout(ctx
.get(), config
.d_sessionTimeout
);
662 if (config
.d_preferServerCiphers
) {
663 sslOptions
|= SSL_OP_CIPHER_SERVER_PREFERENCE
;
666 SSL_CTX_set_options(ctx
.get(), sslOptions
);
667 if (!libssl_set_min_tls_version(ctx
, config
.d_minTLSVersion
)) {
668 throw std::runtime_error("Failed to set the minimum version to '" + libssl_tls_version_to_string(config
.d_minTLSVersion
));
671 #ifdef SSL_CTX_set_ecdh_auto
672 SSL_CTX_set_ecdh_auto(ctx
.get(), 1);
675 if (config
.d_maxStoredSessions
== 0) {
676 /* disable stored sessions entirely */
677 SSL_CTX_set_session_cache_mode(ctx
.get(), SSL_SESS_CACHE_OFF
);
680 /* use the internal built-in cache to store sessions */
681 SSL_CTX_set_session_cache_mode(ctx
.get(), SSL_SESS_CACHE_SERVER
);
682 SSL_CTX_sess_set_cache_size(ctx
.get(), config
.d_maxStoredSessions
);
685 std::vector
<int> keyTypes
;
686 /* load certificate and private key */
687 for (const auto& pair
: config
.d_certKeyPairs
) {
688 if (SSL_CTX_use_certificate_chain_file(ctx
.get(), pair
.first
.c_str()) != 1) {
689 ERR_print_errors_fp(stderr
);
690 throw std::runtime_error("An error occurred while trying to load the TLS server certificate file: " + pair
.first
);
692 if (SSL_CTX_use_PrivateKey_file(ctx
.get(), pair
.second
.c_str(), SSL_FILETYPE_PEM
) != 1) {
693 ERR_print_errors_fp(stderr
);
694 throw std::runtime_error("An error occurred while trying to load the TLS server private key file: " + pair
.second
);
696 if (SSL_CTX_check_private_key(ctx
.get()) != 1) {
697 ERR_print_errors_fp(stderr
);
698 throw std::runtime_error("The key from '" + pair
.second
+ "' does not match the certificate from '" + pair
.first
+ "'");
700 /* store the type of the new key, we might need it later to select the right OCSP stapling response */
701 auto keyType
= libssl_get_last_key_type(ctx
);
703 throw std::runtime_error("The key from '" + pair
.second
+ "' has an unknown type");
705 keyTypes
.push_back(keyType
);
708 if (!config
.d_ocspFiles
.empty()) {
710 ocspResponses
= libssl_load_ocsp_responses(config
.d_ocspFiles
, keyTypes
);
712 catch(const std::exception
& e
) {
713 throw std::runtime_error("Unable to load OCSP responses: " + std::string(e
.what()));
717 if (!config
.d_ciphers
.empty() && SSL_CTX_set_cipher_list(ctx
.get(), config
.d_ciphers
.c_str()) != 1) {
718 throw std::runtime_error("The TLS ciphers could not be set: " + config
.d_ciphers
);
721 #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
722 if (!config
.d_ciphers13
.empty() && SSL_CTX_set_ciphersuites(ctx
.get(), config
.d_ciphers13
.c_str()) != 1) {
723 throw std::runtime_error("The TLS 1.3 ciphers could not be set: " + config
.d_ciphers13
);
725 #endif /* HAVE_SSL_CTX_SET_CIPHERSUITES */
730 #ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
731 static void libssl_key_log_file_callback(const SSL
* ssl
, const char* line
)
733 SSL_CTX
* sslCtx
= SSL_get_SSL_CTX(ssl
);
734 if (sslCtx
== nullptr) {
738 auto fp
= reinterpret_cast<FILE*>(SSL_CTX_get_ex_data(sslCtx
, s_keyLogIndex
));
743 fprintf(fp
, "%s\n", line
);
746 #endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
748 std::unique_ptr
<FILE, int(*)(FILE*)> libssl_set_key_log_file(std::unique_ptr
<SSL_CTX
, void(*)(SSL_CTX
*)>& ctx
, const std::string
& logFile
)
750 #ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
751 auto fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(logFile
.c_str(), "a"), fclose
);
753 throw std::runtime_error("Error opening TLS log file '" + logFile
+ "'");
756 SSL_CTX_set_ex_data(ctx
.get(), s_keyLogIndex
, fp
.get());
757 SSL_CTX_set_keylog_callback(ctx
.get(), &libssl_key_log_file_callback
);
761 return std::unique_ptr
<FILE, int(*)(FILE*)>(nullptr, fclose
);
762 #endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
765 #endif /* HAVE_LIBSSL */