summaryrefslogtreecommitdiff
path: root/lib/extensions.h
blob: 70dc251c8da6276153e8d90a42ee97f3ec28dbfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
 *
 * Author: Nikos Mavrogiannopoulos
 *
 * This file is part of GnuTLS.
 *
 * The GnuTLS is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 */

#ifndef GNUTLS_EXTENSIONS_H
#define GNUTLS_EXTENSIONS_H

#include <gnutls/gnutls.h>

int _gnutls_parse_extensions(gnutls_session_t session,
			     gnutls_ext_flags_t msg,
			     gnutls_ext_parse_type_t parse_type,
			     const uint8_t * data, int data_size);
int _gnutls_gen_extensions(gnutls_session_t session,
			   gnutls_buffer_st * extdata,
			   gnutls_ext_flags_t msg,
			   gnutls_ext_parse_type_t);
int _gnutls_ext_init(void);
void _gnutls_ext_deinit(void);

void _gnutls_ext_free_session_data(gnutls_session_t session);

/* functions to be used by extensions internally
 */
void _gnutls_ext_unset_session_data(gnutls_session_t session,
				    extensions_t ext);
void _gnutls_ext_set_session_data(gnutls_session_t session, extensions_t ext,
				  gnutls_ext_priv_data_t);
int _gnutls_ext_get_session_data(gnutls_session_t session, extensions_t ext,
				 gnutls_ext_priv_data_t *);
int _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
					 extensions_t ext,
					 gnutls_ext_priv_data_t * data);

/* for session packing */
int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed);
int _gnutls_ext_unpack(gnutls_session_t session,
		       gnutls_buffer_st * packed);

inline static const char *ext_msg_validity_to_str(gnutls_ext_flags_t msg)
{
	switch(msg) {
		case GNUTLS_EXT_FLAG_CLIENT_HELLO:
			return "client hello";
		case GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO:
			return "TLS 1.2 server hello";
		case GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO:
			return "TLS 1.3 server hello";
		case GNUTLS_EXT_FLAG_EE:
			return "encrypted extensions";
		case GNUTLS_EXT_FLAG_CT:
			return "certificate";
		case GNUTLS_EXT_FLAG_CR:
			return "certificate request";
		case GNUTLS_EXT_FLAG_NST:
			return "new session ticket";
		case GNUTLS_EXT_FLAG_HRR:
			return "hello retry request";
		default:
			return "(unknown)";
	}
}

typedef struct hello_ext_entry_st {
	const char *name; /* const overriden when free_struct is set */
	unsigned free_struct;

	uint16_t tls_id;
	unsigned gid; /* gnutls internal ID */

	gnutls_ext_parse_type_t parse_type;
	unsigned validity; /* multiple items of gnutls_ext_flags_t */

	/* this function must return 0 when Not Applicable
	 * size of extension data if ok
	 * < 0 on other error.
	 */
	gnutls_ext_recv_func recv_func;

	/* this function must return 0 when Not Applicable
	 * size of extension data if ok
	 * GNUTLS_E_INT_RET_0 if extension data size is zero
	 * < 0 on other error.
	 */
	gnutls_ext_send_func send_func;

	gnutls_ext_deinit_data_func deinit_func;	/* this will be called to deinitialize
							 * internal data 
							 */
	gnutls_ext_pack_func pack_func;	/* packs internal data to machine independent format */
	gnutls_ext_unpack_func unpack_func;	/* unpacks internal data */

	/* non-zero if that extension cannot be overriden by the applications.
	 * That should be set to extensions which allocate data early, e.g., on
	 * gnutls_init(), or modify the TLS protocol in a way that the application
	 * cannot control. */
	unsigned cannot_be_overriden;
} hello_ext_entry_st;

int _gnutls_ext_register(hello_ext_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 hello_ext_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