2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos <nmav@hellug.gr>
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_cert.h"
25 #include "x509_asn1.h"
27 #include "gnutls_global.h"
28 #include "gnutls_num.h" /* GMAX */
29 #include <gnutls_sig.h>
30 #include <gnutls_str.h>
33 /* Return 0 or INVALID, if the issuer is a CA,
36 static int check_if_ca(const gnutls_cert
* cert
,
37 const gnutls_cert
* issuer
)
39 CertificateStatus ret
= GNUTLS_CERT_INVALID
;
41 /* Check if the issuer is the same with the
42 * certificate. This is added in order for trusted
43 * certificates to be able to verify themselves.
45 if (cert
->raw
.size
== issuer
->raw
.size
) {
47 (cert
->raw
.data
, issuer
->raw
.data
,
48 cert
->raw
.size
) == 0) {
53 if (issuer
->CA
== 1) {
63 void _gnutls_int2str(int k
, char *data
);
65 #define MAX_DN_ELEM 1024
67 /* This function checks if 'certs' issuer is 'issuer_cert'.
68 * This does a straight (DER) compare of the issuer/subject fields in
69 * the given certificates.
71 * FIXME: use a real DN comparison algorithm.
74 int compare_dn(gnutls_cert
* cert
, gnutls_cert
* issuer_cert
)
80 int start1
, start2
, end1
, end2
;
82 /* get the issuer of 'cert'
85 asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate",
86 &c2
, "certificate2")) != ASN_OK
) {
88 return _gnutls_asn2err(result
);
91 result
= asn1_get_der(c2
, cert
->raw
.data
, cert
->raw
.size
);
92 if (result
!= ASN_OK
) {
93 /* couldn't decode DER */
95 asn1_delete_structure(c2
);
96 return _gnutls_asn2err(result
);
101 /* get the 'subject' info of 'issuer_cert'
104 asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate",
105 &c3
, "certificate2")) != ASN_OK
) {
107 asn1_delete_structure(c2
);
108 return _gnutls_asn2err(result
);
112 asn1_get_der(c3
, issuer_cert
->raw
.data
, issuer_cert
->raw
.size
);
113 if (result
!= ASN_OK
) {
114 /* couldn't decode DER */
116 asn1_delete_structure(c2
);
117 return _gnutls_asn2err(result
);
121 _gnutls_str_cpy(tmpstr
, sizeof(tmpstr
),
122 "certificate2.tbsCertificate.issuer");
124 asn1_get_start_end_der(c2
, cert
->raw
.data
, cert
->raw
.size
,
125 tmpstr
, &start1
, &end1
);
126 asn1_delete_structure(c2
);
128 if (result
!= ASN_OK
) {
130 asn1_delete_structure(c3
);
131 return _gnutls_asn2err(result
);
134 len1
= end1
- start1
+ 1;
136 _gnutls_str_cpy(tmpstr
, sizeof(tmpstr
),
137 "certificate2.tbsCertificate.subject");
139 asn1_get_start_end_der(c3
, issuer_cert
->raw
.data
,
140 issuer_cert
->raw
.size
, tmpstr
, &start2
,
142 asn1_delete_structure(c3
);
144 if (result
!= ASN_OK
) {
146 return _gnutls_asn2err(result
);
149 len2
= end2
- start2
+ 1;
151 /* The error code returned does not really matter
156 return GNUTLS_E_UNKNOWN_ERROR
;
158 if (memcmp(&issuer_cert
->raw
.data
[start2
],
159 &cert
->raw
.data
[start1
], len1
) != 0) {
161 return GNUTLS_E_UNKNOWN_ERROR
;
169 static gnutls_cert
*find_issuer(gnutls_cert
* cert
,
170 gnutls_cert
* trusted_cas
, int tcas_size
)
174 /* this is serial search.
177 for (i
= 0; i
< tcas_size
; i
++) {
178 if (compare_dn(cert
, &trusted_cas
[i
]) == 0)
179 return &trusted_cas
[i
];
186 /* ret_trust is the value to return when the certificate chain is ok
187 * ret_else is the value to return otherwise.
189 int gnutls_verify_certificate2(gnutls_cert
* cert
,
190 gnutls_cert
* trusted_cas
, int tcas_size
,
191 void *CRLs
, int crls_size
, int ret_trust
,
194 /* CRL is ignored for now */
200 issuer
= find_issuer(cert
, trusted_cas
, tcas_size
);
206 /* issuer is not in trusted certificate
209 if (issuer
== NULL
) {
214 ret
= check_if_ca(cert
, issuer
);
217 return ret_else
| GNUTLS_CERT_INVALID
;
220 ret
= gnutls_x509_verify_signature(cert
, issuer
);
223 return ret_else
| GNUTLS_CERT_INVALID
;
226 /* FIXME: Check CRL --not done yet.
233 /* The algorithm used is:
234 * 1. Check the certificate chain given by the peer, if it is ok.
235 * 2. If any certificate in the chain are revoked, not
236 * valid, or they are not CAs then the certificate is invalid.
237 * 3. If 1 is ok, then find a certificate in the trusted CAs file
238 * that has the DN of the issuer field in the last certificate
239 * in the peer's certificate chain.
240 * 4. If it does exist then verify it. If verification is ok then
241 * it is trusted. Otherwise it is just valid (but not trusted).
243 /* This function verifies a X.509 certificate list. The certificate list should
244 * lead to a trusted CA in order to be trusted.
246 int _gnutls_x509_verify_certificate(gnutls_cert
* certificate_list
,
248 gnutls_cert
* trusted_cas
,
249 int tcas_size
, void *CRLs
,
253 CertificateStatus status
= 0;
255 if (clist_size
== 0) {
256 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
259 /* Verify the certificate path */
260 for (i
= 0; i
< clist_size
; i
++) {
261 if (i
+ 1 >= clist_size
)
265 gnutls_verify_certificate2(&certificate_list
[i
],
266 &certificate_list
[i
+ 1],
268 GNUTLS_CERT_INVALID
)) !=
271 * We only accept the first certificate to be
272 * expired, revoked etc. If any of the certificates in the
273 * certificate chain is expired then the certificate
286 if (status
> 0) { /* If there is any problem in the
287 * certificate chain then mark as not trusted
288 * and return immediately.
290 return (status
| GNUTLS_CERT_NOT_TRUSTED
);
293 /* Now verify the last certificate in the certificate path
294 * against the trusted CA certificate list.
296 * If no CAs are present returns NOT_TRUSTED. Thus works
297 * in self signed etc certificates.
300 gnutls_verify_certificate2(&certificate_list
[i
], trusted_cas
,
301 tcas_size
, CRLs
, crls_size
, 0,
302 GNUTLS_CERT_NOT_TRUSTED
);
305 /* if the last certificate in the certificate
306 * list is invalid, then the certificate is not
318 /* if we got here, then it's trusted.