return NULL;
}
-/* Checks if the extension @id provided has been requested
- * by us (in client side). In that case it returns zero,
- * otherwise a negative error value.
- */
-int
-_gnutls_extension_list_check(gnutls_session_t session, extensions_t id)
-{
- unsigned i;
-
- for (i = 0; i < session->internals.used_exts_size; i++) {
- if (id == session->internals.used_exts[i]->gid)
- return 0;
- }
-
- return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
-}
-
-/* Adds the extension we want to send in the extensions list.
- * This list is used in client side to check whether the (later) received
- * extensions are the ones we requested.
- *
- * In server side, this list is used to ensure we don't send
- * extensions that we didn't receive a corresponding value.
- *
- * Returns zero if failed, non-zero on success.
- */
-static unsigned _gnutls_extension_list_add(gnutls_session_t session, const struct extension_entry_st *e, unsigned check_dup)
-{
- unsigned i;
-
- if (check_dup) {
- for (i=0;i<session->internals.used_exts_size;i++) {
- if (session->internals.used_exts[i]->gid == e->gid)
- return 0;
- }
- }
-
- if (session->internals.used_exts_size < MAX_EXT_TYPES) {
- session->internals.used_exts[session->
- internals.used_exts_size]
- = e;
- session->internals.used_exts_size++;
- return 1;
- } else {
- _gnutls_handshake_log
- ("extensions: Increase MAX_EXT_TYPES\n");
- return 0;
- }
-}
-
static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
{
unsigned i;
return 0;
}
-
void _gnutls_extension_list_add_sr(gnutls_session_t session)
{
_gnutls_extension_list_add(session, &ext_mod_sr, 1);
}
-
int
_gnutls_parse_extensions(gnutls_session_t session,
gnutls_ext_flags_t msg,
unsigned int i;
int ret;
int total_exts_pos;
- int exts = 0;
+ int n_exts = 0;
+ const struct extension_entry_st *ext;
total_exts_pos = packed->length;
BUFFER_APPEND_NUM(packed, 0);
- for (i = 0; i < session->internals.used_exts_size; i++) {
- ret = pack_extension(session, session->internals.used_exts[i], packed);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
+ if (session->internals.used_exts & (1<<i)) {
+
+ ext = _gnutls_ext_ptr(session, i, GNUTLS_EXT_ANY);
+ if (ext == NULL)
+ continue;
- if (ret > 0)
- exts++;
+ ret = pack_extension(session, ext, packed);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (ret > 0)
+ n_exts++;
+ }
}
- _gnutls_write_uint32(exts, packed->data + total_exts_pos);
+ _gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
return 0;
}
int _gnutls_ext_init(void);
void _gnutls_ext_deinit(void);
-void _gnutls_extension_list_add_sr(gnutls_session_t session);
-int _gnutls_extension_list_check(gnutls_session_t session, extensions_t type);
-
void _gnutls_ext_free_session_data(gnutls_session_t session);
/* functions to be used by extensions internally
int _gnutls_ext_register(extension_entry_st *);
+void _gnutls_extension_list_add_sr(gnutls_session_t session);
+
+/* Checks if the extension @id provided has been requested
+ * by us (in client side). In that case it returns zero,
+ * otherwise a negative error value.
+ */
+inline static int
+_gnutls_extension_list_check(gnutls_session_t session, extensions_t id)
+{
+ if (id != 0 && ((1 << id) & session->internals.used_exts))
+ return 0;
+
+ return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
+}
+
+/* Adds the extension we want to send in the extensions list.
+ * This list is used in client side to check whether the (later) received
+ * extensions are the ones we requested.
+ *
+ * In server side, this list is used to ensure we don't send
+ * extensions that we didn't receive a corresponding value.
+ *
+ * Returns zero if failed, non-zero on success.
+ */
+inline static
+unsigned _gnutls_extension_list_add(gnutls_session_t session,
+ const struct extension_entry_st *e,
+ unsigned check_dup)
+{
+ if (check_dup && _gnutls_extension_list_check(session, e->gid) == 0) {
+ return 0;
+ }
+
+ session->internals.used_exts |= (1 << e->gid);
+
+ return 1;
+}
+
#endif
GNUTLS_EXTENSION_MAX = GNUTLS_EXTENSION_SERVER_NAME
} extensions_t;
-#define GNUTLS_EXTENSION_MAX_VALUE 63
+#define GNUTLS_EXTENSION_MAX_VALUE 31
#if GNUTLS_EXTENSION_MAX >= GNUTLS_EXTENSION_MAX_VALUE
# error over limit
#endif
+#if GNUTLS_EXTENSION_MAX >= MAX_EXT_TYPES
+# error over limit
+#endif
+
+/* we must provide at least 16 extensions for users to register */
+#if GNUTLS_EXTENSION_MAX_VALUE - GNUTLS_EXTENSION_MAX < 16
+# error not enough extension types; increase GNUTLS_EXTENSION_MAX_VALUE, MAX_EXT_TYPES and used_exts type
+#endif
+
+
typedef enum { CIPHER_STREAM, CIPHER_BLOCK, CIPHER_AEAD } cipher_type_t;
#define RESUME_TRUE 1
} ext_data[MAX_EXT_TYPES];
/* In case of a client holds the extensions we sent to the peer;
- * otherwise the extensions we received from the client.
+ * otherwise the extensions we received from the client. This is
+ * an OR of (1<<extensions_t values).
*/
- const struct extension_entry_st *used_exts[MAX_EXT_TYPES];
- unsigned used_exts_size;
+ uint32_t used_exts;
/* this is not the negotiated max_record_recv_size, but the actual maximum
* receive size */
_gnutls_buffers_log("BUF[HSK]: Emptied buffer\n");
- session->internals.used_exts_size = 0;
+ session->internals.used_exts = 0;
session->internals.handshake_hash_buffer_prev_len = 0;
session->internals.handshake_hash_buffer.length = 0;
return;
if (ret < 0)
return gnutls_assert_val(ret);
- session->internals.used_exts_size = 0;
+ session->internals.used_exts = 0;
session->internals.crt_requested = 0;
session->internals.handshake_in_progress = 1;
session->internals.vc_status = -1;