/src/gnutls/lib/x509/verify.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2003-2014 Free Software Foundation, Inc. |
3 | | * Copyright (C) 2013 Nikos Mavrogiannopoulos |
4 | | * Copyright (C) 2014 Red Hat |
5 | | * |
6 | | * Author: Nikos Mavrogiannopoulos |
7 | | * |
8 | | * This file is part of GnuTLS. |
9 | | * |
10 | | * The GnuTLS is free software; you can redistribute it and/or |
11 | | * modify it under the terms of the GNU Lesser General Public License |
12 | | * as published by the Free Software Foundation; either version 2.1 of |
13 | | * the License, or (at your option) any later version. |
14 | | * |
15 | | * This library is distributed in the hope that it will be useful, but |
16 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | | * Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public License |
21 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
22 | | * |
23 | | */ |
24 | | |
25 | | /* All functions which relate to X.509 certificate verification stuff are |
26 | | * included here |
27 | | */ |
28 | | |
29 | | #include "gnutls_int.h" |
30 | | #include "errors.h" |
31 | | #include <libtasn1.h> |
32 | | #include <global.h> |
33 | | #include <num.h> /* MAX */ |
34 | | #include <tls-sig.h> |
35 | | #include <str.h> |
36 | | #include <datum.h> |
37 | | #include <pkcs11_int.h> |
38 | | #include <x509_int.h> |
39 | | #include <common.h> |
40 | | #include <pk.h> |
41 | | #include <x509/verify-high.h> |
42 | | #include "supported_exts.h" |
43 | | #include "profiles.h" |
44 | | |
45 | | /* Checks if two certs have the same name and the same key. Return 1 on match. |
46 | | * If @is_ca is zero then this function is identical to gnutls_x509_crt_equals() |
47 | | */ |
48 | | unsigned |
49 | | _gnutls_check_if_same_key(gnutls_x509_crt_t cert1, |
50 | | gnutls_x509_crt_t cert2, unsigned is_ca) |
51 | 0 | { |
52 | 0 | int ret; |
53 | 0 | unsigned result; |
54 | |
|
55 | 0 | if (is_ca == 0) |
56 | 0 | return gnutls_x509_crt_equals(cert1, cert2); |
57 | | |
58 | 0 | ret = _gnutls_is_same_dn(cert1, cert2); |
59 | 0 | if (ret == 0) |
60 | 0 | return 0; |
61 | | |
62 | 0 | if (cert1->raw_spki.size > 0 |
63 | 0 | && (cert1->raw_spki.size == cert2->raw_spki.size) |
64 | 0 | && |
65 | 0 | (memcmp |
66 | 0 | (cert1->raw_spki.data, cert2->raw_spki.data, |
67 | 0 | cert1->raw_spki.size) == 0)) |
68 | 0 | result = 1; |
69 | 0 | else |
70 | 0 | result = 0; |
71 | |
|
72 | 0 | return result; |
73 | 0 | } |
74 | | |
75 | | unsigned |
76 | | _gnutls_check_if_same_key2(gnutls_x509_crt_t cert1, gnutls_datum_t * cert2bin) |
77 | 0 | { |
78 | 0 | int ret; |
79 | 0 | gnutls_x509_crt_t cert2; |
80 | |
|
81 | 0 | ret = gnutls_x509_crt_init(&cert2); |
82 | 0 | if (ret < 0) |
83 | 0 | return gnutls_assert_val(0); |
84 | | |
85 | 0 | ret = gnutls_x509_crt_import(cert2, cert2bin, GNUTLS_X509_FMT_DER); |
86 | 0 | if (ret < 0) { |
87 | 0 | gnutls_x509_crt_deinit(cert2); |
88 | 0 | return gnutls_assert_val(0); |
89 | 0 | } |
90 | | |
91 | 0 | ret = _gnutls_check_if_same_key(cert1, cert2, 1); |
92 | |
|
93 | 0 | gnutls_x509_crt_deinit(cert2); |
94 | 0 | return ret; |
95 | 0 | } |
96 | | |
97 | | /* checks whether there are present unknown/unsupported critical extensions. |
98 | | * |
99 | | * Returns true if they are present. |
100 | | */ |
101 | | static unsigned check_for_unknown_exts(gnutls_x509_crt_t cert) |
102 | 0 | { |
103 | 0 | unsigned i; |
104 | 0 | char oid[MAX_OID_SIZE]; |
105 | 0 | size_t oid_size; |
106 | 0 | unsigned critical; |
107 | 0 | int ret; |
108 | |
|
109 | 0 | for (i = 0;; i++) { |
110 | 0 | oid_size = sizeof(oid); |
111 | 0 | oid[0] = 0; |
112 | 0 | critical = 0; |
113 | |
|
114 | 0 | ret = |
115 | 0 | gnutls_x509_crt_get_extension_info(cert, i, oid, &oid_size, |
116 | 0 | &critical); |
117 | 0 | if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
118 | 0 | return 0; |
119 | 0 | } else if (ret < 0) { |
120 | 0 | gnutls_assert(); |
121 | | /* could not decode? */ |
122 | 0 | _gnutls_debug_log("Could not decode extension %d\n", i); |
123 | 0 | return 1; |
124 | 0 | } |
125 | | |
126 | 0 | if (critical == 0) |
127 | 0 | continue; |
128 | | |
129 | 0 | if (is_ext_oid_supported(oid, oid_size) == NULL) { |
130 | 0 | gnutls_assert(); |
131 | 0 | _gnutls_debug_log |
132 | 0 | ("Unsupported critical extension: %s\n", oid); |
133 | 0 | return 1; |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | 0 | return 0; |
138 | 0 | } |
139 | | |
140 | | /* Checks if the issuer of a certificate is a |
141 | | * Certificate Authority, or if the certificate is the same |
142 | | * as the issuer (and therefore it doesn't need to be a CA). |
143 | | * |
144 | | * Returns true or false, if the issuer is a CA, |
145 | | * or not. |
146 | | */ |
147 | | static unsigned |
148 | | check_if_ca(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer, |
149 | | unsigned int *max_path, unsigned int flags) |
150 | 0 | { |
151 | 0 | gnutls_datum_t cert_signed_data = { NULL, 0 }; |
152 | 0 | gnutls_datum_t issuer_signed_data = { NULL, 0 }; |
153 | 0 | gnutls_datum_t cert_signature = { NULL, 0 }; |
154 | 0 | gnutls_datum_t issuer_signature = { NULL, 0 }; |
155 | 0 | int pathlen = -1, ret; |
156 | 0 | unsigned result; |
157 | 0 | unsigned int ca_status = 0; |
158 | | |
159 | | /* Check if the issuer is the same with the |
160 | | * certificate. This is added in order for trusted |
161 | | * certificates to be able to verify themselves. |
162 | | */ |
163 | |
|
164 | 0 | ret = |
165 | 0 | _gnutls_x509_get_signed_data(issuer->cert, &issuer->der, |
166 | 0 | "tbsCertificate", &issuer_signed_data); |
167 | 0 | if (ret < 0) { |
168 | 0 | gnutls_assert(); |
169 | 0 | goto fail; |
170 | 0 | } |
171 | | |
172 | 0 | ret = |
173 | 0 | _gnutls_x509_get_signed_data(cert->cert, &cert->der, |
174 | 0 | "tbsCertificate", &cert_signed_data); |
175 | 0 | if (ret < 0) { |
176 | 0 | gnutls_assert(); |
177 | 0 | goto fail; |
178 | 0 | } |
179 | | |
180 | 0 | ret = |
181 | 0 | _gnutls_x509_get_signature(issuer->cert, "signature", |
182 | 0 | &issuer_signature); |
183 | 0 | if (ret < 0) { |
184 | 0 | gnutls_assert(); |
185 | 0 | goto fail; |
186 | 0 | } |
187 | | |
188 | 0 | ret = |
189 | 0 | _gnutls_x509_get_signature(cert->cert, "signature", |
190 | 0 | &cert_signature); |
191 | 0 | if (ret < 0) { |
192 | 0 | gnutls_assert(); |
193 | 0 | goto fail; |
194 | 0 | } |
195 | | |
196 | | /* If the subject certificate is the same as the issuer |
197 | | * return true. |
198 | | */ |
199 | 0 | if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) |
200 | 0 | if (cert_signed_data.size == issuer_signed_data.size) { |
201 | 0 | if ((memcmp |
202 | 0 | (cert_signed_data.data, |
203 | 0 | issuer_signed_data.data, |
204 | 0 | cert_signed_data.size) == 0) |
205 | 0 | && (cert_signature.size == issuer_signature.size) |
206 | 0 | && |
207 | 0 | (memcmp |
208 | 0 | (cert_signature.data, issuer_signature.data, |
209 | 0 | cert_signature.size) == 0)) { |
210 | 0 | result = 1; |
211 | 0 | goto cleanup; |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | 0 | ret = |
216 | 0 | gnutls_x509_crt_get_basic_constraints(issuer, NULL, &ca_status, |
217 | 0 | &pathlen); |
218 | 0 | if (ret < 0) { |
219 | 0 | ca_status = 0; |
220 | 0 | pathlen = -1; |
221 | 0 | } |
222 | |
|
223 | 0 | if (ca_status != 0 && pathlen != -1) { |
224 | 0 | if ((unsigned)pathlen < *max_path) |
225 | 0 | *max_path = pathlen; |
226 | 0 | } |
227 | |
|
228 | 0 | if (ca_status != 0) { |
229 | 0 | result = 1; |
230 | 0 | goto cleanup; |
231 | 0 | } |
232 | | /* Handle V1 CAs that do not have a basicConstraint, but accept |
233 | | these certs only if the appropriate flags are set. */ |
234 | 0 | else if ((ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) && |
235 | 0 | ((flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT) || |
236 | 0 | (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) && |
237 | 0 | (gnutls_x509_crt_check_issuer(issuer, issuer) != 0)))) { |
238 | 0 | gnutls_assert(); |
239 | 0 | result = 1; |
240 | 0 | goto cleanup; |
241 | 0 | } else { |
242 | 0 | gnutls_assert(); |
243 | 0 | } |
244 | | |
245 | 0 | fail: |
246 | 0 | result = 0; |
247 | |
|
248 | 0 | cleanup: |
249 | 0 | _gnutls_free_datum(&cert_signed_data); |
250 | 0 | _gnutls_free_datum(&issuer_signed_data); |
251 | 0 | _gnutls_free_datum(&cert_signature); |
252 | 0 | _gnutls_free_datum(&issuer_signature); |
253 | 0 | return result; |
254 | 0 | } |
255 | | |
256 | | /* This function checks if cert's issuer is issuer. |
257 | | * This does a straight (DER) compare of the issuer/subject DN fields in |
258 | | * the given certificates, as well as check the authority key ID. |
259 | | * |
260 | | * Returns 1 if they match and (0) if they don't match. |
261 | | */ |
262 | | static unsigned is_issuer(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer) |
263 | 0 | { |
264 | 0 | uint8_t id1[MAX_KEY_ID_SIZE]; |
265 | 0 | uint8_t id2[MAX_KEY_ID_SIZE]; |
266 | 0 | size_t id1_size; |
267 | 0 | size_t id2_size; |
268 | 0 | int ret; |
269 | 0 | unsigned result; |
270 | |
|
271 | 0 | if (_gnutls_x509_compare_raw_dn |
272 | 0 | (&cert->raw_issuer_dn, &issuer->raw_dn) != 0) |
273 | 0 | result = 1; |
274 | 0 | else |
275 | 0 | result = 0; |
276 | |
|
277 | 0 | if (result != 0) { |
278 | | /* check if the authority key identifier matches the subject key identifier |
279 | | * of the issuer */ |
280 | 0 | id1_size = sizeof(id1); |
281 | |
|
282 | 0 | ret = |
283 | 0 | gnutls_x509_crt_get_authority_key_id(cert, id1, |
284 | 0 | &id1_size, NULL); |
285 | 0 | if (ret < 0) { |
286 | | /* If there is no authority key identifier in the |
287 | | * certificate, assume they match */ |
288 | 0 | result = 1; |
289 | 0 | goto cleanup; |
290 | 0 | } |
291 | | |
292 | 0 | id2_size = sizeof(id2); |
293 | 0 | ret = |
294 | 0 | gnutls_x509_crt_get_subject_key_id(issuer, id2, |
295 | 0 | &id2_size, NULL); |
296 | 0 | if (ret < 0) { |
297 | | /* If there is no subject key identifier in the |
298 | | * issuer certificate, assume they match */ |
299 | 0 | result = 1; |
300 | 0 | gnutls_assert(); |
301 | 0 | goto cleanup; |
302 | 0 | } |
303 | | |
304 | 0 | if (id1_size == id2_size && memcmp(id1, id2, id1_size) == 0) |
305 | 0 | result = 1; |
306 | 0 | else |
307 | 0 | result = 0; |
308 | 0 | } |
309 | | |
310 | 0 | cleanup: |
311 | 0 | return result; |
312 | 0 | } |
313 | | |
314 | | /* Check if the given certificate is the issuer of the CRL. |
315 | | * Returns 1 on success and 0 otherwise. |
316 | | */ |
317 | | static unsigned is_crl_issuer(gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer) |
318 | 0 | { |
319 | 0 | if (_gnutls_x509_compare_raw_dn |
320 | 0 | (&crl->raw_issuer_dn, &issuer->raw_dn) != 0) |
321 | 0 | return 1; |
322 | 0 | else |
323 | 0 | return 0; |
324 | 0 | } |
325 | | |
326 | | /* Checks if the DN of two certificates is the same. |
327 | | * Returns 1 if they match and (0) if they don't match. Otherwise |
328 | | * a negative error code is returned to indicate error. |
329 | | */ |
330 | | unsigned _gnutls_is_same_dn(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2) |
331 | 0 | { |
332 | 0 | if (_gnutls_x509_compare_raw_dn(&cert1->raw_dn, &cert2->raw_dn) != 0) |
333 | 0 | return 1; |
334 | 0 | else |
335 | 0 | return 0; |
336 | 0 | } |
337 | | |
338 | | /* Finds an issuer of the certificate. If multiple issuers |
339 | | * are present, returns one that is activated and not expired. |
340 | | */ |
341 | | static inline gnutls_x509_crt_t |
342 | | find_issuer(gnutls_x509_crt_t cert, |
343 | | const gnutls_x509_crt_t * trusted_cas, int tcas_size) |
344 | 0 | { |
345 | 0 | int i; |
346 | 0 | gnutls_x509_crt_t issuer = NULL; |
347 | | |
348 | | /* this is serial search. |
349 | | */ |
350 | 0 | for (i = 0; i < tcas_size; i++) { |
351 | 0 | if (is_issuer(cert, trusted_cas[i]) != 0) { |
352 | 0 | if (issuer == NULL) { |
353 | 0 | issuer = trusted_cas[i]; |
354 | 0 | } else { |
355 | 0 | time_t now = gnutls_time(0); |
356 | |
|
357 | 0 | if (now < |
358 | 0 | gnutls_x509_crt_get_expiration_time |
359 | 0 | (trusted_cas[i]) |
360 | 0 | && now >= |
361 | 0 | gnutls_x509_crt_get_activation_time |
362 | 0 | (trusted_cas[i])) { |
363 | 0 | issuer = trusted_cas[i]; |
364 | 0 | } |
365 | 0 | } |
366 | 0 | } |
367 | 0 | } |
368 | |
|
369 | 0 | return issuer; |
370 | 0 | } |
371 | | |
372 | | static unsigned int check_time_status(gnutls_x509_crt_t crt, time_t now) |
373 | 0 | { |
374 | 0 | int status = 0; |
375 | 0 | time_t t; |
376 | |
|
377 | 0 | t = gnutls_x509_crt_get_activation_time(crt); |
378 | 0 | if (t == (time_t) - 1 || now < t) { |
379 | 0 | status |= GNUTLS_CERT_NOT_ACTIVATED; |
380 | 0 | status |= GNUTLS_CERT_INVALID; |
381 | 0 | return status; |
382 | 0 | } |
383 | | |
384 | 0 | t = gnutls_x509_crt_get_expiration_time(crt); |
385 | 0 | if (t == (time_t) - 1 || now > t) { |
386 | 0 | status |= GNUTLS_CERT_EXPIRED; |
387 | 0 | status |= GNUTLS_CERT_INVALID; |
388 | 0 | return status; |
389 | 0 | } |
390 | | |
391 | 0 | return 0; |
392 | 0 | } |
393 | | |
394 | | unsigned _gnutls_is_broken_sig_allowed(const gnutls_sign_entry_st * se, |
395 | | unsigned int flags) |
396 | 0 | { |
397 | 0 | gnutls_digest_algorithm_t hash; |
398 | | |
399 | | /* we have a catch all */ |
400 | 0 | if ((flags & GNUTLS_VERIFY_ALLOW_BROKEN) == GNUTLS_VERIFY_ALLOW_BROKEN) |
401 | 0 | return 1; |
402 | | |
403 | | /* the first two are for backwards compatibility */ |
404 | 0 | if ((se->id == GNUTLS_SIGN_RSA_MD2) |
405 | 0 | && (flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) |
406 | 0 | return 1; |
407 | 0 | if ((se->id == GNUTLS_SIGN_RSA_MD5) |
408 | 0 | && (flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)) |
409 | 0 | return 1; |
410 | | |
411 | 0 | hash = se->hash; |
412 | 0 | if (hash == GNUTLS_DIG_SHA1 |
413 | 0 | && (flags & GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1)) |
414 | 0 | return 1; |
415 | | |
416 | 0 | return 0; |
417 | 0 | } |
418 | | |
419 | | #define CASE_SEC_PARAM(profile, level) \ |
420 | 0 | case profile: \ |
421 | 0 | sym_bits = gnutls_sec_param_to_symmetric_bits(level); \ |
422 | 0 | se = _gnutls_sign_to_entry(sigalg); \ |
423 | 0 | if (unlikely(se == NULL)) { \ |
424 | 0 | _gnutls_cert_log("cert", crt); \ |
425 | 0 | _gnutls_debug_log(#level": certificate's signature algorithm is unknown\n"); \ |
426 | 0 | return gnutls_assert_val(0); \ |
427 | 0 | } \ |
428 | 0 | if (unlikely(se->hash == GNUTLS_DIG_UNKNOWN)) { \ |
429 | 0 | _gnutls_cert_log("cert", crt); \ |
430 | 0 | _gnutls_debug_log(#level": certificate's signature hash is unknown\n"); \ |
431 | 0 | return gnutls_assert_val(0); \ |
432 | 0 | } \ |
433 | 0 | if (!trusted && \ |
434 | 0 | _gnutls_sign_get_hash_strength(sigalg) < sym_bits) { \ |
435 | 0 | _gnutls_cert_log("cert", crt); \ |
436 | 0 | _gnutls_debug_log(#level": certificate's signature hash strength is unacceptable (is %u bits, needed %u)\n", _gnutls_sign_get_hash_strength(sigalg), sym_bits); \ |
437 | 0 | return gnutls_assert_val(0); \ |
438 | 0 | } \ |
439 | 0 | sp = gnutls_pk_bits_to_sec_param(pkalg, bits); \ |
440 | 0 | if (sp < level) { \ |
441 | 0 | _gnutls_cert_log("cert", crt); \ |
442 | 0 | _gnutls_debug_log(#level": certificate's security level is unacceptable\n"); \ |
443 | 0 | return gnutls_assert_val(0); \ |
444 | 0 | } \ |
445 | 0 | if (issuer) { \ |
446 | 0 | sp = gnutls_pk_bits_to_sec_param(issuer_pkalg, issuer_bits); \ |
447 | 0 | if (sp < level) { \ |
448 | 0 | _gnutls_cert_log("issuer", issuer); \ |
449 | 0 | _gnutls_debug_log(#level": certificate's issuer security level is unacceptable\n"); \ |
450 | 0 | return gnutls_assert_val(0); \ |
451 | 0 | } \ |
452 | 0 | } \ |
453 | 0 | break; |
454 | | |
455 | | /* Checks whether the provided certificates are acceptable |
456 | | * according to verification profile specified. |
457 | | * |
458 | | * @crt: a certificate |
459 | | * @issuer: the certificates issuer (allowed to be NULL) |
460 | | * @sigalg: the signature algorithm used |
461 | | * @trusted: whether @crt is treated as trusted (e.g., present in the system |
462 | | * trust list); if it is true, the check on signature algorithm will |
463 | | * be skipped |
464 | | * @flags: the specified verification flags |
465 | | */ |
466 | | static unsigned is_level_acceptable(gnutls_x509_crt_t crt, |
467 | | gnutls_x509_crt_t issuer, |
468 | | gnutls_sign_algorithm_t sigalg, |
469 | | bool trusted, unsigned flags) |
470 | 0 | { |
471 | 0 | gnutls_certificate_verification_profiles_t profile = |
472 | 0 | GNUTLS_VFLAGS_TO_PROFILE(flags); |
473 | 0 | int issuer_pkalg = 0, pkalg, ret; |
474 | 0 | unsigned bits = 0, issuer_bits = 0, sym_bits = 0; |
475 | 0 | gnutls_pk_params_st params; |
476 | 0 | gnutls_sec_param_t sp; |
477 | 0 | const gnutls_sign_entry_st *se; |
478 | 0 | gnutls_certificate_verification_profiles_t min_profile; |
479 | |
|
480 | 0 | min_profile = _gnutls_get_system_wide_verification_profile(); |
481 | |
|
482 | 0 | if (min_profile) { |
483 | 0 | if (profile < min_profile) { |
484 | 0 | gnutls_assert(); |
485 | 0 | profile = min_profile; |
486 | 0 | } |
487 | 0 | } |
488 | |
|
489 | 0 | if (profile == GNUTLS_PROFILE_UNKNOWN) { |
490 | 0 | return 1; |
491 | 0 | } |
492 | | |
493 | 0 | pkalg = gnutls_x509_crt_get_pk_algorithm(crt, &bits); |
494 | 0 | if (pkalg < 0) |
495 | 0 | return gnutls_assert_val(0); |
496 | | |
497 | 0 | if (issuer) { |
498 | 0 | issuer_pkalg = |
499 | 0 | gnutls_x509_crt_get_pk_algorithm(issuer, &issuer_bits); |
500 | 0 | if (issuer_pkalg < 0) |
501 | 0 | return gnutls_assert_val(0); |
502 | 0 | } |
503 | | |
504 | 0 | switch (profile) { |
505 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_VERY_WEAK, |
506 | 0 | GNUTLS_SEC_PARAM_VERY_WEAK); |
507 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_LOW, GNUTLS_SEC_PARAM_LOW); |
508 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_LEGACY, GNUTLS_SEC_PARAM_LEGACY); |
509 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_MEDIUM, GNUTLS_SEC_PARAM_MEDIUM); |
510 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_HIGH, GNUTLS_SEC_PARAM_HIGH); |
511 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_ULTRA, GNUTLS_SEC_PARAM_ULTRA); |
512 | 0 | CASE_SEC_PARAM(GNUTLS_PROFILE_FUTURE, GNUTLS_SEC_PARAM_FUTURE); |
513 | 0 | case GNUTLS_PROFILE_SUITEB128: |
514 | 0 | case GNUTLS_PROFILE_SUITEB192:{ |
515 | 0 | unsigned curve, issuer_curve; |
516 | | |
517 | | /* check suiteB params validity: rfc5759 */ |
518 | |
|
519 | 0 | if (gnutls_x509_crt_get_version(crt) != 3) { |
520 | 0 | _gnutls_debug_log |
521 | 0 | ("SUITEB: certificate uses an unacceptable version number\n"); |
522 | 0 | return gnutls_assert_val(0); |
523 | 0 | } |
524 | | |
525 | 0 | if (sigalg != GNUTLS_SIGN_ECDSA_SHA256 |
526 | 0 | && sigalg != GNUTLS_SIGN_ECDSA_SHA384) { |
527 | 0 | _gnutls_debug_log |
528 | 0 | ("SUITEB: certificate is not signed using ECDSA-SHA256 or ECDSA-SHA384\n"); |
529 | 0 | return gnutls_assert_val(0); |
530 | 0 | } |
531 | | |
532 | 0 | if (pkalg != GNUTLS_PK_EC) { |
533 | 0 | _gnutls_debug_log |
534 | 0 | ("SUITEB: certificate does not contain ECC parameters\n"); |
535 | 0 | return gnutls_assert_val(0); |
536 | 0 | } |
537 | | |
538 | 0 | if (issuer_pkalg != GNUTLS_PK_EC) { |
539 | 0 | _gnutls_debug_log |
540 | 0 | ("SUITEB: certificate's issuer does not have ECC parameters\n"); |
541 | 0 | return gnutls_assert_val(0); |
542 | 0 | } |
543 | | |
544 | 0 | ret = _gnutls_x509_crt_get_mpis(crt, ¶ms); |
545 | 0 | if (ret < 0) { |
546 | 0 | _gnutls_debug_log |
547 | 0 | ("SUITEB: cannot read certificate params\n"); |
548 | 0 | return gnutls_assert_val(0); |
549 | 0 | } |
550 | | |
551 | 0 | curve = params.curve; |
552 | 0 | gnutls_pk_params_release(¶ms); |
553 | |
|
554 | 0 | if (curve != GNUTLS_ECC_CURVE_SECP256R1 && |
555 | 0 | curve != GNUTLS_ECC_CURVE_SECP384R1) { |
556 | 0 | _gnutls_debug_log |
557 | 0 | ("SUITEB: certificate's ECC params do not contain SECP256R1 or SECP384R1\n"); |
558 | 0 | return gnutls_assert_val(0); |
559 | 0 | } |
560 | | |
561 | 0 | if (profile == GNUTLS_PROFILE_SUITEB192) { |
562 | 0 | if (curve != GNUTLS_ECC_CURVE_SECP384R1) { |
563 | 0 | _gnutls_debug_log |
564 | 0 | ("SUITEB192: certificate does not use SECP384R1\n"); |
565 | 0 | return gnutls_assert_val(0); |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | 0 | if (issuer != NULL) { |
570 | 0 | if (gnutls_x509_crt_get_version(issuer) != 3) { |
571 | 0 | _gnutls_debug_log |
572 | 0 | ("SUITEB: certificate's issuer uses an unacceptable version number\n"); |
573 | 0 | return gnutls_assert_val(0); |
574 | 0 | } |
575 | | |
576 | 0 | ret = |
577 | 0 | _gnutls_x509_crt_get_mpis(issuer, ¶ms); |
578 | 0 | if (ret < 0) { |
579 | 0 | _gnutls_debug_log |
580 | 0 | ("SUITEB: cannot read certificate params\n"); |
581 | 0 | return gnutls_assert_val(0); |
582 | 0 | } |
583 | | |
584 | 0 | issuer_curve = params.curve; |
585 | 0 | gnutls_pk_params_release(¶ms); |
586 | |
|
587 | 0 | if (issuer_curve != GNUTLS_ECC_CURVE_SECP256R1 |
588 | 0 | && issuer_curve != |
589 | 0 | GNUTLS_ECC_CURVE_SECP384R1) { |
590 | 0 | _gnutls_debug_log |
591 | 0 | ("SUITEB: certificate's issuer ECC params do not contain SECP256R1 or SECP384R1\n"); |
592 | 0 | return gnutls_assert_val(0); |
593 | 0 | } |
594 | | |
595 | 0 | if (issuer_curve < curve) { |
596 | 0 | _gnutls_debug_log |
597 | 0 | ("SUITEB: certificate's issuer ECC params are weaker than the certificate's\n"); |
598 | 0 | return gnutls_assert_val(0); |
599 | 0 | } |
600 | | |
601 | 0 | if (sigalg == GNUTLS_SIGN_ECDSA_SHA256 && |
602 | 0 | issuer_curve == |
603 | 0 | GNUTLS_ECC_CURVE_SECP384R1) { |
604 | 0 | _gnutls_debug_log |
605 | 0 | ("SUITEB: certificate is signed with ECDSA-SHA256 when using SECP384R1\n"); |
606 | 0 | return gnutls_assert_val(0); |
607 | 0 | } |
608 | 0 | } |
609 | | |
610 | 0 | break; |
611 | 0 | case GNUTLS_PROFILE_UNKNOWN: /* already checked; avoid compiler warnings */ |
612 | 0 | _gnutls_debug_log |
613 | 0 | ("An unknown profile (%d) was encountered\n", |
614 | 0 | (int)profile); |
615 | 0 | } |
616 | 0 | } |
617 | | |
618 | 0 | return 1; |
619 | 0 | } |
620 | | |
621 | | typedef struct verify_state_st { |
622 | | time_t now; |
623 | | unsigned int max_path; |
624 | | gnutls_x509_name_constraints_t nc; |
625 | | gnutls_x509_tlsfeatures_t tls_feat; |
626 | | gnutls_verify_output_function *func; |
627 | | } verify_state_st; |
628 | | |
629 | 0 | #define MARK_INVALID(x) { gnutls_assert(); \ |
630 | 0 | out |= (x|GNUTLS_CERT_INVALID); \ |
631 | 0 | result = 0; } |
632 | | |
633 | | static int _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign, |
634 | | const gnutls_datum_t * data, |
635 | | const gnutls_datum_t * signature, |
636 | | gnutls_x509_crt_t cert, |
637 | | gnutls_x509_crt_t issuer, unsigned vflags); |
638 | | |
639 | | /* |
640 | | * Verifies the given certificate against a certificate list of |
641 | | * trusted CAs. |
642 | | * |
643 | | * Returns only 0 or 1. If 1 it means that the certificate |
644 | | * was successfully verified. |
645 | | * |
646 | | * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. |
647 | | * |
648 | | * Output will hold some extra information about the verification |
649 | | * procedure. |
650 | | */ |
651 | | static unsigned verify_crt(gnutls_x509_trust_list_t tlist, |
652 | | gnutls_x509_crt_t cert, |
653 | | const gnutls_x509_crt_t * trusted_cas, |
654 | | int tcas_size, unsigned int flags, |
655 | | unsigned int *output, |
656 | | verify_state_st * vparams, unsigned end_cert) |
657 | 0 | { |
658 | 0 | gnutls_datum_t cert_signed_data = { NULL, 0 }; |
659 | 0 | gnutls_datum_t cert_signature = { NULL, 0 }; |
660 | 0 | gnutls_x509_crt_t issuer = NULL; |
661 | 0 | int issuer_version; |
662 | 0 | unsigned result = 1; |
663 | 0 | unsigned int out = 0, usage; |
664 | 0 | int sigalg, ret; |
665 | 0 | const gnutls_sign_entry_st *se; |
666 | |
|
667 | 0 | if (output) |
668 | 0 | *output = 0; |
669 | |
|
670 | 0 | if (vparams->max_path == 0) { |
671 | 0 | MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
672 | | /* bail immediately, to avoid inconistency */ |
673 | 0 | goto cleanup; |
674 | 0 | } |
675 | 0 | vparams->max_path--; |
676 | |
|
677 | 0 | if (tcas_size >= 1) |
678 | 0 | issuer = find_issuer(cert, trusted_cas, tcas_size); |
679 | |
|
680 | 0 | ret = |
681 | 0 | _gnutls_x509_get_signed_data(cert->cert, &cert->der, |
682 | 0 | "tbsCertificate", &cert_signed_data); |
683 | 0 | if (ret < 0) { |
684 | 0 | MARK_INVALID(0); |
685 | 0 | cert_signed_data.data = NULL; |
686 | 0 | } |
687 | |
|
688 | 0 | ret = |
689 | 0 | _gnutls_x509_get_signature(cert->cert, "signature", |
690 | 0 | &cert_signature); |
691 | 0 | if (ret < 0) { |
692 | 0 | MARK_INVALID(0); |
693 | 0 | cert_signature.data = NULL; |
694 | 0 | } |
695 | |
|
696 | 0 | ret = |
697 | 0 | _gnutls_x509_get_signature_algorithm(cert->cert, |
698 | 0 | "signatureAlgorithm"); |
699 | 0 | if (ret < 0) { |
700 | 0 | MARK_INVALID(0); |
701 | 0 | } |
702 | 0 | sigalg = ret; |
703 | |
|
704 | 0 | se = _gnutls_sign_to_entry(sigalg); |
705 | | |
706 | | /* issuer is not in trusted certificate |
707 | | * authorities. |
708 | | */ |
709 | 0 | if (issuer == NULL) { |
710 | 0 | MARK_INVALID(GNUTLS_CERT_SIGNER_NOT_FOUND); |
711 | 0 | } else { |
712 | 0 | if (vparams->nc != NULL) { |
713 | | /* append the issuer's constraints */ |
714 | 0 | ret = |
715 | 0 | gnutls_x509_crt_get_name_constraints(issuer, |
716 | 0 | vparams->nc, |
717 | 0 | GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, |
718 | 0 | NULL); |
719 | 0 | if (ret < 0 |
720 | 0 | && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
721 | 0 | MARK_INVALID |
722 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
723 | 0 | goto nc_done; |
724 | 0 | } |
725 | | |
726 | | /* only check name constraints in server certificates, not CAs */ |
727 | 0 | if (end_cert != 0) { |
728 | 0 | ret = |
729 | 0 | gnutls_x509_name_constraints_check_crt |
730 | 0 | (vparams->nc, GNUTLS_SAN_DNSNAME, cert); |
731 | 0 | if (ret == 0) { |
732 | 0 | MARK_INVALID |
733 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
734 | 0 | goto nc_done; |
735 | 0 | } |
736 | | |
737 | 0 | ret = |
738 | 0 | gnutls_x509_name_constraints_check_crt |
739 | 0 | (vparams->nc, GNUTLS_SAN_RFC822NAME, cert); |
740 | 0 | if (ret == 0) { |
741 | 0 | MARK_INVALID |
742 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
743 | 0 | goto nc_done; |
744 | 0 | } |
745 | | |
746 | 0 | ret = |
747 | 0 | gnutls_x509_name_constraints_check_crt |
748 | 0 | (vparams->nc, GNUTLS_SAN_DN, cert); |
749 | 0 | if (ret == 0) { |
750 | 0 | MARK_INVALID |
751 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
752 | 0 | goto nc_done; |
753 | 0 | } |
754 | | |
755 | 0 | ret = |
756 | 0 | gnutls_x509_name_constraints_check_crt |
757 | 0 | (vparams->nc, GNUTLS_SAN_URI, cert); |
758 | 0 | if (ret == 0) { |
759 | 0 | MARK_INVALID |
760 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
761 | 0 | goto nc_done; |
762 | 0 | } |
763 | | |
764 | 0 | ret = |
765 | 0 | gnutls_x509_name_constraints_check_crt |
766 | 0 | (vparams->nc, GNUTLS_SAN_IPADDRESS, cert); |
767 | 0 | if (ret == 0) { |
768 | 0 | MARK_INVALID |
769 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
770 | 0 | goto nc_done; |
771 | 0 | } |
772 | 0 | } |
773 | 0 | } |
774 | | |
775 | 0 | nc_done: |
776 | 0 | if (vparams->tls_feat != NULL) { |
777 | | /* append the issuer's constraints */ |
778 | 0 | ret = |
779 | 0 | gnutls_x509_crt_get_tlsfeatures(issuer, |
780 | 0 | vparams->tls_feat, |
781 | 0 | GNUTLS_EXT_FLAG_APPEND, |
782 | 0 | NULL); |
783 | 0 | if (ret < 0 |
784 | 0 | && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
785 | 0 | MARK_INVALID |
786 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
787 | 0 | goto feat_done; |
788 | 0 | } |
789 | | |
790 | 0 | ret = |
791 | 0 | gnutls_x509_tlsfeatures_check_crt(vparams->tls_feat, |
792 | 0 | cert); |
793 | 0 | if (ret == 0) { |
794 | 0 | MARK_INVALID |
795 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
796 | 0 | goto feat_done; |
797 | 0 | } |
798 | 0 | } |
799 | | |
800 | 0 | feat_done: |
801 | 0 | issuer_version = gnutls_x509_crt_get_version(issuer); |
802 | |
|
803 | 0 | if (issuer_version < 0) { |
804 | 0 | MARK_INVALID(0); |
805 | 0 | } else if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && |
806 | 0 | ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) |
807 | 0 | || issuer_version != 1)) { |
808 | 0 | if (check_if_ca(cert, issuer, &vparams->max_path, flags) |
809 | 0 | != 1) { |
810 | 0 | MARK_INVALID(GNUTLS_CERT_SIGNER_NOT_CA); |
811 | 0 | } |
812 | |
|
813 | 0 | ret = |
814 | 0 | gnutls_x509_crt_get_key_usage(issuer, &usage, NULL); |
815 | 0 | if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
816 | 0 | if (ret < 0) { |
817 | 0 | MARK_INVALID(0); |
818 | 0 | } else if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) { |
819 | 0 | MARK_INVALID |
820 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
821 | 0 | } |
822 | 0 | } |
823 | 0 | } |
824 | |
|
825 | 0 | if (sigalg < 0) { |
826 | 0 | MARK_INVALID(0); |
827 | 0 | } else if (cert_signed_data.data != NULL && |
828 | 0 | cert_signature.data != NULL) { |
829 | 0 | ret = |
830 | 0 | _gnutls_x509_verify_data(sigalg, |
831 | 0 | &cert_signed_data, |
832 | 0 | &cert_signature, |
833 | 0 | cert, issuer, flags); |
834 | |
|
835 | 0 | if (ret == GNUTLS_E_PK_SIG_VERIFY_FAILED) { |
836 | 0 | MARK_INVALID(GNUTLS_CERT_SIGNATURE_FAILURE); |
837 | 0 | } else if (ret == GNUTLS_E_CONSTRAINT_ERROR) { |
838 | 0 | MARK_INVALID |
839 | 0 | (GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE); |
840 | 0 | } else if (ret < 0) { |
841 | 0 | MARK_INVALID(0); |
842 | 0 | } |
843 | 0 | } |
844 | 0 | } |
845 | | |
846 | | /* we always check the issuer for unsupported critical extensions */ |
847 | 0 | if (issuer && check_for_unknown_exts(issuer) != 0) { |
848 | 0 | if (!(flags & GNUTLS_VERIFY_IGNORE_UNKNOWN_CRIT_EXTENSIONS)) { |
849 | 0 | MARK_INVALID(GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS); |
850 | 0 | } |
851 | 0 | } |
852 | | |
853 | | /* we only check the end-certificate for critical extensions; that |
854 | | * way do not perform this check twice on the certificates when |
855 | | * verifying a large list */ |
856 | 0 | if (end_cert && check_for_unknown_exts(cert) != 0) { |
857 | 0 | if (!(flags & GNUTLS_VERIFY_IGNORE_UNKNOWN_CRIT_EXTENSIONS)) { |
858 | 0 | MARK_INVALID(GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS); |
859 | 0 | } |
860 | 0 | } |
861 | |
|
862 | 0 | if (sigalg >= 0 && se) { |
863 | 0 | if (is_level_acceptable(cert, issuer, sigalg, false, flags) == |
864 | 0 | 0) { |
865 | 0 | MARK_INVALID(GNUTLS_CERT_INSECURE_ALGORITHM); |
866 | 0 | } |
867 | | |
868 | | /* If the certificate is not self signed check if the algorithms |
869 | | * used are secure. If the certificate is self signed it doesn't |
870 | | * really matter. |
871 | | */ |
872 | 0 | if (_gnutls_sign_is_secure2 |
873 | 0 | (se, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0 |
874 | 0 | && _gnutls_is_broken_sig_allowed(se, flags) == 0 |
875 | 0 | && is_issuer(cert, cert) == 0) { |
876 | 0 | MARK_INVALID(GNUTLS_CERT_INSECURE_ALGORITHM); |
877 | 0 | } |
878 | 0 | } |
879 | | |
880 | | /* Check activation/expiration times |
881 | | */ |
882 | 0 | if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) { |
883 | | /* check the time of the issuer first */ |
884 | 0 | if (issuer != NULL && |
885 | 0 | !(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS)) { |
886 | 0 | out |= check_time_status(issuer, vparams->now); |
887 | 0 | if (out != 0) { |
888 | 0 | gnutls_assert(); |
889 | 0 | result = 0; |
890 | 0 | } |
891 | 0 | } |
892 | |
|
893 | 0 | out |= check_time_status(cert, vparams->now); |
894 | 0 | if (out != 0) { |
895 | 0 | gnutls_assert(); |
896 | 0 | result = 0; |
897 | 0 | } |
898 | 0 | } |
899 | |
|
900 | 0 | cleanup: |
901 | 0 | if (output) |
902 | 0 | *output |= out; |
903 | |
|
904 | 0 | if (vparams->func) { |
905 | 0 | if (result == 0) { |
906 | 0 | out |= GNUTLS_CERT_INVALID; |
907 | 0 | } |
908 | 0 | vparams->func(cert, issuer, NULL, out); |
909 | 0 | } |
910 | 0 | _gnutls_free_datum(&cert_signed_data); |
911 | 0 | _gnutls_free_datum(&cert_signature); |
912 | |
|
913 | 0 | return result; |
914 | 0 | } |
915 | | |
916 | | /** |
917 | | * gnutls_x509_crt_check_issuer: |
918 | | * @cert: is the certificate to be checked |
919 | | * @issuer: is the certificate of a possible issuer |
920 | | * |
921 | | * This function will check if the given certificate was issued by the |
922 | | * given issuer. It checks the DN fields and the authority |
923 | | * key identifier and subject key identifier fields match. |
924 | | * |
925 | | * If the same certificate is provided at the @cert and @issuer fields, |
926 | | * it will check whether the certificate is self-signed. |
927 | | * |
928 | | * Returns: It will return true (1) if the given certificate is issued |
929 | | * by the given issuer, and false (0) if not. |
930 | | **/ |
931 | | unsigned |
932 | | gnutls_x509_crt_check_issuer(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer) |
933 | 0 | { |
934 | 0 | return is_issuer(cert, issuer); |
935 | 0 | } |
936 | | |
937 | | static |
938 | | unsigned check_ca_sanity(const gnutls_x509_crt_t issuer, |
939 | | time_t now, unsigned int flags) |
940 | 0 | { |
941 | 0 | unsigned int status = 0; |
942 | 0 | unsigned sigalg; |
943 | 0 | int ret; |
944 | | |
945 | | /* explicit time check for trusted CA that we remove from |
946 | | * list. GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS |
947 | | */ |
948 | 0 | if (!(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS) && |
949 | 0 | !(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) { |
950 | 0 | status |= check_time_status(issuer, now); |
951 | 0 | } |
952 | |
|
953 | 0 | ret = |
954 | 0 | _gnutls_x509_get_signature_algorithm(issuer->cert, |
955 | 0 | "signatureAlgorithm"); |
956 | 0 | sigalg = ret; |
957 | | |
958 | | /* we explicitly allow CAs which we do not support their self-algorithms |
959 | | * to pass. */ |
960 | 0 | if (ret >= 0 && !is_level_acceptable(issuer, NULL, sigalg, true, flags)) { |
961 | 0 | status |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; |
962 | 0 | } |
963 | |
|
964 | 0 | return status; |
965 | |
|
966 | 0 | } |
967 | | |
968 | | /* Verify X.509 certificate chain. |
969 | | * |
970 | | * Note that the return value is an OR of GNUTLS_CERT_* elements. |
971 | | * |
972 | | * This function verifies a X.509 certificate list. The certificate |
973 | | * list should lead to a trusted certificate in order to be trusted. |
974 | | */ |
975 | | unsigned int |
976 | | _gnutls_verify_crt_status(gnutls_x509_trust_list_t tlist, |
977 | | const gnutls_x509_crt_t * certificate_list, |
978 | | int clist_size, |
979 | | const gnutls_x509_crt_t * trusted_cas, |
980 | | int tcas_size, |
981 | | unsigned int flags, |
982 | | const char *purpose, |
983 | | gnutls_verify_output_function func) |
984 | 0 | { |
985 | 0 | int i = 0, ret; |
986 | 0 | unsigned int status = 0, output; |
987 | 0 | time_t now = gnutls_time(0); |
988 | 0 | verify_state_st vparams; |
989 | |
|
990 | 0 | if (clist_size > 1) { |
991 | | /* Check if the last certificate in the path is self signed. |
992 | | * In that case ignore it (a certificate is trusted only if it |
993 | | * leads to a trusted party by us, not the server's). |
994 | | * |
995 | | * This prevents from verifying self signed certificates against |
996 | | * themselves. This (although not bad) caused verification |
997 | | * failures on some root self signed certificates that use the |
998 | | * MD2 algorithm. |
999 | | */ |
1000 | 0 | if (gnutls_x509_crt_check_issuer |
1001 | 0 | (certificate_list[clist_size - 1], |
1002 | 0 | certificate_list[clist_size - 1]) != 0) { |
1003 | 0 | clist_size--; |
1004 | 0 | } |
1005 | 0 | } |
1006 | | |
1007 | | /* We want to shorten the chain by removing the cert that matches |
1008 | | * one of the certs we trust and all the certs after that i.e. if |
1009 | | * cert chain is A signed-by B signed-by C signed-by D (signed-by |
1010 | | * self-signed E but already removed above), and we trust B, remove |
1011 | | * B, C and D. */ |
1012 | 0 | if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) |
1013 | 0 | i = 0; /* also replace the first one */ |
1014 | 0 | else |
1015 | 0 | i = 1; /* do not replace the first one */ |
1016 | |
|
1017 | 0 | for (; i < clist_size; i++) { |
1018 | 0 | int j; |
1019 | |
|
1020 | 0 | for (j = 0; j < tcas_size; j++) { |
1021 | | /* we check for a certificate that may not be identical with the one |
1022 | | * sent by the client, but will have the same name and key. That is |
1023 | | * because it can happen that a CA certificate is upgraded from intermediate |
1024 | | * CA to self-signed CA at some point. */ |
1025 | 0 | if (_gnutls_check_if_same_key |
1026 | 0 | (certificate_list[i], trusted_cas[j], i) != 0) { |
1027 | |
|
1028 | 0 | status |= |
1029 | 0 | check_ca_sanity(trusted_cas[j], now, flags); |
1030 | |
|
1031 | 0 | if (func) |
1032 | 0 | func(certificate_list[i], |
1033 | 0 | trusted_cas[j], NULL, status); |
1034 | |
|
1035 | 0 | if (status != 0) { |
1036 | 0 | return gnutls_assert_val(status); |
1037 | 0 | } |
1038 | | |
1039 | 0 | clist_size = i; |
1040 | 0 | break; |
1041 | 0 | } |
1042 | 0 | } |
1043 | | /* clist_size may have been changed which gets out of loop */ |
1044 | 0 | } |
1045 | | |
1046 | 0 | if (clist_size == 0) { |
1047 | | /* The certificate is already present in the trusted certificate list. |
1048 | | * Nothing to verify. */ |
1049 | 0 | return status; |
1050 | 0 | } |
1051 | | |
1052 | 0 | memset(&vparams, 0, sizeof(vparams)); |
1053 | 0 | vparams.now = now; |
1054 | 0 | vparams.max_path = MAX_VERIFY_DEPTH; |
1055 | 0 | vparams.func = func; |
1056 | |
|
1057 | 0 | ret = gnutls_x509_name_constraints_init(&vparams.nc); |
1058 | 0 | if (ret < 0) { |
1059 | 0 | gnutls_assert(); |
1060 | 0 | status |= GNUTLS_CERT_INVALID; |
1061 | 0 | return status; |
1062 | 0 | } |
1063 | | |
1064 | 0 | ret = gnutls_x509_tlsfeatures_init(&vparams.tls_feat); |
1065 | 0 | if (ret < 0) { |
1066 | 0 | gnutls_assert(); |
1067 | 0 | status |= GNUTLS_CERT_INVALID; |
1068 | 0 | goto cleanup; |
1069 | 0 | } |
1070 | | |
1071 | | /* Verify the last certificate in the certificate path |
1072 | | * against the trusted CA certificate list. |
1073 | | * |
1074 | | * If no CAs are present returns CERT_INVALID. Thus works |
1075 | | * in self signed etc certificates. |
1076 | | */ |
1077 | 0 | output = 0; |
1078 | |
|
1079 | 0 | ret = verify_crt(tlist, |
1080 | 0 | certificate_list[clist_size - 1], |
1081 | 0 | trusted_cas, tcas_size, flags, |
1082 | 0 | &output, &vparams, clist_size == 1 ? 1 : 0); |
1083 | 0 | if (ret != 1) { |
1084 | | /* if the last certificate in the certificate |
1085 | | * list is invalid, then the certificate is not |
1086 | | * trusted. |
1087 | | */ |
1088 | 0 | gnutls_assert(); |
1089 | 0 | status |= output; |
1090 | 0 | status |= GNUTLS_CERT_INVALID; |
1091 | 0 | goto cleanup; |
1092 | 0 | } |
1093 | | |
1094 | | /* Verify the certificate path (chain) |
1095 | | */ |
1096 | 0 | for (i = clist_size - 1; i > 0; i--) { |
1097 | 0 | output = 0; |
1098 | |
|
1099 | 0 | if (purpose != NULL) { |
1100 | 0 | ret = |
1101 | 0 | _gnutls_check_key_purpose(certificate_list[i], |
1102 | 0 | purpose, 1); |
1103 | 0 | if (ret != 1) { |
1104 | 0 | gnutls_assert(); |
1105 | 0 | status |= GNUTLS_CERT_INVALID; |
1106 | 0 | status |= GNUTLS_CERT_PURPOSE_MISMATCH; |
1107 | |
|
1108 | 0 | if (func) |
1109 | 0 | func(certificate_list[i - 1], |
1110 | 0 | certificate_list[i], NULL, status); |
1111 | 0 | goto cleanup; |
1112 | 0 | } |
1113 | 0 | } |
1114 | | |
1115 | | /* note that here we disable this V1 CA flag. So that no version 1 |
1116 | | * certificates can exist in a supplied chain. |
1117 | | */ |
1118 | 0 | if (!(flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT)) { |
1119 | 0 | flags |= GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT; |
1120 | 0 | } |
1121 | |
|
1122 | 0 | if (!verify_crt(tlist, |
1123 | 0 | certificate_list[i - 1], |
1124 | 0 | &certificate_list[i], 1, |
1125 | 0 | flags, &output, &vparams, i == 1 ? 1 : 0)) { |
1126 | 0 | gnutls_assert(); |
1127 | 0 | status |= output; |
1128 | 0 | status |= GNUTLS_CERT_INVALID; |
1129 | 0 | goto cleanup; |
1130 | 0 | } |
1131 | 0 | } |
1132 | | |
1133 | 0 | cleanup: |
1134 | 0 | gnutls_x509_name_constraints_deinit(vparams.nc); |
1135 | 0 | gnutls_x509_tlsfeatures_deinit(vparams.tls_feat); |
1136 | 0 | return status; |
1137 | 0 | } |
1138 | | |
1139 | 0 | #define PURPOSE_NSSGC "2.16.840.1.113730.4.1" |
1140 | 0 | #define PURPOSE_VSGC "2.16.840.1.113733.1.8.1" |
1141 | | |
1142 | | /* Returns true if the provided purpose is in accordance with the certificate. |
1143 | | */ |
1144 | | unsigned _gnutls_check_key_purpose(gnutls_x509_crt_t cert, const char *purpose, |
1145 | | unsigned no_any) |
1146 | 0 | { |
1147 | 0 | char oid[MAX_OID_SIZE]; |
1148 | 0 | size_t oid_size; |
1149 | 0 | int ret; |
1150 | 0 | unsigned critical = 0; |
1151 | 0 | unsigned check_obsolete_oids = 0; |
1152 | 0 | unsigned i; |
1153 | | |
1154 | | /* The check_obsolete_oids hack is because of certain very old CA certificates |
1155 | | * around which instead of having the GNUTLS_KP_TLS_WWW_SERVER have some old |
1156 | | * OIDs for that purpose. Assume these OIDs equal GNUTLS_KP_TLS_WWW_SERVER in |
1157 | | * CA certs */ |
1158 | 0 | if (strcmp(purpose, GNUTLS_KP_TLS_WWW_SERVER) == 0) { |
1159 | 0 | unsigned ca_status; |
1160 | 0 | ret = |
1161 | 0 | gnutls_x509_crt_get_basic_constraints(cert, NULL, |
1162 | 0 | &ca_status, NULL); |
1163 | 0 | if (ret < 0) |
1164 | 0 | ca_status = 0; |
1165 | |
|
1166 | 0 | if (ca_status) |
1167 | 0 | check_obsolete_oids = 1; |
1168 | 0 | } |
1169 | |
|
1170 | 0 | for (i = 0;; i++) { |
1171 | 0 | oid_size = sizeof(oid); |
1172 | 0 | ret = |
1173 | 0 | gnutls_x509_crt_get_key_purpose_oid(cert, i, oid, &oid_size, |
1174 | 0 | &critical); |
1175 | 0 | if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1176 | 0 | if (i == 0) { |
1177 | | /* no key purpose in certificate, assume ANY */ |
1178 | 0 | return 1; |
1179 | 0 | } else { |
1180 | 0 | gnutls_assert(); |
1181 | 0 | break; |
1182 | 0 | } |
1183 | 0 | } else if (ret < 0) { |
1184 | 0 | gnutls_assert(); |
1185 | 0 | break; |
1186 | 0 | } |
1187 | | |
1188 | 0 | if (check_obsolete_oids) { |
1189 | 0 | if (strcmp(oid, PURPOSE_NSSGC) == 0) { |
1190 | 0 | return 1; |
1191 | 0 | } else if (strcmp(oid, PURPOSE_VSGC) == 0) { |
1192 | 0 | return 1; |
1193 | 0 | } |
1194 | 0 | } |
1195 | | |
1196 | 0 | if (strcmp(oid, purpose) == 0 |
1197 | 0 | || (no_any == 0 && strcmp(oid, GNUTLS_KP_ANY) == 0)) { |
1198 | 0 | return 1; |
1199 | 0 | } |
1200 | 0 | _gnutls_debug_log |
1201 | 0 | ("looking for key purpose '%s', but have '%s'\n", purpose, |
1202 | 0 | oid); |
1203 | 0 | } |
1204 | 0 | return 0; |
1205 | 0 | } |
1206 | | |
1207 | | #ifdef ENABLE_PKCS11 |
1208 | | /* Verify X.509 certificate chain using a PKCS #11 token. |
1209 | | * |
1210 | | * Note that the return value is an OR of GNUTLS_CERT_* elements. |
1211 | | * |
1212 | | * Unlike the non-PKCS#11 version, this function accepts a key purpose |
1213 | | * (from GNUTLS_KP_...). That is because in the p11-kit trust modules |
1214 | | * anchors are mixed and get assigned a purpose. |
1215 | | * |
1216 | | * This function verifies a X.509 certificate list. The certificate |
1217 | | * list should lead to a trusted certificate in order to be trusted. |
1218 | | */ |
1219 | | unsigned int |
1220 | | _gnutls_pkcs11_verify_crt_status(gnutls_x509_trust_list_t tlist, |
1221 | | const char *url, |
1222 | | const gnutls_x509_crt_t * certificate_list, |
1223 | | unsigned clist_size, |
1224 | | const char *purpose, |
1225 | | unsigned int flags, |
1226 | | gnutls_verify_output_function func) |
1227 | | { |
1228 | | int ret; |
1229 | | unsigned int status = 0, i; |
1230 | | gnutls_x509_crt_t issuer = NULL; |
1231 | | gnutls_datum_t raw_issuer = { NULL, 0 }; |
1232 | | time_t now = gnutls_time(0); |
1233 | | time_t distrust_after; |
1234 | | |
1235 | | if (clist_size > 1) { |
1236 | | /* Check if the last certificate in the path is self signed. |
1237 | | * In that case ignore it (a certificate is trusted only if it |
1238 | | * leads to a trusted party by us, not the server's). |
1239 | | * |
1240 | | * This prevents from verifying self signed certificates against |
1241 | | * themselves. This (although not bad) caused verification |
1242 | | * failures on some root self signed certificates that use the |
1243 | | * MD2 algorithm. |
1244 | | */ |
1245 | | if (gnutls_x509_crt_check_issuer |
1246 | | (certificate_list[clist_size - 1], |
1247 | | certificate_list[clist_size - 1]) != 0) { |
1248 | | clist_size--; |
1249 | | } |
1250 | | } |
1251 | | |
1252 | | /* We want to shorten the chain by removing the cert that matches |
1253 | | * one of the certs we trust and all the certs after that i.e. if |
1254 | | * cert chain is A signed-by B signed-by C signed-by D (signed-by |
1255 | | * self-signed E but already removed above), and we trust B, remove |
1256 | | * B, C and D. */ |
1257 | | if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) |
1258 | | i = 0; /* also replace the first one */ |
1259 | | else |
1260 | | i = 1; /* do not replace the first one */ |
1261 | | |
1262 | | for (; i < clist_size; i++) { |
1263 | | unsigned vflags; |
1264 | | gnutls_x509_crt_t trusted_cert; |
1265 | | |
1266 | | if (i == 0) /* in the end certificate do full comparison */ |
1267 | | vflags = |
1268 | | GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE | |
1269 | | GNUTLS_PKCS11_OBJ_FLAG_COMPARE | |
1270 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED; |
1271 | | else |
1272 | | vflags = |
1273 | | GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE | |
1274 | | GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY | |
1275 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED; |
1276 | | |
1277 | | if (_gnutls_pkcs11_crt_is_known |
1278 | | (url, certificate_list[i], vflags, &trusted_cert) != 0) { |
1279 | | |
1280 | | status |= check_ca_sanity(trusted_cert, now, flags); |
1281 | | |
1282 | | if (func) |
1283 | | func(trusted_cert, |
1284 | | certificate_list[i], NULL, status); |
1285 | | |
1286 | | gnutls_x509_crt_deinit(trusted_cert); |
1287 | | |
1288 | | if (status != 0) { |
1289 | | return gnutls_assert_val(status); |
1290 | | } |
1291 | | |
1292 | | clist_size = i; |
1293 | | break; |
1294 | | } |
1295 | | /* clist_size may have been changed which gets out of loop */ |
1296 | | } |
1297 | | |
1298 | | if (clist_size == 0) { |
1299 | | /* The certificate is already present in the trusted certificate list. |
1300 | | * Nothing to verify. */ |
1301 | | return status; |
1302 | | } |
1303 | | |
1304 | | /* check for blocklists */ |
1305 | | for (i = 0; i < clist_size; i++) { |
1306 | | if (gnutls_pkcs11_crt_is_known(url, certificate_list[i], |
1307 | | GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE |
1308 | | | |
1309 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) |
1310 | | != 0) { |
1311 | | status |= GNUTLS_CERT_INVALID; |
1312 | | status |= GNUTLS_CERT_REVOKED; |
1313 | | if (func) |
1314 | | func(certificate_list[i], certificate_list[i], |
1315 | | NULL, status); |
1316 | | goto cleanup; |
1317 | | } |
1318 | | } |
1319 | | |
1320 | | /* check against issuer */ |
1321 | | ret = |
1322 | | gnutls_pkcs11_get_raw_issuer(url, certificate_list[clist_size - 1], |
1323 | | &raw_issuer, GNUTLS_X509_FMT_DER, |
1324 | | GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT |
1325 | | | |
1326 | | GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE); |
1327 | | if (ret < 0) { |
1328 | | gnutls_assert(); |
1329 | | if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE |
1330 | | && clist_size > 2) { |
1331 | | |
1332 | | /* check if the last certificate in the chain is present |
1333 | | * in our trusted list, and if yes, verify against it. */ |
1334 | | ret = |
1335 | | gnutls_pkcs11_crt_is_known(url, |
1336 | | certificate_list |
1337 | | [clist_size - 1], |
1338 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED |
1339 | | | |
1340 | | GNUTLS_PKCS11_OBJ_FLAG_COMPARE); |
1341 | | if (ret != 0) { |
1342 | | return _gnutls_verify_crt_status(tlist, |
1343 | | certificate_list, |
1344 | | clist_size, |
1345 | | &certificate_list |
1346 | | [clist_size - |
1347 | | 1], 1, flags, |
1348 | | purpose, func); |
1349 | | } |
1350 | | } |
1351 | | |
1352 | | status |= GNUTLS_CERT_INVALID; |
1353 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; |
1354 | | /* verify the certificate list against 0 trusted CAs in order |
1355 | | * to get, any additional flags from the certificate list (e.g., |
1356 | | * insecure algorithms or expired */ |
1357 | | status |= |
1358 | | _gnutls_verify_crt_status(tlist, certificate_list, |
1359 | | clist_size, NULL, 0, flags, |
1360 | | purpose, func); |
1361 | | goto cleanup; |
1362 | | } |
1363 | | |
1364 | | ret = gnutls_x509_crt_init(&issuer); |
1365 | | if (ret < 0) { |
1366 | | gnutls_assert(); |
1367 | | status |= GNUTLS_CERT_INVALID; |
1368 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; |
1369 | | goto cleanup; |
1370 | | } |
1371 | | |
1372 | | ret = gnutls_x509_crt_import(issuer, &raw_issuer, GNUTLS_X509_FMT_DER); |
1373 | | if (ret < 0) { |
1374 | | gnutls_assert(); |
1375 | | status |= GNUTLS_CERT_INVALID; |
1376 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; |
1377 | | goto cleanup; |
1378 | | } |
1379 | | |
1380 | | /* check if the raw issuer is assigned with a time-based |
1381 | | * distrust and the certificate is issued after that period |
1382 | | */ |
1383 | | distrust_after = |
1384 | | _gnutls_pkcs11_get_distrust_after(url, issuer, |
1385 | | purpose == NULL ? |
1386 | | GNUTLS_KP_TLS_WWW_SERVER : |
1387 | | purpose, |
1388 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED); |
1389 | | if (distrust_after != (time_t) - 1 |
1390 | | && distrust_after < |
1391 | | gnutls_x509_crt_get_activation_time(certificate_list |
1392 | | [clist_size - 1])) { |
1393 | | gnutls_assert(); |
1394 | | status |= GNUTLS_CERT_INVALID; |
1395 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; |
1396 | | goto cleanup; |
1397 | | } |
1398 | | |
1399 | | /* check if the raw issuer is distrusted (it can happen if |
1400 | | * the issuer is both in the trusted list and the distrusted) |
1401 | | */ |
1402 | | if (gnutls_pkcs11_crt_is_known(url, issuer, |
1403 | | GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE |
1404 | | | |
1405 | | GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED) |
1406 | | != 0) { |
1407 | | status |= GNUTLS_CERT_INVALID; |
1408 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; /* if the signer is revoked - it is as if it doesn't exist */ |
1409 | | goto cleanup; |
1410 | | } |
1411 | | |
1412 | | /* security modules that provide trust, bundle all certificates (of all purposes) |
1413 | | * together. In software that doesn't specify any purpose assume the default to |
1414 | | * be www-server. */ |
1415 | | ret = |
1416 | | _gnutls_check_key_purpose(issuer, |
1417 | | purpose == |
1418 | | NULL ? GNUTLS_KP_TLS_WWW_SERVER : purpose, |
1419 | | 0); |
1420 | | if (ret != 1) { |
1421 | | gnutls_assert(); |
1422 | | status |= GNUTLS_CERT_INVALID; |
1423 | | status |= GNUTLS_CERT_SIGNER_NOT_FOUND; |
1424 | | goto cleanup; |
1425 | | } |
1426 | | |
1427 | | status = _gnutls_verify_crt_status(tlist, certificate_list, clist_size, |
1428 | | &issuer, 1, flags, purpose, func); |
1429 | | |
1430 | | cleanup: |
1431 | | gnutls_free(raw_issuer.data); |
1432 | | if (issuer != NULL) |
1433 | | gnutls_x509_crt_deinit(issuer); |
1434 | | |
1435 | | return status; |
1436 | | } |
1437 | | #endif |
1438 | | |
1439 | | static int |
1440 | | _gnutls_x509_validate_sign_params(gnutls_pk_algorithm_t pk_algorithm, |
1441 | | asn1_node cert, |
1442 | | const char *name, |
1443 | | gnutls_x509_spki_st * sig_params) |
1444 | 0 | { |
1445 | | /* The signature parameter validation is only needed for RSA-PSS */ |
1446 | 0 | if (pk_algorithm == GNUTLS_PK_RSA_PSS) { |
1447 | 0 | int result; |
1448 | 0 | gnutls_x509_spki_st params; |
1449 | |
|
1450 | 0 | result = _gnutls_x509_read_sign_params(cert, name, ¶ms); |
1451 | 0 | if (result < 0) { |
1452 | | /* If parameters field is absent, no parameter |
1453 | | * validation is needed */ |
1454 | 0 | if (result != GNUTLS_E_ASN1_ELEMENT_NOT_FOUND && |
1455 | 0 | result != GNUTLS_E_ASN1_VALUE_NOT_FOUND) { |
1456 | 0 | gnutls_assert(); |
1457 | 0 | return result; |
1458 | 0 | } |
1459 | 0 | } else { |
1460 | | /* Check if the underlying hash algorithms are same. */ |
1461 | 0 | if (sig_params->rsa_pss_dig != params.rsa_pss_dig) { |
1462 | 0 | gnutls_assert(); |
1463 | 0 | return GNUTLS_E_CONSTRAINT_ERROR; |
1464 | 0 | } |
1465 | | |
1466 | | /* The salt length used to generate the |
1467 | | * signature must be equal to or larger than |
1468 | | * the one in the key parameter. */ |
1469 | 0 | if (sig_params->salt_size < params.salt_size) { |
1470 | 0 | gnutls_assert(); |
1471 | 0 | return GNUTLS_E_CONSTRAINT_ERROR; |
1472 | 0 | } |
1473 | 0 | } |
1474 | 0 | } |
1475 | 0 | return 0; |
1476 | 0 | } |
1477 | | |
1478 | | /* verifies if the certificate is properly signed. |
1479 | | * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success. |
1480 | | * |
1481 | | * 'data' is the signed data |
1482 | | * 'signature' is the signature! |
1483 | | */ |
1484 | | static int |
1485 | | _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign, |
1486 | | const gnutls_datum_t * data, |
1487 | | const gnutls_datum_t * signature, |
1488 | | gnutls_x509_crt_t cert, |
1489 | | gnutls_x509_crt_t issuer, unsigned vflags) |
1490 | 0 | { |
1491 | 0 | gnutls_pk_params_st params; |
1492 | 0 | gnutls_pk_algorithm_t issuer_pk; |
1493 | 0 | int ret; |
1494 | 0 | gnutls_x509_spki_st sign_params; |
1495 | 0 | const gnutls_sign_entry_st *se; |
1496 | | |
1497 | | /* Read the MPI parameters from the issuer's certificate. |
1498 | | */ |
1499 | 0 | ret = _gnutls_x509_crt_get_mpis(issuer, ¶ms); |
1500 | 0 | if (ret < 0) { |
1501 | 0 | gnutls_assert(); |
1502 | 0 | return ret; |
1503 | 0 | } |
1504 | | |
1505 | 0 | issuer_pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL); |
1506 | |
|
1507 | 0 | se = _gnutls_sign_to_entry(sign); |
1508 | 0 | if (se == NULL) |
1509 | 0 | return |
1510 | 0 | gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); |
1511 | | |
1512 | 0 | if (cert != NULL) { |
1513 | 0 | ret = _gnutls_x509_read_sign_params(cert->cert, |
1514 | 0 | "signatureAlgorithm", |
1515 | 0 | &sign_params); |
1516 | 0 | if (ret < 0) { |
1517 | 0 | gnutls_assert(); |
1518 | 0 | goto cleanup; |
1519 | 0 | } |
1520 | | |
1521 | 0 | ret = _gnutls_x509_validate_sign_params(issuer_pk, |
1522 | 0 | issuer->cert, |
1523 | 0 | "tbsCertificate." |
1524 | 0 | "subjectPublicKeyInfo." |
1525 | 0 | "algorithm", |
1526 | 0 | &sign_params); |
1527 | 0 | if (ret < 0) { |
1528 | 0 | gnutls_assert(); |
1529 | 0 | goto cleanup; |
1530 | 0 | } |
1531 | 0 | } else { |
1532 | 0 | memcpy(&sign_params, ¶ms.spki, sizeof(gnutls_x509_spki_st)); |
1533 | |
|
1534 | 0 | sign_params.pk = se->pk; |
1535 | 0 | if (sign_params.pk == GNUTLS_PK_RSA_PSS) |
1536 | 0 | sign_params.rsa_pss_dig = se->hash; |
1537 | 0 | } |
1538 | | |
1539 | 0 | ret = |
1540 | 0 | pubkey_verify_data(se, hash_to_entry(se->hash), data, signature, |
1541 | 0 | ¶ms, &sign_params, vflags); |
1542 | 0 | if (ret < 0) { |
1543 | 0 | gnutls_assert(); |
1544 | 0 | } |
1545 | |
|
1546 | 0 | cleanup: |
1547 | | /* release all allocated MPIs |
1548 | | */ |
1549 | 0 | gnutls_pk_params_release(¶ms); |
1550 | |
|
1551 | 0 | return ret; |
1552 | 0 | } |
1553 | | |
1554 | | /** |
1555 | | * gnutls_x509_crt_list_verify: |
1556 | | * @cert_list: is the certificate list to be verified |
1557 | | * @cert_list_length: holds the number of certificate in cert_list |
1558 | | * @CA_list: is the CA list which will be used in verification |
1559 | | * @CA_list_length: holds the number of CA certificate in CA_list |
1560 | | * @CRL_list: holds a list of CRLs. |
1561 | | * @CRL_list_length: the length of CRL list. |
1562 | | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. |
1563 | | * @verify: will hold the certificate verification output. |
1564 | | * |
1565 | | * |
1566 | | * This function will try to verify the given certificate list and |
1567 | | * return its status. The details of the verification are the same |
1568 | | * as in gnutls_x509_trust_list_verify_crt2(). |
1569 | | * |
1570 | | * You must check the peer's name in order to check if the verified |
1571 | | * certificate belongs to the actual peer. |
1572 | | * |
1573 | | * The certificate verification output will be put in @verify and will |
1574 | | * be one or more of the gnutls_certificate_status_t enumerated |
1575 | | * elements bitwise or'd. For a more detailed verification status use |
1576 | | * gnutls_x509_crt_verify() per list element. |
1577 | | * |
1578 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1579 | | * negative error value. |
1580 | | **/ |
1581 | | int |
1582 | | gnutls_x509_crt_list_verify(const gnutls_x509_crt_t * cert_list, |
1583 | | unsigned cert_list_length, |
1584 | | const gnutls_x509_crt_t * CA_list, |
1585 | | unsigned CA_list_length, |
1586 | | const gnutls_x509_crl_t * CRL_list, |
1587 | | unsigned CRL_list_length, unsigned int flags, |
1588 | | unsigned int *verify) |
1589 | 0 | { |
1590 | 0 | unsigned i; |
1591 | 0 | int ret; |
1592 | 0 | gnutls_x509_trust_list_t tlist; |
1593 | |
|
1594 | 0 | if (cert_list == NULL || cert_list_length == 0) |
1595 | 0 | return GNUTLS_E_NO_CERTIFICATE_FOUND; |
1596 | | |
1597 | 0 | gnutls_x509_trust_list_init(&tlist, 0); |
1598 | | |
1599 | | /* Verify certificate |
1600 | | */ |
1601 | 0 | *verify = _gnutls_verify_crt_status(tlist, cert_list, cert_list_length, |
1602 | 0 | CA_list, CA_list_length, |
1603 | 0 | flags, NULL, NULL); |
1604 | | |
1605 | | /* Check for revoked certificates in the chain. |
1606 | | */ |
1607 | 0 | for (i = 0; i < cert_list_length; i++) { |
1608 | 0 | ret = gnutls_x509_crt_check_revocation(cert_list[i], |
1609 | 0 | CRL_list, |
1610 | 0 | CRL_list_length); |
1611 | 0 | if (ret == 1) { /* revoked */ |
1612 | 0 | *verify |= GNUTLS_CERT_REVOKED; |
1613 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1614 | 0 | } |
1615 | 0 | } |
1616 | |
|
1617 | 0 | gnutls_x509_trust_list_deinit(tlist, 0); |
1618 | 0 | return 0; |
1619 | 0 | } |
1620 | | |
1621 | | /** |
1622 | | * gnutls_x509_crt_verify: |
1623 | | * @cert: is the certificate to be verified |
1624 | | * @CA_list: is one certificate that is considered to be trusted one |
1625 | | * @CA_list_length: holds the number of CA certificate in CA_list |
1626 | | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. |
1627 | | * @verify: will hold the certificate verification output. |
1628 | | * |
1629 | | * This function will try to verify the given certificate and return |
1630 | | * its status. Note that a verification error does not imply a negative |
1631 | | * return status. In that case the @verify status is set. |
1632 | | * |
1633 | | * The details of the verification are the same |
1634 | | * as in gnutls_x509_trust_list_verify_crt2(). |
1635 | | * |
1636 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1637 | | * negative error value. |
1638 | | **/ |
1639 | | int |
1640 | | gnutls_x509_crt_verify(gnutls_x509_crt_t cert, |
1641 | | const gnutls_x509_crt_t * CA_list, |
1642 | | unsigned CA_list_length, unsigned int flags, |
1643 | | unsigned int *verify) |
1644 | 0 | { |
1645 | 0 | gnutls_x509_trust_list_t tlist; |
1646 | |
|
1647 | 0 | gnutls_x509_trust_list_init(&tlist, 0); |
1648 | | |
1649 | | /* Verify certificate |
1650 | | */ |
1651 | 0 | *verify = _gnutls_verify_crt_status(tlist, &cert, 1, |
1652 | 0 | CA_list, CA_list_length, |
1653 | 0 | flags, NULL, NULL); |
1654 | |
|
1655 | 0 | gnutls_x509_trust_list_deinit(tlist, 0); |
1656 | 0 | return 0; |
1657 | 0 | } |
1658 | | |
1659 | | /** |
1660 | | * gnutls_x509_crl_check_issuer: |
1661 | | * @crl: is the CRL to be checked |
1662 | | * @issuer: is the certificate of a possible issuer |
1663 | | * |
1664 | | * This function will check if the given CRL was issued by the given |
1665 | | * issuer certificate. |
1666 | | * |
1667 | | * Returns: true (1) if the given CRL was issued by the given issuer, |
1668 | | * and false (0) if not. |
1669 | | **/ |
1670 | | unsigned |
1671 | | gnutls_x509_crl_check_issuer(gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer) |
1672 | 0 | { |
1673 | 0 | return is_crl_issuer(crl, issuer); |
1674 | 0 | } |
1675 | | |
1676 | | static inline gnutls_x509_crt_t |
1677 | | find_crl_issuer(gnutls_x509_crl_t crl, |
1678 | | const gnutls_x509_crt_t * trusted_cas, int tcas_size) |
1679 | 0 | { |
1680 | 0 | int i; |
1681 | | |
1682 | | /* this is serial search. |
1683 | | */ |
1684 | |
|
1685 | 0 | for (i = 0; i < tcas_size; i++) { |
1686 | 0 | if (is_crl_issuer(crl, trusted_cas[i]) != 0) |
1687 | 0 | return trusted_cas[i]; |
1688 | 0 | } |
1689 | | |
1690 | 0 | gnutls_assert(); |
1691 | 0 | return NULL; |
1692 | 0 | } |
1693 | | |
1694 | | /** |
1695 | | * gnutls_x509_crl_verify: |
1696 | | * @crl: is the crl to be verified |
1697 | | * @trusted_cas: is a certificate list that is considered to be trusted one |
1698 | | * @tcas_size: holds the number of CA certificates in CA_list |
1699 | | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. |
1700 | | * @verify: will hold the crl verification output. |
1701 | | * |
1702 | | * This function will try to verify the given crl and return its verification status. |
1703 | | * See gnutls_x509_crt_list_verify() for a detailed description of |
1704 | | * return values. Note that since GnuTLS 3.1.4 this function includes |
1705 | | * the time checks. |
1706 | | * |
1707 | | * Note that value in @verify is set only when the return value of this |
1708 | | * function is success (i.e, failure to trust a CRL a certificate does not imply |
1709 | | * a negative return value). |
1710 | | * |
1711 | | * Before GnuTLS 3.5.7 this function would return zero or a positive |
1712 | | * number on success. |
1713 | | * |
1714 | | * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a |
1715 | | * negative error value. |
1716 | | **/ |
1717 | | int |
1718 | | gnutls_x509_crl_verify(gnutls_x509_crl_t crl, |
1719 | | const gnutls_x509_crt_t * trusted_cas, |
1720 | | unsigned tcas_size, unsigned int flags, |
1721 | | unsigned int *verify) |
1722 | 0 | { |
1723 | | /* CRL is ignored for now */ |
1724 | 0 | gnutls_datum_t crl_signed_data = { NULL, 0 }; |
1725 | 0 | gnutls_datum_t crl_signature = { NULL, 0 }; |
1726 | 0 | gnutls_x509_crt_t issuer = NULL; |
1727 | 0 | int result, sigalg; |
1728 | 0 | time_t now = gnutls_time(0); |
1729 | 0 | time_t nextu; |
1730 | 0 | unsigned int usage; |
1731 | |
|
1732 | 0 | if (verify) |
1733 | 0 | *verify = 0; |
1734 | |
|
1735 | 0 | if (tcas_size >= 1) |
1736 | 0 | issuer = find_crl_issuer(crl, trusted_cas, tcas_size); |
1737 | |
|
1738 | 0 | result = |
1739 | 0 | _gnutls_x509_get_signed_data(crl->crl, &crl->der, "tbsCertList", |
1740 | 0 | &crl_signed_data); |
1741 | 0 | if (result < 0) { |
1742 | 0 | gnutls_assert(); |
1743 | 0 | if (verify) |
1744 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1745 | 0 | goto cleanup; |
1746 | 0 | } |
1747 | | |
1748 | 0 | result = |
1749 | 0 | _gnutls_x509_get_signature(crl->crl, "signature", &crl_signature); |
1750 | 0 | if (result < 0) { |
1751 | 0 | gnutls_assert(); |
1752 | 0 | if (verify) |
1753 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1754 | 0 | goto cleanup; |
1755 | 0 | } |
1756 | | |
1757 | 0 | sigalg = |
1758 | 0 | _gnutls_x509_get_signature_algorithm(crl->crl, |
1759 | 0 | "signatureAlgorithm"); |
1760 | 0 | if (sigalg < 0) { |
1761 | 0 | gnutls_assert(); |
1762 | 0 | if (verify) |
1763 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1764 | 0 | goto cleanup; |
1765 | 0 | } |
1766 | | |
1767 | | /* issuer is not in trusted certificate |
1768 | | * authorities. |
1769 | | */ |
1770 | 0 | if (issuer == NULL) { |
1771 | 0 | gnutls_assert(); |
1772 | 0 | if (verify) |
1773 | 0 | *verify |= |
1774 | 0 | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; |
1775 | 0 | } else { |
1776 | 0 | if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) { |
1777 | 0 | if (gnutls_x509_crt_get_ca_status(issuer, NULL) != 1) { |
1778 | 0 | gnutls_assert(); |
1779 | 0 | if (verify) |
1780 | 0 | *verify |= |
1781 | 0 | GNUTLS_CERT_SIGNER_NOT_CA | |
1782 | 0 | GNUTLS_CERT_INVALID; |
1783 | 0 | } |
1784 | |
|
1785 | 0 | result = |
1786 | 0 | gnutls_x509_crt_get_key_usage(issuer, &usage, NULL); |
1787 | 0 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1788 | 0 | if (result < 0) { |
1789 | 0 | gnutls_assert(); |
1790 | 0 | if (verify) |
1791 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1792 | 0 | } else if (!(usage & GNUTLS_KEY_CRL_SIGN)) { |
1793 | 0 | gnutls_assert(); |
1794 | 0 | if (verify) |
1795 | 0 | *verify |= |
1796 | 0 | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE |
1797 | 0 | | GNUTLS_CERT_INVALID; |
1798 | 0 | } |
1799 | 0 | } |
1800 | 0 | } |
1801 | |
|
1802 | 0 | result = |
1803 | 0 | _gnutls_x509_verify_data(sigalg, |
1804 | 0 | &crl_signed_data, &crl_signature, |
1805 | 0 | NULL, issuer, flags); |
1806 | 0 | if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) { |
1807 | 0 | gnutls_assert(); |
1808 | | /* error. ignore it */ |
1809 | 0 | if (verify) |
1810 | 0 | *verify |= GNUTLS_CERT_SIGNATURE_FAILURE; |
1811 | 0 | result = 0; |
1812 | 0 | } else if (result == GNUTLS_E_CONSTRAINT_ERROR) { |
1813 | 0 | if (verify) |
1814 | 0 | *verify |= |
1815 | 0 | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE; |
1816 | 0 | result = 0; |
1817 | 0 | } else if (result < 0) { |
1818 | 0 | gnutls_assert(); |
1819 | 0 | if (verify) |
1820 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1821 | 0 | goto cleanup; |
1822 | 0 | } else { |
1823 | 0 | result = 0; /* everything ok */ |
1824 | 0 | } |
1825 | 0 | } |
1826 | | |
1827 | 0 | { |
1828 | 0 | sigalg = gnutls_x509_crl_get_signature_algorithm(crl); |
1829 | |
|
1830 | 0 | if (((sigalg == GNUTLS_SIGN_RSA_MD2) && |
1831 | 0 | !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || |
1832 | 0 | ((sigalg == GNUTLS_SIGN_RSA_MD5) && |
1833 | 0 | !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) { |
1834 | 0 | if (verify) |
1835 | 0 | *verify |= GNUTLS_CERT_INSECURE_ALGORITHM; |
1836 | 0 | result = 0; |
1837 | 0 | } |
1838 | 0 | } |
1839 | |
|
1840 | 0 | if (gnutls_x509_crl_get_this_update(crl) > now && verify) |
1841 | 0 | *verify |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE; |
1842 | |
|
1843 | 0 | nextu = gnutls_x509_crl_get_next_update(crl); |
1844 | 0 | if (nextu != -1 && nextu < now && verify) |
1845 | 0 | *verify |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED; |
1846 | |
|
1847 | 0 | cleanup: |
1848 | 0 | if (verify && *verify != 0) |
1849 | 0 | *verify |= GNUTLS_CERT_INVALID; |
1850 | |
|
1851 | 0 | _gnutls_free_datum(&crl_signed_data); |
1852 | 0 | _gnutls_free_datum(&crl_signature); |
1853 | |
|
1854 | 0 | return result; |
1855 | 0 | } |