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