2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos <nmav@hellug.gr>
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include "gnutls_int.h"
22 #include "gnutls_errors.h"
23 #include "gnutls_cert.h"
24 #include "x509_asn1.h"
26 #include "gnutls_global.h"
27 #include "gnutls_num.h" /* GMAX */
28 #include <gnutls_sig.h>
29 #include <gnutls_str.h>
32 /* Return 0 or INVALID, if the issuer is a CA,
35 static int check_if_ca(const gnutls_cert
* cert
,
36 const gnutls_cert
* issuer
)
38 CertificateStatus ret
= GNUTLS_CERT_INVALID
;
40 /* Check if the issuer is the same with the
41 * certificate. This is added in order for trusted
42 * certificates to be able to verify themselves.
44 if (cert
->raw
.size
== issuer
->raw
.size
) {
46 (cert
->raw
.data
, issuer
->raw
.data
,
47 cert
->raw
.size
) == 0) {
52 if (issuer
->CA
== 1) {
62 void _gnutls_int2str(int k
, char *data
);
64 #define MAX_DN_ELEM 1024
66 /* This function checks if 'certs' issuer is 'issuer_cert'.
67 * This does a straight (DER) compare of the issuer/subject fields in
68 * the given certificates.
70 * FIXME: use a real DN comparison algorithm.
73 int compare_dn(gnutls_cert
* cert
, gnutls_cert
* issuer_cert
)
79 int start1
, start2
, end1
, end2
;
81 /* get the issuer of 'cert'
84 asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate",
85 &c2
, "certificate2")) != ASN_OK
) {
87 return _gnutls_asn2err(result
);
90 result
= asn1_get_der(c2
, cert
->raw
.data
, cert
->raw
.size
);
91 if (result
!= ASN_OK
) {
92 /* couldn't decode DER */
94 asn1_delete_structure(c2
);
95 return _gnutls_asn2err(result
);
100 /* get the 'subject' info of 'issuer_cert'
103 asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate",
104 &c3
, "certificate2")) != ASN_OK
) {
106 asn1_delete_structure(c2
);
107 return _gnutls_asn2err(result
);
111 asn1_get_der(c3
, issuer_cert
->raw
.data
, issuer_cert
->raw
.size
);
112 if (result
!= ASN_OK
) {
113 /* couldn't decode DER */
115 asn1_delete_structure(c2
);
116 return _gnutls_asn2err(result
);
120 _gnutls_str_cpy(tmpstr
, sizeof(tmpstr
),
121 "certificate2.tbsCertificate.issuer");
123 asn1_get_start_end_der(c2
, cert
->raw
.data
, cert
->raw
.size
,
124 tmpstr
, &start1
, &end1
);
125 asn1_delete_structure(c2
);
127 if (result
!= ASN_OK
) {
129 asn1_delete_structure(c3
);
130 return _gnutls_asn2err(result
);
133 len1
= end1
- start1
+ 1;
135 _gnutls_str_cpy(tmpstr
, sizeof(tmpstr
),
136 "certificate2.tbsCertificate.subject");
138 asn1_get_start_end_der(c3
, issuer_cert
->raw
.data
,
139 issuer_cert
->raw
.size
, tmpstr
, &start2
,
141 asn1_delete_structure(c3
);
143 if (result
!= ASN_OK
) {
145 return _gnutls_asn2err(result
);
148 len2
= end2
- start2
+ 1;
150 /* The error code returned does not really matter
155 return GNUTLS_E_UNKNOWN_ERROR
;
157 if (memcmp(&issuer_cert
->raw
.data
[start2
],
158 &cert
->raw
.data
[start1
], len1
) != 0) {
160 return GNUTLS_E_UNKNOWN_ERROR
;
168 static gnutls_cert
*find_issuer(gnutls_cert
* cert
,
169 gnutls_cert
* trusted_cas
, int tcas_size
)
173 /* this is serial search.
176 for (i
= 0; i
< tcas_size
; i
++) {
177 if (compare_dn(cert
, &trusted_cas
[i
]) == 0)
178 return &trusted_cas
[i
];
185 /* ret_trust is the value to return when the certificate chain is ok
186 * ret_else is the value to return otherwise.
188 int gnutls_verify_certificate2(gnutls_cert
* cert
,
189 gnutls_cert
* trusted_cas
, int tcas_size
,
190 void *CRLs
, int crls_size
, int ret_trust
,
193 /* CRL is ignored for now */
199 issuer
= find_issuer(cert
, trusted_cas
, tcas_size
);
205 /* issuer is not in trusted certificate
208 if (issuer
== NULL
) {
213 ret
= check_if_ca(cert
, issuer
);
216 return ret_else
| GNUTLS_CERT_INVALID
;
219 ret
= gnutls_x509_verify_signature(cert
, issuer
);
222 return ret_else
| GNUTLS_CERT_INVALID
;
225 /* FIXME: Check CRL --not done yet.
232 /* The algorithm used is:
233 * 1. Check the certificate chain given by the peer, if it is ok.
234 * 2. If any certificate in the chain are revoked, not
235 * valid, or they are not CAs then the certificate is invalid.
236 * 3. If 1 is ok, then find a certificate in the trusted CAs file
237 * that has the DN of the issuer field in the last certificate
238 * in the peer's certificate chain.
239 * 4. If it does exist then verify it. If verification is ok then
240 * it is trusted. Otherwise it is just valid (but not trusted).
242 /* This function verifies a X.509 certificate list. The certificate list should
243 * lead to a trusted CA in order to be trusted.
245 int _gnutls_x509_verify_certificate(gnutls_cert
* certificate_list
,
247 gnutls_cert
* trusted_cas
,
248 int tcas_size
, void *CRLs
,
252 CertificateStatus status
= 0;
254 if (clist_size
== 0) {
255 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
258 /* Verify the certificate path */
259 for (i
= 0; i
< clist_size
; i
++) {
260 if (i
+ 1 >= clist_size
)
264 gnutls_verify_certificate2(&certificate_list
[i
],
265 &certificate_list
[i
+ 1],
267 GNUTLS_CERT_INVALID
)) !=
270 * We only accept the first certificate to be
271 * expired, revoked etc. If any of the certificates in the
272 * certificate chain is expired then the certificate
285 if (status
> 0) { /* If there is any problem in the
286 * certificate chain then mark as not trusted
287 * and return immediately.
289 return (status
| GNUTLS_CERT_NOT_TRUSTED
);
292 /* Now verify the last certificate in the certificate path
293 * against the trusted CA certificate list.
295 * If no CAs are present returns NOT_TRUSTED. Thus works
296 * in self signed etc certificates.
299 gnutls_verify_certificate2(&certificate_list
[i
], trusted_cas
,
300 tcas_size
, CRLs
, crls_size
, 0,
301 GNUTLS_CERT_NOT_TRUSTED
);
304 /* if the last certificate in the certificate
305 * list is invalid, then the certificate is not
317 /* if we got here, then it's trusted.