Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/iocore/net/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ add_library(
SSLSessionCache.cc
SSLSessionTicket.cc
SSLUtils.cc
SSLKeyUtils.cc
OCSPStapling.cc
TLSBasicSupport.cc
TLSEventSupport.cc
Expand Down Expand Up @@ -144,6 +145,9 @@ if(BUILD_TESTING)
unit_tests/unit_test_main.cc
unit_tests/benchmark_TLSCertCompression.cc
)
if(SSLLIB_IS_OPENSSL3)
target_sources(test_net PRIVATE unit_tests/test_SSLDHParams.cc)
endif()
# Use link groups to solve circular dependency
set(LINK_GROUP_LIBS
ts::logging
Expand Down
26 changes: 26 additions & 0 deletions src/iocore/net/P_SSLUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include "iocore/net/SSLTypes.h"
#include "tscore/Diags.h"

#ifdef OPENSSL_IS_OPENSSL3
#include <openssl/decoder.h>
#include <openssl/evp.h>
#endif
#define OPENSSL_THREAD_DEFINES
#if __has_include(<openssl/opensslconf.h>)
#include <openssl/opensslconf.h>
Expand Down Expand Up @@ -110,6 +114,24 @@ namespace detail
}
};

#ifdef OPENSSL_IS_OPENSSL3
struct PKEYCTXDeleter {
void
operator()(EVP_PKEY_CTX *pctx)
{
EVP_PKEY_CTX_free(pctx);
}
};

struct DecoderCTXDeleter {
void
operator()(OSSL_DECODER_CTX *dctx)
{
OSSL_DECODER_CTX_free(dctx);
}
};
#endif

} // namespace detail
} // namespace ssl

Expand All @@ -134,3 +156,7 @@ struct ats_wildcard_matcher {

using scoped_X509 = std::unique_ptr<X509, ssl::detail::X509Deleter>;
using scoped_BIO = std::unique_ptr<BIO, ssl::detail::BIODeleter>;
#ifdef OPENSSL_IS_OPENSSL3
using scoped_PKEY_CTX = std::unique_ptr<EVP_PKEY_CTX, ssl::detail::PKEYCTXDeleter>;
using scoped_Decoder_CTX = std::unique_ptr<OSSL_DECODER_CTX, ssl::detail::DecoderCTXDeleter>;
#endif
218 changes: 218 additions & 0 deletions src/iocore/net/SSLKeyUtils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/** @file

@section license License

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "SSLKeyUtils.h"
#include "P_SSLUtils.h"

#include <tscore/Diags.h>
#ifdef OPENSSL_IS_OPENSSL3
#include <tscore/ink_assert.h>
#else
#include <tscore/ink_config.h>
#endif

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>

#ifdef OPENSSL_IS_OPENSSL3
#include <openssl/decoder.h>
#include <openssl/params.h>
#else
#include <openssl/bn.h>
#endif

#ifdef OPENSSL_IS_OPENSSL3

EVP_PKEY *
gen_dh_2048_256_pkey()
{
scoped_PKEY_CTX pctx{EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)};
if (!pctx) {
Error("failed to create OpenSSL pkey context");
return nullptr;
}

if (EVP_PKEY_keygen_init(pctx.get()) <= 0) {
Error("failed to initialize OpenSSL keygen");
return nullptr;
}

char prime_group[]{"dh_2048_256"};
OSSL_PARAM const params[]{OSSL_PARAM_utf8_string("group", prime_group, 0), OSSL_PARAM_END};

if (!EVP_PKEY_CTX_set_params(pctx.get(), params)) {
Error("SSL dhparams source returned invalid parameters");
return nullptr;
}

EVP_PKEY *pkey{};
EVP_PKEY_generate(pctx.get(), &pkey);

return pkey;
}

EVP_PKEY *
load_dhparams_file(char const *dhparams_file)
{
EVP_PKEY *pkey{};
scoped_Decoder_CTX dctx{OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "DH", OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL, NULL)};
if (!dctx) {
Error("failed to create OpenSSL decoder context");
return nullptr;
}

ink_assert(OSSL_DECODER_CTX_get_num_decoders(dctx.get()) > 0);
scoped_BIO bio{BIO_new_file(dhparams_file, "r")};
if (!OSSL_DECODER_from_bio(dctx.get(), bio.get())) {
Error("SSL dhparams source returned invalid parameters");
return nullptr;
}

return pkey;
}

bool
set_ctx_dh(SSL_CTX *ctx, dh_key_t *pkey)
{
bool result{SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE) && SSL_CTX_set0_tmp_dh_pkey(ctx, pkey)};
if (!result) {
EVP_PKEY_free(pkey);
}
return result;
}

#else

DH *
load_dhparams_file(char const *dhparams_file)
{
scoped_BIO bio(BIO_new_file(dhparams_file, "r"));
DH *dh{PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr)};
if (!dh) {
Error("SSL dhparams source returned invalid parameters");
return nullptr;
}

return dh;
}

#if TS_USE_GET_DH_2048_256
DH *
gen_dh_2048_256_pkey()
{
return DH_get_2048_256();
}
#else
DH *
gen_dh_2048_256_pkey()
{
/* Build 2048-bit MODP Group with 256-bit Prime Order Subgroup from RFC 5114 */
static const unsigned char dh2048_p[] = {
0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C, 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99, 0x8C, 0xEE, 0xF6, 0x08,
0x66, 0x0D, 0xD0, 0xF2, 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00, 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4,
0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30, 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA, 0x3B, 0xF4, 0x29, 0x6D,
0x83, 0x0E, 0x9A, 0x7C, 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD, 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED,
0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0, 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B, 0x6C, 0x5B, 0xFC, 0x11,
0xD4, 0x5F, 0x90, 0x88, 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8, 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C,
0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76, 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90, 0x2D, 0x52, 0x52, 0x67,
0x35, 0x48, 0x8A, 0x0E, 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB, 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E,
0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9, 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25, 0x1C, 0xCA, 0xCB, 0x83,
0xE6, 0xB4, 0x86, 0xF6, 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26, 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56,
0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21, 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3, 0x75, 0xF2, 0x63, 0x75,
0xD7, 0x01, 0x41, 0x03, 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12, 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F,
0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA, 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97};
static const unsigned char dh2048_g[] = {
0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, 0x4C, 0xA7, 0xB1, 0x8F,
0x21, 0xEF, 0x20, 0x54, 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F,
0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, 0xBC, 0x37, 0x73, 0xBF,
0x7E, 0x8C, 0x6F, 0x62, 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65,
0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, 0x77, 0x7D, 0xE6, 0x2A,
0xAA, 0xB8, 0xA8, 0x62, 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83,
0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, 0xDF, 0xC9, 0x67, 0xC1,
0xFB, 0x3F, 0x2E, 0x55, 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A,
0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, 0xB7, 0xD2, 0xBB, 0xD2,
0xDF, 0x01, 0x61, 0x99, 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37,
0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, 0x18, 0x4B, 0x52, 0x3D,
0x1D, 0xB2, 0x46, 0xC3, 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51,
0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59};
DH *dh;
BIGNUM *p;
BIGNUM *g;

if ((dh = DH_new()) == nullptr) {
return nullptr;
}
p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), nullptr);
g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), nullptr);
if (p == nullptr || g == nullptr) {
DH_free(dh);
BN_free(p);
BN_free(g);
return nullptr;
}
DH_set0_pqg(dh, p, nullptr, g);
return (dh);
}
#endif // TS_USE_GET_DH_2048_256

