1 /*
2 * Copyright (C) 2017 Red Hat, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 /* Internal API functions to be used by extension handlers.
24 */
25
26 #include "gnutls_int.h"
27 #include "hello_ext.h"
28 #include "hello_ext_lib.h"
29
_gnutls_hello_ext_default_deinit(gnutls_ext_priv_data_t priv)30 void _gnutls_hello_ext_default_deinit(gnutls_ext_priv_data_t priv)
31 {
32 gnutls_free(priv);
33 }
34
35 /* When this is used, the deinitialization function must be set to default:
36 * _gnutls_hello_ext_default_deinit.
37 *
38 * This also prevents and errors on duplicate entries.
39 */
40 int
_gnutls_hello_ext_set_datum(gnutls_session_t session,extensions_t id,const gnutls_datum_t * data)41 _gnutls_hello_ext_set_datum(gnutls_session_t session,
42 extensions_t id, const gnutls_datum_t *data)
43 {
44 gnutls_ext_priv_data_t epriv;
45
46 if (_gnutls_hello_ext_get_priv(session, id, &epriv) >= 0)
47 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
48
49 if (data->size >= UINT16_MAX)
50 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
51
52 epriv = gnutls_malloc(data->size+2);
53 if (epriv == NULL)
54 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
55
56 _gnutls_write_uint16(data->size, epriv);
57 memcpy(((uint8_t*)epriv)+2, data->data, data->size);
58
59 _gnutls_hello_ext_set_priv(session, id, epriv);
60
61 return 0;
62 }
63
64 int
_gnutls_hello_ext_get_datum(gnutls_session_t session,extensions_t id,gnutls_datum_t * data)65 _gnutls_hello_ext_get_datum(gnutls_session_t session,
66 extensions_t id, gnutls_datum_t *data /* constant contents */)
67 {
68 gnutls_ext_priv_data_t epriv;
69 int ret;
70
71 ret = _gnutls_hello_ext_get_priv(session, id, &epriv);
72 if (ret < 0 || epriv == NULL)
73 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
74
75 data->size = _gnutls_read_uint16(epriv);
76 data->data = ((uint8_t*)epriv)+2;
77
78 return 0;
79 }
80
81 int
_gnutls_hello_ext_get_resumed_datum(gnutls_session_t session,extensions_t id,gnutls_datum_t * data)82 _gnutls_hello_ext_get_resumed_datum(gnutls_session_t session,
83 extensions_t id, gnutls_datum_t *data /* constant contents */)
84 {
85 gnutls_ext_priv_data_t epriv;
86 int ret;
87
88 ret = _gnutls_hello_ext_get_resumed_priv(session, id, &epriv);
89 if (ret < 0 || epriv == NULL)
90 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
91
92 data->size = _gnutls_read_uint16(epriv);
93 data->data = ((uint8_t*)epriv)+2;
94
95 return 0;
96 }
97
98 int
_gnutls_hello_ext_default_pack(gnutls_ext_priv_data_t epriv,gnutls_buffer_st * ps)99 _gnutls_hello_ext_default_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st *ps)
100 {
101 size_t size;
102
103 size = _gnutls_read_uint16(epriv);
104
105 return _gnutls_buffer_append_data(ps, epriv, size+2);
106 }
107
108 int
_gnutls_hello_ext_default_unpack(gnutls_buffer_st * ps,gnutls_ext_priv_data_t * epriv)109 _gnutls_hello_ext_default_unpack(gnutls_buffer_st *ps, gnutls_ext_priv_data_t *epriv)
110 {
111 gnutls_datum_t data;
112 uint8_t *store;
113 int ret;
114
115 ret = _gnutls_buffer_pop_datum_prefix16(ps, &data);
116 if (ret < 0)
117 return gnutls_assert_val(ret);
118
119 store = gnutls_calloc(1, data.size+2);
120 if (store == NULL)
121 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
122
123 _gnutls_write_uint16(data.size, store);
124 memcpy(store+2, data.data, data.size);
125
126 *epriv = store;
127 return 0;
128 }
129