Skip to content

Commit

Permalink
Merge pull request #2056 from nghttp2/bssl-cert-compression
Browse files Browse the repository at this point in the history
src: Certificate Compression with boringssl
  • Loading branch information
tatsuhiro-t committed Feb 7, 2024
2 parents 4ae7fe9 + 4b34dd1 commit f3b1422
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 2 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ jobs:
libjemalloc-dev \
libc-ares-dev \
libelf-dev \
libbrotli-dev \
cmake \
cmake-data
echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $GITHUB_ENV
Expand All @@ -262,6 +263,7 @@ jobs:
c-ares \
cunit \
libressl \
brotli \
autoconf \
automake \
pkg-config \
Expand Down Expand Up @@ -433,12 +435,12 @@ jobs:
if: matrix.buildtool == 'autotools' && runner.os == 'Linux'
run: |
make -j"$(nproc)" distcheck \
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --with-librotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
- name: Build nghttp2 with autotools (MacOS)
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
run: |
make -j"$(sysctl -n hw.ncpu)" distcheck \
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --with-librotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
- name: Build nghttp2 with cmake
if: matrix.buildtool == 'cmake'
run: |
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ if(NOT ENABLE_LIB_ONLY)
find_package(Libev 4.11)
find_package(Libcares 1.7.5)
find_package(ZLIB 1.2.3)
find_package(Libbrotlienc 1.0.9)
find_package(Libbrotlidec 1.0.9)
endif()

find_package(OpenSSL 1.1.1)
Expand Down Expand Up @@ -474,6 +476,8 @@ message(STATUS "summary of build options:
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
Libbrotlienc: ${HAVE_LIBBROTLIENC} (LIBS='${LIBBROTLIENC_LIBRARIES}')
Libbrotlidec: ${HAVE_LIBBROTLIDEC} (LIBS='${LIBBROTLIDEC_LIBRARIES}')
Third-party:
http-parser: ${ENABLE_THIRD_PARTY}
MRuby: ${HAVE_MRUBY}
Expand Down
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
cmake/FindLibnghttp3.cmake \
cmake/FindLibngtcp2.cmake \
cmake/FindLibngtcp2_crypto_quictls.cmake \
cmake/FindLibbrotlienc.cmake \
cmake/FindLibbrotlidec.cmake \
cmake/PickyWarningsC.cmake \
cmake/PickyWarningsCXX.cmake

Expand Down
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ To mitigate heap fragmentation in long running server programs
Alpine Linux currently does not support malloc replacement
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.

For BoringSSL or aws-lc build, to enable :rfc:`8879` TLS Certificate
Compression in applications, the following library is required:

* libbrotli-dev >= 1.0.9

To enable mruby support for nghttpx, `mruby
<https://github.com/mruby/mruby>`_ is required. We need to build
mruby with C++ ABI explicitly turned on, and probably need other
Expand Down
36 changes: 36 additions & 0 deletions cmake/FindLibbrotlidec.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# - Try to find libbrotlidec
# Once done this will define
# LIBBROTLIDEC_FOUND - System has libbrotlidec
# LIBBROTLIDEC_INCLUDE_DIRS - The libbrotlidec include directories
# LIBBROTLIDEC_LIBRARIES - The libraries needed to use libbrotlidec

find_package(PkgConfig QUIET)
pkg_check_modules(PC_LIBBROTLIDEC QUIET libbrotlidec)

find_path(LIBBROTLIDEC_INCLUDE_DIR
NAMES brotli/decode.h
HINTS ${PC_LIBBROTLIDEC_INCLUDE_DIRS}
)
find_library(LIBBROTLIDEC_LIBRARY
NAMES brotlidec
HINTS ${PC_LIBBROTLIDEC_LIBRARY_DIRS}
)

if(PC_LIBBROTLIDEC_FOUND)
set(LIBBROTLIDEC_VERSION ${PC_LIBBROTLIDEC_VERSION})
endif()

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIDEC_FOUND
# to TRUE if all listed variables are TRUE and the requested version
# matches.
find_package_handle_standard_args(Libbrotlidec REQUIRED_VARS
LIBBROTLIDEC_LIBRARY LIBBROTLIDEC_INCLUDE_DIR
VERSION_VAR LIBBROTLIDEC_VERSION)

if(LIBBROTLIDEC_FOUND)
set(LIBBROTLIDEC_LIBRARIES ${LIBBROTLIDEC_LIBRARY})
set(LIBBROTLIDEC_INCLUDE_DIRS ${LIBBROTLIDEC_INCLUDE_DIR})
endif()

mark_as_advanced(LIBBROTLIDEC_INCLUDE_DIR LIBBROTLIDEC_LIBRARY)
36 changes: 36 additions & 0 deletions cmake/FindLibbrotlienc.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# - Try to find libbrotlienc
# Once done this will define
# LIBBROTLIENC_FOUND - System has libbrotlienc
# LIBBROTLIENC_INCLUDE_DIRS - The libbrotlienc include directories
# LIBBROTLIENC_LIBRARIES - The libraries needed to use libbrotlienc

find_package(PkgConfig QUIET)
pkg_check_modules(PC_LIBBROTLIENC QUIET libbrotlienc)

find_path(LIBBROTLIENC_INCLUDE_DIR
NAMES brotli/encode.h
HINTS ${PC_LIBBROTLIENC_INCLUDE_DIRS}
)
find_library(LIBBROTLIENC_LIBRARY
NAMES brotlienc
HINTS ${PC_LIBBROTLIENC_LIBRARY_DIRS}
)

if(PC_LIBBROTLIENC_FOUND)
set(LIBBROTLIENC_VERSION ${PC_LIBBROTLIENC_VERSION})
endif()

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIENC_FOUND
# to TRUE if all listed variables are TRUE and the requested version
# matches.
find_package_handle_standard_args(Libbrotlienc REQUIRED_VARS
LIBBROTLIENC_LIBRARY LIBBROTLIENC_INCLUDE_DIR
VERSION_VAR LIBBROTLIENC_VERSION)

if(LIBBROTLIENC_FOUND)
set(LIBBROTLIENC_LIBRARIES ${LIBBROTLIENC_LIBRARY})
set(LIBBROTLIENC_INCLUDE_DIRS ${LIBBROTLIENC_INCLUDE_DIR})
endif()

mark_as_advanced(LIBBROTLIENC_INCLUDE_DIR LIBBROTLIENC_LIBRARY)
53 changes: 53 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ AC_ARG_WITH([libbpf],
[Use libbpf [default=no]])],
[request_libbpf=$withval], [request_libbpf=no])

