Skip to content

Commit

Permalink
Adds OCSP support for BoringSSL
Browse files Browse the repository at this point in the history
Requires the external library boringocsp
  • Loading branch information
randall committed Jul 6, 2021
1 parent aa1d73b commit 148db52
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 11 deletions.
88 changes: 88 additions & 0 deletions build/boringocsp.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
dnl -------------------------------------------------------- -*- autoconf -*-
dnl Licensed to the Apache Software Foundation (ASF) under one or more
dnl contributor license agreements. See the NOTICE file distributed with
dnl this work for additional information regarding copyright ownership.
dnl The ASF licenses this file to You under the Apache License, Version 2.0
dnl (the "License"); you may not use this file except in compliance with
dnl the License. You may obtain a copy of the License at
dnl
dnl http://www.apache.org/licenses/LICENSE-2.0
dnl
dnl Unless required by applicable law or agreed to in writing, software
dnl distributed under the License is distributed on an "AS IS" BASIS,
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dnl See the License for the specific language governing permissions and
dnl limitations under the License.

dnl
dnl TS_CHECK_BORINGOCSP: look for boringocsp libraries and headers
dnl
AC_DEFUN([TS_CHECK_BORINGOCSP], [
has_boringocsp=no
AC_ARG_WITH(boringocsp, [AC_HELP_STRING([--with-boringocsp=DIR], [use a specific boringocsp library])],
[
if test "x$withval" != "xyes" && test "x$withval" != "x"; then
boringocsp_base_dir="$withval"
if test "$withval" != "no"; then
has_boringocsp=1
use_tls_ocsp=1
case "$withval" in
*":"*)
boringocsp_include="`echo $withval |sed -e 's/:.*$//'`"
boringocsp_ldflags="`echo $withval |sed -e 's/^.*://'`"
AC_MSG_CHECKING(checking for boringocsp includes in $boringocsp_include libs in $boringocsp_ldflags)
;;
*)
boringocsp_include="$withval"
boringocsp_ldflags="$withval"
boringocsp_base_dir="$withval"
AC_MSG_CHECKING(boringocsp includes in $withval libs in $boringocsp_ldflags)
;;
esac
fi
fi
if test -d $boringocsp_include && test -d $boringocsp_ldflags && test -f $boringocsp_include/ocsp.h; then
AC_MSG_RESULT([ok])
else
AC_MSG_RESULT([not found])
fi
AC_SUBST(use_boringocsp)
if test "$has_boringocsp" != "0"; then
saved_ldflags=$LDFLAGS
saved_cppflags=$CPPFLAGS
BORINGOCSP_LIBS=-lboringocsp
if test "$boringocsp_base_dir" != "/usr"; then
BORINGOCSP_INCLUDES=-I${boringocsp_include}
BORINGOCSP_LDFLAGS=-L${boringocsp_ldflags}
TS_ADDTO_RPATH(${boringocsp_ldflags})
fi
if test "$boringocsp_include" != "0"; then
BORINGOCSP_INCLUDES=-I${boringocsp_include}
else
has_boringocsp=0
use_tls_ocsp=0
CPPFLAGS=$saved_cppflags
LDFLAGS=$saved_ldflags
fi
fi
],
[
has_boringocsp=0
# we might be non-boringssl, don't disable if test has previously passed
if test "$use_tls_ocsp" != "1"; then
use_tls_ocsp=0
fi
])
AC_SUBST(has_boringocsp)
AC_SUBST(use_tls_ocsp)
AC_SUBST([BORINGOCSP_INCLUDES])
AC_SUBST([BORINGOCSP_LIBS])
AC_SUBST([BORINGOCSP_LDFLAGS])
])
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,9 @@ AM_CONDITIONAL([BUILD_YAML_CPP], [test x"$has_yaml_cpp" = x"no"])
TS_CHECK_YAML_HEADERS_EXPORT
AM_CONDITIONAL([EXPORT_YAML_HEADERS], [test x"$enable_yaml_headers" = x"yes"])

# Check for optional boringocsp library
TS_CHECK_BORINGOCSP

# Check for optional hiredis library
TS_CHECK_HIREDIS

Expand Down
2 changes: 2 additions & 0 deletions include/tscore/ink_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
#define TS_USE_HRW_GEOIP @use_hrw_geoip@
#define TS_USE_HRW_MAXMINDDB @use_hrw_maxminddb@

#define TS_HAS_BORINGOCSP @has_boringocsp@

#define TS_HAS_SO_PEERCRED @has_so_peercred@

