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