bool
set_ctx_dh(SSL_CTX *ctx, dh_key_t *pkey)
{
bool result{SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE) && SSL_CTX_set_tmp_dh(ctx, pkey)};
DH_free(pkey);
return result;
}

#endif // OPENSSL_IS_OPENSSL3

bool
use_rsa_pkey_from_file(SSL_CTX *ctx, const char *keyPath)
{
ink_assert(keyPath && keyPath[0] != '\0');
int const result{SSL_CTX_use_RSAPrivateKey_file(ctx, keyPath, SSL_FILETYPE_PEM)};
if (1 != result) {
char err_buf[256]{};
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
Error("failed to load RSA key %s: %s", keyPath, err_buf);
}
return 1 == result;
}

bool
use_rsa_pkey_from_secret_data(SSL_CTX *ctx, const char *secret_data, int secret_data_len)
{
scoped_BIO bio(BIO_new_mem_buf(secret_data, secret_data_len));

pem_password_cb *password_cb = SSL_CTX_get_default_passwd_cb(ctx);
void *u = SSL_CTX_get_default_passwd_cb_userdata(ctx);
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio.get(), nullptr, password_cb, u);
if (nullptr == pkey) {
return false;
}
if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
EVP_PKEY_free(pkey);
return false;
}
return true;
}
45 changes: 45 additions & 0 deletions src/iocore/net/SSLKeyUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/** @file

@section license License

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#pragma once

#if OPENSSL_IS_OPENSSL3
#include <openssl/evp.h>
#else
#include <openssl/dh.h>
#endif
#include <openssl/ssl.h>

#ifdef OPENSSL_IS_OPENSSL3
using dh_key_t = EVP_PKEY;
#else
using dh_key_t = DH;
#endif

// Both gen_dh_2048_256_pkey and load_dhparams_file return owning pointers.
dh_key_t *gen_dh_2048_256_pkey();
dh_key_t *load_dhparams_file(char const *dhparams_file);

// Takes ownership of pkey.
bool set_ctx_dh(SSL_CTX *ctx, dh_key_t *pkey);

bool use_rsa_pkey_from_file(SSL_CTX *ctx, const char *keyPath);
bool use_rsa_pkey_from_secret_data(SSL_CTX *ctx, const char *secret_data, int secret_data_len);
Loading