/* OS API definitions */
Expand Down
1 change: 1 addition & 0 deletions iocore/net/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ AM_CPPFLAGS += \
-I$(abs_top_srcdir)/proxy/http \
$(TS_INCLUDES) \
@OPENSSL_INCLUDES@ \
@BORINGOCSP_INCLUDES@ \
@YAMLCPP_INCLUDES@

TESTS = $(check_PROGRAMS)
Expand Down
63 changes: 55 additions & 8 deletions iocore/net/OCSPStapling.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@
*/

#include "P_OCSPStapling.h"

#if TS_USE_TLS_OCSP

#include <openssl/bio.h>
#include <openssl/ssl.h>

#if TS_HAS_BORINGOCSP
#include "boringocsp/ocsp.h"
#else
#include <openssl/ocsp.h>
#endif

#include "P_Net.h"
#include "P_SSLConfig.h"
#include "P_SSLUtils.h"
Expand Down Expand Up @@ -214,6 +221,7 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
cinf->expire_time = 0;

if (cinf->is_prefetched) {
#ifndef OPENSSL_IS_BORINGSSL
Debug("ssl_ocsp", "using OCSP prefetched response file %s", rsp_file);
rsp_bio = BIO_new_file(rsp_file, "r");
if (rsp_bio) {
Expand All @@ -235,6 +243,9 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
BIO_free(rsp_bio);
rsp_bio = nullptr;
}
#else
Warning("failed to set prefetched OCSP response; this functionality not supported by BoringSSL");
#endif
}

issuer = stapling_get_issuer(ctx, cert);
Expand All @@ -261,10 +272,14 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
goto err;
}

#ifdef OPENSSL_IS_BORINGSSL
X509_up_ref(cert);
#endif

map->insert(std::make_pair(cert, cinf));
SSL_CTX_set_ex_data(ctx, ssl_stapling_index, map);

Note("successfully initialized stapling for %s into SSL_CTX: %p", certname, ctx);
Note("successfully initialized stapling for %s into SSL_CTX: %p uri=%s", certname, ctx, cinf->uri);
return true;

err:
Expand Down Expand Up @@ -458,7 +473,7 @@ stapling_refresh_response(certinfo *cinf, OCSP_RESPONSE **prsp)
if (!stapling_cache_response(*prsp, cinf)) {
Error("stapling_refresh_response: can not cache response");
} else {
Debug("ssl_ocsp", "stapling_refresh_response: successful refresh OCSP response");
Debug("ssl_ocsp", "stapling_refresh_response: successfully refreshed OCSP response");
}
goto done;

Expand Down Expand Up @@ -489,6 +504,7 @@ ocsp_update()
SSLCertificateConfig::scoped_config certLookup;
const unsigned ctxCount = certLookup->count();

