2 * Copyright (C) 2001 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 "gnutls_extensions.h"
24 #include "gnutls_errors.h"
25 #include "ext_max_record.h"
26 #include <ext_cert_type.h>
27 #include "gnutls_num.h"
29 /* Key Exchange Section */
30 #define GNUTLS_EXTENSION_ENTRY(type, ext_func_recv, ext_func_send) \
31 { #type, type, ext_func_recv, ext_func_send }
34 #define MAX_EXT_SIZE 10
35 const int _gnutls_extensions_size
= MAX_EXT_SIZE
;
37 gnutls_extension_entry _gnutls_extensions
[MAX_EXT_SIZE
] = {
38 GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_MAX_RECORD_SIZE
, _gnutls_max_record_recv_params
, _gnutls_max_record_send_params
),
39 GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_CERT_TYPE
, _gnutls_cert_type_recv_params
, _gnutls_cert_type_send_params
),
43 #define GNUTLS_EXTENSION_LOOP2(b) \
44 gnutls_extension_entry *p; \
45 for(p = _gnutls_extensions; p->name != NULL; p++) { b ; }
47 #define GNUTLS_EXTENSION_LOOP(a) \
48 GNUTLS_EXTENSION_LOOP2( if(p->type == type) { a; break; } )
51 /* EXTENSION functions */
53 void* _gnutls_ext_func_recv(uint16 type
)
56 GNUTLS_EXTENSION_LOOP(ret
= p
->gnutls_ext_func_recv
);
60 void* _gnutls_ext_func_send(uint16 type
)
63 GNUTLS_EXTENSION_LOOP(ret
= p
->gnutls_ext_func_send
);
68 const char *_gnutls_extension_get_name(uint16 type
)
73 GNUTLS_EXTENSION_LOOP(ret
= p
->name
+ sizeof("EXTENSION_") - 1);
78 /* Checks if the extension we just received is one of the
79 * requested ones. Otherwise it's a fatal error.
81 static int _gnutls_extension_list_check( GNUTLS_STATE state
, uint8 type
) {
83 if (state
->security_parameters
.entity
==GNUTLS_CLIENT
) {
84 for(i
=0;i
<state
->gnutls_internals
.extensions_sent_size
;i
++) {
85 if (type
==state
->gnutls_internals
.extensions_sent
[i
])
86 return 0; /* ok found */
88 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
;
94 int _gnutls_parse_extensions( GNUTLS_STATE state
, const opaque
* data
, int data_size
) {
99 int (*ext_func_recv
)( GNUTLS_STATE
, const opaque
*, int);
105 if (state
->security_parameters
.entity
==GNUTLS_CLIENT
)
106 for (i
=0;i
<state
->gnutls_internals
.extensions_sent_size
;i
++) {
107 _gnutls_log("EXT: expecting extension %d\n", state
->gnutls_internals
.extensions_sent
[i
]);
111 DECR_LENGTH_RET( data_size
, 2, 0);
112 next
= _gnutls_read_uint16( data
);
115 DECR_LENGTH_RET( data_size
, next
, 0);
118 DECR_LENGTH_RET( next
, 1, 0);
119 type
= _gnutls_read_uint16( &data
[pos
]);
122 if ( (ret
=_gnutls_extension_list_check( state
, type
)) < 0) {
127 DECR_LENGTH_RET( next
, 2, 0);
128 size
= _gnutls_read_uint16(&data
[pos
]);
131 DECR_LENGTH_RET( next
, size
, 0);
135 ext_func_recv
= _gnutls_ext_func_recv(type
);
136 if (ext_func_recv
== NULL
) continue;
137 if ( (ret
=ext_func_recv( state
, sdata
, size
)) < 0) {
148 /* Adds the extension we want to send in the extensions list.
149 * This list is used to check whether the (later) received
150 * extensions are the ones we requested.
152 static void _gnutls_extension_list_add( GNUTLS_STATE state
, uint8 type
) {
154 if (state
->security_parameters
.entity
==GNUTLS_CLIENT
) {
155 if (state
->gnutls_internals
.extensions_sent_size
<
156 sizeof(state
->gnutls_internals
.extensions_sent
)) {
158 state
->gnutls_internals
.extensions_sent
[state
->gnutls_internals
.extensions_sent_size
] = type
;
159 state
->gnutls_internals
.extensions_sent_size
++;
162 _gnutls_log("EXT: Increase MAX_EXT_TYPES\n");
170 int _gnutls_gen_extensions( GNUTLS_STATE state
, opaque
** data
) {
174 int sdata_size
= sizeof(sdata
);
175 int (*ext_func_send
)( GNUTLS_STATE
, opaque
*, int);
178 (*data
) = gnutls_malloc(2); /* allocate size for size */
183 return GNUTLS_E_MEMORY_ERROR
;
186 next
= MAX_EXT_TYPES
; /* maximum supported extensions */
189 ext_func_send
= _gnutls_ext_func_send(next
);
190 if (ext_func_send
== NULL
) continue;
191 size
= ext_func_send( state
, sdata
, sdata_size
);
194 (*data
) = gnutls_realloc( (*data
), pos
+size
+4);
197 return GNUTLS_E_MEMORY_ERROR
;
200 /* write extension type */
201 _gnutls_write_uint16( next
, &(*data
)[pos
]);
205 _gnutls_write_uint16( size
, &(*data
)[pos
]);
208 memcpy( &(*data
)[pos
], sdata
, size
);
211 /* add this extension to the extension list
213 _gnutls_extension_list_add( state
, next
);
219 pos
-=2; /* remove the size of the size header! */
221 _gnutls_write_uint16( pos
, (*data
));
223 if (size
==2) { /* empty */