diff options
Diffstat (limited to 'src/daemon/https/x509/x509_verify.c')
-rw-r--r-- | src/daemon/https/x509/x509_verify.c | 715 |
1 files changed, 0 insertions, 715 deletions
diff --git a/src/daemon/https/x509/x509_verify.c b/src/daemon/https/x509/x509_verify.c deleted file mode 100644 index a3eea5e7..00000000 --- a/src/daemon/https/x509/x509_verify.c +++ /dev/null | |||
@@ -1,715 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This library is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
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 <gnutls_errors.h> | ||
31 | #include <gnutls_cert.h> | ||
32 | #include <libtasn1.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_num.h> /* MAX */ | ||
35 | #include <gnutls_sig.h> | ||
36 | #include <gnutls_str.h> | ||
37 | #include <gnutls_datum.h> | ||
38 | #include <dn.h> | ||
39 | #include <x509.h> | ||
40 | #include <mpi.h> | ||
41 | #include <common.h> | ||
42 | #include <verify.h> | ||
43 | |||
44 | static int MHD__gnutls_verify_certificate2 (MHD_gnutls_x509_crt_t cert, | ||
45 | const MHD_gnutls_x509_crt_t * | ||
46 | trusted_cas, int tcas_size, | ||
47 | unsigned int flags, | ||
48 | unsigned int *output); | ||
49 | static int MHD__gnutls_x509_verify_signature (const MHD_gnutls_datum_t * signed_data, | ||
50 | const MHD_gnutls_datum_t * signature, | ||
51 | MHD_gnutls_x509_crt_t issuer); | ||
52 | |||
53 | /* Checks if the issuer of a certificate is a | ||
54 | * Certificate Authority, or if the certificate is the same | ||
55 | * as the issuer (and therefore it doesn't need to be a CA). | ||
56 | * | ||
57 | * Returns true or false, if the issuer is a CA, | ||
58 | * or not. | ||
59 | */ | ||
60 | static int | ||
61 | check_if_ca (MHD_gnutls_x509_crt_t cert, | ||
62 | MHD_gnutls_x509_crt_t issuer, unsigned int flags) | ||
63 | { | ||
64 | MHD_gnutls_datum_t cert_signed_data = { NULL, | ||
65 | 0 | ||
66 | }; | ||
67 | MHD_gnutls_datum_t issuer_signed_data = { NULL, | ||
68 | 0 | ||
69 | }; | ||
70 | MHD_gnutls_datum_t cert_signature = { NULL, | ||
71 | 0 | ||
72 | }; | ||
73 | MHD_gnutls_datum_t issuer_signature = { NULL, | ||
74 | 0 | ||
75 | }; | ||
76 | int result; | ||
77 | |||
78 | /* Check if the issuer is the same with the | ||
79 | * certificate. This is added in order for trusted | ||
80 | * certificates to be able to verify themselves. | ||
81 | */ | ||
82 | |||
83 | result = MHD__gnutls_x509_get_signed_data (issuer->cert, "tbsCertificate", | ||
84 | &issuer_signed_data); | ||
85 | if (result < 0) | ||
86 | { | ||
87 | MHD_gnutls_assert (); | ||
88 | goto cleanup; | ||
89 | } | ||
90 | |||
91 | result = MHD__gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", | ||
92 | &cert_signed_data); | ||
93 | if (result < 0) | ||
94 | { | ||
95 | MHD_gnutls_assert (); | ||
96 | goto cleanup; | ||
97 | } | ||
98 | |||
99 | result = MHD__gnutls_x509_get_signature (issuer->cert, "signature", | ||
100 | &issuer_signature); | ||
101 | if (result < 0) | ||
102 | { | ||
103 | MHD_gnutls_assert (); | ||
104 | goto cleanup; | ||
105 | } | ||
106 | |||
107 | result = | ||
108 | MHD__gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); | ||
109 | if (result < 0) | ||
110 | { | ||
111 | MHD_gnutls_assert (); | ||
112 | goto cleanup; | ||
113 | } | ||
114 | |||
115 | /* If the subject certificate is the same as the issuer | ||
116 | * return true. | ||
117 | */ | ||
118 | if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) | ||
119 | if (cert_signed_data.size == issuer_signed_data.size) | ||
120 | { | ||
121 | if ((memcmp (cert_signed_data.data, issuer_signed_data.data, | ||
122 | cert_signed_data.size) == 0) && (cert_signature.size | ||
123 | == | ||
124 | issuer_signature.size) | ||
125 | && | ||
126 | (memcmp | ||
127 | (cert_signature.data, issuer_signature.data, | ||
128 | cert_signature.size) == 0)) | ||
129 | { | ||
130 | result = 1; | ||
131 | goto cleanup; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | if (MHD_gnutls_x509_crt_get_ca_status (issuer, NULL) == 1) | ||
136 | { | ||
137 | result = 1; | ||
138 | goto cleanup; | ||
139 | } | ||
140 | else | ||
141 | MHD_gnutls_assert (); | ||
142 | |||
143 | result = 0; | ||
144 | |||
145 | cleanup:MHD__gnutls_free_datum (&cert_signed_data); | ||
146 | MHD__gnutls_free_datum (&issuer_signed_data); | ||
147 | MHD__gnutls_free_datum (&cert_signature); | ||
148 | MHD__gnutls_free_datum (&issuer_signature); | ||
149 | return result; | ||
150 | } | ||
151 | |||
152 | /* This function checks if 'certs' issuer is 'issuer_cert'. | ||
153 | * This does a straight (DER) compare of the issuer/subject fields in | ||
154 | * the given certificates. | ||
155 | * | ||
156 | * Returns 1 if they match and zero if they don't match. Otherwise | ||
157 | * a negative value is returned to indicate error. | ||
158 | */ | ||
159 | static int | ||
160 | is_issuer (MHD_gnutls_x509_crt_t cert, MHD_gnutls_x509_crt_t issuer_cert) | ||
161 | { | ||
162 | MHD_gnutls_datum_t dn1 = { NULL, | ||
163 | 0 | ||
164 | }, dn2 = | ||
165 | { | ||
166 | NULL, 0}; | ||
167 | int ret; | ||
168 | |||
169 | ret = MHD_gnutls_x509_crt_get_raw_issuer_dn (cert, &dn1); | ||
170 | if (ret < 0) | ||
171 | { | ||
172 | MHD_gnutls_assert (); | ||
173 | goto cleanup; | ||
174 | } | ||
175 | |||
176 | ret = MHD_gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2); | ||
177 | if (ret < 0) | ||
178 | { | ||
179 | MHD_gnutls_assert (); | ||
180 | goto cleanup; | ||
181 | } | ||
182 | |||
183 | ret = MHD__gnutls_x509_compare_raw_dn (&dn1, &dn2); | ||
184 | |||
185 | cleanup:MHD__gnutls_free_datum (&dn1); | ||
186 | MHD__gnutls_free_datum (&dn2); | ||
187 | return ret; | ||
188 | |||
189 | } | ||
190 | |||
191 | static inline MHD_gnutls_x509_crt_t | ||
192 | find_issuer (MHD_gnutls_x509_crt_t cert, | ||
193 | const MHD_gnutls_x509_crt_t * trusted_cas, int tcas_size) | ||
194 | { | ||
195 | int i; | ||
196 | |||
197 | /* this is serial search. | ||
198 | */ | ||
199 | |||
200 | for (i = 0; i < tcas_size; i++) | ||
201 | { | ||
202 | if (is_issuer (cert, trusted_cas[i]) == 1) | ||
203 | return trusted_cas[i]; | ||
204 | } | ||
205 | |||
206 | MHD_gnutls_assert (); | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Verifies the given certificate again a certificate list of | ||
212 | * trusted CAs. | ||
213 | * | ||
214 | * Returns only 0 or 1. If 1 it means that the certificate | ||
215 | * was successfuly verified. | ||
216 | * | ||
217 | * 'flags': an OR of the MHD_gnutls_certificate_verify_flags enumeration. | ||
218 | * | ||
219 | * Output will hold some extra information about the verification | ||
220 | * procedure. | ||
221 | */ | ||
222 | static int | ||
223 | MHD__gnutls_verify_certificate2 (MHD_gnutls_x509_crt_t cert, | ||
224 | const MHD_gnutls_x509_crt_t * trusted_cas, | ||
225 | int tcas_size, | ||
226 | unsigned int flags, unsigned int *output) | ||
227 | { | ||
228 | MHD_gnutls_datum_t cert_signed_data = { NULL, | ||
229 | 0 | ||
230 | }; | ||
231 | MHD_gnutls_datum_t cert_signature = { NULL, | ||
232 | 0 | ||
233 | }; | ||
234 | MHD_gnutls_x509_crt_t issuer; | ||
235 | int ret, issuer_version, result; | ||
236 | |||
237 | if (output) | ||
238 | *output = 0; | ||
239 | |||
240 | if (tcas_size >= 1) | ||
241 | issuer = find_issuer (cert, trusted_cas, tcas_size); | ||
242 | else | ||
243 | { | ||
244 | MHD_gnutls_assert (); | ||
245 | if (output) | ||
246 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* issuer is not in trusted certificate | ||
251 | * authorities. | ||
252 | */ | ||
253 | if (issuer == NULL) | ||
254 | { | ||
255 | if (output) | ||
256 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
257 | MHD_gnutls_assert (); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | issuer_version = MHD_gnutls_x509_crt_get_version (issuer); | ||
262 | if (issuer_version < 0) | ||
263 | { | ||
264 | MHD_gnutls_assert (); | ||
265 | return issuer_version; | ||
266 | } | ||
267 | |||
268 | if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && !((flags | ||
269 | & | ||
270 | GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT) | ||
271 | && issuer_version == 1)) | ||
272 | { | ||
273 | if (check_if_ca (cert, issuer, flags) == 0) | ||
274 | { | ||
275 | MHD_gnutls_assert (); | ||
276 | if (output) | ||
277 | *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; | ||
278 | return 0; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | result = MHD__gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", | ||
283 | &cert_signed_data); | ||
284 | if (result < 0) | ||
285 | { | ||
286 | MHD_gnutls_assert (); | ||
287 | goto cleanup; | ||
288 | } | ||
289 | |||
290 | result = | ||
291 | MHD__gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); | ||
292 | if (result < 0) | ||
293 | { | ||
294 | MHD_gnutls_assert (); | ||
295 | goto cleanup; | ||
296 | } | ||
297 | |||
298 | ret = MHD__gnutls_x509_verify_signature (&cert_signed_data, &cert_signature, | ||
299 | issuer); | ||
300 | if (ret < 0) | ||
301 | { | ||
302 | MHD_gnutls_assert (); | ||
303 | } | ||
304 | else if (ret == 0) | ||
305 | { | ||
306 | MHD_gnutls_assert (); | ||
307 | /* error. ignore it */ | ||
308 | if (output) | ||
309 | *output |= GNUTLS_CERT_INVALID; | ||
310 | ret = 0; | ||
311 | } | ||
312 | |||
313 | /* If the certificate is not self signed check if the algorithms | ||
314 | * used are secure. If the certificate is self signed it doesn't | ||
315 | * really matter. | ||
316 | */ | ||
317 | if (is_issuer (cert, cert) == 0) | ||
318 | { | ||
319 | int sigalg; | ||
320 | |||
321 | sigalg = MHD_gnutls_x509_crt_get_signature_algorithm (cert); | ||
322 | |||
323 | if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags | ||
324 | & | ||
325 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) | ||
326 | || ((sigalg == GNUTLS_SIGN_RSA_MD5) | ||
327 | && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) | ||
328 | { | ||
329 | if (output) | ||
330 | *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | result = ret; | ||
335 | |||
336 | cleanup:MHD__gnutls_free_datum (&cert_signed_data); | ||
337 | MHD__gnutls_free_datum (&cert_signature); | ||
338 | |||
339 | return result; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * MHD_gnutls_x509_crt_check_issuer - This function checks if the certificate given has the given issuer | ||
344 | * @cert: is the certificate to be checked | ||
345 | * @issuer: is the certificate of a possible issuer | ||
346 | * | ||
347 | * This function will check if the given certificate was issued by the | ||
348 | * given issuer. It will return true (1) if the given certificate is issued | ||
349 | * by the given issuer, and false (0) if not. | ||
350 | * | ||
351 | * A negative value is returned in case of an error. | ||
352 | * | ||
353 | **/ | ||
354 | static int | ||
355 | MHD_gnutls_x509_crt_check_issuer (MHD_gnutls_x509_crt_t cert, | ||
356 | MHD_gnutls_x509_crt_t issuer) | ||
357 | { | ||
358 | return is_issuer (cert, issuer); | ||
359 | } | ||
360 | |||
361 | /* The algorithm used is: | ||
362 | * 1. Check last certificate in the chain. If it is not verified return. | ||
363 | * 2. Check if any certificates in the chain are revoked. If yes return. | ||
364 | * 3. Try to verify the rest of certificates in the chain. If not verified return. | ||
365 | * 4. Return 0. | ||
366 | * | ||
367 | * Note that the return value is an OR of GNUTLS_CERT_* elements. | ||
368 | * | ||
369 | * This function verifies a X.509 certificate list. The certificate list should | ||
370 | * lead to a trusted CA in order to be trusted. | ||
371 | */ | ||
372 | static unsigned int | ||
373 | MHD__gnutls_x509_verify_certificate (const MHD_gnutls_x509_crt_t * | ||
374 | certificate_list, int clist_size, | ||
375 | const MHD_gnutls_x509_crt_t * | ||
376 | trusted_cas, int tcas_size, | ||
377 | const MHD_gnutls_x509_crl_t * CRLs, | ||
378 | int crls_size, unsigned int flags) | ||
379 | { | ||
380 | int i = 0, ret; | ||
381 | unsigned int status = 0, output; | ||
382 | |||
383 | /* Verify the last certificate in the certificate path | ||
384 | * against the trusted CA certificate list. | ||
385 | * | ||
386 | * If no CAs are present returns CERT_INVALID. Thus works | ||
387 | * in self signed etc certificates. | ||
388 | */ | ||
389 | ret = MHD__gnutls_verify_certificate2 (certificate_list[clist_size - 1], | ||
390 | trusted_cas, tcas_size, flags, | ||
391 | &output); | ||
392 | |||
393 | if (ret == 0) | ||
394 | { | ||
395 | /* if the last certificate in the certificate | ||
396 | * list is invalid, then the certificate is not | ||
397 | * trusted. | ||
398 | */ | ||
399 | MHD_gnutls_assert (); | ||
400 | status |= output; | ||
401 | status |= GNUTLS_CERT_INVALID; | ||
402 | return status; | ||
403 | } | ||
404 | |||
405 | /* Check if the last certificate in the path is self signed. | ||
406 | * In that case ignore it (a certificate is trusted only if it | ||
407 | * leads to a trusted party by us, not the server's). | ||
408 | */ | ||
409 | if (MHD_gnutls_x509_crt_check_issuer (certificate_list[clist_size - 1], | ||
410 | certificate_list[clist_size - 1]) > 0 | ||
411 | && clist_size > 0) | ||
412 | { | ||
413 | clist_size--; | ||
414 | } | ||
415 | |||
416 | /* Verify the certificate path (chain) | ||
417 | */ | ||
418 | for (i = clist_size - 1; i > 0; i--) | ||
419 | { | ||
420 | if (i - 1 < 0) | ||
421 | break; | ||
422 | |||
423 | /* note that here we disable this V1 CA flag. So that no version 1 | ||
424 | * certificates can exist in a supplied chain. | ||
425 | */ | ||
426 | if (!(flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT)) | ||
427 | flags ^= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; | ||
428 | if ((ret = MHD__gnutls_verify_certificate2 (certificate_list[i - 1], | ||
429 | &certificate_list[i], 1, | ||
430 | flags, NULL)) == 0) | ||
431 | { | ||
432 | status |= GNUTLS_CERT_INVALID; | ||
433 | return status; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /* Reads the digest information. | ||
441 | * we use DER here, although we should use BER. It works fine | ||
442 | * anyway. | ||
443 | */ | ||
444 | static int | ||
445 | decode_ber_digest_info (const MHD_gnutls_datum_t * info, | ||
446 | enum MHD_GNUTLS_HashAlgorithm *hash, | ||
447 | opaque * digest, int *digest_size) | ||
448 | { | ||
449 | ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; | ||
450 | int result; | ||
451 | char str[1024]; | ||
452 | int len; | ||
453 | |||
454 | if ((result = MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (), | ||
455 | "GNUTLS.DigestInfo", | ||
456 | &dinfo)) != ASN1_SUCCESS) | ||
457 | { | ||
458 | MHD_gnutls_assert (); | ||
459 | return MHD_gtls_asn2err (result); | ||
460 | } | ||
461 | |||
462 | result = MHD__asn1_der_decoding (&dinfo, info->data, info->size, NULL); | ||
463 | if (result != ASN1_SUCCESS) | ||
464 | { | ||
465 | MHD_gnutls_assert (); | ||
466 | MHD__asn1_delete_structure (&dinfo); | ||
467 | return MHD_gtls_asn2err (result); | ||
468 | } | ||
469 | |||
470 | len = sizeof (str) - 1; | ||
471 | result = | ||
472 | MHD__asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len); | ||
473 | if (result != ASN1_SUCCESS) | ||
474 | { | ||
475 | MHD_gnutls_assert (); | ||
476 | MHD__asn1_delete_structure (&dinfo); | ||
477 | return MHD_gtls_asn2err (result); | ||
478 | } | ||
479 | |||
480 | *hash = MHD_gtls_x509_oid2mac_algorithm (str); | ||
481 | |||
482 | if (*hash == MHD_GNUTLS_MAC_UNKNOWN) | ||
483 | { | ||
484 | |||
485 | MHD__gnutls_x509_log ("verify.c: HASH OID: %s\n", str); | ||
486 | |||
487 | MHD_gnutls_assert (); | ||
488 | MHD__asn1_delete_structure (&dinfo); | ||
489 | return GNUTLS_E_UNKNOWN_ALGORITHM; | ||
490 | } | ||
491 | |||
492 | len = sizeof (str) - 1; | ||
493 | result = | ||
494 | MHD__asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len); | ||
495 | /* To avoid permitting garbage in the parameters field, either the | ||
496 | parameters field is not present, or it contains 0x05 0x00. */ | ||
497 | if (! | ||
498 | (result == ASN1_ELEMENT_NOT_FOUND | ||
499 | || (result == ASN1_SUCCESS && len == 2 && str[0] == 0x05 | ||
500 | && str[1] == 0x00))) | ||
501 | { | ||
502 | MHD_gnutls_assert (); | ||
503 | MHD__asn1_delete_structure (&dinfo); | ||
504 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
505 | } | ||
506 | |||
507 | result = MHD__asn1_read_value (dinfo, "digest", digest, digest_size); | ||
508 | if (result != ASN1_SUCCESS) | ||
509 | { | ||
510 | MHD_gnutls_assert (); | ||
511 | MHD__asn1_delete_structure (&dinfo); | ||
512 | return MHD_gtls_asn2err (result); | ||
513 | } | ||
514 | |||
515 | MHD__asn1_delete_structure (&dinfo); | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* if hash==MD5 then we do RSA-MD5 | ||
521 | * if hash==SHA then we do RSA-SHA | ||
522 | * params[0] is modulus | ||
523 | * params[1] is public key | ||
524 | */ | ||
525 | static int | ||
526 | _pkcs1_rsa_verify_sig (const MHD_gnutls_datum_t * text, | ||
527 | const MHD_gnutls_datum_t * signature, | ||
528 | mpi_t * params, int params_len) | ||
529 | { | ||
530 | enum MHD_GNUTLS_HashAlgorithm hash = MHD_GNUTLS_MAC_UNKNOWN; | ||
531 | int ret; | ||
532 | opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE]; | ||
533 | int digest_size; | ||
534 | GNUTLS_HASH_HANDLE hd; | ||
535 | MHD_gnutls_datum_t decrypted; | ||
536 | |||
537 | ret = | ||
538 | MHD_gtls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1); | ||
539 | if (ret < 0) | ||
540 | { | ||
541 | MHD_gnutls_assert (); | ||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | /* decrypted is a BER encoded data of type DigestInfo | ||
546 | */ | ||
547 | |||
548 | digest_size = sizeof (digest); | ||
549 | if ((ret = decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) | ||
550 | != 0) | ||
551 | { | ||
552 | MHD_gnutls_assert (); | ||
553 | MHD__gnutls_free_datum (&decrypted); | ||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | MHD__gnutls_free_datum (&decrypted); | ||
558 | |||
559 | if (digest_size != MHD_gnutls_hash_get_algo_len (hash)) | ||
560 | { | ||
561 | MHD_gnutls_assert (); | ||
562 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
563 | } | ||
564 | |||
565 | hd = MHD_gtls_hash_init (hash); | ||
566 | if (hd == NULL) | ||
567 | { | ||
568 | MHD_gnutls_assert (); | ||
569 | return GNUTLS_E_HASH_FAILED; | ||
570 | } | ||
571 | |||
572 | MHD_gnutls_hash (hd, text->data, text->size); | ||
573 | MHD_gnutls_hash_deinit (hd, md); | ||
574 | |||
575 | if (memcmp (md, digest, digest_size) != 0) | ||
576 | { | ||
577 | MHD_gnutls_assert (); | ||
578 | return GNUTLS_E_PK_SIG_VERIFY_FAILED; | ||
579 | } | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | /* Verifies the signature data, and returns 0 if not verified, | ||
585 | * or 1 otherwise. | ||
586 | */ | ||
587 | static int | ||
588 | verify_sig (const MHD_gnutls_datum_t * tbs, | ||
589 | const MHD_gnutls_datum_t * signature, | ||
590 | enum MHD_GNUTLS_PublicKeyAlgorithm pk, | ||
591 | mpi_t * issuer_params, int issuer_params_size) | ||
592 | { | ||
593 | |||
594 | switch (pk) | ||
595 | { | ||
596 | case MHD_GNUTLS_PK_RSA: | ||
597 | |||
598 | if (_pkcs1_rsa_verify_sig | ||
599 | (tbs, signature, issuer_params, issuer_params_size) != 0) | ||
600 | { | ||
601 | MHD_gnutls_assert (); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | return 1; | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | MHD_gnutls_assert (); | ||
610 | return GNUTLS_E_INTERNAL_ERROR; | ||
611 | |||
612 | } | ||
613 | } | ||
614 | |||
615 | /* verifies if the certificate is properly signed. | ||
616 | * returns 0 on failure and 1 on success. | ||
617 | * | ||
618 | * 'tbs' is the signed data | ||
619 | * 'signature' is the signature! | ||
620 | */ | ||
621 | static int | ||
622 | MHD__gnutls_x509_verify_signature (const MHD_gnutls_datum_t * tbs, | ||
623 | const MHD_gnutls_datum_t * signature, | ||
624 | MHD_gnutls_x509_crt_t issuer) | ||
625 | { | ||
626 | mpi_t issuer_params[MAX_PUBLIC_PARAMS_SIZE]; | ||
627 | int ret, issuer_params_size, i; | ||
628 | |||
629 | /* Read the MPI parameters from the issuer's certificate. | ||
630 | */ | ||
631 | issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; | ||
632 | ret = | ||
633 | MHD__gnutls_x509_crt_get_mpis (issuer, issuer_params, | ||
634 | &issuer_params_size); | ||
635 | if (ret < 0) | ||
636 | { | ||
637 | MHD_gnutls_assert (); | ||
638 | return ret; | ||
639 | } | ||
640 | |||
641 | ret = | ||
642 | verify_sig (tbs, signature, | ||
643 | MHD_gnutls_x509_crt_get_pk_algorithm (issuer, NULL), | ||
644 | issuer_params, issuer_params_size); | ||
645 | if (ret < 0) | ||
646 | { | ||
647 | MHD_gnutls_assert (); | ||
648 | } | ||
649 | |||
650 | /* release all allocated MPIs | ||
651 | */ | ||
652 | for (i = 0; i < issuer_params_size; i++) | ||
653 | { | ||
654 | MHD_gtls_mpi_release (&issuer_params[i]); | ||
655 | } | ||
656 | |||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * MHD_gnutls_x509_crt_list_verify - This function verifies the given certificate list | ||
662 | * @cert_list: is the certificate list to be verified | ||
663 | * @cert_list_length: holds the number of certificate in cert_list | ||
664 | * @CA_list: is the CA list which will be used in verification | ||
665 | * @CA_list_length: holds the number of CA certificate in CA_list | ||
666 | * @CRL_list: holds a list of CRLs. | ||
667 | * @CRL_list_length: the length of CRL list. | ||
668 | * @flags: Flags that may be used to change the verification algorithm. Use OR of the MHD_gnutls_certificate_verify_flags enumerations. | ||
669 | * @verify: will hold the certificate verification output. | ||
670 | * | ||
671 | * This function will try to verify the given certificate list and return its status. | ||
672 | * Note that expiration and activation dates are not checked | ||
673 | * by this function, you should check them using the appropriate functions. | ||
674 | * | ||
675 | * If no flags are specified (0), this function will use the | ||
676 | * basicConstraints (2.5.29.19) PKIX extension. This means that only a certificate | ||
677 | * authority is allowed to sign a certificate. | ||
678 | * | ||
679 | * You must also check the peer's name in order to check if the verified | ||
680 | * certificate belongs to the actual peer. | ||
681 | * | ||
682 | * The certificate verification output will be put in @verify and will be | ||
683 | * one or more of the MHD_gnutls_certificate_status_t enumerated elements bitwise or'd. | ||
684 | * For a more detailed verification status use MHD_gnutls_x509_crt_verify() per list | ||
685 | * element. | ||
686 | * | ||
687 | * GNUTLS_CERT_INVALID: the certificate chain is not valid. | ||
688 | * | ||
689 | * GNUTLS_CERT_REVOKED: a certificate in the chain has been revoked. | ||
690 | * | ||
691 | * Returns 0 on success and a negative value in case of an error. | ||
692 | * | ||
693 | **/ | ||
694 | int | ||
695 | MHD_gnutls_x509_crt_list_verify (const MHD_gnutls_x509_crt_t * cert_list, | ||
696 | int cert_list_length, | ||
697 | const MHD_gnutls_x509_crt_t * CA_list, | ||
698 | int CA_list_length, | ||
699 | const MHD_gnutls_x509_crl_t * CRL_list, | ||
700 | int CRL_list_length, | ||
701 | unsigned int flags, unsigned int *verify) | ||
702 | { | ||
703 | if (cert_list == NULL || cert_list_length == 0) | ||
704 | return GNUTLS_E_NO_CERTIFICATE_FOUND; | ||
705 | |||
706 | /* Verify certificate | ||
707 | */ | ||
708 | *verify = MHD__gnutls_x509_verify_certificate (cert_list, cert_list_length, | ||
709 | CA_list, CA_list_length, | ||
710 | CRL_list, CRL_list_length, | ||
711 | flags); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||