Skip to content

Commit 5ddb462

Browse files
authored
Adds OCSP support for BoringSSL (#7298)
Requires the external library boringocsp
1 parent 46422df commit 5ddb462

8 files changed

Lines changed: 165 additions & 11 deletions

File tree

build/boringocsp.m4

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
dnl -------------------------------------------------------- -*- autoconf -*-
2+
dnl Licensed to the Apache Software Foundation (ASF) under one or more
3+
dnl contributor license agreements. See the NOTICE file distributed with
4+
dnl this work for additional information regarding copyright ownership.
5+
dnl The ASF licenses this file to You under the Apache License, Version 2.0
6+
dnl (the "License"); you may not use this file except in compliance with
7+
dnl the License. You may obtain a copy of the License at
8+
dnl
9+
dnl http://www.apache.org/licenses/LICENSE-2.0
10+
dnl
11+
dnl Unless required by applicable law or agreed to in writing, software
12+
dnl distributed under the License is distributed on an "AS IS" BASIS,
13+
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
dnl See the License for the specific language governing permissions and
15+
dnl limitations under the License.
16+
17+
dnl
18+
dnl TS_CHECK_BORINGOCSP: look for boringocsp libraries and headers
19+
dnl
20+
AC_DEFUN([TS_CHECK_BORINGOCSP], [
21+
has_boringocsp=no
22+
AC_ARG_WITH(boringocsp, [AS_HELP_STRING([--with-boringocsp=DIR], [use a specific BoringOCSP library])],
23+
[
24+
if test "x$withval" != "xyes" && test "x$withval" != "x"; then
25+
boringocsp_base_dir="$withval"
26+
if test "$withval" != "no"; then
27+
has_boringocsp=1
28+
use_tls_ocsp=1
29+
case "$withval" in
30+
*":"*)
31+
boringocsp_include="`echo $withval |sed -e 's/:.*$//'`"
32+
boringocsp_ldflags="`echo $withval |sed -e 's/^.*://'`"
33+
AC_MSG_CHECKING(checking for boringocsp includes in $boringocsp_include libs in $boringocsp_ldflags)
34+
;;
35+
*)
36+
boringocsp_include="$withval"
37+
boringocsp_ldflags="$withval"
38+
boringocsp_base_dir="$withval"
39+
AC_MSG_CHECKING(boringocsp includes in $withval libs in $boringocsp_ldflags)
40+
;;
41+
esac
42+
fi
43+
fi
44+
45+
if test -d $boringocsp_include && test -d $boringocsp_ldflags && test -f $boringocsp_include/ocsp.h; then
46+
AC_MSG_RESULT([ok])
47+
else
48+
AC_MSG_RESULT([not found])
49+
fi
50+
AC_SUBST(use_boringocsp)
51+
52+
if test "$has_boringocsp" != "0"; then
53+
saved_ldflags=$LDFLAGS
54+
saved_cppflags=$CPPFLAGS
55+
56+
BORINGOCSP_LIBS=-lboringocsp
57+
if test "$boringocsp_base_dir" != "/usr"; then
58+
BORINGOCSP_INCLUDES=-I${boringocsp_include}
59+
BORINGOCSP_LDFLAGS=-L${boringocsp_ldflags}
60+
61+
TS_ADDTO_RPATH(${boringocsp_ldflags})
62+
fi
63+
64+
if test "$boringocsp_include" != "0"; then
65+
BORINGOCSP_INCLUDES=-I${boringocsp_include}
66+
else
67+
has_boringocsp=0
68+
use_tls_ocsp=0
69+
CPPFLAGS=$saved_cppflags
70+
LDFLAGS=$saved_ldflags
71+
fi
72+
fi
73+
],
74+
[
75+
has_boringocsp=0
76+
# we might be non-boringssl, don't disable if test has previously passed
77+
if test "$use_tls_ocsp" != "1"; then
78+
use_tls_ocsp=0
79+
fi
80+
])
81+
82+
AC_SUBST(has_boringocsp)
83+
AC_SUBST(use_tls_ocsp)
84+
AC_SUBST([BORINGOCSP_INCLUDES])
85+
AC_SUBST([BORINGOCSP_LIBS])
86+
AC_SUBST([BORINGOCSP_LDFLAGS])
87+
88+
])

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,9 @@ AM_CONDITIONAL([BUILD_YAML_CPP], [test x"$has_yaml_cpp" = x"no"])
14371437
TS_CHECK_YAML_HEADERS_EXPORT
14381438
AM_CONDITIONAL([EXPORT_YAML_HEADERS], [test x"$enable_yaml_headers" = x"yes"])
14391439

