1 /*
2  * Copyright (C) 2016 - 2018 ARPA2 project
3  *
4  * Author: Tom Vrancken (dev@tomvrancken.nl)
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  * This file is part of the server_certificate_type extension as
22  * defined in RFC7250 (https://tools.ietf.org/html/rfc7250).
23  *
24  * The server_certificate_type extension in the client hello indicates
25  * the types of certificates the client is able to process when provided
26  * by the server in a subsequent certificate payload.
27  */
28 
29 #include <gnutls_int.h>
30 #include <gnutls/gnutls.h>
31 #include "ext/cert_types.h"
32 #include "ext/server_cert_type.h"
33 #include "hello_ext.h"
34 #include "hello_ext_lib.h"
35 #include "errors.h"
36 #include "state.h"
37 #include "datum.h"
38 
39 
40 static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
41 						const uint8_t* data,
42 						size_t data_size);
43 static int _gnutls_server_cert_type_send_params(gnutls_session_t session,
44 						gnutls_buffer_st* data);
45 
46 
47 const hello_ext_entry_st ext_mod_server_cert_type = {
48 	.name = "Server Certificate Type",
49 	.tls_id = 20,
50 	.gid = GNUTLS_EXTENSION_SERVER_CERT_TYPE,
51 	.client_parse_point = GNUTLS_EXT_TLS,
52 	.server_parse_point = GNUTLS_EXT_TLS,
53 	.validity = GNUTLS_EXT_FLAG_TLS |
54 		GNUTLS_EXT_FLAG_DTLS |
55 		GNUTLS_EXT_FLAG_CLIENT_HELLO |
56 		GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
57 		GNUTLS_EXT_FLAG_EE,
58 	.recv_func = _gnutls_server_cert_type_recv_params,
59 	.send_func = _gnutls_server_cert_type_send_params,
60 	.pack_func = _gnutls_hello_ext_default_pack,
61 	.unpack_func = _gnutls_hello_ext_default_unpack,
62 	.deinit_func = _gnutls_hello_ext_default_deinit,
63 	.cannot_be_overriden = 1
64 };
65 
66 
_gnutls_server_cert_type_recv_params(gnutls_session_t session,const uint8_t * data,size_t data_size)67 static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
68 						const uint8_t* data,
69 						size_t data_size)
70 {
71 	int ret;
72 	gnutls_datum_t cert_types; // Holds the received cert types
73 	gnutls_datum_t sent_cert_types; // Holds the previously sent cert types
74 	gnutls_certificate_type_t cert_type;
75 
76 	uint8_t i, found = 0;
77 	const uint8_t* pdata = data;
78 
79 	/* Only activate this extension if we have cert credentials set
80 	 * and alternative cert types are allowed */
81 	if (!are_alternative_cert_types_allowed(session) ||
82 		(_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL))
83 		return 0;
84 
85 	if (!IS_SERVER(session)) {	// client mode
86 
87 		/* Compare packet length with expected packet length. For the
88 		 * client this is a single byte. */
89 		if (data_size != 1) {
90 			return
91 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
92 		}
93 
94 		/* The server picked one of the offered cert types if he supports
95 		 * at least one of them. If both parties play by the rules then we
96 		 * may only receive a cert type that we offered, i.e. one that we
97 		 * support. Because the world isn't as beautiful as it may seem,
98 		 * we're going to check it nevertheless. */
99 		cert_type = IANA2cert_type(pdata[0]);
100 
101 		// Check validity of cert type
102 		if (cert_type == GNUTLS_CRT_UNKNOWN) {
103 			return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
104 		}
105 
106 		/* Get the cert types that we sent to the server (they were stored
107 		 * in IANA representation.
108 		 */
109 		ret = _gnutls_hello_ext_get_datum(session,
110 							 GNUTLS_EXTENSION_SERVER_CERT_TYPE,
111 							 &sent_cert_types);
112 		if (ret < 0) {
113 			/* This should not happen and indicate a memory corruption!
114 			 * Assertion are always on in production code so execution
115 			 * will halt here. */
116 			assert(false);
117 		}
118 
119 		// Check whether what we got back is actually offered by us
120 		for (i = 0; i < sent_cert_types.size; i++) {
121 			if (IANA2cert_type(sent_cert_types.data[i]) == cert_type)
122 				found = 1;
123 		}
124 
125 		if (found) {
126 			// Everything OK, now set the server certificate type
127 			_gnutls_session_server_cert_type_set(session, cert_type);
128 			ret = GNUTLS_E_SUCCESS;
129 		} else {
130 			// No valid cert type found
131 			ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
132 		}
133 
134 		return ret;
135 
136 	} else {		// server mode
137 		// Compare packet length with expected packet length.
138 		DECR_LEN(data_size, 1);
139 		if (data[0] != data_size) {
140 			return
141 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
142 		}
143 		pdata += 1;
144 
145 		// Assign the contents of our data buffer to a gnutls_datum_t
146 		cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning
147 		cert_types.size = data_size;
148 
149 		// Store the server certificate types in our session
150 		_gnutls_hello_ext_set_datum(session,
151 							 GNUTLS_EXTENSION_SERVER_CERT_TYPE,
152 							 &cert_types);
153 
154 		/* We receive a list of supported certificate types that the client
155 		 * is able to process when offered by the server via a subsequent
156 		 * Certificate message. This list is sorted by order of preference.
157 		 * We now check in this order of preference whether we support any
158 		 * of these certificate types.
159 		 */
160 		for (i = 0; i < cert_types.size; i++) {
161 			// Convert to internal representation
162 			cert_type = IANA2cert_type(cert_types.data[i]);
163 
164 			// If we have an invalid cert id then continue to the next
165 			if (cert_type == GNUTLS_CRT_UNKNOWN)
166 				continue;
167 
168 			// Check for support of this cert type
169 			if (_gnutls_session_cert_type_supported
170 					(session, cert_type, true, GNUTLS_CTYPE_SERVER) == 0) {
171 				found = 1;
172 				break;
173 			}
174 		}
175 
176 		// We found a matching ctype, we pick this one
177 		if (found) {
178 			_gnutls_session_server_cert_type_set(session, cert_type);
179 			ret = GNUTLS_E_SUCCESS;
180 		} else {
181 			/* If no supported certificate type can be found we terminate
182 			 * with a fatal alert of type "unsupported_certificate"
183 			 * (according to specification rfc7250).
184 			 */
185 			ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
186 		}
187 
188 		return ret;
189 	}
190 }
191 
_gnutls_server_cert_type_send_params(gnutls_session_t session,gnutls_buffer_st * data)192 static int _gnutls_server_cert_type_send_params(gnutls_session_t session,
193 						gnutls_buffer_st* data)
194 {
195 	int ret;
196 	uint8_t cert_type; // Holds an IANA cert type ID
197 	uint8_t i = 0, num_cert_types = 0;
198 	priority_st* cert_priorities;
199 	gnutls_datum_t tmp_cert_types; // For type conversion
200 	uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported cert types. Inv: 0 <= cert type Id < 256
201 
202 	/* Only activate this extension if we have cert credentials set
203 	 * and alternative cert types are allowed */
204 	if (!are_alternative_cert_types_allowed(session) ||
205 		(_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL))
206 		return 0;
207 
208 	if (!IS_SERVER(session)) {	// Client mode
209 		// For brevity
210 		cert_priorities =
211 				&session->internals.priorities->server_ctype;
212 
213 		/* Retrieve server certificate type priorities if any. If no
214 		 * priorities are set then the default server certificate type
215 		 * initialization values apply. This default is currently set to
216 		 * X.509 in which case we don't enable this extension.
217 		 */
218 		if (cert_priorities->num_priorities > 0) {	// Priorities are explicitly set
219 			/* If the certificate priority is explicitly set to only
220 			 * X.509 (default) then, according to spec we don't send
221 			 * this extension. We check this here to avoid further work in
222 			 * this routine. We also check it below after pruning supported
223 			 * types.
224 			 */
225 			if (cert_priorities->num_priorities == 1 &&
226 					cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) {
227 				_gnutls_handshake_log
228 						("EXT[%p]: Server certificate type was set to default cert type (%s). "
229 						 "We therefore do not send this extension.\n",
230 						 session,
231 						 gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));
232 
233 				// Explicitly set but default ctype, so don't send anything
234 				return 0;
235 			}
236 
237 			/* We are only allowed to send certificate types that we support.
238 			 * Therefore we check this here and prune our original list.
239 			 * This check might seem redundant now because we don't check for
240 			 * credentials (they are not needed for a client) and only check the
241 			 * priorities over which we already iterate. In the future,
242 			 * additional checks might be necessary and they can be easily
243 			 * added in the ..type_supported() routine without modifying the
244 			 * structure of the code here.
245 			 */
246 			for (i = 0; i < cert_priorities->num_priorities; i++) {
247 				if (_gnutls_session_cert_type_supported
248 						(session, cert_priorities->priorities[i],
249 						 false, GNUTLS_CTYPE_SERVER) == 0) {
250 					/* Check whether we are allowed to store another cert type
251 					 * in our buffer. In other words, prevent a possible buffer
252 					 * overflow. This situation can occur when a user sets
253 					 * duplicate cert types in the priority strings. */
254 					if (num_cert_types >= GNUTLS_CRT_MAX)
255 						return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
256 
257 					// Convert to IANA representation
258 					ret = cert_type2IANA(cert_priorities->priorities[i]);
259 
260 					if (ret < 0)
261 						return gnutls_assert_val(ret);
262 
263 					cert_type = ret; // For readability
264 
265 					// Add this cert type to our list with supported types
266 					cert_types[num_cert_types] = cert_type;
267 					num_cert_types++;
268 
269 					_gnutls_handshake_log
270 							("EXT[%p]: Server certificate type %s (%d) was queued.\n",
271 							 session,
272 							 gnutls_certificate_type_get_name(cert_priorities->priorities[i]),
273 							 cert_type);
274 				}
275 			}
276 
277 			/* Check whether there are any supported certificate types left
278 			 * after the previous pruning step. If not, we do not send this
279 			 * extension. Also, if the only supported type is the default type
280 			 * we do not send this extension (according to RFC7250).
281 			 */
282 			if (num_cert_types == 0) {	// For now, this should not occur since we only check priorities while pruning.
283 				_gnutls_handshake_log
284 						("EXT[%p]: Server certificate types were set but none of them is supported. "
285 						 "We do not send this extension.\n",
286 						 session);
287 
288 				return 0;
289 			} else if (num_cert_types == 1 &&
290 					 IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) {
291 				_gnutls_handshake_log
292 						("EXT[%p]: The only supported server certificate type is (%s) which is the default. "
293 						 "We therefore do not send this extension.\n",
294 						 session,
295 						 gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));
296 
297 				return 0;
298 			}
299 
300 			/* We have data to send and store a copy internally. We convert
301 			 * our list with supported cert types to a datum_t in order to
302 			 * be able to make the ..._set_datum call.
303 			 */
304 			tmp_cert_types.data = cert_types;
305 			tmp_cert_types.size = num_cert_types;
306 
307 			_gnutls_hello_ext_set_datum(session,
308 								 GNUTLS_EXTENSION_SERVER_CERT_TYPE,
309 								 &tmp_cert_types);
310 
311 			/* Serialize the certificate types into a sequence of octets
312 			 * uint8: length of sequence of cert types (1 octet)
313 			 * uint8: cert types (0 <= #octets <= 255)
314 			 */
315 			ret = _gnutls_buffer_append_data_prefix(data, 8,
316 								cert_types,
317 								num_cert_types);
318 
319 			// Check for errors and cleanup in case of error
320 			if (ret < 0) {
321 				return gnutls_assert_val(ret);
322 			} else {
323 				// Number of bytes we are sending
324 				return num_cert_types + 1;
325 			}
326 		}
327 	} else {	// Server mode
328 		// Retrieve negotiated server certificate type and send it
329 		ret = cert_type2IANA(get_certificate_type(
330 					session, GNUTLS_CTYPE_SERVER));
331 
332 		if (ret < 0)
333 			return gnutls_assert_val(ret);
334 
335 		cert_type = ret; // For readability
336 
337 		ret = gnutls_buffer_append_data(data, &cert_type, 1);
338 
339 		if (ret < 0)
340 			return gnutls_assert_val(ret);
341 
342 		return 1;	// sent one byte
343 	}
344 
345 	// In all other cases don't enable this extension
346 	return 0;
347 }
348 
349 
350 /** Extension interface **/
351 
352 /* The interface is defined in state.c:
353  * Public:
354  * - gnutls_certificate_type_get2
355  *
356  * Private:
357  * - _gnutls_session_server_cert_type_set
358  */
359