diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2020-01-09 13:38:09 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2020-01-09 13:38:09 +0000 |
commit | 16802c66b835c1b4050f2f999995ea1bd3e7a1af (patch) | |
tree | 2d44e2c1877236144e911436ecb63dc03f305b81 | |
parent | 68d111e358061623bcc225303fe991324b135062 (diff) | |
parent | bd383624af417cbb5cac831ee359b970383bbe42 (diff) | |
download | gnutls-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-- | NEWS | 4 | ||||
-rw-r--r-- | devel/libgnutls.abignore | 5 | ||||
-rw-r--r-- | lib/algorithms/protocols.c | 1 | ||||
-rw-r--r-- | lib/cert-session.c | 3 | ||||
-rw-r--r-- | lib/ext/status_request.c | 72 | ||||
-rw-r--r-- | lib/gnutls_int.h | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 8 | ||||
-rw-r--r-- | lib/ocsp-api.c | 7 | ||||
-rw-r--r-- | lib/state.c | 2 | ||||
-rw-r--r-- | lib/tls13/certificate.c | 2 | ||||
-rw-r--r-- | tests/mini-x509.c | 3 | ||||
-rw-r--r-- | tests/status-request.c | 6 | ||||
-rw-r--r-- | tests/x509-cert-callback-ocsp.c | 3 |
13 files changed, 79 insertions, 39 deletions
@@ -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)); |