109 using namespace openssl;
111 static auto defaultRSA = []() {
112 BIGNUM* bn = BN_new();
113 BN_set_word(bn, RSA_F4);
115 auto rsa = RSA_new();
128 static auto defaultEphemeralPrivateKey = []() {
129 auto pkey = EVP_PKEY_new();
136 if (RSA_up_ref(defaultRSA) != 1)
138 "EVP_PKEY_assign_RSA: incrementing reference count failed");
140 if (!EVP_PKEY_assign_RSA(pkey, defaultRSA))
146 static auto defaultCert = []() {
147 auto x509 = X509_new();
155 X509_set_version(x509, 2);
161 auto const ts =
std::time(
nullptr) - (25 * 60 * 60);
164 buf,
sizeof(buf) - 1,
"%y%m%d000000Z",
std::gmtime(&ts));
168 if (ASN1_TIME_set_string_X509(X509_get_notBefore(x509), buf) != 1)
169 LogicError(
"Unable to set certificate validity date");
172 X509_gmtime_adj(X509_get_notAfter(x509), 2 * 365 * 24 * 60 * 60);
175 if (
auto b = BN_new(); b !=
nullptr)
177 if (BN_rand(b, 128, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
179 if (
auto a = ASN1_INTEGER_new(); a !=
nullptr)
181 if (BN_to_ASN1_INTEGER(b, a))
182 X509_set_serialNumber(x509, a);
184 ASN1_INTEGER_free(a);
195 X509V3_set_ctx_nodb(&ctx);
196 X509V3_set_ctx(&ctx, x509, x509,
nullptr,
nullptr, 0);
198 if (
auto ext = X509V3_EXT_conf_nid(
199 nullptr, &ctx, NID_basic_constraints,
"critical,CA:FALSE"))
201 X509_add_ext(x509, ext, -1);
202 X509_EXTENSION_free(ext);
205 if (
auto ext = X509V3_EXT_conf_nid(
209 "critical,serverAuth,clientAuth"))
211 X509_add_ext(x509, ext, -1);
212 X509_EXTENSION_free(ext);
215 if (
auto ext = X509V3_EXT_conf_nid(
216 nullptr, &ctx, NID_key_usage,
"critical,digitalSignature"))
218 X509_add_ext(x509, ext, -1);
219 X509_EXTENSION_free(ext);
222 if (
auto ext = X509V3_EXT_conf_nid(
223 nullptr, &ctx, NID_subject_key_identifier,
"hash"))
225 X509_add_ext(x509, ext, -1);
226 X509_EXTENSION_free(ext);
231 X509_set_pubkey(x509, defaultEphemeralPrivateKey);
233 if (!X509_sign(x509, defaultEphemeralPrivateKey, EVP_sha256()))
239 SSL_CTX*
const ctx = context.native_handle();
241 if (SSL_CTX_use_certificate(ctx, defaultCert) <= 0)
244 if (SSL_CTX_use_PrivateKey(ctx, defaultEphemeralPrivateKey) <= 0)
250 boost::asio::ssl::context& context,
255 auto fmt_error = [](boost::system::error_code ec) ->
std::string {
256 return " [" +
std::to_string(ec.value()) +
": " + ec.message() +
"]";
259 SSL_CTX*
const ssl = context.native_handle();
261 bool cert_set =
false;
263 if (!cert_file.
empty())
265 boost::system::error_code ec;
267 context.use_certificate_file(
268 cert_file, boost::asio::ssl::context::pem, ec);
271 LogicError(
"Problem with SSL certificate file" + fmt_error(ec));
276 if (!chain_file.
empty())
279 FILE* f = fopen(chain_file.
c_str(),
"r");
284 "Problem opening SSL chain file" +
285 fmt_error(boost::system::error_code(
286 errno, boost::system::generic_category())));
293 X509*
const x = PEM_read_X509(f,
nullptr,
nullptr,
nullptr);
300 if (SSL_CTX_use_certificate(ssl, x) != 1)
302 "Problem retrieving SSL certificate from chain "
307 else if (SSL_CTX_add_extra_chain_cert(ssl, x) != 1)
310 LogicError(
"Problem adding SSL chain certificate.");
321 "Reading the SSL chain file generated an exception: ") +
326 if (!key_file.
empty())
328 boost::system::error_code ec;
330 context.use_private_key_file(
331 key_file, boost::asio::ssl::context::pem, ec);
336 "Problem using the SSL private key file" + fmt_error(ec));
340 if (SSL_CTX_check_private_key(ssl) != 1)
342 LogicError(
"Invalid key in SSL private key file.");
350 boost::asio::ssl::context::sslv23);
353 boost::asio::ssl::context::default_workarounds |
354 boost::asio::ssl::context::no_sslv2 |
355 boost::asio::ssl::context::no_sslv3 |
356 boost::asio::ssl::context::no_tlsv1 |
357 boost::asio::ssl::context::no_tlsv1_1 |
358 boost::asio::ssl::context::single_dh_use |
359 boost::asio::ssl::context::no_compression);
361 if (cipherList.
empty())
365 SSL_CTX_set_cipher_list(c->native_handle(), cipherList.
c_str());
375 SSL_CTX_set_options(c->native_handle(), SSL_OP_NO_RENEGOTIATION);