AC_ARG_WITH([libbrotlienc],
[AS_HELP_STRING([--with-libbrotlienc],
[Use libbrotlienc [default=check]])],
[request_libbrotlienc=$withval], [request_libbrotlienc=check])

AC_ARG_WITH([libbrotlidec],
[AS_HELP_STRING([--with-libbrotlidec],
[Use libbrotlidec [default=check]])],
[request_libbrotlidec=$withval], [request_libbrotlidec=check])

dnl Define variables
AC_ARG_VAR([LIBEV_CFLAGS], [C compiler flags for libev, skipping any checks])
AC_ARG_VAR([LIBEV_LIBS], [linker flags for libev, skipping any checks])
Expand Down Expand Up @@ -626,6 +636,47 @@ fi

AM_CONDITIONAL([HAVE_LIBBPF], [ test "x${have_libbpf}" = "xyes" ])

# libbrotlienc (for src)
have_libbrotlienc=no
if test "x${request_libbrotlienc}" != "xno"; then
PKG_CHECK_MODULES([LIBBROTLIENC], [libbrotlienc >= 1.0.9],
[have_libbrotlienc=yes],
[have_libbrotlienc=no])
if test "x${have_libbrotlienc}" = "xno"; then
AC_MSG_NOTICE($LIBBROTLIENC_PKG_ERRORS)
fi
fi

if test "x${request_libbrotlienc}" = "xyes" &&
test "x${have_libbrotlienc}" != "xyes"; then
AC_MSG_ERROR([libbrotlienc was requested (--with-libbrotlienc) but not found])
fi

