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