1 /*
2  * TLSv1 Record Protocol
3  * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "crypto/md5.h"
13 #include "crypto/sha1.h"
14 #include "crypto/sha256.h"
15 #include "tls/tlsv1_common.h"
16 #include "tls/tlsv1_record.h"
17 
18 #include "eap_peer/eap_i.h"
19 
20 /**
21  * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite
22  * @rl: Pointer to TLS record layer data
23  * @cipher_suite: New cipher suite
24  * Returns: 0 on success, -1 on failure
25  *
26  * This function is used to prepare TLS record layer for cipher suite change.
27  * tlsv1_record_change_write_cipher() and
28  * tlsv1_record_change_read_cipher() functions can then be used to change the
29  * currently used ciphers.
30  */
tlsv1_record_set_cipher_suite(struct tlsv1_record_layer * rl,u16 cipher_suite)31 int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl,
32 				  u16 cipher_suite)
33 {
34 	const struct tls_cipher_suite *suite;
35 	const struct tls_cipher_data *data;
36 
37 	wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x",
38 		   cipher_suite);
39 	rl->cipher_suite = cipher_suite;
40 
41 	suite = tls_get_cipher_suite(cipher_suite);
42 	if (suite == NULL)
43 		return -1;
44 
45 	if (suite->hash == TLS_HASH_MD5) {
46 		rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5;
47 		rl->hash_size = MD5_MAC_LEN;
48 	} else if (suite->hash == TLS_HASH_SHA) {
49 		rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1;
50 		rl->hash_size = SHA1_MAC_LEN;
51 	} else if (suite->hash == TLS_HASH_SHA256) {
52 		rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA256;
53 		rl->hash_size = SHA256_MAC_LEN;
54 	}
55 
56 	data = tls_get_cipher_data(suite->cipher);
57 	if (data == NULL)
58 		return -1;
59 
60 	rl->key_material_len = data->key_material;
61 	rl->iv_size = data->block_size;
62 	rl->cipher_alg = data->alg;
63 
64 	return 0;
65 }
66 
67 
68 /**
69  * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher
70  * @rl: Pointer to TLS record layer data
71  * Returns: 0 on success (cipher changed), -1 on failure
72  *
73  * This function changes TLS record layer to use the new cipher suite
74  * configured with tlsv1_record_set_cipher_suite() for writing.
75  */
tlsv1_record_change_write_cipher(struct tlsv1_record_layer * rl)76 int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl)
77 {
78 	wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite "
79 		   "0x%04x", rl->cipher_suite);
80 	rl->write_cipher_suite = rl->cipher_suite;
81 	os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN);
82 
83 	if (rl->write_cbc) {
84 		crypto_cipher_deinit(rl->write_cbc);
85 		rl->write_cbc = NULL;
86 
87 	}
88 	if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
89 		rl->write_cbc = crypto_cipher_init(rl->cipher_alg,
90 									rl->write_iv, rl->write_key,
91 									rl->key_material_len);
92 
93 		if (rl->write_cbc == NULL) {
94 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
95 				   "cipher");
96 			return -1;
97 		}
98 	}
99 
100 	return 0;
101 }
102 
103 
104 /**
105  * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher
106  * @rl: Pointer to TLS record layer data
107  * Returns: 0 on success (cipher changed), -1 on failure
108  *
109  * This function changes TLS record layer to use the new cipher suite
110  * configured with tlsv1_record_set_cipher_suite() for reading.
111  */
tlsv1_record_change_read_cipher(struct tlsv1_record_layer * rl)112 int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl)
113 {
114 	wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite "
115 		   "0x%04x \n", rl->cipher_suite);
116 	rl->read_cipher_suite = rl->cipher_suite;
117 	os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN);
118 
119 	if (rl->read_cbc) {
120 		crypto_cipher_deinit(rl->read_cbc);
121 		rl->read_cbc =  NULL;
122 	}
123 
124 	if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
125 		rl->read_cbc = crypto_cipher_init(rl->cipher_alg,
126 									rl->read_iv, rl->read_key,
127 									rl->key_material_len);
128 		if (rl->read_cbc == NULL) {
129 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
130 				   "cipher");
131 			return -1;
132 		}
133 	}
134 
135 	return 0;
136 }
137 
138 
139 /**
140  * tlsv1_record_send - TLS record layer: Send a message
141  * @rl: Pointer to TLS record layer data
142  * @content_type: Content type (TLS_CONTENT_TYPE_*)
143  * @buf: Buffer for the generated TLS message (needs to have extra space for
144  * header, IV (TLS v1.1), and HMAC)
145  * @buf_size: Maximum buf size
146  * @payload: Payload to be sent
147  * @payload_len: Length of the payload
148  * @out_len: Buffer for returning the used buf length
149  * Returns: 0 on success, -1 on failure
150  *
151  * This function fills in the TLS record layer header, adds HMAC, and encrypts
152  * the data using the current write cipher.
153  */
tlsv1_record_send(struct tlsv1_record_layer * rl,u8 content_type,u8 * buf,size_t buf_size,const u8 * payload,size_t payload_len,size_t * out_len)154 int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
155 		      size_t buf_size, const u8 *payload, size_t payload_len,
156 		      size_t *out_len)
157 {
158 	u8 *pos, *ct_start, *length, *cpayload;
159 	struct crypto_hash *hmac = NULL;
160 	size_t clen;
161 	int explicit_iv;
162 
163 	pos = buf;
164 	if (pos + TLS_RECORD_HEADER_LEN > buf + buf_size)
165 		return -1;
166 
167 	/* ContentType type */
168 	ct_start = pos;
169 	*pos++ = content_type;
170 	/* ProtocolVersion version */
171 	WPA_PUT_BE16(pos, rl->tls_version);
172 	pos += 2;
173 	/* uint16 length */
174 	length = pos;
175 	WPA_PUT_BE16(length, payload_len);
176 	pos += 2;
177 
178 	cpayload = pos;
179 	explicit_iv = rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL &&
180 		rl->iv_size && rl->tls_version >= TLS_VERSION_1_1;
181 	if (explicit_iv) {
182 		/* opaque IV[Cipherspec.block_length] */
183 		if (pos + rl->iv_size > buf + buf_size)
184 			return -1;
185 
186 		/*
187 		 * Use random number R per the RFC 4346, 6.2.3.2 CBC Block
188 		 * Cipher option 2a.
189 		 */
190 
191 		if (os_get_random(pos, rl->iv_size))
192 			return -1;
193 		pos += rl->iv_size;
194 	}
195 
196 	/*
197 	 * opaque fragment[TLSPlaintext.length]
198 	 * (opaque content[TLSCompressed.length] in GenericBlockCipher)
199 	 */
200 	if (pos + payload_len > buf + buf_size)
201 		return -1;
202 	os_memmove(pos, payload, payload_len);
203 	pos += payload_len;
204 
205 	if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
206 		/*
207 		 * MAC calculated over seq_num + TLSCompressed.type +
208 		 * TLSCompressed.version + TLSCompressed.length +
209 		 * TLSCompressed.fragment
210 		 */
211 		hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret, rl->hash_size);
212 		if (hmac == NULL) {
213 			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
214 				   "to initialize HMAC");
215 			return -1;
216 		}
217 		crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN);
218 		/* type + version + length + fragment */
219 		crypto_hash_update(hmac, ct_start, TLS_RECORD_HEADER_LEN);
220 		crypto_hash_update(hmac, payload, payload_len);
221 		clen = buf + buf_size - pos;
222 		if (clen < rl->hash_size) {
223 			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not "
224 				   "enough room for MAC");
225 			crypto_hash_finish(hmac, NULL, NULL);
226 
227 			return -1;
228 		}
229 
230 		if ((int)crypto_hash_finish(hmac, pos, &clen) < 0) {
231 			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed to calculate HMAC");
232 			return -1;
233 		}
234 
235 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC",
236 			    pos, clen);
237 		pos += clen;
238 		if (rl->iv_size) {
239 			size_t len = pos - cpayload;
240 			size_t pad;
241 			pad = (len + 1) % rl->iv_size;
242 			if (pad)
243 				pad = rl->iv_size - pad;
244 			if (pos + pad + 1 > buf + buf_size) {
245 				wpa_printf(MSG_DEBUG, "TLSv1: No room for "
246 					   "block cipher padding");
247 				return -1;
248 			}
249 			os_memset(pos, pad, pad + 1);
250 			pos += pad + 1;
251 		}
252 
253 		if ((int)crypto_cipher_encrypt(rl->write_cbc, cpayload,
254 							cpayload, pos - cpayload) < 0)
255 			return -1;
256 	}
257 
258 	WPA_PUT_BE16(length, pos - length - 2);
259 	inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN);
260 
261 	*out_len = pos - buf;
262 
263 	return 0;
264 }
265 
266 
267 /**
268  * tlsv1_record_receive - TLS record layer: Process a received message
269  * @rl: Pointer to TLS record layer data
270  * @in_data: Received data
271  * @in_len: Length of the received data
272  * @out_data: Buffer for output data (must be at least as long as in_data)
273  * @out_len: Set to maximum out_data length by caller; used to return the
274  * length of the used data
275  * @alert: Buffer for returning an alert value on failure
276  * Returns: Number of bytes used from in_data on success, 0 if record was not
277  *	complete (more data needed), or -1 on failure
278  *
279  * This function decrypts the received message, verifies HMAC and TLS record
280  * layer header.
281  */
tlsv1_record_receive(struct tlsv1_record_layer * rl,const u8 * in_data,size_t in_len,u8 * out_data,size_t * out_len,u8 * alert)282 int tlsv1_record_receive(struct tlsv1_record_layer *rl,
283 			 const u8 *in_data, size_t in_len,
284 			 u8 *out_data, size_t *out_len, u8 *alert)
285 {
286 	size_t i, rlen, hlen;
287 	u8 padlen;
288 	struct crypto_hash *hmac = NULL;
289 	u8 len[2], hash[100];
290 	int force_mac_error = 0;
291 	u8 ct;
292 
293 	if (in_len < TLS_RECORD_HEADER_LEN) {
294 		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu) - "
295 			   "need more data",
296 			   (unsigned long) in_len);
297 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received",
298 			    in_data, in_len);
299 		return 0;
300 	}
301 
302 	ct = in_data[0];
303 	rlen = WPA_GET_BE16(in_data + 3);
304 	wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d "
305 		   "length %d", ct, in_data[1], in_data[2], (int) rlen);
306 
307 	/*
308 	 * TLS v1.0 and v1.1 RFCs were not exactly clear on the use of the
309 	 * protocol version in record layer. As such, accept any {03,xx} value
310 	 * to remain compatible with existing implementations.
311 	 */
312 	if (in_data[1] != 0x03) {
313 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version "
314 			   "%u.%u", in_data[1], in_data[2]);
315 		*alert = TLS_ALERT_PROTOCOL_VERSION;
316 		return -1;
317 	}
318 
319 	/* TLSCiphertext must not be more than 2^14+2048 bytes */
320 	if (TLS_RECORD_HEADER_LEN + rlen > 18432) {
321 		wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
322 			   (unsigned long) (TLS_RECORD_HEADER_LEN + rlen));
323 		*alert = TLS_ALERT_RECORD_OVERFLOW;
324 		return -1;
325 	}
326 
327 	in_data += TLS_RECORD_HEADER_LEN;
328 	in_len -= TLS_RECORD_HEADER_LEN;
329 
330 	if (rlen > in_len) {
331 		wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included "
332 			   "(rlen=%lu > in_len=%lu)",
333 			   (unsigned long) rlen, (unsigned long) in_len);
334 		return 0;
335 	}
336 
337 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received",
338 		    in_data, rlen);
339 
340 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE &&
341 	    ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC &&
342 	    ct != TLS_CONTENT_TYPE_ALERT &&
343 	    ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
344 		wpa_printf(MSG_DEBUG, "TLSv1: Ignore record with unknown "
345 			   "content type 0x%x", ct);
346 		*alert = TLS_ALERT_UNEXPECTED_MESSAGE;
347 		return -1;
348 	}
349 
350 	in_len = rlen;
351 
352 	if (*out_len < in_len) {
353 		wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for "
354 			   "processing received record");
355 		*alert = TLS_ALERT_INTERNAL_ERROR;
356 		return -1;
357 	}
358 
359 	if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
360 		size_t plen;
361 		if ((int)crypto_cipher_decrypt(rl->read_cbc, in_data,
362 					                        out_data, in_len) < 0) {
363 			*alert = TLS_ALERT_DECRYPTION_FAILED;
364 			return -1;
365 		}
366 
367 		plen = in_len;
368 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted "
369 				"data", out_data, plen);
370 
371 		if (rl->iv_size) {
372 			/*
373 			 * TLS v1.0 defines different alert values for various
374 			 * failures. That may information to aid in attacks, so
375 			 * use the same bad_record_mac alert regardless of the
376 			 * issues.
377 			 *
378 			 * In addition, instead of returning immediately on
379 			 * error, run through the MAC check to make timing
380 			 * attacks more difficult.
381 			 */
382 
383 			if (rl->tls_version >= TLS_VERSION_1_1) {
384 				/* Remove opaque IV[Cipherspec.block_length] */
385 				if (plen < rl->iv_size) {
386 					wpa_printf(MSG_DEBUG, "TLSv1.1: Not "
387 						   "enough room for IV");
388 					force_mac_error = 1;
389 					goto check_mac;
390 				}
391 				os_memmove(out_data, out_data + rl->iv_size,
392 					   plen - rl->iv_size);
393 				plen -= rl->iv_size;
394 			}
395 
396 			/* Verify and remove padding */
397 			if (plen == 0) {
398 				wpa_printf(MSG_DEBUG, "TLSv1: Too short record"
399 					   " (no pad)");
400 				force_mac_error = 1;
401 				goto check_mac;
402 			}
403 			padlen = out_data[plen - 1];
404 			if (padlen >= plen) {
405 				wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad "
406 					   "length (%u, plen=%lu) in "
407 					   "received record",
408 					   padlen, (unsigned long) plen);
409 				force_mac_error = 1;
410 				goto check_mac;
411 			}
412 			for (i = plen - padlen - 1; i < plen - 1; i++) {
413 				if (out_data[i] != padlen) {
414 					wpa_hexdump(MSG_DEBUG,
415 						    "TLSv1: Invalid pad in "
416 						    "received record",
417 						    out_data + plen - padlen -
418 						    1, padlen + 1);
419 					force_mac_error = 1;
420 					goto check_mac;
421 				}
422 			}
423 
424 			plen -= padlen + 1;
425 
426 			wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - "
427 					"Decrypted data with IV and padding "
428 					"removed", out_data, plen);
429 		}
430 
431 	check_mac:
432 		if (plen < rl->hash_size) {
433 			wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no "
434 				   "hash value");
435 			*alert = TLS_ALERT_BAD_RECORD_MAC;
436 			return -1;
437 		}
438 
439 		plen -= rl->hash_size;
440 
441 		hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, rl->hash_size);
442 
443 		if (hmac == NULL) {
444 			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
445 				   "to initialize HMAC");
446 			*alert = TLS_ALERT_INTERNAL_ERROR;
447 			return -1;
448 		}
449 
450 		crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN);
451 		/* type + version + length + fragment */
452 		crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3);
453 		WPA_PUT_BE16(len, plen);
454 		crypto_hash_update(hmac, len, 2);
455 		crypto_hash_update(hmac, out_data, plen);
456 
457 		hlen = sizeof(hash);
458 		if ((int)crypto_hash_finish(hmac, hash, &hlen) < 0) {
459 			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed to calculate HMAC");
460 			*alert = TLS_ALERT_INTERNAL_ERROR;
461 			return -1;
462 		}
463 
464 		if (hlen != rl->hash_size ||
465 		    os_memcmp(hash, out_data + plen, hlen) != 0 ||
466 		    force_mac_error) {
467 			wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in "
468 				   "received message (force_mac_error=%d)",
469 				   force_mac_error);
470 			*alert = TLS_ALERT_BAD_RECORD_MAC;
471 			return -1;
472 		}
473 
474 		*out_len = plen;
475 	} else {
476 		os_memcpy(out_data, in_data, in_len);
477 		*out_len = in_len;
478 	}
479 
480 	/* TLSCompressed must not be more than 2^14+1024 bytes */
481 	if (TLS_RECORD_HEADER_LEN + *out_len > 17408) {
482 		wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
483 			   (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len));
484 		*alert = TLS_ALERT_RECORD_OVERFLOW;
485 		return -1;
486 	}
487 
488 	inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN);
489 
490 	return TLS_RECORD_HEADER_LEN + rlen;
491 }
492