# libbrotlidec (for src)
have_libbrotlidec=no
if test "x${request_libbrotlidec}" != "xno"; then
PKG_CHECK_MODULES([LIBBROTLIDEC], [libbrotlidec >= 1.0.9],
[have_libbrotlidec=yes],
[have_libbrotlidec=no])
if test "x${have_libbrotlidec}" = "xno"; then
AC_MSG_NOTICE($LIBBROTLIDEC_PKG_ERRORS)
fi
fi

if test "x${request_libbrotlidec}" = "xyes" &&
test "x${have_libbrotlidec}" != "xyes"; then
AC_MSG_ERROR([libbrotlidec was requested (--with-libbrotlidec) but not found])
fi

have_libbrotli=no
if test "x${have_libbrotlienc}" = "xyes" &&
test "x${have_libbrotlidec}" = "xyes"; then
have_libbrotli=yes

AC_DEFINE([HAVE_LIBBROTLI], [1],
[Define to 1 if you have `libbrotlienc` and libbrotlidec` libraries.])
fi

# libevent_openssl (for examples)
# 2.0.8 is required because we use evconnlistener_set_error_cb()
have_libevent_openssl=no
Expand Down Expand Up @@ -1172,6 +1223,8 @@ AC_MSG_NOTICE([summary of build options:
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_LIBS}')
Libbrotlienc ${have_libbrotlienc} (CFLAGS="${LIBBROTLIENC_CFLAGS}' LIBS='${LIBBROTLIENC_LIBS}')
Libbrotlidec ${have_libbrotlidec} (CFLAGS="${LIBBROTLIDEC_CFLAGS}' LIBS='${LIBBROTLIDEC_LIBS}')
Third-party:
http-parser: ${enable_third_party}
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ include_directories(
${JANSSON_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
${LIBBPF_INCLUDE_DIRS}
${LIBBROTLIENC_INCLUDE_DIRS}
${LIBBROTLIDEC_INCLUDE_DIRS}
)

# XXX per-target?
Expand All @@ -38,6 +40,8 @@ link_libraries(
${ZLIB_LIBRARIES}
${APP_LIBRARIES}
${LIBBPF_LIBRARIES}
${LIBBROTLIENC_LIBRARIES}
${LIBBROTLIDEC_LIBRARIES}
)

if(ENABLE_APP)
Expand Down
9 changes: 9 additions & 0 deletions src/HttpServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,15 @@ int HttpServer::run() {

// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);

#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
if (!SSL_CTX_add_cert_compression_alg(
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
std::cerr << "SSL_CTX_add_cert_compression_alg failed." << std::endl;
return -1;
}
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
}

auto loop = EV_DEFAULT;
Expand Down
4 changes: 4 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ AM_CPPFLAGS = \
@JANSSON_CFLAGS@ \
@LIBBPF_CFLAGS@ \
@ZLIB_CFLAGS@ \
@LIBBROTLIENC_CFLAGS@ \
@LIBBROTLIDEC_CFLAGS@ \
@EXTRA_DEFS@ \
@DEFS@
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
Expand All @@ -73,6 +75,8 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
@JANSSON_LIBS@ \
@LIBBPF_LIBS@ \
@ZLIB_LIBS@ \
@LIBBROTLIENC_LIBS@ \
@LIBBROTLIDEC_LIBS@ \
@APPLDFLAGS@

if ENABLE_APP
Expand Down
9 changes: 9 additions & 0 deletions src/h2load.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2973,6 +2973,15 @@ int main(int argc, char **argv) {
}
}

#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
if (!SSL_CTX_add_cert_compression_alg(
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
std::cerr << "SSL_CTX_add_cert_compression_alg failed" << std::endl;
exit(EXIT_FAILURE);
}
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI

std::string user_agent = "h2load nghttp2/" NGHTTP2_VERSION;
Headers shared_nva;
shared_nva.emplace_back(":scheme", config.scheme);
Expand Down
11 changes: 11 additions & 0 deletions src/nghttp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2311,6 +2311,17 @@ int communicate(
auto proto_list = util::get_default_alpn();

SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size());

#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
if (!SSL_CTX_add_cert_compression_alg(
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
std::cerr << "[ERROR] SSL_CTX_add_cert_compression_alg failed."
<< std::endl;
result = -1;
goto fin;
}
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
}
{
HttpClient client{callbacks, loop, ssl_ctx};
Expand Down

0 comments on commit f3b1422

Please sign in to comment.