nghttpx: Enable signed_certificate_timestamp extension for TLSv1.3
This commit is contained in:
parent
980570de71
commit
2d9fd87029
|
@ -123,6 +123,7 @@ void Connection::disconnect() {
|
||||||
tls.handshake_state = 0;
|
tls.handshake_state = 0;
|
||||||
tls.initial_handshake_done = false;
|
tls.initial_handshake_done = false;
|
||||||
tls.reneg_started = false;
|
tls.reneg_started = false;
|
||||||
|
tls.sct_requested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
|
|
|
@ -71,6 +71,9 @@ struct TLSConnection {
|
||||||
bool reneg_started;
|
bool reneg_started;
|
||||||
// true if ssl is prepared to do handshake as server.
|
// true if ssl is prepared to do handshake as server.
|
||||||
bool server_handshake;
|
bool server_handshake;
|
||||||
|
// true if ssl is initialized as server, and client requested
|
||||||
|
// signed_certificate_timestamp extension.
|
||||||
|
bool sct_requested;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TCPHint {
|
struct TCPHint {
|
||||||
|
|
104
src/shrpx_tls.cc
104
src/shrpx_tls.cc
|
@ -534,16 +534,26 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#ifndef TLSEXT_TYPE_signed_certificate_timestamp
|
||||||
namespace {
|
#define TLSEXT_TYPE_signed_certificate_timestamp 18
|
||||||
// https://tools.ietf.org/html/rfc6962#section-6
|
#endif // !TLSEXT_TYPE_signed_certificate_timestamp
|
||||||
constexpr unsigned int TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP = 18;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int sct_add_cb(SSL *ssl, unsigned int ext_type, const unsigned char **out,
|
int sct_add_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
|
||||||
size_t *outlen, int *al, void *add_arg) {
|
const unsigned char **out, size_t *outlen, X509 *x,
|
||||||
assert(ext_type == TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP);
|
size_t chainidx, int *al, void *add_arg) {
|
||||||
|
assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
|
||||||
|
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
if (!conn->tls.sct_requested) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "sct_add_cb is called, chainidx=" << chainidx << ", x=" << x
|
||||||
|
<< ", context=" << std::hex << context;
|
||||||
|
}
|
||||||
|
|
||||||
auto ssl_ctx = SSL_get_SSL_CTX(ssl);
|
auto ssl_ctx = SSL_get_SSL_CTX(ssl);
|
||||||
auto tls_ctx_data =
|
auto tls_ctx_data =
|
||||||
static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
|
static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
|
||||||
|
@ -556,23 +566,59 @@ int sct_add_cb(SSL *ssl, unsigned int ext_type, const unsigned char **out,
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void sct_free_cb(SSL *ssl, unsigned int ext_type, const unsigned char *out,
|
void sct_free_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
|
||||||
void *add_arg) {
|
const unsigned char *out, void *add_arg) {
|
||||||
assert(ext_type == TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP);
|
assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int sct_parse_cb(SSL *ssl, unsigned int ext_type, const unsigned char *in,
|
int sct_parse_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
|
||||||
size_t inlen, int *al, void *parse_arg) {
|
const unsigned char *in, size_t inlen, X509 *x,
|
||||||
assert(ext_type == TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP);
|
size_t chainidx, int *al, void *parse_arg) {
|
||||||
|
assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
|
||||||
// client SHOULD send 0 length extension_data, but it is still
|
// client SHOULD send 0 length extension_data, but it is still
|
||||||
// SHOULD, and not MUST.
|
// SHOULD, and not MUST.
|
||||||
|
|
||||||
|
// For TLSv1.3 Certificate message, sct_add_cb is called even if
|
||||||
|
// client has not sent signed_certificate_timestamp extension in its
|
||||||
|
// ClientHello. Explicitly remember that client has included it
|
||||||
|
// here.
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
conn->tls.sct_requested = true;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \
|
||||||
|
!OPENSSL_1_1_1_API
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int legacy_sct_add_cb(SSL *ssl, unsigned int ext_type,
|
||||||
|
const unsigned char **out, size_t *outlen, int *al,
|
||||||
|
void *add_arg) {
|
||||||
|
return sct_add_cb(ssl, ext_type, 0, out, outlen, nullptr, 0, al, add_arg);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void legacy_sct_free_cb(SSL *ssl, unsigned int ext_type,
|
||||||
|
const unsigned char *out, void *add_arg) {
|
||||||
|
sct_free_cb(ssl, ext_type, 0, out, add_arg);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int legacy_sct_parse_cb(SSL *ssl, unsigned int ext_type,
|
||||||
|
const unsigned char *in, size_t inlen, int *al,
|
||||||
|
void *parse_arg) {
|
||||||
|
return sct_parse_cb(ssl, ext_type, 0, in, inlen, nullptr, 0, al, parse_arg);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
|
||||||
|
// !OPENSSL_1_1_1_API
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE
|
#if !LIBRESSL_IN_USE
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -832,18 +878,36 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
// SSL_extension_supported(TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP)
|
// SSL_extension_supported(TLSEXT_TYPE_signed_certificate_timestamp)
|
||||||
// returns 1, which means OpenSSL internally handles it. But
|
// returns 1, which means OpenSSL internally handles it. But
|
||||||
// OpenSSL handles signed_certificate_timestamp extension specially,
|
// OpenSSL handles signed_certificate_timestamp extension specially,
|
||||||
// and it lets custom handler to process the extension.
|
// and it lets custom handler to process the extension.
|
||||||
if (!sct_data.empty() &&
|
if (!sct_data.empty()) {
|
||||||
SSL_CTX_add_server_custom_ext(
|
#if OPENSSL_1_1_1_API
|
||||||
ssl_ctx, TLS_EXT_SIGNED_CERTIFICATE_TIMESTAMP, sct_add_cb,
|
// It is not entirely clear to me that SSL_EXT_CLIENT_HELLO is
|
||||||
sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) {
|
// required here. sct_parse_cb is called without
|
||||||
|
// SSL_EXT_CLIENT_HELLO being set. But the passed context value
|
||||||
|
// is SSL_EXT_CLIENT_HELLO.
|
||||||
|
if (SSL_CTX_add_custom_ext(
|
||||||
|
ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
|
||||||
|
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO |
|
||||||
|
SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_IGNORE_ON_RESUMPTION,
|
||||||
|
sct_add_cb, sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) {
|
||||||
|
LOG(FATAL) << "SSL_CTX_add_custom_ext failed: "
|
||||||
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
DIE();
|
||||||
|
}
|
||||||
|
#else // !OPENSSL_1_1_1_API
|
||||||
|
if (SSL_CTX_add_server_custom_ext(
|
||||||
|
ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
|
||||||
|
legacy_sct_add_cb, legacy_sct_free_cb, nullptr, legacy_sct_parse_cb,
|
||||||
|
nullptr) != 1) {
|
||||||
LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: "
|
LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
#endif // !OPENSSL_1_1_1_API
|
||||||
|
}
|
||||||
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE
|
#if !LIBRESSL_IN_USE
|
||||||
|
|
|
@ -35,4 +35,7 @@
|
||||||
#define OPENSSL_1_1_API \
|
#define OPENSSL_1_1_API \
|
||||||
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x1010000fL)
|
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x1010000fL)
|
||||||
|
|
||||||
|
#define OPENSSL_1_1_1_API \
|
||||||
|
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10101000L)
|
||||||
|
|
||||||
#endif // OPENSSL_COMPAT_H
|
#endif // OPENSSL_COMPAT_H
|
||||||
|
|
Loading…
Reference in New Issue