summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2020-01-09 13:38:09 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2020-01-09 13:38:09 +0000
commit16802c66b835c1b4050f2f999995ea1bd3e7a1af (patch)
tree2d44e2c1877236144e911436ecb63dc03f305b81
parent68d111e358061623bcc225303fe991324b135062 (diff)
parentbd383624af417cbb5cac831ee359b970383bbe42 (diff)
downloadgnutls-16802c66b835c1b4050f2f999995ea1bd3e7a1af.tar.gz
Merge branch 'tmp-ocsp-check' into 'master'903-add-crl-and-crq-fuzzers
Provide flag to identify sessions that an OCSP response was requested Closes #829 See merge request gnutls/gnutls!1131
-rw-r--r--NEWS4
-rw-r--r--devel/libgnutls.abignore5
-rw-r--r--lib/algorithms/protocols.c1
-rw-r--r--lib/cert-session.c3
-rw-r--r--lib/ext/status_request.c72
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/includes/gnutls/gnutls.h.in8
-rw-r--r--lib/ocsp-api.c7
-rw-r--r--lib/state.c2
-rw-r--r--lib/tls13/certificate.c2
-rw-r--r--tests/mini-x509.c3
-rw-r--r--tests/status-request.c6
-rw-r--r--tests/x509-cert-callback-ocsp.c3
13 files changed, 79 insertions, 39 deletions
diff --git a/NEWS b/NEWS
index 565b15455e..2b4fd94210 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ See the end for copying conditions.
* Version 3.6.12 (unreleased)
+** libgnutls: Introduced flag of gnutls_session_get_flags() to identify
+ sessions that client request OCSP status request (#829).
+
** libgnutls: Introduced the gnutls_ocsp_req_const_t which is compatible
with gnutls_ocsp_req_t but const.
@@ -45,6 +48,7 @@ See the end for copying conditions.
a certificate from a certificate request.
** API and ABI modifications:
+GNUTLS_SFLAGS_CLI_REQUESTED_OCSP: Added
gnutls_ocsp_req_const_t: Added
diff --git a/devel/libgnutls.abignore b/devel/libgnutls.abignore
index c381204fd9..2156ed39a4 100644
--- a/devel/libgnutls.abignore
+++ b/devel/libgnutls.abignore
@@ -49,3 +49,8 @@ changed_enumerators = GNUTLS_GROUP_MAX
[suppress_type]
name = gnutls_sec_param_t
changed_enumerators = GNUTLS_SEC_PARAM_MAX
+
+# return type changed from int to unsigned int; no ABI change
+[suppress_function]
+name = gnutls_ocsp_status_request_is_checked
+return_type_name = unsigned int
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
index 7242e1aa0c..a3d1edeb6c 100644
--- a/lib/algorithms/protocols.c
+++ b/lib/algorithms/protocols.c
@@ -111,6 +111,7 @@ version_entry_st sup_versions[] = {
.obsolete = 0,
.only_extension = 1,
.post_handshake_auth = 1,
+ .multi_ocsp = 1,
.key_shares = 1,
.false_start = 0, /* doesn't make sense */
.tls_sig_sem = SIG_SEM_TLS13
diff --git a/lib/cert-session.c b/lib/cert-session.c
index 4d0e8961d5..e56445d68b 100644
--- a/lib/cert-session.c
+++ b/lib/cert-session.c
@@ -383,9 +383,8 @@ _gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
*
* To proceed, first check whether we have requested the certificate status
*/
- if (!_gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
+ if (!(session->internals.hsk_flags & HSK_OCSP_REQUESTED))
return 0;
- }
ret = gnutls_x509_tlsfeatures_init(&tlsfeatures);
if (ret < 0) {
diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c
index 8053b3b4ba..c9eb7d29f0 100644
--- a/lib/ext/status_request.c
+++ b/lib/ext/status_request.c
@@ -80,12 +80,13 @@ client_send(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
+ session->internals.hsk_flags |= HSK_OCSP_REQUESTED;
+
return len;
}
static int
server_recv(gnutls_session_t session,
- status_request_ext_st * priv,
const uint8_t * data, size_t data_size)
{
unsigned rid_bytes = 0;
@@ -118,6 +119,9 @@ server_recv(gnutls_session_t session,
return
gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ _gnutls_handshake_log("EXT[%p]: OCSP status was requested\n", session);
+ session->internals.hsk_flags |= HSK_OCSP_REQUESTED;
+
return 0;
}
@@ -165,12 +169,20 @@ server_send(gnutls_session_t session,
gnutls_certificate_credentials_t cred;
gnutls_status_request_ocsp_func func;
void *func_ptr;
+ const version_entry_st *ver = get_version(session);
cred = (gnutls_certificate_credentials_t)
_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
if (cred == NULL) /* no certificate authentication */
- return gnutls_assert_val(0);
+ return 0;
+ /* no need to set sresp; responses are send during certificate sending and
+ * no response is required from server side. */
+ if (ver && ver->multi_ocsp)
+ return 0;
+
+ /* Under TLS1.2 we obtain the response at this point in order to respond
+ * appropriately (empty extension vs no response) */
if (session->internals.selected_ocsp_length > 0) {
if (session->internals.selected_ocsp[0].response.data) {
if (session->internals.selected_ocsp[0].exptime != 0 &&
@@ -191,18 +203,18 @@ server_send(gnutls_session_t session,
} else if (session->internals.selected_ocsp_func) {
func = session->internals.selected_ocsp_func;
func_ptr = session->internals.selected_ocsp_func_ptr;
- } else {
- return 0;
- }
- if (func == NULL)
- return 0;
+ if (func == NULL)
+ return 0;
- ret = func(session, func_ptr, &priv->sresp);
- if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS)
+ ret = func(session, func_ptr, &priv->sresp);
+ if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS)
+ return 0;
+ else if (ret < 0)
+ return gnutls_assert_val(ret);
+ } else {
return 0;
- else if (ret < 0)
- return gnutls_assert_val(ret);
+ }
return GNUTLS_E_INT_RET_0;
}
@@ -220,11 +232,10 @@ _gnutls_status_request_send_params(gnutls_session_t session,
if (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)
return 0;
- ret = _gnutls_hello_ext_get_priv(session,
- GNUTLS_EXTENSION_STATUS_REQUEST,
- &epriv);
-
if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ ret = _gnutls_hello_ext_get_priv(session,
+ GNUTLS_EXTENSION_STATUS_REQUEST,
+ &epriv);
if (ret < 0 || epriv == NULL) /* it is ok not to have it */
return 0;
priv = epriv;
@@ -236,8 +247,8 @@ _gnutls_status_request_send_params(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
_gnutls_hello_ext_set_priv(session,
- GNUTLS_EXTENSION_STATUS_REQUEST,
- epriv);
+ GNUTLS_EXTENSION_STATUS_REQUEST,
+ epriv);
return server_send(session, extdata, priv);
}
@@ -251,18 +262,18 @@ _gnutls_status_request_recv_params(gnutls_session_t session,
status_request_ext_st *priv;
int ret;
- ret = _gnutls_hello_ext_get_priv(session,
- GNUTLS_EXTENSION_STATUS_REQUEST,
- &epriv);
- if (ret < 0 || epriv == NULL) /* it is ok not to have it */
- return 0;
-
- priv = epriv;
+ if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ ret = _gnutls_hello_ext_get_priv(session,
+ GNUTLS_EXTENSION_STATUS_REQUEST,
+ &epriv);
+ if (ret < 0 || epriv == NULL) /* it is ok not to have it */
+ return 0;
+ priv = epriv;
- if (session->security_parameters.entity == GNUTLS_CLIENT)
return client_recv(session, priv, data, size);
- else
- return server_recv(session, priv, data, size);
+ } else {
+ return server_recv(session, data, size);
+ }
}
/**
@@ -347,11 +358,14 @@ _gnutls_send_server_certificate_status(gnutls_session_t session, int again)
gnutls_ext_priv_data_t epriv;
status_request_ext_st *priv;
+ if (!(session->internals.hsk_flags & HSK_OCSP_REQUESTED))
+ return 0;
+
if (again == 0) {
ret =
_gnutls_hello_ext_get_priv(session,
- GNUTLS_EXTENSION_STATUS_REQUEST,
- &epriv);
+ GNUTLS_EXTENSION_STATUS_REQUEST,
+ &epriv);
if (ret < 0)
return 0;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 6a5b61cc69..f7cf830ca1 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -719,6 +719,7 @@ typedef struct {
bool only_extension; /* negotiated only with an extension */
bool post_handshake_auth; /* Supports the TLS 1.3 post handshake auth */
bool key_shares; /* TLS 1.3 key share key exchange */
+ bool multi_ocsp; /* TLS 1.3 multiple OCSP responses */
/*
* TLS versions modify the semantics of signature algorithms. This number
* is there to distinguish signature algorithms semantics between versions
@@ -1381,6 +1382,7 @@ typedef struct {
#define HSK_RECORD_SIZE_LIMIT_NEGOTIATED (1<<24)
#define HSK_RECORD_SIZE_LIMIT_SENT (1<<25) /* record_size_limit extension was sent */
#define HSK_RECORD_SIZE_LIMIT_RECEIVED (1<<26) /* server: record_size_limit extension was seen but not accepted yet */
+#define HSK_OCSP_REQUESTED (1<<27) /* server: client requested OCSP stapling */
/* The hsk_flags are for use within the ongoing handshake;
* they are reset to zero prior to handshake start by gnutls_handshake. */
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index fb617f9963..1d0f924c26 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1569,6 +1569,7 @@ unsigned gnutls_session_etm_status(gnutls_session_t session);
* @GNUTLS_SFLAGS_POST_HANDSHAKE_AUTH: Indicates client capability for post-handshake auth; set only on server side.
* @GNUTLS_SFLAGS_EARLY_START: The TLS1.3 server session returned early.
* @GNUTLS_SFLAGS_EARLY_DATA: The TLS1.3 early data has been received by the server.
+ * @GNUTLS_SFLAGS_CLI_REQUESTED_OCSP: Set when the client has requested OCSP staple during handshake.
*
* Enumeration of different session parameters.
*/
@@ -1583,7 +1584,8 @@ typedef enum {
GNUTLS_SFLAGS_SESSION_TICKET = 1<<7,
GNUTLS_SFLAGS_POST_HANDSHAKE_AUTH = 1<<8,
GNUTLS_SFLAGS_EARLY_START = 1<<9,
- GNUTLS_SFLAGS_EARLY_DATA = 1<<10
+ GNUTLS_SFLAGS_EARLY_DATA = 1<<10,
+ GNUTLS_SFLAGS_CLI_REQUESTED_OCSP = 1<<11
} gnutls_session_flags_t;
unsigned gnutls_session_get_flags(gnutls_session_t session);
@@ -2179,8 +2181,8 @@ int gnutls_ocsp_status_request_get(gnutls_session_t session,
gnutls_datum_t * response);
#define GNUTLS_OCSP_SR_IS_AVAIL 1
-int gnutls_ocsp_status_request_is_checked(gnutls_session_t session,
- unsigned int flags);
+unsigned gnutls_ocsp_status_request_is_checked(gnutls_session_t session,
+ unsigned int flags);
int
gnutls_ocsp_status_request_get2(gnutls_session_t session,
diff --git a/lib/ocsp-api.c b/lib/ocsp-api.c
index 685378a696..28f7e05a26 100644
--- a/lib/ocsp-api.c
+++ b/lib/ocsp-api.c
@@ -597,7 +597,8 @@ gnutls_certificate_get_ocsp_expiration(gnutls_certificate_credentials_t sc,
*
* When flags are zero this function returns non-zero if a valid OCSP status
* response was included in the TLS handshake. That is, an OCSP status response
- * which is not too old or superseded. It returns zero otherwise.
+ * which is not too old, superseded or marks the certificate as revoked.
+ * It returns zero otherwise.
*
* When the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the function
* returns non-zero if an OCSP status response was included in the handshake
@@ -612,12 +613,12 @@ gnutls_certificate_get_ocsp_expiration(gnutls_certificate_credentials_t sc,
* under TLS 1.3, which is the first version of TLS that allows cliend-side OCSP
* responses.
*
- * Returns: non zero if the response was valid, or a zero if it wasn't sent,
+ * Returns: Non-zero if the response was valid, or a zero if it wasn't sent,
* or sent and was invalid.
*
* Since: 3.1.4
**/
-int
+unsigned
gnutls_ocsp_status_request_is_checked(gnutls_session_t session,
unsigned int flags)
{
diff --git a/lib/state.c b/lib/state.c
index ae77b9afef..5e3a7f95aa 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -1574,6 +1574,8 @@ unsigned gnutls_session_get_flags(gnutls_session_t session)
flags |= GNUTLS_SFLAGS_POST_HANDSHAKE_AUTH;
if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED)
flags |= GNUTLS_SFLAGS_EARLY_DATA;
+ if (session->internals.hsk_flags & HSK_OCSP_REQUESTED)
+ flags |= GNUTLS_SFLAGS_CLI_REQUESTED_OCSP;
return flags;
}
diff --git a/lib/tls13/certificate.c b/lib/tls13/certificate.c
index 8a1a118727..82a45af336 100644
--- a/lib/tls13/certificate.c
+++ b/lib/tls13/certificate.c
@@ -273,7 +273,7 @@ int _gnutls13_send_certificate(gnutls_session_t session, unsigned again)
#ifdef ENABLE_OCSP
if ((session->internals.selected_ocsp_length > 0 ||
session->internals.selected_ocsp_func) &&
- _gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
+ (session->internals.hsk_flags & HSK_OCSP_REQUESTED)) {
/* append status response if available */
ret = _gnutls_extv_append_init(&buf);
if (ret < 0) {
diff --git a/tests/mini-x509.c b/tests/mini-x509.c
index c26b13f716..a4fb56e991 100644
--- a/tests/mini-x509.c
+++ b/tests/mini-x509.c
@@ -113,6 +113,9 @@ void start(const char *prio, unsigned expect_max)
HANDSHAKE(client, server);
+ assert((gnutls_session_get_flags(server) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) != 0);
+ assert((gnutls_session_get_flags(client) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) != 0);
+
/* check gnutls_certificate_get_ours() - client side */
{
const gnutls_datum_t *mcert;
diff --git a/tests/status-request.c b/tests/status-request.c
index 0e62969ba9..07c7918524 100644
--- a/tests/status-request.c
+++ b/tests/status-request.c
@@ -107,7 +107,7 @@ static void client(int fd, const char *prio)
/* Initialize TLS session
*/
- gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_NO_EXTENSIONS);
+ assert(gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_NO_EXTENSIONS)>=0);
assert(gnutls_priority_set_direct(session, prio, NULL)>=0);
@@ -136,6 +136,8 @@ static void client(int fd, const char *prio)
success("client: Handshake was completed\n");
}
+ assert((gnutls_session_get_flags(session) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) == 0);
+
if (debug)
success("client: TLS version is: %s\n",
gnutls_protocol_get_name
@@ -215,6 +217,8 @@ static void server(int fd, const char *prio)
goto end;
}
+ assert((gnutls_session_get_flags(session) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) == 0);
+
if (debug) {
success("server: Handshake was completed\n");
}
diff --git a/tests/x509-cert-callback-ocsp.c b/tests/x509-cert-callback-ocsp.c
index 036c047af6..b0a6c87620 100644
--- a/tests/x509-cert-callback-ocsp.c
+++ b/tests/x509-cert-callback-ocsp.c
@@ -187,6 +187,9 @@ static void start(const char *prio)
HANDSHAKE(client, server);
+ assert((gnutls_session_get_flags(server) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) != 0);
+ assert((gnutls_session_get_flags(client) & GNUTLS_SFLAGS_CLI_REQUESTED_OCSP) != 0);
+
ret = gnutls_ocsp_status_request_get(client, &response);
if (ret != 0)
fail("no response was found: %s\n", gnutls_strerror(ret));