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
|