diff --git a/lib/base/tlsutility.cpp b/lib/base/tlsutility.cpp index 4102b70001d..a87efa9409d 100644 --- a/lib/base/tlsutility.cpp +++ b/lib/base/tlsutility.cpp @@ -89,6 +89,22 @@ static void SetupSslContext(const std::shared_ptr& co SSL_CTX_set_ecdh_auto(sslContext, 1); #endif /* SSL_CTX_set_ecdh_auto */ + +#ifndef OPENSSL_NO_EC + auto ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); + + if (!ecdh) { + Log(LogWarning, "SSL", "Failed to generate EC private key using EC_KEY_new_by_curve_name()."); + } else { + if (SSL_CTX_set_tmp_ecdh(sslContext, ecdh) != 1) + Log(LogWarning, "SSL", "Failed to set ECDH parameters for SSL context using SSL_CTX_set_tmp_ecdh."); + } + + EC_KEY_free(ecdh); + +#endif /* OPENSSL_NO_EC */ + + if (!pubkey.IsEmpty()) { if (!SSL_CTX_use_certificate_chain_file(sslContext, pubkey.CStr())) { Log(LogCritical, "SSL") @@ -336,54 +352,80 @@ std::shared_ptr GetX509Certificate(const String& pemfile) return std::shared_ptr(cert, X509_free); } +/** + * Create an x.509 signing request + * + * @param cn Common name + * @param keyfile Path to the key file + * @param csrfile Path to the csr file + * @param certfile Path to the certificate file + * @param ca Whether to create a new certificate authority or client certificates. + * + * @return 1 on success, 0 on errors. Throws error exceptions. + */ int MakeX509CSR(const String& cn, const String& keyfile, const String& csrfile, const String& certfile, bool ca) { char errbuf[256]; InitializeOpenSSL(); - RSA *rsa = RSA_new(); - BIGNUM *e = BN_new(); + auto ecKey = EC_KEY_new_by_curve_name(NID_secp384r1); + EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); + + EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); + + if (!EC_KEY_generate_key(ecKey)) { + EC_KEY_free(ecKey); - if (!rsa || !e) { Log(LogCritical, "SSL") - << "Error while creating RSA key: " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + << "Error while generating EC key pair: " << ERR_peek_error() + << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("RSA_generate_key") + << boost::errinfo_api_function("EC_KEY_generate_key") << errinfo_openssl_error(ERR_peek_error())); } - BN_set_word(e, RSA_F4); + auto key = EVP_PKEY_new(); + + if (!EVP_PKEY_assign_EC_KEY(key, ecKey)) { + EVP_PKEY_free(key); + EC_KEY_free(ecKey); - if (!RSA_generate_key_ex(rsa, 4096, e, nullptr)) { Log(LogCritical, "SSL") - << "Error while creating RSA key: " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + << "Error while assigning EC key to EVP_PKEY structure: " << ERR_peek_error() + << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("RSA_generate_key") + << boost::errinfo_api_function("EC_KEY_generate_key") << errinfo_openssl_error(ERR_peek_error())); } - BN_free(e); - Log(LogInformation, "base") << "Writing private key to '" << keyfile << "'."; BIO *bio = BIO_new_file(const_cast(keyfile.CStr()), "w"); if (!bio) { + EVP_PKEY_free(key); + EC_KEY_free(ecKey); + Log(LogCritical, "SSL") - << "Error while opening private RSA key file '" << keyfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + << "Error while opening private key file '" << keyfile << "': " + << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + BOOST_THROW_EXCEPTION(openssl_error() << boost::errinfo_api_function("BIO_new_file") << errinfo_openssl_error(ERR_peek_error()) << boost::errinfo_file_name(keyfile)); } - if (!PEM_write_bio_RSAPrivateKey(bio, rsa, nullptr, nullptr, 0, nullptr, nullptr)) { + if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, 0, NULL)) { + EVP_PKEY_free(key); + EC_KEY_free(ecKey); + Log(LogCritical, "SSL") - << "Error while writing private RSA key to file '" << keyfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + << "Error while writing private key to file '" << keyfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("PEM_write_bio_RSAPrivateKey") + << boost::errinfo_api_function("PEM_write_bio_PrivateKey") << errinfo_openssl_error(ERR_peek_error()) << boost::errinfo_file_name(keyfile)); } @@ -394,9 +436,6 @@ int MakeX509CSR(const String& cn, const String& keyfile, const String& csrfile, chmod(keyfile.CStr(), 0600); #endif /* _WIN32 */ - EVP_PKEY *key = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(key, rsa); - if (!certfile.IsEmpty()) { X509_NAME *subject = X509_NAME_new(); X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, (unsigned char *)cn.CStr(), -1, -1, 0); @@ -583,8 +622,6 @@ std::shared_ptr CreateCertIcingaCA(EVP_PKEY *pubkey, X509_NAME *subject) String cakeyfile = cadir + "/ca.key"; - RSA *rsa; - BIO *cakeybio = BIO_new_file(const_cast(cakeyfile.CStr()), "r"); if (!cakeybio) { @@ -593,11 +630,11 @@ std::shared_ptr CreateCertIcingaCA(EVP_PKEY *pubkey, X509_NAME *subject) return std::shared_ptr(); } - rsa = PEM_read_bio_RSAPrivateKey(cakeybio, nullptr, nullptr, nullptr); + auto privkey = PEM_read_bio_PrivateKey(cakeybio, NULL, NULL, NULL); - if (!rsa) { + if (!privkey) { Log(LogCritical, "SSL") - << "Could not read RSA key from CA key file '" << cakeyfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; + << "Could not read private key from CA key file '" << cakeyfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; return std::shared_ptr(); } @@ -607,9 +644,6 @@ std::shared_ptr CreateCertIcingaCA(EVP_PKEY *pubkey, X509_NAME *subject) std::shared_ptr cacert = GetX509Certificate(cacertfile); - EVP_PKEY *privkey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(privkey, rsa); - return CreateCert(pubkey, subject, X509_get_subject_name(cacert.get()), privkey, false); }