diff options
author | Christian Grothoff <christian@grothoff.org> | 2008-11-16 04:47:42 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2008-11-16 04:47:42 +0000 |
commit | 26766bf6f7a161b7df8170d5e8f1a088da13f12c (patch) | |
tree | bbc5b22ace516fab13da6afc9bfe3244683a183b | |
parent | 3b9bb09488b3d5d03a9517c810539f5b9e985d96 (diff) | |
download | libmicrohttpd-26766bf6f7a161b7df8170d5e8f1a088da13f12c.tar.gz libmicrohttpd-26766bf6f7a161b7df8170d5e8f1a088da13f12c.zip |
more DCE
-rw-r--r-- | src/daemon/https/gnutls.h | 6 | ||||
-rw-r--r-- | src/daemon/https/tls/gnutls_cert.c | 86 | ||||
-rw-r--r-- | src/daemon/https/tls/gnutls_x509.c | 110 | ||||
-rw-r--r-- | src/daemon/https/x509/Makefile.am | 1 | ||||
-rw-r--r-- | src/daemon/https/x509/common.c | 198 | ||||
-rw-r--r-- | src/daemon/https/x509/common.h | 16 | ||||
-rw-r--r-- | src/daemon/https/x509/verify.h | 33 | ||||
-rw-r--r-- | src/daemon/https/x509/x509.c | 1 | ||||
-rw-r--r-- | src/daemon/https/x509/x509.h | 9 | ||||
-rw-r--r-- | src/daemon/https/x509/x509_privkey.c | 1 | ||||
-rw-r--r-- | src/daemon/https/x509/x509_verify.c | 715 |
11 files changed, 2 insertions, 1174 deletions
diff --git a/src/daemon/https/gnutls.h b/src/daemon/https/gnutls.h index 985455c8..a8f8d47f 100644 --- a/src/daemon/https/gnutls.h +++ b/src/daemon/https/gnutls.h | |||
@@ -700,12 +700,6 @@ extern "C" | |||
700 | time_t MHD_gtls_certificate_expiration_time_peers (MHD_gtls_session_t | 700 | time_t MHD_gtls_certificate_expiration_time_peers (MHD_gtls_session_t |
701 | session); | 701 | session); |
702 | 702 | ||
703 | int MHD_gtls_certificate_verify_peers2 (MHD_gtls_session_t session, | ||
704 | unsigned int *status); | ||
705 | |||
706 | /* this is obsolete (?). */ | ||
707 | int MHD_gtls_certificate_verify_peers (MHD_gtls_session_t session); | ||
708 | |||
709 | int MHD_gtls_pem_base64_encode (const char *msg, | 703 | int MHD_gtls_pem_base64_encode (const char *msg, |
710 | const MHD_gnutls_datum_t * data, | 704 | const MHD_gnutls_datum_t * data, |
711 | char *result, size_t * result_size); | 705 | char *result, size_t * result_size); |
diff --git a/src/daemon/https/tls/gnutls_cert.c b/src/daemon/https/tls/gnutls_cert.c index 201557b3..f5d657d4 100644 --- a/src/daemon/https/tls/gnutls_cert.c +++ b/src/daemon/https/tls/gnutls_cert.c | |||
@@ -430,92 +430,6 @@ MHD__gnutls_x509_get_raw_crt_expiration_time (const MHD_gnutls_datum_t * cert) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | /** | 432 | /** |
433 | * MHD_gtls_certificate_verify_peers2 - This function returns the peer's certificate verification status | ||
434 | * @session: is a gnutls session | ||
435 | * @status: is the output of the verification | ||
436 | * | ||
437 | * This function will try to verify the peer's certificate and return | ||
438 | * its status (trusted, invalid etc.). The value of @status should | ||
439 | * be one or more of the MHD_gnutls_certificate_status_t enumerated | ||
440 | * elements bitwise or'd. To avoid denial of service attacks some | ||
441 | * default upper limits regarding the certificate key size and chain | ||
442 | * size are set. To override them use | ||
443 | * MHD__gnutls_certificate_set_verify_limits(). | ||
444 | * | ||
445 | * Note that you must also check the peer's name in order to check if | ||
446 | * the verified certificate belongs to the actual peer. | ||
447 | * | ||
448 | * This is the same as MHD_gnutls_x509_crt_list_verify() and uses the | ||
449 | * loaded CAs in the credentials as trusted CAs. | ||
450 | * | ||
451 | * Note that some commonly used X.509 Certificate Authorities are | ||
452 | * still using Version 1 certificates. If you want to accept them, | ||
453 | * you need to call MHD__gnutls_certificate_set_verify_flags() with, e.g., | ||
454 | * %GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT parameter. | ||
455 | * | ||
456 | * Returns: a negative error code on error and zero on success. | ||
457 | **/ | ||
458 | int | ||
459 | MHD_gtls_certificate_verify_peers2 (MHD_gtls_session_t session, | ||
460 | unsigned int *status) | ||
461 | { | ||
462 | cert_auth_info_t info; | ||
463 | |||
464 | CHECK_AUTH (MHD_GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); | ||
465 | |||
466 | info = MHD_gtls_get_auth_info (session); | ||
467 | if (info == NULL) | ||
468 | { | ||
469 | return GNUTLS_E_NO_CERTIFICATE_FOUND; | ||
470 | } | ||
471 | |||
472 | if (info->raw_certificate_list == NULL || info->ncerts == 0) | ||
473 | return GNUTLS_E_NO_CERTIFICATE_FOUND; | ||
474 | |||
475 | switch (MHD_gnutls_certificate_type_get (session)) | ||
476 | { | ||
477 | case MHD_GNUTLS_CRT_X509: | ||
478 | return MHD__gnutls_x509_cert_verify_peers (session, status); | ||
479 | default: | ||
480 | return GNUTLS_E_INVALID_REQUEST; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * MHD_gtls_certificate_verify_peers - This function returns the peer's certificate verification status | ||
486 | * @session: is a gnutls session | ||
487 | * | ||
488 | * This function will try to verify the peer's certificate and return | ||
489 | * its status (trusted, invalid etc.). However you must also check | ||
490 | * the peer's name in order to check if the verified certificate | ||
491 | * belongs to the actual peer. | ||
492 | * | ||
493 | * The return value should be one or more of the | ||
494 | * MHD_gnutls_certificate_status_t enumerated elements bitwise or'd, or a | ||
495 | * negative value on error. | ||
496 | * | ||
497 | * This is the same as MHD_gnutls_x509_crt_list_verify(). | ||
498 | * | ||
499 | * Deprecated: Use MHD_gtls_certificate_verify_peers2() instead. | ||
500 | **/ | ||
501 | int | ||
502 | MHD_gtls_certificate_verify_peers (MHD_gtls_session_t session) | ||
503 | { | ||
504 | unsigned int status; | ||
505 | int ret; | ||
506 | |||
507 | ret = MHD_gtls_certificate_verify_peers2 (session, &status); | ||
508 | |||
509 | if (ret < 0) | ||
510 | { | ||
511 | MHD_gnutls_assert (); | ||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | return status; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * MHD_gtls_certificate_expiration_time_peers - This function returns the peer's certificate expiration time | 433 | * MHD_gtls_certificate_expiration_time_peers - This function returns the peer's certificate expiration time |
520 | * @session: is a gnutls session | 434 | * @session: is a gnutls session |
521 | * | 435 | * |
diff --git a/src/daemon/https/tls/gnutls_x509.c b/src/daemon/https/tls/gnutls_x509.c index 3ec47e94..1e479fe5 100644 --- a/src/daemon/https/tls/gnutls_x509.c +++ b/src/daemon/https/tls/gnutls_x509.c | |||
@@ -48,7 +48,6 @@ | |||
48 | /* x509 */ | 48 | /* x509 */ |
49 | #include "common.h" | 49 | #include "common.h" |
50 | #include "x509.h" | 50 | #include "x509.h" |
51 | #include "verify.h" | ||
52 | #include "mpi.h" | 51 | #include "mpi.h" |
53 | #include "privkey.h" | 52 | #include "privkey.h" |
54 | 53 | ||
@@ -89,115 +88,6 @@ check_bits (MHD_gnutls_x509_crt_t crt, unsigned int max_bits) | |||
89 | } \ | 88 | } \ |
90 | MHD_gnutls_free( peer_certificate_list) | 89 | MHD_gnutls_free( peer_certificate_list) |
91 | 90 | ||
92 | /*- | ||
93 | * MHD__gnutls_x509_cert_verify_peers - This function returns the peer's certificate status | ||
94 | * @session: is a gnutls session | ||
95 | * | ||
96 | * This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.). | ||
97 | * The return value (status) should be one of the MHD_gnutls_certificate_status_t enumerated elements. | ||
98 | * However you must also check the peer's name in order to check if the verified certificate belongs to the | ||
99 | * actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent. | ||
100 | * | ||
101 | -*/ | ||
102 | int | ||
103 | MHD__gnutls_x509_cert_verify_peers (MHD_gtls_session_t session, | ||
104 | unsigned int *status) | ||
105 | { | ||
106 | cert_auth_info_t info; | ||
107 | MHD_gtls_cert_credentials_t cred; | ||
108 | MHD_gnutls_x509_crt_t *peer_certificate_list; | ||
109 | int peer_certificate_list_size, i, x, ret; | ||
110 | |||
111 | CHECK_AUTH (MHD_GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); | ||
112 | |||
113 | info = MHD_gtls_get_auth_info (session); | ||
114 | if (info == NULL) | ||
115 | { | ||
116 | MHD_gnutls_assert (); | ||
117 | return GNUTLS_E_INVALID_REQUEST; | ||
118 | } | ||
119 | |||
120 | cred = (MHD_gtls_cert_credentials_t) | ||
121 | MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL); | ||
122 | if (cred == NULL) | ||
123 | { | ||
124 | MHD_gnutls_assert (); | ||
125 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS; | ||
126 | } | ||
127 | |||
128 | if (info->raw_certificate_list == NULL || info->ncerts == 0) | ||
129 | return GNUTLS_E_NO_CERTIFICATE_FOUND; | ||
130 | |||
131 | if (info->ncerts > cred->verify_depth && cred->verify_depth > 0) | ||
132 | { | ||
133 | MHD_gnutls_assert (); | ||
134 | return GNUTLS_E_CONSTRAINT_ERROR; | ||
135 | } | ||
136 | |||
137 | /* generate a list of MHD_gnutls_certs based on the auth info | ||
138 | * raw certs. | ||
139 | */ | ||
140 | peer_certificate_list_size = info->ncerts; | ||
141 | peer_certificate_list = | ||
142 | MHD_gnutls_calloc (peer_certificate_list_size, | ||
143 | sizeof (MHD_gnutls_x509_crt_t)); | ||
144 | if (peer_certificate_list == NULL) | ||
145 | { | ||
146 | MHD_gnutls_assert (); | ||
147 | return GNUTLS_E_MEMORY_ERROR; | ||
148 | } | ||
149 | |||
150 | for (i = 0; i < peer_certificate_list_size; i++) | ||
151 | { | ||
152 | ret = MHD_gnutls_x509_crt_init (&peer_certificate_list[i]); | ||
153 | if (ret < 0) | ||
154 | { | ||
155 | MHD_gnutls_assert (); | ||
156 | CLEAR_CERTS; | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | ret = | ||
161 | MHD_gnutls_x509_crt_import (peer_certificate_list[i], | ||
162 | &info->raw_certificate_list[i], | ||
163 | GNUTLS_X509_FMT_DER); | ||
164 | if (ret < 0) | ||
165 | { | ||
166 | MHD_gnutls_assert (); | ||
167 | CLEAR_CERTS; | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | ret = check_bits (peer_certificate_list[i], cred->verify_bits); | ||
172 | if (ret < 0) | ||
173 | { | ||
174 | MHD_gnutls_assert (); | ||
175 | CLEAR_CERTS; | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | } | ||
180 | |||
181 | /* Verify certificate | ||
182 | */ | ||
183 | ret = | ||
184 | MHD_gnutls_x509_crt_list_verify (peer_certificate_list, | ||
185 | peer_certificate_list_size, | ||
186 | cred->x509_ca_list, cred->x509_ncas, | ||
187 | cred->x509_crl_list, cred->x509_ncrls, | ||
188 | cred->verify_flags, status); | ||
189 | |||
190 | CLEAR_CERTS; | ||
191 | |||
192 | if (ret < 0) | ||
193 | { | ||
194 | MHD_gnutls_assert (); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* | 91 | /* |
202 | * Read certificates and private keys, from memory etc. | 92 | * Read certificates and private keys, from memory etc. |
203 | */ | 93 | */ |
diff --git a/src/daemon/https/x509/Makefile.am b/src/daemon/https/x509/Makefile.am index 54982372..9091fc4f 100644 --- a/src/daemon/https/x509/Makefile.am +++ b/src/daemon/https/x509/Makefile.am | |||
@@ -23,6 +23,5 @@ extensions.c extensions.h \ | |||
23 | mpi.c mpi.h \ | 23 | mpi.c mpi.h \ |
24 | pkcs12.h \ | 24 | pkcs12.h \ |
25 | x509_privkey.c privkey.h \ | 25 | x509_privkey.c privkey.h \ |
26 | x509_verify.c verify.h \ | ||
27 | x509.c x509.h | 26 | x509.c x509.h |
28 | 27 | ||
diff --git a/src/daemon/https/x509/common.c b/src/daemon/https/x509/common.c index 1d9c60c7..2dabe3e9 100644 --- a/src/daemon/https/x509/common.c +++ b/src/daemon/https/x509/common.c | |||
@@ -218,7 +218,7 @@ MHD_gnutls_x509_dn_oid_known (const char *oid) | |||
218 | /* Returns 1 if the data defined by the OID are of a choice | 218 | /* Returns 1 if the data defined by the OID are of a choice |
219 | * type. | 219 | * type. |
220 | */ | 220 | */ |
221 | int | 221 | static int |
222 | MHD__gnutls_x509_oid_data_choice (const char *oid) | 222 | MHD__gnutls_x509_oid_data_choice (const char *oid) |
223 | { | 223 | { |
224 | int i = 0; | 224 | int i = 0; |
@@ -815,7 +815,7 @@ MHD__gnutls_x509_export_int (ASN1_TYPE MHD__asn1_data, | |||
815 | * octet string. Otherwise put something like BMPString, PrintableString | 815 | * octet string. Otherwise put something like BMPString, PrintableString |
816 | * etc. | 816 | * etc. |
817 | */ | 817 | */ |
818 | int | 818 | static int |
819 | MHD__gnutls_x509_decode_octet_string (const char *string_type, | 819 | MHD__gnutls_x509_decode_octet_string (const char *string_type, |
820 | const opaque * der, | 820 | const opaque * der, |
821 | size_t der_size, | 821 | size_t der_size, |
@@ -1029,200 +1029,6 @@ cleanup:MHD_gnutls_free (data); | |||
1029 | 1029 | ||
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | /* DER Encodes the src ASN1_TYPE and stores it to | ||
1033 | * dest in dest_name. Useful to encode something and store it | ||
1034 | * as OCTET. If str is non null then the data are encoded as | ||
1035 | * an OCTET STRING. | ||
1036 | */ | ||
1037 | int | ||
1038 | MHD__gnutls_x509_der_encode_and_copy (ASN1_TYPE src, | ||
1039 | const char *src_name, | ||
1040 | ASN1_TYPE dest, | ||
1041 | const char *dest_name, int str) | ||
1042 | { | ||
1043 | int result; | ||
1044 | MHD_gnutls_datum_t encoded; | ||
1045 | |||
1046 | result = MHD__gnutls_x509_der_encode (src, src_name, &encoded, str); | ||
1047 | |||
1048 | if (result < 0) | ||
1049 | { | ||
1050 | MHD_gnutls_assert (); | ||
1051 | return result; | ||
1052 | } | ||
1053 | |||
1054 | /* Write the data. | ||
1055 | */ | ||
1056 | result = | ||
1057 | MHD__asn1_write_value (dest, dest_name, encoded.data, encoded.size); | ||
1058 | |||
1059 | MHD__gnutls_free_datum (&encoded); | ||
1060 | |||
1061 | if (result != ASN1_SUCCESS) | ||
1062 | { | ||
1063 | MHD_gnutls_assert (); | ||
1064 | return MHD_gtls_asn2err (result); | ||
1065 | } | ||
1066 | |||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1070 | /* Writes the value of the datum in the given ASN1_TYPE. If str is non | ||
1071 | * zero it encodes it as OCTET STRING. | ||
1072 | */ | ||
1073 | int | ||
1074 | MHD__gnutls_x509_write_value (ASN1_TYPE c, | ||
1075 | const char *root, | ||
1076 | const MHD_gnutls_datum_t * data, int str) | ||
1077 | { | ||
1078 | int result; | ||
1079 | int asize; | ||
1080 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1081 | MHD_gnutls_datum_t val; | ||
1082 | |||
1083 | asize = data->size + 16; | ||
1084 | |||
1085 | val.data = MHD_gnutls_malloc (asize); | ||
1086 | if (val.data == NULL) | ||
1087 | { | ||
1088 | MHD_gnutls_assert (); | ||
1089 | result = GNUTLS_E_MEMORY_ERROR; | ||
1090 | goto cleanup; | ||
1091 | } | ||
1092 | |||
1093 | if (str) | ||
1094 | { | ||
1095 | /* Convert it to OCTET STRING | ||
1096 | */ | ||
1097 | if ((result = | ||
1098 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
1099 | "PKIX1.pkcs-7-Data", | ||
1100 | &c2)) != ASN1_SUCCESS) | ||
1101 | { | ||
1102 | MHD_gnutls_assert (); | ||
1103 | result = MHD_gtls_asn2err (result); | ||
1104 | goto cleanup; | ||
1105 | } | ||
1106 | |||
1107 | result = MHD__asn1_write_value (c2, "", data->data, data->size); | ||
1108 | if (result != ASN1_SUCCESS) | ||
1109 | { | ||
1110 | MHD_gnutls_assert (); | ||
1111 | result = MHD_gtls_asn2err (result); | ||
1112 | goto cleanup; | ||
1113 | } | ||
1114 | |||
1115 | result = MHD__gnutls_x509_der_encode (c2, "", &val, 0); | ||
1116 | if (result < 0) | ||
1117 | { | ||
1118 | MHD_gnutls_assert (); | ||
1119 | goto cleanup; | ||
1120 | } | ||
1121 | |||
1122 | } | ||
1123 | else | ||
1124 | { | ||
1125 | val.data = data->data; | ||
1126 | val.size = data->size; | ||
1127 | } | ||
1128 | |||
1129 | /* Write the data. | ||
1130 | */ | ||
1131 | result = MHD__asn1_write_value (c, root, val.data, val.size); | ||
1132 | |||
1133 | if (val.data != data->data) | ||
1134 | MHD__gnutls_free_datum (&val); | ||
1135 | |||
1136 | if (result != ASN1_SUCCESS) | ||
1137 | { | ||
1138 | MHD_gnutls_assert (); | ||
1139 | return MHD_gtls_asn2err (result); | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | |||
1144 | cleanup:if (val.data != data->data) | ||
1145 | MHD__gnutls_free_datum (&val); | ||
1146 | return result; | ||
1147 | } | ||
1148 | |||
1149 | /* Encodes and copies the private key parameters into a | ||
1150 | * subjectPublicKeyInfo structure. | ||
1151 | * | ||
1152 | */ | ||
1153 | int | ||
1154 | MHD__gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, | ||
1155 | const char *dst_name, | ||
1156 | enum | ||
1157 | MHD_GNUTLS_PublicKeyAlgorithm | ||
1158 | pk_algorithm, mpi_t * params, | ||
1159 | int params_size) | ||
1160 | { | ||
1161 | const char *pk; | ||
1162 | MHD_gnutls_datum_t der = { NULL, | ||
1163 | 0 | ||
1164 | }; | ||
1165 | int result; | ||
1166 | char name[128]; | ||
1167 | |||
1168 | pk = MHD_gtls_x509_pk_to_oid (pk_algorithm); | ||
1169 | if (pk == NULL) | ||
1170 | { | ||
1171 | MHD_gnutls_assert (); | ||
1172 | return GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
1173 | } | ||
1174 | |||
1175 | /* write the OID | ||
1176 | */ | ||
1177 | MHD_gtls_str_cpy (name, sizeof (name), dst_name); | ||
1178 | MHD_gtls_str_cat (name, sizeof (name), ".algorithm.algorithm"); | ||
1179 | result = MHD__asn1_write_value (dst, name, pk, 1); | ||
1180 | if (result != ASN1_SUCCESS) | ||
1181 | { | ||
1182 | MHD_gnutls_assert (); | ||
1183 | return MHD_gtls_asn2err (result); | ||
1184 | } | ||
1185 | |||
1186 | if (pk_algorithm == MHD_GNUTLS_PK_RSA) | ||
1187 | { | ||
1188 | /* disable parameters, which are not used in RSA. | ||
1189 | */ | ||
1190 | MHD_gtls_str_cpy (name, sizeof (name), dst_name); | ||
1191 | MHD_gtls_str_cat (name, sizeof (name), ".algorithm.parameters"); | ||
1192 | result = MHD__asn1_write_value (dst, name, NULL, 0); | ||
1193 | if (result != ASN1_SUCCESS) | ||
1194 | { | ||
1195 | MHD_gnutls_assert (); | ||
1196 | return MHD_gtls_asn2err (result); | ||
1197 | } | ||
1198 | |||
1199 | result = MHD__gnutls_x509_write_rsa_params (params, params_size, &der); | ||
1200 | if (result < 0) | ||
1201 | { | ||
1202 | MHD_gnutls_assert (); | ||
1203 | return result; | ||
1204 | } | ||
1205 | |||
1206 | /* Write the DER parameters. (in bits) | ||
1207 | */ | ||
1208 | MHD_gtls_str_cpy (name, sizeof (name), dst_name); | ||
1209 | MHD_gtls_str_cat (name, sizeof (name), ".subjectPublicKey"); | ||
1210 | result = MHD__asn1_write_value (dst, name, der.data, der.size * 8); | ||
1211 | |||
1212 | MHD__gnutls_free_datum (&der); | ||
1213 | |||
1214 | if (result != ASN1_SUCCESS) | ||
1215 | { | ||
1216 | MHD_gnutls_assert (); | ||
1217 | return MHD_gtls_asn2err (result); | ||
1218 | } | ||
1219 | } | ||
1220 | else | ||
1221 | return GNUTLS_E_UNIMPLEMENTED_FEATURE; | ||
1222 | |||
1223 | return 0; | ||
1224 | } | ||
1225 | |||
1226 | /* Reads and returns the PK algorithm of the given certificate-like | 1032 | /* Reads and returns the PK algorithm of the given certificate-like |
1227 | * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". | 1033 | * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". |
1228 | */ | 1034 | */ |
diff --git a/src/daemon/https/x509/common.h b/src/daemon/https/x509/common.h index a35bbc0b..5fa84808 100644 --- a/src/daemon/https/x509/common.h +++ b/src/daemon/https/x509/common.h | |||
@@ -58,10 +58,6 @@ | |||
58 | #define SIG_GOST_R3410_94_OID "1.2.643.2.2.4" | 58 | #define SIG_GOST_R3410_94_OID "1.2.643.2.2.4" |
59 | #define SIG_GOST_R3410_2001_OID "1.2.643.2.2.3" | 59 | #define SIG_GOST_R3410_2001_OID "1.2.643.2.2.3" |
60 | 60 | ||
61 | int MHD__gnutls_x509_decode_octet_string (const char *string_type, | ||
62 | const opaque * der, size_t der_size, | ||
63 | opaque * output, | ||
64 | size_t * output_size); | ||
65 | int MHD__gnutls_x509_oid_data2string (const char *OID, void *value, | 61 | int MHD__gnutls_x509_oid_data2string (const char *OID, void *value, |
66 | int value_size, char *res, | 62 | int value_size, char *res, |
67 | size_t * res_size); | 63 | size_t * res_size); |
@@ -70,7 +66,6 @@ int MHD__gnutls_x509_data2hex (const opaque * data, size_t data_size, | |||
70 | 66 | ||
71 | const char *MHD__gnutls_x509_oid2ldap_string (const char *OID); | 67 | const char *MHD__gnutls_x509_oid2ldap_string (const char *OID); |
72 | 68 | ||
73 | int MHD__gnutls_x509_oid_data_choice (const char *OID); | ||
74 | int MHD__gnutls_x509_oid_data_printable (const char *OID); | 69 | int MHD__gnutls_x509_oid_data_printable (const char *OID); |
75 | 70 | ||
76 | time_t MHD__gnutls_x509_get_time (ASN1_TYPE c2, const char *when); | 71 | time_t MHD__gnutls_x509_get_time (ASN1_TYPE c2, const char *when); |
@@ -78,9 +73,6 @@ time_t MHD__gnutls_x509_get_time (ASN1_TYPE c2, const char *when); | |||
78 | MHD_gnutls_x509_subject_alt_name_t MHD__gnutls_x509_san_find_type (char | 73 | MHD_gnutls_x509_subject_alt_name_t MHD__gnutls_x509_san_find_type (char |
79 | *str_type); | 74 | *str_type); |
80 | 75 | ||
81 | int MHD__gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const char *src_name, | ||
82 | ASN1_TYPE dest, | ||
83 | const char *dest_name, int str); | ||
84 | int MHD__gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, | 76 | int MHD__gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, |
85 | MHD_gnutls_datum_t * res, int str); | 77 | MHD_gnutls_datum_t * res, int str); |
86 | 78 | ||
@@ -91,8 +83,6 @@ int MHD__gnutls_x509_export_int (ASN1_TYPE MHD__asn1_data, | |||
91 | 83 | ||
92 | int MHD__gnutls_x509_read_value (ASN1_TYPE c, const char *root, | 84 | int MHD__gnutls_x509_read_value (ASN1_TYPE c, const char *root, |
93 | MHD_gnutls_datum_t * ret, int str); | 85 | MHD_gnutls_datum_t * ret, int str); |
94 | int MHD__gnutls_x509_write_value (ASN1_TYPE c, const char *root, | ||
95 | const MHD_gnutls_datum_t * data, int str); | ||
96 | 86 | ||
97 | int MHD__gnutls_x509_decode_and_read_attribute (ASN1_TYPE MHD__asn1_struct, | 87 | int MHD__gnutls_x509_decode_and_read_attribute (ASN1_TYPE MHD__asn1_struct, |
98 | const char *where, char *oid, | 88 | const char *where, char *oid, |
@@ -103,12 +93,6 @@ int MHD__gnutls_x509_decode_and_read_attribute (ASN1_TYPE MHD__asn1_struct, | |||
103 | int MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, | 93 | int MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, |
104 | unsigned int *bits); | 94 | unsigned int *bits); |
105 | 95 | ||
106 | int MHD__gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, | ||
107 | const char *dst_name, | ||
108 | enum | ||
109 | MHD_GNUTLS_PublicKeyAlgorithm | ||
110 | pk_algorithm, mpi_t * params, | ||
111 | int params_size); | ||
112 | int MHD__gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name, | 96 | int MHD__gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name, |
113 | ASN1_TYPE src, const char *src_name); | 97 | ASN1_TYPE src, const char *src_name); |
114 | 98 | ||
diff --git a/src/daemon/https/x509/verify.h b/src/daemon/https/x509/verify.h deleted file mode 100644 index 8949d0b6..00000000 --- a/src/daemon/https/x509/verify.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 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 | #include "x509.h" | ||
26 | |||
27 | int MHD_gnutls_x509_crt_is_issuer (MHD_gnutls_x509_crt_t cert, | ||
28 | MHD_gnutls_x509_crt_t issuer); | ||
29 | int MHD__gnutls_x509_privkey_verify_signature (const MHD_gnutls_datum_t * tbs, | ||
30 | const MHD_gnutls_datum_t * | ||
31 | signature, | ||
32 | MHD_gnutls_x509_privkey_t | ||
33 | issuer); | ||
diff --git a/src/daemon/https/x509/x509.c b/src/daemon/https/x509/x509.c index 21c27371..8e3135c8 100644 --- a/src/daemon/https/x509/x509.c +++ b/src/daemon/https/x509/x509.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <libtasn1.h> | 37 | #include <libtasn1.h> |
38 | #include <mpi.h> | 38 | #include <mpi.h> |
39 | #include <privkey.h> | 39 | #include <privkey.h> |
40 | #include <verify.h> | ||
41 | 40 | ||
42 | /** | 41 | /** |
43 | * MHD_gnutls_x509_crt_init - This function initializes a MHD_gnutls_x509_crt_t structure | 42 | * MHD_gnutls_x509_crt_init - This function initializes a MHD_gnutls_x509_crt_t structure |
diff --git a/src/daemon/https/x509/x509.h b/src/daemon/https/x509/x509.h index f48a7d69..1c060373 100644 --- a/src/daemon/https/x509/x509.h +++ b/src/daemon/https/x509/x509.h | |||
@@ -300,15 +300,6 @@ extern "C" | |||
300 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32 | 300 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32 |
301 | } MHD_gnutls_certificate_verify_flags; | 301 | } MHD_gnutls_certificate_verify_flags; |
302 | 302 | ||
303 | int MHD_gnutls_x509_crt_list_verify (const MHD_gnutls_x509_crt_t * | ||
304 | cert_list, int cert_list_length, | ||
305 | const MHD_gnutls_x509_crt_t * CA_list, | ||
306 | int CA_list_length, | ||
307 | const MHD_gnutls_x509_crl_t * CRL_list, | ||
308 | int CRL_list_length, | ||
309 | unsigned int flags, | ||
310 | unsigned int *verify); | ||
311 | |||
312 | int MHD_gnutls_x509_crt_check_revocation (MHD_gnutls_x509_crt_t cert, | 303 | int MHD_gnutls_x509_crt_check_revocation (MHD_gnutls_x509_crt_t cert, |
313 | const MHD_gnutls_x509_crl_t * | 304 | const MHD_gnutls_x509_crl_t * |
314 | crl_list, int crl_list_length); | 305 | crl_list, int crl_list_length); |
diff --git a/src/daemon/https/x509/x509_privkey.c b/src/daemon/https/x509/x509_privkey.c index 473e8756..df4e0faa 100644 --- a/src/daemon/https/x509/x509_privkey.c +++ b/src/daemon/https/x509/x509_privkey.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <dn.h> | 35 | #include <dn.h> |
36 | #include <mpi.h> | 36 | #include <mpi.h> |
37 | #include <extensions.h> | 37 | #include <extensions.h> |
38 | #include <verify.h> | ||
39 | 38 | ||
40 | static int MHD__gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params); | 39 | static int MHD__gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params); |
41 | int MHD__gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params); | 40 | int MHD__gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params); |
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 | |||