Debug("ssl_ocsp", "updating OCSP data");
for (unsigned i = 0; i < ctxCount; i++) {
SSLCertContext *cc = certLookup->get(i);
if (cc) {
Expand All @@ -505,7 +521,7 @@ ocsp_update()
if (cinf->resp_derlen == 0 || cinf->is_expire || cinf->expire_time < current_time) {
ink_mutex_release(&cinf->stapling_mutex);
if (stapling_refresh_response(cinf, &resp)) {
Debug("Successfully refreshed OCSP for %s certificate. url=%s", cinf->certname, cinf->uri);
Debug("ssl_ocsp", "Successfully refreshed OCSP for %s certificate. url=%s", cinf->certname, cinf->uri);
SSL_INCREMENT_DYN_STAT(ssl_ocsp_refreshed_cert_stat);
} else {
Error("Failed to refresh OCSP for %s certificate. url=%s", cinf->certname, cinf->uri);
Expand All @@ -523,7 +539,11 @@ ocsp_update()

// RFC 6066 Section-8: Certificate Status Request
int
#ifndef OPENSSL_IS_BORINGSSL
ssl_callback_ocsp_stapling(SSL *ssl)
#else
ssl_callback_ocsp_stapling(SSL *ssl, void *)
#endif
{
// Assume SSL_get_SSL_CTX() is the same as reaching into the ssl structure
// Using the official call, to avoid leaking internal openssl knowledge
Expand All @@ -533,18 +553,43 @@ ssl_callback_ocsp_stapling(SSL *ssl)
Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: failed to get certificate map");
return SSL_TLSEXT_ERR_NOACK;
}

if (map->empty()) {
Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: certificate map empty");
return SSL_TLSEXT_ERR_NOACK;
}

// Fetch the specific certificate used in this negotiation
X509 *cert = SSL_get_certificate(ssl);
if (!cert) {
Error("ssl_callback_ocsp_stapling: failed to get certificate");
return SSL_TLSEXT_ERR_NOACK;
}

certinfo *cinf = nullptr;
#ifndef OPENSSL_IS_BORINGSSL
certinfo_map::iterator iter = map->find(cert);
if (iter == map->end()) {
Error("ssl_callback_ocsp_stapling: failed to get certificate information");
if (iter != map->end()) {
cinf = iter->second;
}
#else
for (certinfo_map::iterator iter = map->begin(); iter != map->end(); ++iter) {
X509 *key = iter->first;
if (key == nullptr) {
continue;
}

if (X509_cmp(key, cert) == 0) {
cinf = iter->second;
break;
}
}
#endif

if (cinf == nullptr) {
Error("ssl_callback_ocsp_stapling: failed to get certificate information for ssl=%p", ssl);
return SSL_TLSEXT_ERR_NOACK;
}
certinfo *cinf = iter->second;

ink_mutex_acquire(&cinf->stapling_mutex);
time_t current_time = time(nullptr);
Expand All @@ -554,11 +599,13 @@ ssl_callback_ocsp_stapling(SSL *ssl)
return SSL_TLSEXT_ERR_NOACK;
} else {
unsigned char *p = static_cast<unsigned char *>(OPENSSL_malloc(cinf->resp_derlen));
unsigned int len = cinf->resp_derlen;

memcpy(p, cinf->resp_der, cinf->resp_derlen);
ink_mutex_release(&cinf->stapling_mutex);
SSL_set_tlsext_status_ocsp_resp(ssl, p, len);
SSL_set_tlsext_status_ocsp_resp(ssl, p, cinf->resp_derlen);

Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: successfully got certificate status for %s", cinf->certname);

return SSL_TLSEXT_ERR_OK;
}
}
Expand Down
11 changes: 11 additions & 0 deletions iocore/net/P_OCSPStapling.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,21 @@

#if TS_USE_TLS_OCSP
#include <openssl/ssl.h>

#if TS_HAS_BORINGOCSP
#include "boringocsp/ocsp.h"
#else
#include <openssl/ocsp.h>
#endif

void ssl_stapling_ex_init();
bool ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const char *rsp_file);
void ocsp_update();

#ifndef OPENSSL_IS_BORINGSSL
int ssl_callback_ocsp_stapling(SSL *);
#else
int ssl_callback_ocsp_stapling(SSL *, void *);
#endif

#endif
4 changes: 3 additions & 1 deletion src/traffic_quic/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ traffic_quic_traffic_quic_CPPFLAGS = \

traffic_quic_traffic_quic_LDFLAGS = \
$(AM_LDFLAGS) \
@OPENSSL_LDFLAGS@
@OPENSSL_LDFLAGS@ \
@BORINGOCSP_LDFLAGS@

traffic_quic_traffic_quic_SOURCES = \
traffic_quic/quic_client.cc \
Expand All @@ -60,5 +61,6 @@ traffic_quic_traffic_quic_LDADD = \
@HWLOC_LIBS@ \
@YAMLCPP_LIBS@ \
@OPENSSL_LIBS@ \
@BORINGOCSP_LIBS@ \
@LIBPCRE@

7 changes: 5 additions & 2 deletions src/traffic_server/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ traffic_server_traffic_server_CPPFLAGS = \
-I$(abs_top_srcdir)/mgmt \
-I$(abs_top_srcdir)/mgmt/utils \
$(TS_INCLUDES) \
@OPENSSL_INCLUDES@
@OPENSSL_INCLUDES@ \
@BORINGOCSP_INCLUDES@

traffic_server_traffic_server_LDFLAGS = \
$(AM_LDFLAGS) \
@YAMLCPP_LDFLAGS@
@YAMLCPP_LDFLAGS@ \
@BORINGOCSP_LDFLAGS@

traffic_server_traffic_server_SOURCES = \
traffic_server/Crash.cc \
Expand Down Expand Up @@ -87,6 +89,7 @@ traffic_server_traffic_server_LDADD = \
@LIBPROFILER@ \
@OPENSSL_LIBS@ \
@YAMLCPP_LIBS@ \
@BORINGOCSP_LIBS@ \
-lm

if IS_DARWIN
Expand Down

0 comments on commit 148db52

Please sign in to comment.