*** empty log message ***
[gnutls.git] / lib / x509_extensions.c
blobbb737cc2b9147f7d5c4eb0cf2e7583a3c7e10a81
1 /*
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>
24 #include <x509_der.h>
25 #include <gnutls_num.h>
26 #include <gnutls_cert.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_global.h>
29 #include "debug.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,
36 int extnValueLen)
38 node_asn *ext;
39 char str[10];
40 int len, result;
42 keyUsage[0] = 0;
44 if ((result=asn1_create_structure
45 (_gnutls_get_pkix(), "PKIX1.KeyUsage", &ext,
46 "ku")) != ASN_OK) {
47 gnutls_assert();
48 return _gnutls_asn2err(result);
51 result = asn1_get_der(ext, extnValue, extnValueLen);
53 if (result != ASN_OK) {
54 gnutls_assert();
55 asn1_delete_structure(ext);
56 return 0;
59 len = sizeof(str) - 1;
60 result = asn1_read_value(ext, "ku", str, &len);
61 if (result != ASN_OK) {
62 gnutls_assert();
63 asn1_delete_structure(ext);
64 return 0;
67 keyUsage[0] = str[0];
69 asn1_delete_structure(ext);
71 return 0;
74 static int _extract_basicConstraints(int *CA, opaque * extnValue,
75 int extnValueLen)
77 node_asn *ext;
78 char str[128];
79 int len, result;
81 *CA = 0;
83 if ((result=asn1_create_structure
84 (_gnutls_get_pkix(), "PKIX1.BasicConstraints", &ext,
85 "bc")) != ASN_OK) {
86 gnutls_assert();
87 return _gnutls_asn2err(result);
90 result = asn1_get_der(ext, extnValue, extnValueLen);
92 if (result != ASN_OK) {
93 gnutls_assert();
94 asn1_delete_structure(ext);
95 return 0;
98 len = sizeof(str) - 1;
99 result = asn1_read_value(ext, "bc.cA", str, &len);
100 if (result != ASN_OK) {
101 gnutls_assert();
102 asn1_delete_structure(ext);
103 return 0;
106 asn1_delete_structure(ext);
108 if (strcmp(str, "TRUE") == 0)
109 *CA = 1;
110 else
111 *CA = 0;
114 return 0;
118 static int _parse_extension(gnutls_cert * cert, char *extnID,
119 char *critical, char *extnValue,
120 int extnValueLen)
123 if (strcmp(extnID, "2 5 29 14") == 0) { /* subject Key ID */
124 /* we don't use it */
125 return 0;
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,
137 extnValueLen);
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) {
144 gnutls_assert();
145 return GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION;
147 return 0;
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)
156 int k, result, len;
157 char name[128], name2[128], counter[MAX_INT_DIGITS];
158 char str[1024];
159 char critical[10];
160 char extnID[128];
161 char extnValue[256];
163 k = 0;
164 do {
165 k++;
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);
175 /* move to next
178 if (result == ASN_ELEMENT_NOT_FOUND)
179 break;
181 do {
183 _gnutls_str_cpy(name2, sizeof(name2), name);
184 _gnutls_str_cat(name2, sizeof(name2), ".extnID");
186 len = sizeof(extnID) - 1;
187 result =
188 asn1_read_value(rasn, name2, extnID, &len);
190 if (result == ASN_ELEMENT_NOT_FOUND)
191 break;
192 else if (result != ASN_OK) {
193 gnutls_assert();
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;
201 result =
202 asn1_read_value(rasn, name2, critical, &len);
204 if (result == ASN_ELEMENT_NOT_FOUND)
205 break;
206 else if (result != ASN_OK) {
207 gnutls_assert();
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;
215 result =
216 asn1_read_value(rasn, name2, extnValue, &len);
218 if (result == ASN_ELEMENT_NOT_FOUND)
219 break;
220 else {
221 if (result == ASN_MEM_ERROR
222 && strcmp(critical, "FALSE") == 0) {
224 _gnutls_x509_log
225 ("X509_EXT: Cannot parse extension: %s. Too small buffer.",
226 extnID);
228 continue;
230 if (result != ASN_OK) {
231 gnutls_assert();
232 return _gnutls_asn2err(result);
236 /* Handle Extension */
237 if ((result =
238 _parse_extension(cert, extnID, critical,
239 extnValue, len)) < 0) {
240 gnutls_assert();
241 return result;
245 } while (0);
246 } while (1);
248 if (result == ASN_ELEMENT_NOT_FOUND)
249 return 0;
250 else
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
256 * ret.
258 int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, gnutls_datum* ret)
260 int k, result, len;
261 char name[128], name2[128], counter[MAX_INT_DIGITS];
262 char str[1024];
263 char critical[10];
264 char extnID[128];
265 char extnValue[256];
266 node_asn* rasn;
268 ret->data = NULL;
269 ret->size = 0;
271 if ((result=asn1_create_structure
272 (_gnutls_get_pkix(), "PKIX1.Certificate", &rasn,
273 "certificate2"))
274 != ASN_OK) {
275 gnutls_assert();
276 return _gnutls_asn2err(result);
279 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);
286 gnutls_assert();
287 asn1_delete_structure(rasn);
288 return _gnutls_asn2err(result);
291 k = 0;
292 do {
293 k++;
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);
303 /* move to next
306 if (result == ASN_ELEMENT_NOT_FOUND) {
307 gnutls_assert();
308 break;
311 do {
313 _gnutls_str_cpy(name2, sizeof(name2), name);
314 _gnutls_str_cat(name2, sizeof(name2), ".extnID");
316 len = sizeof(extnID) - 1;
317 result =
318 asn1_read_value(rasn, name2, extnID, &len);
320 if (result == ASN_ELEMENT_NOT_FOUND) {
321 gnutls_assert();
322 break;
323 } else if (result != ASN_OK) {
324 gnutls_assert();
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;
332 result =
333 asn1_read_value(rasn, name2, critical, &len);
335 if (result == ASN_ELEMENT_NOT_FOUND) {
336 gnutls_assert();
337 break;
338 } else if (result != ASN_OK) {
339 gnutls_assert();
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;
348 result =
349 asn1_read_value(rasn, name2, extnValue, &len);
351 if (result == ASN_ELEMENT_NOT_FOUND)
352 break;
353 else {
354 if (result == ASN_MEM_ERROR
355 && strcmp(critical, "FALSE") == 0) {
357 _gnutls_x509_log
358 ("X509_EXT: Cannot parse extension: %s. Too small buffer.",
359 extnID);
361 continue;
363 if (result != ASN_OK) {
364 gnutls_assert();
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);
374 if (ret->data==NULL)
375 return GNUTLS_E_MEMORY_ERROR;
377 ret->size = len;
378 memcpy( ret->data, extnValue, len);
380 return 0;
384 } while (0);
385 } while (1);
387 asn1_delete_structure(rasn);
390 if (result == ASN_ELEMENT_NOT_FOUND) {
391 gnutls_assert();
392 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
393 } else {
394 gnutls_assert();
395 return _gnutls_asn2err(result);