1 /*
2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3 * Copyright (C) 2015-2018 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 #ifndef GNUTLS_LIB_HELLO_EXT_H
25 #define GNUTLS_LIB_HELLO_EXT_H
26
27 #include "gnutls_int.h"
28 #include <gnutls/gnutls.h>
29 #include "str.h"
30
31 /* Functions for hello extension parsing.
32 */
33 int _gnutls_parse_hello_extensions(gnutls_session_t session,
34 gnutls_ext_flags_t msg,
35 gnutls_ext_parse_type_t parse_type,
36 const uint8_t * data, int data_size);
37 int _gnutls_gen_hello_extensions(gnutls_session_t session,
38 gnutls_buffer_st * extdata,
39 gnutls_ext_flags_t msg,
40 gnutls_ext_parse_type_t);
41 int _gnutls_hello_ext_init(void);
42 void _gnutls_hello_ext_deinit(void);
43
44 void _gnutls_hello_ext_priv_deinit(gnutls_session_t session);
45
46 /* functions to be used by extensions internally
47 */
48 void _gnutls_hello_ext_unset_priv(gnutls_session_t session,
49 extensions_t ext);
50 void _gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t ext,
51 gnutls_ext_priv_data_t);
52 int _gnutls_hello_ext_get_priv(gnutls_session_t session, extensions_t ext,
53 gnutls_ext_priv_data_t *);
54 int _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
55 extensions_t ext,
56 gnutls_ext_priv_data_t * data);
57
58 #define GNUTLS_EXT_FLAG_MSG_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO| \
59 GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
60
61 /* these flags can only be set in the extensions, but cannot be requested;
62 * they are handled internally by the hello parsing/generating functions. */
63 #define GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK ~(GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)
64
65 /* obtain the message this extension was received at */
_gnutls_ext_get_msg(gnutls_session_t session)66 inline static gnutls_ext_flags_t _gnutls_ext_get_msg(gnutls_session_t session)
67 {
68 return session->internals.ext_msg & GNUTLS_EXT_FLAG_MSG_MASK;
69 }
70
_gnutls_ext_set_msg(gnutls_session_t session,gnutls_ext_flags_t msg)71 inline static void _gnutls_ext_set_msg(gnutls_session_t session, gnutls_ext_flags_t msg)
72 {
73 session->internals.ext_msg = msg;
74 }
75
_gnutls_ext_set_extensions_offset(gnutls_session_t session,int offset)76 inline static void _gnutls_ext_set_extensions_offset(gnutls_session_t session,
77 int offset)
78 {
79 session->internals.extensions_offset = offset;
80 }
81
_gnutls_ext_get_extensions_offset(gnutls_session_t session)82 inline static int _gnutls_ext_get_extensions_offset(gnutls_session_t session)
83 {
84 return session->internals.extensions_offset;
85 }
86
87 int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
88 handshake_buffer_st *recv_buf);
89 unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
90 gnutls_datum_t *datum);
91
92 /* for session packing */
93 int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed);
94 int _gnutls_hello_ext_unpack(gnutls_session_t session,
95 gnutls_buffer_st * packed);
96
ext_msg_validity_to_str(gnutls_ext_flags_t msg)97 inline static const char *ext_msg_validity_to_str(gnutls_ext_flags_t msg)
98 {
99 msg &= GNUTLS_EXT_FLAG_MSG_MASK;
100
101 switch(msg) {
102 case GNUTLS_EXT_FLAG_CLIENT_HELLO:
103 return "client hello";
104 case GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO:
105 return "TLS 1.2 server hello";
106 case GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO:
107 return "TLS 1.3 server hello";
108 case GNUTLS_EXT_FLAG_EE:
109 return "encrypted extensions";
110 case GNUTLS_EXT_FLAG_HRR:
111 return "hello retry request";
112 default:
113 return "(unknown)";
114 }
115 }
116
117 typedef struct hello_ext_entry_st {
118 const char *name; /* const overridden when free_struct is set */
119 unsigned free_struct;
120
121 uint16_t tls_id;
122 unsigned gid; /* gnutls internal ID */
123
124 gnutls_ext_parse_type_t client_parse_point;
125 gnutls_ext_parse_type_t server_parse_point;
126 unsigned validity; /* multiple items of gnutls_ext_flags_t */
127
128 /* this function must return 0 when Not Applicable
129 * size of extension data if ok
130 * < 0 on other error.
131 */
132 gnutls_ext_recv_func recv_func;
133
134 /* this function must return 0 when Not Applicable
135 * size of extension data if ok
136 * GNUTLS_E_INT_RET_0 if extension data size is zero
137 * < 0 on other error.
138 */
139 gnutls_ext_send_func send_func;
140
141 gnutls_ext_deinit_data_func deinit_func; /* this will be called to deinitialize
142 * internal data
143 */
144 gnutls_ext_pack_func pack_func; /* packs internal data to machine independent format */
145 gnutls_ext_unpack_func unpack_func; /* unpacks internal data */
146
147 /* non-zero if that extension cannot be overridden by the applications.
148 * That should be set to extensions which allocate data early, e.g., on
149 * gnutls_init(), or modify the TLS protocol in a way that the application
150 * cannot control. */
151 unsigned cannot_be_overriden;
152 } hello_ext_entry_st;
153
154 /* Checks if the extension @id provided has been requested
155 * by us (in client side).In server side it checks whether this
156 * extension was advertized by the client.
157 *
158 * It returns non-zero for true, otherwise zero.
159 */
160 inline static unsigned
_gnutls_hello_ext_is_present(gnutls_session_t session,extensions_t id)161 _gnutls_hello_ext_is_present(gnutls_session_t session, extensions_t id)
162 {
163 if (session->internals.used_exts & ((ext_track_t)1 << id))
164 return 1;
165
166 return 0;
167 }
168
169 /* Adds the extension we want to send in the extensions list.
170 * This list is used in client side to check whether the (later) received
171 * extensions are the ones we requested.
172 *
173 * In server side, this list is used to ensure we don't send
174 * extensions that we didn't receive a corresponding value.
175 *
176 * Returns zero if failed, non-zero on success.
177 */
178 inline static
_gnutls_hello_ext_save(gnutls_session_t session,extensions_t id,unsigned check_dup)179 unsigned _gnutls_hello_ext_save(gnutls_session_t session,
180 extensions_t id,
181 unsigned check_dup)
182 {
183 if (check_dup && _gnutls_hello_ext_is_present(session, id)) {
184 return 0;
185 }
186
187 session->internals.used_exts |= ((ext_track_t)1 << id);
188
189 return 1;
190 }
191
192 inline static
_gnutls_hello_ext_save_sr(gnutls_session_t session)193 void _gnutls_hello_ext_save_sr(gnutls_session_t session)
194 {
195 _gnutls_hello_ext_save(session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, 1);
196 }
197
198 #endif /* GNUTLS_LIB_HELLO_EXT_H */
199