1440+
# Check for optional boringocsp library
1441+
TS_CHECK_BORINGOCSP
1442+
14401443
# Check for optional hiredis library
14411444
TS_CHECK_HIREDIS
14421445

include/tscore/ink_config.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
#define TS_USE_HRW_GEOIP @use_hrw_geoip@
8686
#define TS_USE_HRW_MAXMINDDB @use_hrw_maxminddb@
8787

88+
#define TS_HAS_BORINGOCSP @has_boringocsp@
89+
8890
#define TS_HAS_SO_PEERCRED @has_so_peercred@
8991

9092
/* OS API definitions */

iocore/net/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ AM_CPPFLAGS += \
3333
-I$(abs_top_srcdir)/proxy/http \
3434
$(TS_INCLUDES) \
3535
@OPENSSL_INCLUDES@ \
36+
@BORINGOCSP_INCLUDES@ \
3637
@YAMLCPP_INCLUDES@
3738

3839
TESTS = $(check_PROGRAMS)

iocore/net/OCSPStapling.cc

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@
2020
*/
2121

2222
#include "P_OCSPStapling.h"
23+
2324
#if TS_USE_TLS_OCSP
2425

2526
#include <openssl/bio.h>
2627
#include <openssl/ssl.h>
28+
29+
#if TS_HAS_BORINGOCSP
30+
#include <boringocsp/ocsp.h>
31+
#else
2732
#include <openssl/ocsp.h>
33+
#endif
34+
2835
#include "P_Net.h"
2936
#include "P_SSLConfig.h"
3037
#include "P_SSLUtils.h"
@@ -214,6 +221,7 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
214221
cinf->expire_time = 0;
215222

216223
if (cinf->is_prefetched) {
224+
#ifndef OPENSSL_IS_BORINGSSL
217225
Debug("ssl_ocsp", "using OCSP prefetched response file %s", rsp_file);
218226
rsp_bio = BIO_new_file(rsp_file, "r");
219227
if (rsp_bio) {
@@ -235,6 +243,9 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
235243
BIO_free(rsp_bio);
236244
rsp_bio = nullptr;
237245
}
246+
#else
247+
Warning("failed to set prefetched OCSP response; this functionality not supported by BoringSSL");
248+
#endif
238249
}
239250

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

275+
#ifdef OPENSSL_IS_BORINGSSL
276+
X509_up_ref(cert);
277+
#endif
278+
264279
map->insert(std::make_pair(cert, cinf));
265280
SSL_CTX_set_ex_data(ctx, ssl_stapling_index, map);
266281

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

270285
err:
@@ -458,7 +473,7 @@ stapling_refresh_response(certinfo *cinf, OCSP_RESPONSE **prsp)
458473
if (!stapling_cache_response(*prsp, cinf)) {
459474
Error("stapling_refresh_response: can not cache response");
460475
} else {
461-
Debug("ssl_ocsp", "stapling_refresh_response: successful refresh OCSP response");
476+
Debug("ssl_ocsp", "stapling_refresh_response: successfully refreshed OCSP response");
462477
}
463478
goto done;
464479

@@ -489,6 +504,7 @@ ocsp_update()
489504
SSLCertificateConfig::scoped_config certLookup;
490505
const unsigned ctxCount = certLookup->count();
491506

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

