Home | History | Annotate | Download | only in tls
      1 /*
      2  * TLSv1 Record Protocol
      3  * Copyright (c) 2006-2011, Jouni Malinen <j (at) 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  */
     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  */
     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  */
    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  */
    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  */
    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