Line data Source code
1 : /*
2 : * Copyright (C) 2001-2015 Free Software Foundation, Inc.
3 : * Copyright (C) 2015 Nikos Mavrogiannopoulos
4 : *
5 : * Author: 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 : /* This file contains certificate authentication functions to be exported in the
25 : * API which did not fit elsewhere.
26 : */
27 :
28 : #include "gnutls_int.h"
29 : #include <auth/srp_kx.h>
30 : #include <auth/anon.h>
31 : #include <auth/cert.h>
32 : #include <auth/psk.h>
33 : #include "errors.h"
34 : #include <auth.h>
35 : #include <state.h>
36 : #include <datum.h>
37 : #include <algorithms.h>
38 : #include <gnutls/ocsp.h>
39 : #include "x509.h"
40 : #include "hello_ext.h"
41 : #include "x509/ocsp.h"
42 :
43 : /**
44 : * gnutls_certificate_get_ours:
45 : * @session: is a gnutls session
46 : *
47 : * Gets the certificate as sent to the peer in the last handshake.
48 : * The certificate is in raw (DER) format. No certificate
49 : * list is being returned. Only the first certificate.
50 : *
51 : * This function returns the certificate that was sent in the current
52 : * handshake. In subsequent resumed sessions this function will return
53 : * %NULL. That differs from gnutls_certificate_get_peers() which always
54 : * returns the peer's certificate used in the original session.
55 : *
56 : * Returns: a pointer to a #gnutls_datum_t containing our
57 : * certificate, or %NULL in case of an error or if no certificate
58 : * was used.
59 : **/
60 579 : const gnutls_datum_t *gnutls_certificate_get_ours(gnutls_session_t session)
61 : {
62 579 : gnutls_certificate_credentials_t cred;
63 :
64 579 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, NULL);
65 :
66 579 : cred = (gnutls_certificate_credentials_t)
67 579 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
68 579 : if (cred == NULL) {
69 0 : gnutls_assert();
70 0 : return NULL;
71 : }
72 :
73 579 : if (session->internals.selected_cert_list == NULL)
74 : return NULL;
75 :
76 264 : return &session->internals.selected_cert_list[0].cert;
77 : }
78 :
79 : /**
80 : * gnutls_certificate_get_peers:
81 : * @session: is a gnutls session
82 : * @list_size: is the length of the certificate list (may be %NULL)
83 : *
84 : * Get the peer's raw certificate (chain) as sent by the peer. These
85 : * certificates are in raw format (DER encoded for X.509). In case of
86 : * a X.509 then a certificate list may be present. The list
87 : * is provided as sent by the server; the server must send as first
88 : * certificate in the list its own certificate, following the
89 : * issuer's certificate, then the issuer's issuer etc. However, there
90 : * are servers which violate this principle and thus on certain
91 : * occasions this may be an unsorted list.
92 : *
93 : * In resumed sessions, this function will return the peer's certificate
94 : * list as used in the first/original session.
95 : *
96 : * Returns: a pointer to a #gnutls_datum_t containing the peer's
97 : * certificates, or %NULL in case of an error or if no certificate
98 : * was used.
99 : **/
100 7225 : const gnutls_datum_t *gnutls_certificate_get_peers(gnutls_session_t
101 : session,
102 : unsigned int *list_size)
103 : {
104 7225 : cert_auth_info_t info;
105 :
106 7225 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, NULL);
107 :
108 7209 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
109 3092 : if (info == NULL)
110 : return NULL;
111 :
112 3092 : if (list_size)
113 3092 : *list_size = info->ncerts;
114 3092 : return info->raw_certificate_list;
115 : }
116 :
117 : /**
118 : * gnutls_certificate_client_get_request_status:
119 : * @session: is a gnutls session
120 : *
121 : * Get whether client certificate was requested on the last
122 : * handshake or not.
123 : *
124 : * Returns: 0 if the peer (server) did not request client
125 : * authentication or 1 otherwise.
126 : **/
127 : unsigned
128 5830 : gnutls_certificate_client_get_request_status(gnutls_session_t session)
129 : {
130 5830 : return (session->internals.hsk_flags & HSK_CRT_ASKED)?1:0;
131 : }
132 :
133 : /**
134 : * gnutls_certificate_set_params_function:
135 : * @res: is a gnutls_certificate_credentials_t type
136 : * @func: is the function to be called
137 : *
138 : * This function will set a callback in order for the server to get
139 : * the Diffie-Hellman or RSA parameters for certificate
140 : * authentication. The callback should return %GNUTLS_E_SUCCESS (0) on success.
141 : *
142 : * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0
143 : * or later. Since 3.6.0, DH parameters are negotiated
144 : * following RFC7919.
145 : *
146 : **/
147 : void
148 100 : gnutls_certificate_set_params_function(gnutls_certificate_credentials_t
149 : res, gnutls_params_function * func)
150 : {
151 100 : res->params_func = func;
152 100 : }
153 :
154 : /**
155 : * gnutls_certificate_set_flags:
156 : * @res: is a gnutls_certificate_credentials_t type
157 : * @flags: are the flags of #gnutls_certificate_flags type
158 : *
159 : * This function will set flags to tweak the operation of
160 : * the credentials structure. See the #gnutls_certificate_flags enumerations
161 : * for more information on the available flags.
162 : *
163 : * Since: 3.4.7
164 : **/
165 : void
166 302 : gnutls_certificate_set_flags(gnutls_certificate_credentials_t res,
167 : unsigned int flags)
168 : {
169 302 : res->flags = flags;
170 302 : }
171 :
172 : /**
173 : * gnutls_certificate_set_verify_flags:
174 : * @res: is a gnutls_certificate_credentials_t type
175 : * @flags: are the flags
176 : *
177 : * This function will set the flags to be used for verification
178 : * of certificates and override any defaults. The provided flags must be an OR of the
179 : * #gnutls_certificate_verify_flags enumerations.
180 : *
181 : **/
182 : void
183 285 : gnutls_certificate_set_verify_flags(gnutls_certificate_credentials_t
184 : res, unsigned int flags)
185 : {
186 285 : res->verify_flags = flags;
187 285 : }
188 :
189 : /**
190 : * gnutls_certificate_get_verify_flags:
191 : * @res: is a gnutls_certificate_credentials_t type
192 : *
193 : * Returns the verification flags set with
194 : * gnutls_certificate_set_verify_flags().
195 : *
196 : * Returns: The certificate verification flags used by @res.
197 : *
198 : * Since: 3.4.0
199 : */
200 : unsigned int
201 5 : gnutls_certificate_get_verify_flags(gnutls_certificate_credentials_t res)
202 : {
203 5 : return res->verify_flags;
204 : }
205 :
206 : /**
207 : * gnutls_certificate_set_verify_limits:
208 : * @res: is a gnutls_certificate_credentials type
209 : * @max_bits: is the number of bits of an acceptable certificate (default 8200)
210 : * @max_depth: is maximum depth of the verification of a certificate chain (default 5)
211 : *
212 : * This function will set some upper limits for the default
213 : * verification function, gnutls_certificate_verify_peers2(), to avoid
214 : * denial of service attacks. You can set them to zero to disable
215 : * limits.
216 : **/
217 : void
218 0 : gnutls_certificate_set_verify_limits(gnutls_certificate_credentials_t res,
219 : unsigned int max_bits,
220 : unsigned int max_depth)
221 : {
222 0 : res->verify_depth = max_depth;
223 0 : res->verify_bits = max_bits;
224 0 : }
225 :
226 : #ifdef ENABLE_OCSP
227 : static int
228 : _gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
229 : gnutls_x509_crt_t cert,
230 : unsigned int * ocsp_status);
231 :
232 : /* If the certificate is revoked status will be GNUTLS_CERT_REVOKED.
233 : *
234 : * Returns:
235 : * Zero on success, a negative error code otherwise.
236 : */
237 : static int
238 40 : check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
239 : gnutls_x509_trust_list_t tl,
240 : unsigned verify_flags,
241 : gnutls_x509_crt_t *cand_issuers, unsigned cand_issuers_size,
242 : gnutls_datum_t * data, unsigned int *ostatus)
243 : {
244 40 : gnutls_ocsp_resp_t resp;
245 40 : int ret;
246 40 : unsigned int status, cert_status;
247 40 : time_t rtime, vtime, ntime, now;
248 40 : int check_failed = 0;
249 :
250 40 : now = gnutls_time(0);
251 :
252 40 : ret = gnutls_ocsp_resp_init(&resp);
253 40 : if (ret < 0)
254 0 : return gnutls_assert_val(ret);
255 :
256 40 : ret = gnutls_ocsp_resp_import(resp, data);
257 40 : if (ret < 0) {
258 1 : _gnutls_audit_log(session,
259 : "There was an error parsing the OCSP response: %s.\n",
260 : gnutls_strerror(ret));
261 1 : ret = gnutls_assert_val(0);
262 1 : check_failed = 1;
263 1 : *ostatus |= GNUTLS_CERT_INVALID;
264 1 : *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
265 1 : goto cleanup;
266 : }
267 :
268 39 : if (gnutls_ocsp_resp_get_status(resp) != GNUTLS_OCSP_RESP_SUCCESSFUL) {
269 2 : ret = _gnutls_ocsp_verify_mandatory_stapling(session, cert, ostatus);
270 2 : if (ret < 0) {
271 0 : gnutls_assert();
272 0 : goto cleanup;
273 : }
274 2 : if (*ostatus & GNUTLS_CERT_MISSING_OCSP_STATUS) {
275 1 : _gnutls_audit_log(session,
276 : "Missing basic OCSP response while required: %s.\n",
277 : gnutls_strerror(ret));
278 1 : check_failed = 1;
279 : }
280 2 : ret = gnutls_assert_val(0);
281 2 : goto cleanup;
282 : }
283 :
284 37 : ret = gnutls_ocsp_resp_check_crt(resp, 0, cert);
285 37 : if (ret < 0) {
286 2 : ret = gnutls_assert_val(0);
287 2 : _gnutls_audit_log(session,
288 : "Got OCSP response with an unrelated certificate.\n");
289 2 : check_failed = 1;
290 2 : *ostatus |= GNUTLS_CERT_INVALID;
291 2 : *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
292 2 : goto cleanup;
293 : }
294 :
295 : /* Attempt to verify against our trusted list */
296 35 : ret = gnutls_ocsp_resp_verify(resp, tl, &status, verify_flags);
297 35 : if ((ret < 0 || status != 0) && cand_issuers_size > 0) {
298 : /* Attempt to verify against the certificate list provided by the server */
299 :
300 13 : ret = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[0], &status, verify_flags);
301 : /* if verification fails attempt to find whether any of the other
302 : * bundled CAs is an issuer of the OCSP response */
303 13 : if ((ret < 0 || status != 0) && cand_issuers_size > 1) {
304 : int ret2;
305 : unsigned status2, i;
306 :
307 0 : for (i=1;i<cand_issuers_size;i++) {
308 0 : ret2 = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[i], &status2, verify_flags);
309 0 : if (ret2 >= 0 && status2 == 0) {
310 0 : status = status2;
311 0 : ret = ret2;
312 0 : break;
313 : }
314 : }
315 : }
316 : }
317 :
318 35 : if (ret < 0) {
319 0 : ret = gnutls_assert_val(0);
320 0 : gnutls_assert();
321 0 : check_failed = 1;
322 0 : *ostatus |= GNUTLS_CERT_INVALID;
323 0 : *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
324 0 : goto cleanup;
325 : }
326 :
327 : /* do not consider revocation data if response was not verified */
328 35 : if (status != 0) {
329 1 : char buf[MAX_OCSP_MSG_SIZE];
330 :
331 1 : _gnutls_debug_log("OCSP rejection reason: %s\n",
332 : _gnutls_ocsp_verify_status_to_str(status, buf));
333 :
334 1 : ret = gnutls_assert_val(0);
335 1 : check_failed = 1;
336 1 : *ostatus |= GNUTLS_CERT_INVALID;
337 1 : *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
338 1 : goto cleanup;
339 : }
340 :
341 34 : ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
342 : &cert_status, &vtime, &ntime,
343 : &rtime, NULL);
344 34 : if (ret < 0) {
345 0 : _gnutls_audit_log(session,
346 : "There was an error parsing the OCSP response: %s.\n",
347 : gnutls_strerror(ret));
348 0 : ret = gnutls_assert_val(0);
349 0 : check_failed = 1;
350 0 : *ostatus |= GNUTLS_CERT_INVALID;
351 0 : *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
352 0 : goto cleanup;
353 : }
354 :
355 34 : if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
356 6 : _gnutls_audit_log(session,
357 : "The certificate was revoked via OCSP\n");
358 6 : check_failed = 1;
359 6 : *ostatus |= GNUTLS_CERT_INVALID;
360 6 : *ostatus |= GNUTLS_CERT_REVOKED;
361 6 : ret = gnutls_assert_val(0);
362 6 : goto cleanup;
363 : }
364 :
365 : /* Report but do not fail on the following errors. That is
366 : * because including the OCSP response in the handshake shouldn't
367 : * cause more problems that not including it.
368 : */
369 28 : if (ntime == -1) {
370 27 : if (now - vtime > MAX_OCSP_VALIDITY_SECS) {
371 1 : _gnutls_audit_log(session,
372 : "The OCSP response is old\n");
373 1 : check_failed = 1;
374 1 : *ostatus |= GNUTLS_CERT_INVALID;
375 1 : *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
376 1 : goto cleanup;
377 : }
378 : } else {
379 : /* there is a newer OCSP answer, don't trust this one */
380 1 : if (ntime < now) {
381 1 : _gnutls_audit_log(session,
382 : "There is a newer OCSP response but was not provided by the server\n");
383 1 : check_failed = 1;
384 1 : *ostatus |= GNUTLS_CERT_INVALID;
385 1 : *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
386 1 : goto cleanup;
387 : }
388 : }
389 :
390 : ret = 0;
391 2 : cleanup:
392 14 : if (check_failed == 0)
393 27 : session->internals.ocsp_check_ok = 1;
394 :
395 40 : gnutls_ocsp_resp_deinit(resp);
396 :
397 40 : return ret;
398 : }
399 :
400 : static int
401 592 : _gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
402 : gnutls_x509_crt_t cert,
403 : unsigned int * ocsp_status)
404 : {
405 592 : gnutls_x509_tlsfeatures_t tlsfeatures;
406 592 : int i, ret;
407 592 : unsigned feature;
408 :
409 : /* RFC 7633: If cert has TLS feature GNUTLS_EXTENSION_STATUS_REQUEST, stapling is mandatory.
410 : *
411 : * At this point, we know that we did not get the certificate status.
412 : *
413 : * To proceed, first check whether we have requested the certificate status
414 : */
415 592 : if (!(session->internals.hsk_flags & HSK_OCSP_REQUESTED))
416 : return 0;
417 :
418 591 : ret = gnutls_x509_tlsfeatures_init(&tlsfeatures);
419 591 : if (ret < 0) {
420 0 : gnutls_assert();
421 0 : return ret;
422 : }
423 :
424 : /* We have requested the status, now check whether the certificate mandates a response */
425 591 : if (gnutls_x509_crt_get_tlsfeatures(cert, tlsfeatures, 0, NULL) == 0) {
426 0 : for (i = 0;; ++i) {
427 8 : ret = gnutls_x509_tlsfeatures_get(tlsfeatures, i, &feature);
428 8 : if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
429 : break;
430 : }
431 :
432 8 : if (ret < 0) {
433 0 : gnutls_assert();
434 0 : goto cleanup;
435 : }
436 :
437 8 : if (feature == 5 /* TLS ID for status request */) {
438 : /* We sent a status request, the certificate mandates a reply, but we did not get any. */
439 8 : *ocsp_status |= GNUTLS_CERT_INVALID;
440 8 : *ocsp_status |= GNUTLS_CERT_MISSING_OCSP_STATUS;
441 8 : break;
442 : }
443 : }
444 : }
445 :
446 : ret = 0;
447 591 : cleanup:
448 591 : gnutls_x509_tlsfeatures_deinit(tlsfeatures);
449 591 : return ret;
450 : }
451 : #endif
452 :
453 : #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) { \
454 : if (peer_certificate_list[x]) \
455 : gnutls_x509_crt_deinit(peer_certificate_list[x]); \
456 : } \
457 : gnutls_free( peer_certificate_list)
458 :
459 : /*-
460 : * _gnutls_x509_cert_verify_peers - return the peer's certificate status
461 : * @session: is a gnutls session
462 : *
463 : * This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.).
464 : * The return value (status) should be one of the gnutls_certificate_status_t enumerated elements.
465 : * However you must also check the peer's name in order to check if the verified certificate belongs to the
466 : * actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
467 : -*/
468 : int
469 431 : _gnutls_x509_cert_verify_peers(gnutls_session_t session,
470 : gnutls_typed_vdata_st * data,
471 : unsigned int elements,
472 : unsigned int *status)
473 : {
474 431 : cert_auth_info_t info;
475 431 : gnutls_certificate_credentials_t cred;
476 431 : gnutls_x509_crt_t *peer_certificate_list;
477 431 : gnutls_datum_t resp;
478 431 : int peer_certificate_list_size, i, x, ret;
479 431 : gnutls_x509_crt_t *cand_issuers;
480 431 : unsigned cand_issuers_size;
481 431 : unsigned int ocsp_status = 0;
482 431 : unsigned int verify_flags;
483 :
484 : /* No OCSP check so far */
485 431 : session->internals.ocsp_check_ok = 0;
486 :
487 431 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
488 :
489 431 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
490 431 : if (info == NULL) {
491 0 : gnutls_assert();
492 0 : return GNUTLS_E_INVALID_REQUEST;
493 : }
494 :
495 431 : cred = (gnutls_certificate_credentials_t)
496 431 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
497 431 : if (cred == NULL) {
498 0 : gnutls_assert();
499 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
500 : }
501 :
502 431 : if (info->raw_certificate_list == NULL || info->ncerts == 0)
503 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
504 :
505 431 : if (info->ncerts > cred->verify_depth && cred->verify_depth > 0) {
506 0 : gnutls_assert();
507 0 : return GNUTLS_E_CONSTRAINT_ERROR;
508 : }
509 :
510 431 : verify_flags =
511 431 : cred->verify_flags | session->internals.additional_verify_flags;
512 : /* generate a list of gnutls_certs based on the auth info
513 : * raw certs.
514 : */
515 431 : peer_certificate_list_size = info->ncerts;
516 431 : peer_certificate_list =
517 431 : gnutls_calloc(peer_certificate_list_size,
518 : sizeof(gnutls_x509_crt_t));
519 431 : if (peer_certificate_list == NULL) {
520 0 : gnutls_assert();
521 0 : return GNUTLS_E_MEMORY_ERROR;
522 : }
523 :
524 1113 : for (i = 0; i < peer_certificate_list_size; i++) {
525 682 : ret = gnutls_x509_crt_init(&peer_certificate_list[i]);
526 682 : if (ret < 0) {
527 0 : gnutls_assert();
528 0 : CLEAR_CERTS;
529 0 : return ret;
530 : }
531 :
532 682 : ret =
533 1364 : gnutls_x509_crt_import(peer_certificate_list[i],
534 682 : &info->raw_certificate_list[i],
535 : GNUTLS_X509_FMT_DER);
536 682 : if (ret < 0) {
537 0 : gnutls_assert();
538 0 : CLEAR_CERTS;
539 0 : return ret;
540 : }
541 : }
542 :
543 : /* Use the OCSP extension if any */
544 : #ifdef ENABLE_OCSP
545 431 : if (verify_flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS)
546 26 : goto skip_ocsp;
547 :
548 1035 : for (i=0;i<peer_certificate_list_size;i++) {
549 630 : ret = gnutls_ocsp_status_request_get2(session, i, &resp);
550 630 : if (ret < 0) {
551 590 : ret = _gnutls_ocsp_verify_mandatory_stapling(session, peer_certificate_list[i], &ocsp_status);
552 590 : if (ret < 0) {
553 0 : gnutls_assert();
554 0 : CLEAR_CERTS;
555 0 : return ret;
556 : }
557 :
558 590 : continue;
559 : }
560 :
561 40 : cand_issuers = NULL;
562 40 : cand_issuers_size = 0;
563 40 : if (peer_certificate_list_size > i+1) {
564 19 : cand_issuers = &peer_certificate_list[i+1];
565 19 : cand_issuers_size = peer_certificate_list_size-i-1;
566 : }
567 :
568 40 : ret =
569 80 : check_ocsp_response(session,
570 40 : peer_certificate_list[i],
571 : cred->tlist,
572 : verify_flags, cand_issuers,
573 : cand_issuers_size,
574 : &resp, &ocsp_status);
575 :
576 40 : if (ret < 0) {
577 0 : CLEAR_CERTS;
578 0 : return gnutls_assert_val(ret);
579 : }
580 : }
581 : #endif
582 :
583 405 : skip_ocsp:
584 : /* Verify certificate
585 : */
586 431 : ret =
587 431 : gnutls_x509_trust_list_verify_crt2(cred->tlist,
588 : peer_certificate_list,
589 : peer_certificate_list_size,
590 : data, elements,
591 : verify_flags, status, NULL);
592 :
593 431 : if (ret < 0) {
594 0 : gnutls_assert();
595 0 : CLEAR_CERTS;
596 0 : return ret;
597 : }
598 :
599 1113 : CLEAR_CERTS;
600 :
601 431 : *status |= ocsp_status;
602 :
603 431 : return 0;
604 : }
605 :
606 : /**
607 : * gnutls_certificate_verify_peers2:
608 : * @session: is a gnutls session
609 : * @status: is the output of the verification
610 : *
611 : * This function will verify the peer's certificate and store
612 : * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
613 : * values or zero if the certificate is trusted. Note that value in @status
614 : * is set only when the return value of this function is success (i.e, failure
615 : * to trust a certificate does not imply a negative return value).
616 : * The default verification flags used by this function can be overridden
617 : * using gnutls_certificate_set_verify_flags().
618 : *
619 : * This function will take into account the stapled OCSP responses sent by the server,
620 : * as well as the following X.509 certificate extensions: Name Constraints,
621 : * Key Usage, and Basic Constraints (pathlen).
622 : *
623 : * Note that you must also check the peer's name in order to check if
624 : * the verified certificate belongs to the actual peer, see gnutls_x509_crt_check_hostname(),
625 : * or use gnutls_certificate_verify_peers3().
626 : *
627 : * To avoid denial of service attacks some
628 : * default upper limits regarding the certificate key size and chain
629 : * size are set. To override them use gnutls_certificate_set_verify_limits().
630 : *
631 : * Note that when using raw public-keys verification will not work because there is
632 : * no corresponding certificate body belonging to the raw key that can be verified. In that
633 : * case this function will return %GNUTLS_E_INVALID_REQUEST.
634 : *
635 : * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
636 : * A successful error code means that the @status parameter must be checked to obtain the validation status.
637 : **/
638 : int
639 30 : gnutls_certificate_verify_peers2(gnutls_session_t session,
640 : unsigned int *status)
641 : {
642 30 : return gnutls_certificate_verify_peers(session, NULL, 0, status);
643 : }
644 :
645 : /**
646 : * gnutls_certificate_verify_peers3:
647 : * @session: is a gnutls session
648 : * @hostname: is the expected name of the peer; may be %NULL
649 : * @status: is the output of the verification
650 : *
651 : * This function will verify the peer's certificate and store the
652 : * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
653 : * values or zero if the certificate is trusted. Note that value in @status
654 : * is set only when the return value of this function is success (i.e, failure
655 : * to trust a certificate does not imply a negative return value).
656 : * The default verification flags used by this function can be overridden
657 : * using gnutls_certificate_set_verify_flags(). See the documentation
658 : * of gnutls_certificate_verify_peers2() for details in the verification process.
659 : *
660 : * This function will take into account the stapled OCSP responses sent by the server,
661 : * as well as the following X.509 certificate extensions: Name Constraints,
662 : * Key Usage, and Basic Constraints (pathlen).
663 : *
664 : * If the @hostname provided is non-NULL then this function will compare
665 : * the hostname in the certificate against it. The comparison will follow
666 : * the RFC6125 recommendations. If names do not match the
667 : * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
668 : *
669 : * In order to verify the purpose of the end-certificate (by checking the extended
670 : * key usage), use gnutls_certificate_verify_peers().
671 : *
672 : * To avoid denial of service attacks some
673 : * default upper limits regarding the certificate key size and chain
674 : * size are set. To override them use gnutls_certificate_set_verify_limits().
675 : *
676 : * Note that when using raw public-keys verification will not work because there is
677 : * no corresponding certificate body belonging to the raw key that can be verified. In that
678 : * case this function will return %GNUTLS_E_INVALID_REQUEST.
679 : *
680 : * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
681 : * A successful error code means that the @status parameter must be checked to obtain the validation status.
682 : *
683 : * Since: 3.1.4
684 : **/
685 : int
686 56 : gnutls_certificate_verify_peers3(gnutls_session_t session,
687 : const char *hostname,
688 : unsigned int *status)
689 : {
690 56 : gnutls_typed_vdata_st data;
691 :
692 56 : data.type = GNUTLS_DT_DNS_HOSTNAME;
693 56 : data.size = 0;
694 56 : data.data = (void*)hostname;
695 :
696 56 : return gnutls_certificate_verify_peers(session, &data, 1, status);
697 : }
698 :
699 : /**
700 : * gnutls_certificate_verify_peers:
701 : * @session: is a gnutls session
702 : * @data: an array of typed data
703 : * @elements: the number of data elements
704 : * @status: is the output of the verification
705 : *
706 : * This function will verify the peer's certificate and store the
707 : * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
708 : * values or zero if the certificate is trusted. Note that value in @status
709 : * is set only when the return value of this function is success (i.e, failure
710 : * to trust a certificate does not imply a negative return value).
711 : * The default verification flags used by this function can be overridden
712 : * using gnutls_certificate_set_verify_flags(). See the documentation
713 : * of gnutls_certificate_verify_peers2() for details in the verification process.
714 : *
715 : * This function will take into account the stapled OCSP responses sent by the server,
716 : * as well as the following X.509 certificate extensions: Name Constraints,
717 : * Key Usage, and Basic Constraints (pathlen).
718 : *
719 : * The acceptable @data types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_RFC822NAME and %GNUTLS_DT_KEY_PURPOSE_OID.
720 : * The former two accept as data a null-terminated hostname or email address, and the latter a null-terminated
721 : * object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
722 : *
723 : * If a DNS hostname is provided then this function will compare
724 : * the hostname in the certificate against the given. If names do not match the
725 : * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
726 : * If a key purpose OID is provided and the end-certificate contains the extended key
727 : * usage PKIX extension, it will be required to be have the provided key purpose
728 : * or be marked for any purpose, otherwise verification status will have the
729 : * %GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE flag set.
730 : *
731 : * To avoid denial of service attacks some
732 : * default upper limits regarding the certificate key size and chain
733 : * size are set. To override them use gnutls_certificate_set_verify_limits().
734 : *
735 : * Note that when using raw public-keys verification will not work because there is
736 : * no corresponding certificate body belonging to the raw key that can be verified. In that
737 : * case this function will return %GNUTLS_E_INVALID_REQUEST.
738 : *
739 : * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
740 : * A successful error code means that the @status parameter must be checked to obtain the validation status.
741 : *
742 : * Since: 3.3.0
743 : **/
744 : int
745 431 : gnutls_certificate_verify_peers(gnutls_session_t session,
746 : gnutls_typed_vdata_st * data,
747 : unsigned int elements,
748 : unsigned int *status)
749 : {
750 431 : cert_auth_info_t info;
751 :
752 431 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
753 :
754 431 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
755 431 : if (info == NULL) {
756 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
757 : }
758 :
759 431 : if (info->raw_certificate_list == NULL || info->ncerts == 0)
760 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
761 :
762 :
763 862 : switch (get_certificate_type(session, GNUTLS_CTYPE_PEERS)) {
764 431 : case GNUTLS_CRT_X509:
765 431 : return _gnutls_x509_cert_verify_peers(session, data, elements,
766 : status);
767 : default:
768 : return GNUTLS_E_INVALID_REQUEST;
769 : }
770 : }
771 :
772 : /*-
773 : * _gnutls_x509_extract_certificate_activation_time - return the peer's certificate activation time
774 : * @cert: should contain an X.509 DER encoded certificate
775 : *
776 : * This function will return the certificate's activation time in UNIX time
777 : * (ie seconds since 00:00:00 UTC January 1, 1970).
778 : *
779 : * Returns a (time_t) -1 in case of an error.
780 : *
781 : -*/
782 : static time_t
783 3 : _gnutls_x509_get_raw_crt_activation_time(const gnutls_datum_t * cert)
784 : {
785 3 : gnutls_x509_crt_t xcert;
786 3 : time_t result;
787 :
788 3 : result = gnutls_x509_crt_init(&xcert);
789 3 : if (result < 0)
790 : return (time_t) - 1;
791 :
792 3 : result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
793 3 : if (result < 0) {
794 0 : gnutls_x509_crt_deinit(xcert);
795 0 : return (time_t) - 1;
796 : }
797 :
798 3 : result = gnutls_x509_crt_get_activation_time(xcert);
799 :
800 3 : gnutls_x509_crt_deinit(xcert);
801 :
802 3 : return result;
803 : }
804 :
805 : /*-
806 : * gnutls_x509_extract_certificate_expiration_time:
807 : * @cert: should contain an X.509 DER encoded certificate
808 : *
809 : * This function will return the certificate's expiration time in UNIX
810 : * time (ie seconds since 00:00:00 UTC January 1, 1970). Returns a
811 : *
812 : * (time_t) -1 in case of an error.
813 : *
814 : -*/
815 : static time_t
816 3 : _gnutls_x509_get_raw_crt_expiration_time(const gnutls_datum_t * cert)
817 : {
818 3 : gnutls_x509_crt_t xcert;
819 3 : time_t result;
820 :
821 3 : result = gnutls_x509_crt_init(&xcert);
822 3 : if (result < 0)
823 : return (time_t) - 1;
824 :
825 3 : result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
826 3 : if (result < 0) {
827 0 : gnutls_x509_crt_deinit(xcert);
828 0 : return (time_t) - 1;
829 : }
830 :
831 3 : result = gnutls_x509_crt_get_expiration_time(xcert);
832 :
833 3 : gnutls_x509_crt_deinit(xcert);
834 :
835 3 : return result;
836 : }
837 :
838 : /**
839 : * gnutls_certificate_expiration_time_peers:
840 : * @session: is a gnutls session
841 : *
842 : * This function will return the peer's certificate expiration time.
843 : *
844 : * Returns: (time_t)-1 on error.
845 : *
846 : * Deprecated: gnutls_certificate_verify_peers2() now verifies expiration times.
847 : **/
848 3 : time_t gnutls_certificate_expiration_time_peers(gnutls_session_t session)
849 : {
850 3 : cert_auth_info_t info;
851 :
852 3 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
853 :
854 3 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
855 3 : if (info == NULL) {
856 : return (time_t) - 1;
857 : }
858 :
859 3 : if (info->raw_certificate_list == NULL || info->ncerts == 0) {
860 0 : gnutls_assert();
861 0 : return (time_t) - 1;
862 : }
863 :
864 6 : switch (get_certificate_type(session, GNUTLS_CTYPE_PEERS)) {
865 3 : case GNUTLS_CRT_X509:
866 3 : return
867 3 : _gnutls_x509_get_raw_crt_expiration_time(&info->
868 : raw_certificate_list[0]);
869 : default:
870 : return (time_t) - 1;
871 : }
872 : }
873 :
874 : /**
875 : * gnutls_certificate_activation_time_peers:
876 : * @session: is a gnutls session
877 : *
878 : * This function will return the peer's certificate activation time.
879 : *
880 : * Returns: (time_t)-1 on error.
881 : *
882 : * Deprecated: gnutls_certificate_verify_peers2() now verifies activation times.
883 : **/
884 3 : time_t gnutls_certificate_activation_time_peers(gnutls_session_t session)
885 : {
886 3 : cert_auth_info_t info;
887 :
888 3 : CHECK_AUTH_TYPE(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
889 :
890 3 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
891 3 : if (info == NULL) {
892 : return (time_t) - 1;
893 : }
894 :
895 3 : if (info->raw_certificate_list == NULL || info->ncerts == 0) {
896 0 : gnutls_assert();
897 0 : return (time_t) - 1;
898 : }
899 :
900 6 : switch (get_certificate_type(session, GNUTLS_CTYPE_PEERS)) {
901 3 : case GNUTLS_CRT_X509:
902 3 : return
903 3 : _gnutls_x509_get_raw_crt_activation_time(&info->
904 : raw_certificate_list[0]);
905 : default:
906 : return (time_t) - 1;
907 : }
908 : }
|