LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - ocsp-api.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 159 179 88.8 %
Date: 2020-10-30 04:50:48 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2012-2017 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2017 Red Hat, Inc.
       4             :  *
       5             :  * Author: Simon Josefsson, Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : /*
      25             :  *  Status Request (OCSP) API.
      26             :  */
      27             : 
      28             : #include "gnutls_int.h"
      29             : #include "errors.h"
      30             : #include <auth.h>
      31             : #include <auth/cert.h>
      32             : #include <handshake.h>
      33             : #include <minmax.h>
      34             : 
      35             : #ifdef ENABLE_OCSP
      36             : 
      37             : #include <gnutls/ocsp.h>
      38             : #include "x509/ocsp.h"
      39             : 
      40             : /**
      41             :  * gnutls_ocsp_status_request_get:
      42             :  * @session: is a #gnutls_session_t type.
      43             :  * @response: a #gnutls_datum_t with DER encoded OCSP response
      44             :  *
      45             :  * This function returns the OCSP status response received
      46             :  * from the TLS server. The @response should be treated as
      47             :  * constant. If no OCSP response is available then
      48             :  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
      49             :  *
      50             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
      51             :  *   otherwise a negative error code is returned.
      52             :  *
      53             :  * Since: 3.1.3
      54             :  **/
      55             : int
      56        6354 : gnutls_ocsp_status_request_get(gnutls_session_t session,
      57             :                                gnutls_datum_t * response)
      58             : {
      59        6354 :         return gnutls_ocsp_status_request_get2(session, 0, response);
      60             : }
      61             : 
      62             : /**
      63             :  * gnutls_ocsp_status_request_get2:
      64             :  * @session: is a #gnutls_session_t type.
      65             :  * @idx: the index of peer's certificate
      66             :  * @response: a #gnutls_datum_t with DER encoded OCSP response
      67             :  *
      68             :  * This function returns the OCSP status response received
      69             :  * from the TLS server for the certificate index provided.
      70             :  * The index corresponds to certificates as returned by
      71             :  * gnutls_certificate_get_peers. When index is zero this
      72             :  * function operates identically to gnutls_ocsp_status_request_get().
      73             :  *
      74             :  * The returned @response should be treated as
      75             :  * constant. If no OCSP response is available for the
      76             :  * given index then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
      77             :  * is returned.
      78             :  *
      79             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
      80             :  *   otherwise a negative error code is returned.
      81             :  *
      82             :  * Since: 3.6.3
      83             :  **/
      84             : int
      85        7002 : gnutls_ocsp_status_request_get2(gnutls_session_t session,
      86             :                                 unsigned idx,
      87             :                                 gnutls_datum_t * response)
      88             : {
      89        7002 :         const version_entry_st *ver = get_version(session);
      90        7002 :         cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
      91             : 
      92        7002 :         if (!ver->tls13_sem && session->security_parameters.entity == GNUTLS_SERVER)
      93        5985 :                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
      94             : 
      95        4002 :         if (info == NULL || info->raw_ocsp_list == NULL ||
      96         517 :             info->nocsp <= idx || info->raw_ocsp_list[idx].size == 0)
      97        3919 :                 return
      98        3919 :                     gnutls_assert_val
      99             :                     (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     100             : 
     101          83 :         response->data = info->raw_ocsp_list[idx].data;
     102          83 :         response->size = info->raw_ocsp_list[idx].size;
     103             : 
     104          83 :         return 0;
     105             : }
     106             : 
     107             : /**
     108             :  * gnutls_certificate_set_ocsp_status_request_function:
     109             :  * @sc: is a #gnutls_certificate_credentials_t type.
     110             :  * @ocsp_func: function pointer to OCSP status request callback.
     111             :  * @ptr: opaque pointer passed to callback function
     112             :  *
     113             :  * This function is to be used by server to register a callback to
     114             :  * handle OCSP status requests from the client.  The callback will be
     115             :  * invoked if the client supplied a status-request OCSP extension.
     116             :  * The callback function prototype is:
     117             :  *
     118             :  * typedef int (*gnutls_status_request_ocsp_func)
     119             :  *    (gnutls_session_t session, void *ptr, gnutls_datum_t *ocsp_response);
     120             :  *
     121             :  * The callback will be invoked if the client requests an OCSP certificate
     122             :  * status.  The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if
     123             :  * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS,
     124             :  * it is expected to have the @ocsp_response field set with a valid (DER-encoded)
     125             :  * OCSP response. The response must be a value allocated using gnutls_malloc(),
     126             :  * and will be deinitialized by the caller.
     127             :  *
     128             :  * It is possible to set a specific callback for each provided certificate
     129             :  * using gnutls_certificate_set_ocsp_status_request_function2().
     130             :  *
     131             :  * Since: 3.1.3
     132             :  **/
     133             : void
     134          10 : gnutls_certificate_set_ocsp_status_request_function
     135             : (gnutls_certificate_credentials_t sc,
     136             : gnutls_status_request_ocsp_func ocsp_func, void *ptr)
     137             : {
     138             : 
     139          10 :         sc->glob_ocsp_func = ocsp_func;
     140          10 :         sc->glob_ocsp_func_ptr = ptr;
     141          10 : }
     142             : 
     143             : /**
     144             :  * gnutls_certificate_set_ocsp_status_request_function2:
     145             :  * @sc: is a #gnutls_certificate_credentials_t type.
     146             :  * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends
     147             :  * @ocsp_func: function pointer to OCSP status request callback.
     148             :  * @ptr: opaque pointer passed to callback function
     149             :  *
     150             :  * This function is to be used by server to register a callback to
     151             :  * provide OCSP status requests that correspond to the indexed certificate chain
     152             :  * from the client.  The callback will be invoked if the client supplied a
     153             :  * status-request OCSP extension.
     154             :  *
     155             :  * The callback function prototype is:
     156             :  *
     157             :  * typedef int (*gnutls_status_request_ocsp_func)
     158             :  *    (gnutls_session_t session, void *ptr, gnutls_datum_t *ocsp_response);
     159             :  *
     160             :  * The callback will be invoked if the client requests an OCSP certificate
     161             :  * status.  The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if
     162             :  * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS,
     163             :  * it is expected to have the @ocsp_response field set with a valid (DER-encoded)
     164             :  * OCSP response. The response must be a value allocated using gnutls_malloc(),
     165             :  * and will be deinitialized by the caller.
     166             :  *
     167             :  * Note: the ability to set multiple OCSP responses per credential
     168             :  * structure via the index @idx was added in version 3.5.6. To keep
     169             :  * backwards compatibility, it requires using gnutls_certificate_set_flags()
     170             :  * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate
     171             :  * functions return an index usable by this function.
     172             :  *
     173             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     174             :  *   otherwise a negative error code is returned.
     175             :  *
     176             :  * Since: 3.5.5
     177             :  **/
     178             : int
     179           4 : gnutls_certificate_set_ocsp_status_request_function2
     180             : (gnutls_certificate_credentials_t sc, unsigned idx, gnutls_status_request_ocsp_func ocsp_func, void *ptr)
     181             : {
     182           4 :         if (idx >= sc->ncerts)
     183           1 :                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     184             : 
     185           3 :         sc->certs[idx].ocsp_func = ocsp_func;
     186           3 :         sc->certs[idx].ocsp_func_ptr = ptr;
     187             : 
     188           3 :         return 0;
     189             : }
     190             : 
     191             : static
     192          41 : unsigned resp_matches_pcert(gnutls_ocsp_resp_t resp, const gnutls_pcert_st *cert)
     193             : {
     194          41 :         gnutls_x509_crt_t crt;
     195          41 :         int ret;
     196          41 :         unsigned retval;
     197             : 
     198          41 :         ret = gnutls_x509_crt_init(&crt);
     199          41 :         if (ret < 0)
     200             :                 return 0;
     201             : 
     202          41 :         ret = gnutls_x509_crt_import(crt, &cert->cert, GNUTLS_X509_FMT_DER);
     203          41 :         if (ret < 0) {
     204           0 :                 gnutls_assert();
     205           0 :                 retval = 0;
     206           0 :                 goto cleanup;
     207             :         }
     208             : 
     209          41 :         ret = gnutls_ocsp_resp_check_crt(resp, 0, crt);
     210          41 :         if (ret == 0)
     211             :                 retval = 1;
     212             :         else
     213          15 :                 retval = 0;
     214             : 
     215          41 :  cleanup:
     216          41 :         gnutls_x509_crt_deinit(crt);
     217          41 :         return retval;
     218             : }
     219             : 
     220             : /**
     221             :  * gnutls_certificate_set_ocsp_status_request_file:
     222             :  * @sc: is a credentials structure.
     223             :  * @response_file: a filename of the OCSP response
     224             :  * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends
     225             :  *
     226             :  * This function loads the provided OCSP response. It will be
     227             :  * sent to the client if requests an OCSP certificate status for
     228             :  * the certificate chain specified by @idx.
     229             :  *
     230             :  * Note: the ability to set multiple OCSP responses per credential
     231             :  * structure via the index @idx was added in version 3.5.6. To keep
     232             :  * backwards compatibility, it requires using gnutls_certificate_set_flags()
     233             :  * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate
     234             :  * functions return an index usable by this function.
     235             :  *
     236             :  * This function can be called multiple times since GnuTLS 3.6.3
     237             :  * when multiple responses which apply to the chain are available.
     238             :  * If the response provided does not match any certificates present
     239             :  * in the chain, the code %GNUTLS_E_OCSP_MISMATCH_WITH_CERTS is returned.
     240             :  * To revert to the previous behavior set the flag %GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK
     241             :  * in the certificate credentials structure. In that case, only the
     242             :  * end-certificate's OCSP response can be set.
     243             :  * If the response is already expired at the time of loading the code
     244             :  * %GNUTLS_E_EXPIRED is returned.
     245             :  *
     246             :  * To revert to the previous behavior of this function which does not return
     247             :  * any errors, set the flag %GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK
     248             :  *
     249             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     250             :  *   otherwise a negative error code is returned.
     251             :  *
     252             :  * Since: 3.1.3
     253             :  **/
     254             : int
     255          25 : gnutls_certificate_set_ocsp_status_request_file(gnutls_certificate_credentials_t sc,
     256             :                                                 const char *response_file,
     257             :                                                 unsigned idx)
     258             : {
     259          25 :         int ret;
     260             : 
     261          25 :         ret = gnutls_certificate_set_ocsp_status_request_file2(sc, response_file,
     262             :                                                                idx, GNUTLS_X509_FMT_DER);
     263          25 :         if (ret >= 0)
     264             :                 return 0;
     265             :         else
     266           6 :                 return ret;
     267             : }
     268             : 
     269          30 : static int append_response(gnutls_certificate_credentials_t sc, unsigned idx,
     270             :                            gnutls_ocsp_resp_t resp, const gnutls_datum_t *der)
     271             : {
     272          30 :         int ret;
     273          30 :         unsigned i, found = 0;
     274          30 :         unsigned try_already_set = 0;
     275          40 :         time_t t;
     276             : 
     277          40 :  retry:
     278             : 
     279             :         /* iterate through all certificates in chain, and add the response
     280             :          * to the certificate that it matches with.
     281             :          */
     282          75 :         for (i=0;i<MIN(sc->certs[idx].cert_list_length, MAX_OCSP_RESPONSES);i++) {
     283          61 :                 if (!try_already_set && sc->certs[idx].ocsp_data[i].response.data)
     284          20 :                         continue;
     285             : 
     286          41 :                 if (!resp_matches_pcert(resp, &sc->certs[idx].cert_list[i]))
     287          15 :                         continue;
     288             : 
     289          26 :                 t = _gnutls_ocsp_get_validity(resp);
     290             :                 /* if already invalid */
     291          26 :                 if (t == (time_t)-1) {
     292           1 :                         _gnutls_debug_log("the OCSP response associated with chain %d on pos %d, is invalid/expired\n", idx, i);
     293           1 :                         return GNUTLS_E_EXPIRED;
     294          25 :                 } else if (t == (time_t)-2) {
     295           8 :                         _gnutls_debug_log("the OCSP response associated with chain %d on pos %d, is too old (ignoring)\n", idx, i);
     296           8 :                         return 0;
     297             :                 }
     298             : 
     299          17 :                 if (t >= 0)
     300          17 :                         sc->certs[idx].ocsp_data[i].exptime = t;
     301             :                 else
     302           0 :                         sc->certs[idx].ocsp_data[i].exptime = 0;
     303             : 
     304          17 :                 _gnutls_debug_log("associating OCSP response with chain %d on pos %d\n", idx, i);
     305             : 
     306          17 :                 gnutls_free(sc->certs[idx].ocsp_data[i].response.data);
     307             : 
     308          34 :                 ret = _gnutls_set_datum(&sc->certs[idx].ocsp_data[i].response,
     309          17 :                                         der->data,
     310          17 :                                         der->size);
     311          17 :                 if (ret < 0) {
     312           0 :                         gnutls_assert();
     313           0 :                         sc->certs[idx].ocsp_data[i].response.data = NULL;
     314           0 :                         sc->certs[idx].ocsp_data[i].response.size = 0;
     315           0 :                         return ret;
     316             :                 }
     317             : 
     318          17 :                 if (sc->certs[idx].ocsp_data_length <= i)
     319          11 :                         sc->certs[idx].ocsp_data_length = i+1;
     320             : 
     321             :                 found = 1;
     322             :                 break;
     323             :         }
     324             : 
     325          14 :         if (!found) {
     326             :                 /* slow path; if we found no matching certificate for the OCSP
     327             :                  * response, try all the existing, even if a response is already
     328             :                  * given. */
     329          14 :                 if (!try_already_set) {
     330          10 :                         try_already_set = 1;
     331          10 :                         goto retry;
     332             :                 }
     333             :                 ret = GNUTLS_E_OCSP_MISMATCH_WITH_CERTS;
     334             :         } else {
     335             :                 ret = 0;
     336             :         }
     337             : 
     338             :         return ret;
     339             : }
     340             : 
     341             : /**
     342             :  * gnutls_certificate_set_ocsp_status_request_file2:
     343             :  * @sc: is a credentials structure.
     344             :  * @response_file: a filename of the OCSP response
     345             :  * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends
     346             :  * @fmt: is PEM or DER
     347             :  *
     348             :  * This function loads the OCSP responses to be sent to the
     349             :  * peer for the certificate chain specified by @idx. When @fmt is
     350             :  * set to PEM, multiple responses can be loaded.
     351             :  *
     352             :  * This function must be called after setting any certificates, and
     353             :  * cannot be used for certificates that are provided via a callback --
     354             :  * that is when gnutls_certificate_set_retrieve_function() is used. In
     355             :  * that case consider using gnutls_certificate_set_retrieve_function3().
     356             :  *
     357             :  * This function can be called multiple times when multiple responses
     358             :  * applicable to the certificate chain are available.
     359             :  * If the response provided does not match any certificates present
     360             :  * in the chain, the code %GNUTLS_E_OCSP_MISMATCH_WITH_CERTS is returned.
     361             :  * If the response is already expired at the time of loading the code
     362             :  * %GNUTLS_E_EXPIRED is returned.
     363             :  *
     364             :  * Returns: On success, the number of loaded responses is returned,
     365             :  *   otherwise a negative error code.
     366             :  *
     367             :  * Since: 3.1.3
     368             :  **/
     369             : int
     370          29 : gnutls_certificate_set_ocsp_status_request_file2(gnutls_certificate_credentials_t sc,
     371             :                                                 const char *response_file,
     372             :                                                 unsigned idx,
     373             :                                                 gnutls_x509_crt_fmt_t fmt)
     374             : {
     375          29 :         gnutls_datum_t raw = {NULL, 0};
     376          29 :         int ret;
     377             : 
     378          29 :         if (idx >= sc->ncerts)
     379           3 :                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     380             : 
     381          26 :         ret = gnutls_load_file(response_file, &raw);
     382          26 :         if (ret < 0)
     383           0 :                 return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
     384             : 
     385          26 :         ret = gnutls_certificate_set_ocsp_status_request_mem(sc, &raw, idx, fmt);
     386          26 :         gnutls_free(raw.data);
     387          26 :         return ret;
     388             : }
     389             : 
     390             : #define PEM_OCSP_RESPONSE "OCSP RESPONSE"
     391             : #define FULL_PEM_OCSP_RESPONSE "-----BEGIN OCSP RESPONSE"
     392             : 
     393             : /**
     394             :  * gnutls_certificate_set_ocsp_status_request_mem:
     395             :  * @sc: is a credentials structure.
     396             :  * @resp_data: a memory buffer holding an OCSP response
     397             :  * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends
     398             :  * @fmt: is PEM or DER
     399             :  *
     400             :  * This function sets the OCSP responses to be sent to the
     401             :  * peer for the certificate chain specified by @idx. When @fmt is set
     402             :  * to PEM, multiple responses can be loaded.
     403             :  *
     404             :  * Note: the ability to set multiple OCSP responses per credential
     405             :  * structure via the index @idx was added in version 3.5.6. To keep
     406             :  * backwards compatibility, it requires using gnutls_certificate_set_flags()
     407             :  * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate
     408             :  * functions return an index usable by this function.
     409             :  *
     410             :  * This function must be called after setting any certificates, and
     411             :  * cannot be used for certificates that are provided via a callback --
     412             :  * that is when gnutls_certificate_set_retrieve_function() is used.
     413             :  *
     414             :  * This function can be called multiple times when multiple responses which
     415             :  * apply to the certificate chain are available.
     416             :  * If the response provided does not match any certificates present
     417             :  * in the chain, the code %GNUTLS_E_OCSP_MISMATCH_WITH_CERTS is returned.
     418             :  * If the response is already expired at the time of loading the code
     419             :  * %GNUTLS_E_EXPIRED is returned.
     420             :  *
     421             :  * Returns: On success, the number of loaded responses is returned,
     422             :  *   otherwise a negative error code.
     423             :  *
     424             :  * Since: 3.6.3
     425             :  **/
     426             : int
     427          57 : gnutls_certificate_set_ocsp_status_request_mem(gnutls_certificate_credentials_t sc,
     428             :                                                const gnutls_datum_t *resp_data,
     429             :                                                unsigned idx,
     430             :                                                gnutls_x509_crt_fmt_t fmt)
     431             : 
     432             : {
     433          57 :         gnutls_datum_t der = {NULL, 0};
     434          57 :         gnutls_ocsp_resp_t resp = NULL;
     435          57 :         int ret;
     436          57 :         unsigned int nresp = 0;
     437             : 
     438          57 :         ret = gnutls_ocsp_resp_init(&resp);
     439          57 :         if (ret < 0) {
     440           0 :                 return gnutls_assert_val(ret);
     441             :         }
     442             : 
     443          57 :         if (fmt == GNUTLS_X509_FMT_PEM) {
     444             :                 /* load multiple responses */
     445          12 :                 gnutls_datum_t p = {resp_data->data, resp_data->size};
     446             : 
     447          12 :                 p.data = memmem(p.data, p.size, FULL_PEM_OCSP_RESPONSE,
     448             :                                 sizeof(FULL_PEM_OCSP_RESPONSE)-1);
     449          12 :                 if (p.data == NULL) {
     450           0 :                         ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     451           2 :                         goto cleanup;
     452             :                 }
     453             : 
     454          12 :                 p.size -= p.data - resp_data->data;
     455          12 :                 if (p.size <= 0) {
     456           0 :                         ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     457           0 :                         goto cleanup;
     458             :                 }
     459             : 
     460          18 :                 do {
     461          18 :                         ret = gnutls_pem_base64_decode2(PEM_OCSP_RESPONSE, &p, &der);
     462          18 :                         if (ret < 0) {
     463           0 :                                 gnutls_assert();
     464           0 :                                 goto cleanup;
     465             :                         }
     466             : 
     467          18 :                         ret = gnutls_certificate_set_ocsp_status_request_mem(sc, &der, idx,
     468             :                                                                              GNUTLS_X509_FMT_DER);
     469          18 :                         if (ret < 0) {
     470           2 :                                 gnutls_assert();
     471           2 :                                 goto cleanup;
     472             :                         }
     473          16 :                         nresp++;
     474             : 
     475          16 :                         gnutls_free(der.data);
     476             : 
     477          16 :                         p.data++;
     478          16 :                         p.size--;
     479             : 
     480          16 :                         p.data = memmem(p.data, p.size, FULL_PEM_OCSP_RESPONSE,
     481             :                                         sizeof(FULL_PEM_OCSP_RESPONSE)-1);
     482          16 :                         if (p.data == NULL)
     483             :                                 break;
     484           6 :                         p.size = resp_data->size - (p.data - resp_data->data);
     485           6 :                 } while(p.size > 0);
     486             : 
     487          10 :                 ret = nresp;
     488             :         } else {
     489             :                 /* DER: load a single response */
     490          45 :                 if (sc->flags & GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK) {
     491          15 :                         ret = gnutls_ocsp_resp_import2(resp, resp_data, GNUTLS_X509_FMT_DER);
     492          15 :                         if (ret >= 0) {
     493          14 :                                 sc->certs[idx].ocsp_data[0].exptime = _gnutls_ocsp_get_validity(resp);
     494          14 :                                 if (sc->certs[idx].ocsp_data[0].exptime <= 0)
     495          11 :                                         sc->certs[idx].ocsp_data[0].exptime = 0;
     496             :                         }
     497             : 
     498             :                         /* quick load of first response */
     499          15 :                         gnutls_free(sc->certs[idx].ocsp_data[0].response.data);
     500             : 
     501          30 :                         ret = _gnutls_set_datum(&sc->certs[idx].ocsp_data[0].response,
     502          15 :                                                 resp_data->data,
     503          15 :                                                 resp_data->size);
     504          15 :                         if (ret < 0) {
     505           0 :                                 gnutls_assert();
     506           0 :                                 goto cleanup;
     507             :                         }
     508             : 
     509          15 :                         sc->certs[idx].ocsp_data_length = 1;
     510          15 :                         goto cleanup;
     511             :                 }
     512             : 
     513          30 :                 ret = gnutls_ocsp_resp_import2(resp, resp_data, GNUTLS_X509_FMT_DER);
     514          30 :                 if (ret < 0) {
     515           0 :                         gnutls_assert();
     516           0 :                         goto cleanup;
     517             :                 }
     518             : 
     519          30 :                 ret = append_response(sc, idx, resp, resp_data);
     520          30 :                 if (ret < 0) {
     521           5 :                         gnutls_assert();
     522           5 :                         goto cleanup;
     523             :                 }
     524             : 
     525             :                 ret = 1;
     526             :         }
     527          57 :   cleanup:
     528          57 :         gnutls_free(der.data);
     529          57 :         if (resp)
     530          57 :                 gnutls_ocsp_resp_deinit(resp);
     531             : 
     532             :         return ret;
     533             : }
     534             : 
     535             : /**
     536             :  * gnutls_certificate_get_ocsp_expiration:
     537             :  * @sc: is a credentials structure.
     538             :  * @idx: is a certificate chain index as returned by gnutls_certificate_set_key() and friends
     539             :  * @oidx: is an OCSP response index
     540             :  * @flags: should be zero
     541             :  *
     542             :  * This function returns the validity of the loaded OCSP responses,
     543             :  * to provide information on when to reload/refresh them.
     544             :  *
     545             :  * Note that the credentials structure should be read-only when in
     546             :  * use, thus when reloading, either the credentials structure must not
     547             :  * be in use by any sessions, or a new credentials structure should be
     548             :  * allocated for new sessions.
     549             :  *
     550             :  * When @oidx is (-1) then the minimum refresh time for all responses
     551             :  * is returned. Otherwise the index specifies the response corresponding
     552             :  * to the @odix certificate in the certificate chain.
     553             :  *
     554             :  * Returns: On success, the expiration time of the OCSP response. Otherwise
     555             :  *   (time_t)(-1) on error, or (time_t)-2 on out of bounds.
     556             :  *
     557             :  * Since: 3.6.3
     558             :  **/
     559             : time_t
     560           9 : gnutls_certificate_get_ocsp_expiration(gnutls_certificate_credentials_t sc,
     561             :                                        unsigned idx,
     562             :                                        int oidx,
     563             :                                        unsigned flags)
     564             : {
     565           9 :         unsigned j;
     566             : 
     567           9 :         if (idx >= sc->ncerts)
     568             :                 return (time_t)-2;
     569             : 
     570           9 :         if (oidx == -1) {
     571             :                 time_t min = 0;
     572             : 
     573           9 :                 for (j=0;j<MIN(sc->certs[idx].cert_list_length, MAX_OCSP_RESPONSES);j++) {
     574           6 :                         if (min <= 0)
     575           3 :                                 min = sc->certs[idx].ocsp_data[j].exptime;
     576             :                         else
     577           3 :                                 if (sc->certs[idx].ocsp_data[j].exptime > 0 &&
     578             :                                     min >= sc->certs[idx].ocsp_data[j].exptime)
     579           2 :                                         min = sc->certs[idx].ocsp_data[j].exptime;
     580             :                 }
     581             :                 return min;
     582             :         }
     583             : 
     584           6 :         if (oidx >= MAX_OCSP_RESPONSES || (unsigned)oidx >= sc->certs[idx].cert_list_length)
     585             :                 return (time_t)-2;
     586             : 
     587           6 :         if (sc->certs[idx].ocsp_data[oidx].response.data == NULL)
     588             :                 return (time_t)-1;
     589             : 
     590           5 :         return sc->certs[idx].ocsp_data[oidx].exptime;
     591             : }
     592             : 
     593             : /**
     594             :  * gnutls_ocsp_status_request_is_checked:
     595             :  * @session: is a gnutls session
     596             :  * @flags: should be zero or %GNUTLS_OCSP_SR_IS_AVAIL
     597             :  *
     598             :  * When flags are zero this function returns non-zero if a valid OCSP status
     599             :  * response was included in the TLS handshake. That is, an OCSP status response
     600             :  * which is not too old, superseded or marks the certificate as revoked.
     601             :  * It returns zero otherwise.
     602             :  *
     603             :  * When the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the function
     604             :  * returns non-zero if an OCSP status response was included in the handshake
     605             :  * even if it was invalid. Otherwise, if no OCSP status response was included,
     606             :  * it returns zero. The %GNUTLS_OCSP_SR_IS_AVAIL flag was introduced in GnuTLS 3.4.0.
     607             :  *
     608             :  * This is a helper function when needing to decide whether to perform an
     609             :  * explicit OCSP validity check on the peer's certificate. Should be called after
     610             :  * any of gnutls_certificate_verify_peers*() are called.
     611             :  *
     612             :  * This function is always usable on client side, but on server side only
     613             :  * under TLS 1.3, which is the first version of TLS that allows cliend-side OCSP
     614             :  * responses.
     615             :  *
     616             :  * Returns: Non-zero if the response was valid, or a zero if it wasn't sent,
     617             :  * or sent and was invalid.
     618             :  *
     619             :  * Since: 3.1.4
     620             :  **/
     621             : unsigned
     622        6346 : gnutls_ocsp_status_request_is_checked(gnutls_session_t session,
     623             :                                       unsigned int flags)
     624             : {
     625        6346 :         int ret;
     626        6346 :         gnutls_datum_t data;
     627             : 
     628        6346 :         if (flags & GNUTLS_OCSP_SR_IS_AVAIL) {
     629        6324 :                 ret = gnutls_ocsp_status_request_get(session, &data);
     630        6324 :                 if (ret < 0)
     631       12331 :                         return gnutls_assert_val(0);
     632             : 
     633           7 :                 if (data.data == NULL)
     634           0 :                         return gnutls_assert_val(0);
     635             :                 return 1;
     636             :         }
     637          22 :         return session->internals.ocsp_check_ok;
     638             : }
     639             : 
     640             : #endif

Generated by: LCOV version 1.14