aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2008-11-16 04:47:42 +0000
committerChristian Grothoff <christian@grothoff.org>2008-11-16 04:47:42 +0000
commit26766bf6f7a161b7df8170d5e8f1a088da13f12c (patch)
treebbc5b22ace516fab13da6afc9bfe3244683a183b
parent3b9bb09488b3d5d03a9517c810539f5b9e985d96 (diff)
downloadlibmicrohttpd-26766bf6f7a161b7df8170d5e8f1a088da13f12c.tar.gz
libmicrohttpd-26766bf6f7a161b7df8170d5e8f1a088da13f12c.zip
more DCE
-rw-r--r--src/daemon/https/gnutls.h6
-rw-r--r--src/daemon/https/tls/gnutls_cert.c86
-rw-r--r--src/daemon/https/tls/gnutls_x509.c110
-rw-r--r--src/daemon/https/x509/Makefile.am1
-rw-r--r--src/daemon/https/x509/common.c198
-rw-r--r--src/daemon/https/x509/common.h16
-rw-r--r--src/daemon/https/x509/verify.h33
-rw-r--r--src/daemon/https/x509/x509.c1
-rw-r--r--src/daemon/https/x509/x509.h9
-rw-r--r--src/daemon/https/x509/x509_privkey.c1
-rw-r--r--src/daemon/https/x509/x509_verify.c715
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 **/
458int
459MHD_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 **/
501int
502MHD_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 -*/
102int
103MHD__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 \
23mpi.c mpi.h \ 23mpi.c mpi.h \
24pkcs12.h \ 24pkcs12.h \
25x509_privkey.c privkey.h \ 25x509_privkey.c privkey.h \
26x509_verify.c verify.h \
27x509.c x509.h 26x509.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 */
221int 221static int
222MHD__gnutls_x509_oid_data_choice (const char *oid) 222MHD__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 */
818int 818static int
819MHD__gnutls_x509_decode_octet_string (const char *string_type, 819MHD__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 */
1037int
1038MHD__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 */
1073int
1074MHD__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
1144cleanup: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 */
1153int
1154MHD__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
61int 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);
65int MHD__gnutls_x509_oid_data2string (const char *OID, void *value, 61int 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
71const char *MHD__gnutls_x509_oid2ldap_string (const char *OID); 67const char *MHD__gnutls_x509_oid2ldap_string (const char *OID);
72 68
73int MHD__gnutls_x509_oid_data_choice (const char *OID);
74int MHD__gnutls_x509_oid_data_printable (const char *OID); 69int MHD__gnutls_x509_oid_data_printable (const char *OID);
75 70
76time_t MHD__gnutls_x509_get_time (ASN1_TYPE c2, const char *when); 71time_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);
78MHD_gnutls_x509_subject_alt_name_t MHD__gnutls_x509_san_find_type (char 73MHD_gnutls_x509_subject_alt_name_t MHD__gnutls_x509_san_find_type (char
79 *str_type); 74 *str_type);
80 75
81int 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);
84int MHD__gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, 76int 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
92int MHD__gnutls_x509_read_value (ASN1_TYPE c, const char *root, 84int 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);
94int MHD__gnutls_x509_write_value (ASN1_TYPE c, const char *root,
95 const MHD_gnutls_datum_t * data, int str);
96 86
97int MHD__gnutls_x509_decode_and_read_attribute (ASN1_TYPE MHD__asn1_struct, 87int 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,
103int MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, 93int MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name,
104 unsigned int *bits); 94 unsigned int *bits);
105 95
106int 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);
112int MHD__gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name, 96int 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
27int MHD_gnutls_x509_crt_is_issuer (MHD_gnutls_x509_crt_t cert,
28 MHD_gnutls_x509_crt_t issuer);
29int 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
40static int MHD__gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params); 39static int MHD__gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params);
41int MHD__gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params); 40int 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
44static 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);
49static 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 */
60static int
61check_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
145cleanup: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 */
159static int
160is_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
185cleanup:MHD__gnutls_free_datum (&dn1);
186 MHD__gnutls_free_datum (&dn2);
187 return ret;
188
189}
190
191static inline MHD_gnutls_x509_crt_t
192find_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 */
222static int
223MHD__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
336cleanup: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 **/
354static int
355MHD_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 */
372static unsigned int
373MHD__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 */
444static int
445decode_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 */
525static 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 */
587static int
588verify_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 */
621static int
622MHD__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 **/
694int
695MHD_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