524540
// RFC 6066 Section-8: Certificate Status Request
525541
int
542+
#ifndef OPENSSL_IS_BORINGSSL
526543
ssl_callback_ocsp_stapling(SSL *ssl)
544+
#else
545+
ssl_callback_ocsp_stapling(SSL *ssl, void *)
546+
#endif
527547
{
528548
// Assume SSL_get_SSL_CTX() is the same as reaching into the ssl structure
529549
// Using the official call, to avoid leaking internal openssl knowledge
@@ -533,18 +553,43 @@ ssl_callback_ocsp_stapling(SSL *ssl)
533553
Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: failed to get certificate map");
534554
return SSL_TLSEXT_ERR_NOACK;
535555
}
556+
557+
if (map->empty()) {
558+
Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: certificate map empty");
559+
return SSL_TLSEXT_ERR_NOACK;
560+
}
561+
536562
// Fetch the specific certificate used in this negotiation
537563
X509 *cert = SSL_get_certificate(ssl);
538564
if (!cert) {
539565
Error("ssl_callback_ocsp_stapling: failed to get certificate");
540566
return SSL_TLSEXT_ERR_NOACK;
541567
}
568+
569+
certinfo *cinf = nullptr;
570+
#ifndef OPENSSL_IS_BORINGSSL
542571
certinfo_map::iterator iter = map->find(cert);
543-
if (iter == map->end()) {
544-
Error("ssl_callback_ocsp_stapling: failed to get certificate information");
572+
if (iter != map->end()) {
573+
cinf = iter->second;
574+
}
575+
#else
576+
for (certinfo_map::iterator iter = map->begin(); iter != map->end(); ++iter) {
577+
X509 *key = iter->first;
578+
if (key == nullptr) {
579+
continue;
580+
}
581+
582+
if (X509_cmp(key, cert) == 0) {
583+
cinf = iter->second;
584+
break;
585+
}
586+
}
587+
#endif
588+
589+
if (cinf == nullptr) {
590+
Error("ssl_callback_ocsp_stapling: failed to get certificate information for ssl=%p", ssl);
545591
return SSL_TLSEXT_ERR_NOACK;
546592
}
547-
certinfo *cinf = iter->second;
548593

549594
ink_mutex_acquire(&cinf->stapling_mutex);
550595
time_t current_time = time(nullptr);
@@ -554,10 +599,9 @@ ssl_callback_ocsp_stapling(SSL *ssl)
554599
return SSL_TLSEXT_ERR_NOACK;
555600
} else {
556601
unsigned char *p = static_cast<unsigned char *>(OPENSSL_malloc(cinf->resp_derlen));
557-
unsigned int len = cinf->resp_derlen;
558602
memcpy(p, cinf->resp_der, cinf->resp_derlen);
559603
ink_mutex_release(&cinf->stapling_mutex);
560-
SSL_set_tlsext_status_ocsp_resp(ssl, p, len);
604+
SSL_set_tlsext_status_ocsp_resp(ssl, p, cinf->resp_derlen);
561605
Debug("ssl_ocsp", "ssl_callback_ocsp_stapling: successfully got certificate status for %s", cinf->certname);
562606
return SSL_TLSEXT_ERR_OK;
563607
}

iocore/net/P_OCSPStapling.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,21 @@
2525

2626
#if TS_USE_TLS_OCSP
2727
#include <openssl/ssl.h>
28+
29+
#if TS_HAS_BORINGOCSP
30+
#include <boringocsp/ocsp.h>
31+
#else
2832
#include <openssl/ocsp.h>
33+
#endif
2934

3035
void ssl_stapling_ex_init();
3136
bool ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const char *rsp_file);
3237
void ocsp_update();
38+
39+
#ifndef OPENSSL_IS_BORINGSSL
3340
int ssl_callback_ocsp_stapling(SSL *);
41+
#else
42+
int ssl_callback_ocsp_stapling(SSL *, void *);
43+
#endif
44+
3445
#endif

src/traffic_quic/Makefile.inc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ traffic_quic_traffic_quic_CPPFLAGS = \
3737

3838
traffic_quic_traffic_quic_LDFLAGS = \
3939
$(AM_LDFLAGS) \
40-
@OPENSSL_LDFLAGS@
40+
@OPENSSL_LDFLAGS@ \
41+
@BORINGOCSP_LDFLAGS@
4142

4243
traffic_quic_traffic_quic_SOURCES = \
4344
traffic_quic/quic_client.cc \
@@ -60,5 +61,6 @@ traffic_quic_traffic_quic_LDADD = \
6061
@HWLOC_LIBS@ \
6162
@YAMLCPP_LIBS@ \
6263
@OPENSSL_LIBS@ \
64+
@BORINGOCSP_LIBS@ \
6365
@LIBPCRE@
6466

src/traffic_server/Makefile.inc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ traffic_server_traffic_server_CPPFLAGS = \
3535
-I$(abs_top_srcdir)/mgmt \
3636
-I$(abs_top_srcdir)/mgmt/utils \
3737
$(TS_INCLUDES) \
38-
@OPENSSL_INCLUDES@
38+
@OPENSSL_INCLUDES@ \
39+
@BORINGOCSP_INCLUDES@
3940

4041
traffic_server_traffic_server_LDFLAGS = \
4142
$(AM_LDFLAGS) \
42-
@YAMLCPP_LDFLAGS@
43+
@YAMLCPP_LDFLAGS@ \
44+
@BORINGOCSP_LDFLAGS@
4345

4446
traffic_server_traffic_server_SOURCES = \
4547
traffic_server/Crash.cc \
@@ -87,6 +89,7 @@ traffic_server_traffic_server_LDADD = \
8789
@LIBPROFILER@ \
8890
@OPENSSL_LIBS@ \
8991
@YAMLCPP_LIBS@ \
92+
@BORINGOCSP_LIBS@ \
9093
-lm
9194

9295
if IS_DARWIN

0 commit comments

Comments
 (0)