Coverage Report

Created: 2025-03-06 06:58

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