2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
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 <x509_asn1.h>
25 #include <gnutls_num.h>
26 #include <gnutls_cert.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_global.h>
30 #include <gnutls_str.h>
31 #include <gnutls_x509.h>
33 /* Here we only extract the KeyUsage field
35 static int _extract_keyUsage(uint16
*keyUsage
, opaque
* extnValue
,
44 if ((result
=asn1_create_structure
45 (_gnutls_get_pkix(), "PKIX1.KeyUsage", &ext
,
48 return _gnutls_asn2err(result
);
51 result
= asn1_get_der(ext
, extnValue
, extnValueLen
);
53 if (result
!= ASN_OK
) {
55 asn1_delete_structure(ext
);
59 len
= sizeof(str
) - 1;
60 result
= asn1_read_value(ext
, "ku", str
, &len
);
61 if (result
!= ASN_OK
) {
63 asn1_delete_structure(ext
);
69 asn1_delete_structure(ext
);
74 static int _extract_basicConstraints(int *CA
, opaque
* extnValue
,
83 if ((result
=asn1_create_structure
84 (_gnutls_get_pkix(), "PKIX1.BasicConstraints", &ext
,
87 return _gnutls_asn2err(result
);
90 result
= asn1_get_der(ext
, extnValue
, extnValueLen
);
92 if (result
!= ASN_OK
) {
94 asn1_delete_structure(ext
);
98 len
= sizeof(str
) - 1;
99 result
= asn1_read_value(ext
, "bc.cA", str
, &len
);
100 if (result
!= ASN_OK
) {
102 asn1_delete_structure(ext
);
106 asn1_delete_structure(ext
);
108 if (strcmp(str
, "TRUE") == 0)
118 static int _parse_extension(gnutls_cert
* cert
, char *extnID
,
119 char *critical
, char *extnValue
,
123 if (strcmp(extnID
, "2 5 29 14") == 0) { /* subject Key ID */
124 /* we don't use it */
128 if (strcmp(extnID
, "2 5 29 15") == 0) { /* Key Usage */
129 return _extract_keyUsage(&cert
->keyUsage
, extnValue
, extnValueLen
);
132 if (strcmp(extnID
, "2 5 29 19") == 0) { /* Basic Constraints */
133 /* actually checks if a certificate belongs to
134 * a Certificate Authority.
136 return _extract_basicConstraints(&cert
->CA
, extnValue
,
140 _gnutls_x509_log("X509_EXT: CERT[%s]: Unsupported Extension: %s, %s\n",
141 GET_CN(cert
->raw
), extnID
, critical
);
143 if (strcmp(critical
, "TRUE") == 0) {
145 return GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION
;
151 /* This function will attempt to parse Extensions in
152 * an X509v3 certificate
154 int _gnutls_get_ext_type(node_asn
* rasn
, char *root
, gnutls_cert
* cert
)
157 char name
[128], name2
[128], counter
[MAX_INT_DIGITS
];
167 _gnutls_str_cpy(name
, sizeof(name
), root
);
168 _gnutls_str_cat(name
, sizeof(name
), ".?");
169 _gnutls_int2str(k
, counter
);
170 _gnutls_str_cat(name
, sizeof(name
), counter
);
172 len
= sizeof(str
) - 1;
173 result
= asn1_read_value(rasn
, name
, str
, &len
);
178 if (result
== ASN_ELEMENT_NOT_FOUND
)
183 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
184 _gnutls_str_cat(name2
, sizeof(name2
), ".extnID");
186 len
= sizeof(extnID
) - 1;
188 asn1_read_value(rasn
, name2
, extnID
, &len
);
190 if (result
== ASN_ELEMENT_NOT_FOUND
)
192 else if (result
!= ASN_OK
) {
194 return _gnutls_asn2err(result
);
197 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
198 _gnutls_str_cat(name2
, sizeof(name2
), ".critical");
200 len
= sizeof(critical
) - 1;
202 asn1_read_value(rasn
, name2
, critical
, &len
);
204 if (result
== ASN_ELEMENT_NOT_FOUND
)
206 else if (result
!= ASN_OK
) {
208 return _gnutls_asn2err(result
);
211 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
212 _gnutls_str_cat(name2
, sizeof(name2
), ".extnValue");
214 len
= sizeof(extnValue
) - 1;
216 asn1_read_value(rasn
, name2
, extnValue
, &len
);
218 if (result
== ASN_ELEMENT_NOT_FOUND
)
221 if (result
== ASN_MEM_ERROR
222 && strcmp(critical
, "FALSE") == 0) {
225 ("X509_EXT: Cannot parse extension: %s. Too small buffer.",
230 if (result
!= ASN_OK
) {
232 return _gnutls_asn2err(result
);
236 /* Handle Extension */
238 _parse_extension(cert
, extnID
, critical
,
239 extnValue
, len
)) < 0) {
248 if (result
== ASN_ELEMENT_NOT_FOUND
)
251 return _gnutls_asn2err(result
);
254 /* This function will attempt to return the requested extension found in
255 * the given X509v3 certificate. The return value is allocated and stored into
258 int _gnutls_get_extension( const gnutls_datum
* cert
, const char* extension_id
, gnutls_datum
* ret
)
261 char name
[128], name2
[128], counter
[MAX_INT_DIGITS
];
271 if ((result
=asn1_create_structure
272 (_gnutls_get_pkix(), "PKIX1.Certificate", &rasn
,
276 return _gnutls_asn2err(result
);
280 asn1_get_der(rasn
, cert
->data
, cert
->size
);
281 if (result
!= ASN_OK
) {
282 /* couldn't decode DER */
284 _gnutls_x509_log("X509_EXT: Decoding error %d\n", result
);
287 asn1_delete_structure(rasn
);
288 return _gnutls_asn2err(result
);
295 _gnutls_str_cpy(name
, sizeof(name
), "certificate2.tbsCertificate.extensions");
296 _gnutls_str_cat(name
, sizeof(name
), ".?");
297 _gnutls_int2str(k
, counter
);
298 _gnutls_str_cat(name
, sizeof(name
), counter
);
300 len
= sizeof(str
) - 1;
301 result
= asn1_read_value(rasn
, name
, str
, &len
);
306 if (result
== ASN_ELEMENT_NOT_FOUND
) {
313 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
314 _gnutls_str_cat(name2
, sizeof(name2
), ".extnID");
316 len
= sizeof(extnID
) - 1;
318 asn1_read_value(rasn
, name2
, extnID
, &len
);
320 if (result
== ASN_ELEMENT_NOT_FOUND
) {
323 } else if (result
!= ASN_OK
) {
325 return _gnutls_asn2err(result
);
328 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
329 _gnutls_str_cat(name2
, sizeof(name2
), ".critical");
331 len
= sizeof(critical
) - 1;
333 asn1_read_value(rasn
, name2
, critical
, &len
);
335 if (result
== ASN_ELEMENT_NOT_FOUND
) {
338 } else if (result
!= ASN_OK
) {
340 asn1_delete_structure(rasn
);
341 return _gnutls_asn2err(result
);
344 _gnutls_str_cpy(name2
, sizeof(name2
), name
);
345 _gnutls_str_cat(name2
, sizeof(name2
), ".extnValue");
347 len
= sizeof(extnValue
) - 1;
349 asn1_read_value(rasn
, name2
, extnValue
, &len
);
351 if (result
== ASN_ELEMENT_NOT_FOUND
)
354 if (result
== ASN_MEM_ERROR
355 && strcmp(critical
, "FALSE") == 0) {
358 ("X509_EXT: Cannot parse extension: %s. Too small buffer.",
363 if (result
!= ASN_OK
) {
365 asn1_delete_structure(rasn
);
366 return _gnutls_asn2err(result
);
370 /* Handle Extension */
371 if ( strcmp(extnID
, extension_id
)==0) { /* extension was found */
372 asn1_delete_structure(rasn
);
373 ret
->data
= gnutls_malloc( len
);
375 return GNUTLS_E_MEMORY_ERROR
;
378 memcpy( ret
->data
, extnValue
, len
);
387 asn1_delete_structure(rasn
);
390 if (result
== ASN_ELEMENT_NOT_FOUND
) {
392 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
395 return _gnutls_asn2err(result
);