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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
/*
* Copyright (C) 2000-2012 Free Software Foundation, Inc.
* Copyright (C) 2015-2018 Red Hat, 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 <https://www.gnu.org/licenses/>
*
*/
#ifndef GNUTLS_LIB_HELLO_EXT_H
#define GNUTLS_LIB_HELLO_EXT_H
#include "gnutls_int.h"
#include <gnutls/gnutls.h>
#include "str.h"
/* Functions for hello extension parsing.
*/
int _gnutls_parse_hello_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_hello_extensions(gnutls_session_t session,
gnutls_buffer_st *extdata,
gnutls_ext_flags_t msg,
gnutls_ext_parse_type_t);
int _gnutls_hello_ext_init(void);
void _gnutls_hello_ext_deinit(void);
void _gnutls_hello_ext_priv_deinit(gnutls_session_t session);
/* functions to be used by extensions internally
*/
void _gnutls_hello_ext_unset_priv(gnutls_session_t session, extensions_t ext);
void _gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t ext,
gnutls_ext_priv_data_t);
int _gnutls_hello_ext_get_priv(gnutls_session_t session, extensions_t ext,
gnutls_ext_priv_data_t *);
int _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
extensions_t ext,
gnutls_ext_priv_data_t *data);
#define GNUTLS_EXT_FLAG_MSG_MASK \
(GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | \
GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_EE | \
GNUTLS_EXT_FLAG_HRR)
/* these flags can only be set in the extensions, but cannot be requested;
* they are handled internally by the hello parsing/generating functions. */
#define GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK \
~(GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)
/* obtain the message this extension was received at */
inline static gnutls_ext_flags_t _gnutls_ext_get_msg(gnutls_session_t session)
{
return session->internals.ext_msg & GNUTLS_EXT_FLAG_MSG_MASK;
}
inline static void _gnutls_ext_set_msg(gnutls_session_t session,
gnutls_ext_flags_t msg)
{
session->internals.ext_msg = msg;
}
inline static void _gnutls_ext_set_extensions_offset(gnutls_session_t session,
int offset)
{
session->internals.extensions_offset = offset;
}
inline static int _gnutls_ext_get_extensions_offset(gnutls_session_t session)
{
return session->internals.extensions_offset;
}
int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
handshake_buffer_st *recv_buf);
unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
gnutls_datum_t *datum);
/* for session packing */
int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed);
int _gnutls_hello_ext_unpack(gnutls_session_t session,
gnutls_buffer_st *packed);
inline static const char *ext_msg_validity_to_str(gnutls_ext_flags_t msg)
{
msg &= GNUTLS_EXT_FLAG_MSG_MASK;
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_HRR:
return "hello retry request";
default:
return "(unknown)";
}
}
typedef struct hello_ext_entry_st {
const char *name; /* const overridden when free_struct is set */
unsigned free_struct;
uint16_t tls_id;
unsigned gid; /* gnutls internal ID */
gnutls_ext_parse_type_t client_parse_point;
gnutls_ext_parse_type_t server_parse_point;
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 overridden 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;
/* Checks if the extension @id provided has been requested
* by us (in client side).In server side it checks whether this
* extension was advertised by the client.
*
* It returns non-zero for true, otherwise zero.
*/
inline static unsigned _gnutls_hello_ext_is_present(gnutls_session_t session,
extensions_t id)
{
if (session->internals.used_exts & ((ext_track_t)1 << id))
return 1;
return 0;
}
/* 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_hello_ext_save(gnutls_session_t session,
extensions_t id,
unsigned check_dup)
{
if (check_dup && _gnutls_hello_ext_is_present(session, id)) {
return 0;
}
session->internals.used_exts |= ((ext_track_t)1 << id);
return 1;
}
inline static void _gnutls_hello_ext_save_sr(gnutls_session_t session)
{
_gnutls_hello_ext_save(session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, 1);
}
#endif /* GNUTLS_LIB_HELLO_EXT_H */
|