Coverage Report

Created: 2023-03-26 07:33

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