Browse Source

[tls] Support TLS version 1.1

Advertise support for TLS version 1.1, and be prepared to downgrade to
TLS version 1.0.  Tested against Apache with mod_gnutls, using the
GnuTLSPriorities directive to force specific protocol versions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
d9ce3bfe4c
2 changed files with 30 additions and 16 deletions
  1. 2
    0
      src/include/ipxe/tls.h
  2. 28
    16
      src/net/tls.c

+ 2
- 0
src/include/ipxe/tls.h View File

138
 	/** Ciphertext stream */
138
 	/** Ciphertext stream */
139
 	struct interface cipherstream;
139
 	struct interface cipherstream;
140
 
140
 
141
+	/** Protocol version */
142
+	uint16_t version;
141
 	/** Current TX cipher specification */
143
 	/** Current TX cipher specification */
142
 	struct tls_cipherspec tx_cipherspec;
144
 	struct tls_cipherspec tx_cipherspec;
143
 	/** Next TX cipher specification */
145
 	/** Next TX cipher specification */

+ 28
- 16
src/net/tls.c View File

697
 	hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
697
 	hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
698
 			      htonl ( sizeof ( hello ) -
698
 			      htonl ( sizeof ( hello ) -
699
 				      sizeof ( hello.type_length ) ) );
699
 				      sizeof ( hello.type_length ) ) );
700
-	hello.version = htons ( TLS_VERSION_TLS_1_0 );
700
+	hello.version = htons ( tls->version );
701
 	memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
701
 	memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
702
 	hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
702
 	hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
703
 	hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA );
703
 	hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA );
877
 		char next[0];
877
 		char next[0];
878
 	} __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next;
878
 	} __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next;
879
 	void *end = hello_b->next;
879
 	void *end = hello_b->next;
880
+	uint16_t version;
880
 	int rc;
881
 	int rc;
881
 
882
 
882
 	/* Sanity check */
883
 	/* Sanity check */
886
 		return -EINVAL;
887
 		return -EINVAL;
887
 	}
888
 	}
888
 
889
 
889
-	/* Check protocol version */
890
-	if ( ntohs ( hello_a->version ) < TLS_VERSION_TLS_1_0 ) {
890
+	/* Check and store protocol version */
891
+	version = ntohs ( hello_a->version );
892
+	if ( version < TLS_VERSION_TLS_1_0 ) {
891
 		DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
893
 		DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
892
-		       tls, ( ntohs ( hello_a->version ) >> 8 ),
893
-		       ( ntohs ( hello_a->version ) & 0xff ) );
894
+		       tls, ( version >> 8 ), ( version & 0xff ) );
894
 		return -ENOTSUP;
895
 		return -ENOTSUP;
895
 	}
896
 	}
897
+	if ( version > tls->version ) {
898
+		DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
899
+		       "protocol version %d.%d\n",
900
+		       tls, ( version >> 8 ), ( version & 0xff ) );
901
+		return -EPROTO;
902
+	}
903
+	tls->version = version;
904
+	DBGC ( tls, "TLS %p using protocol version %d.%d\n",
905
+	       tls, ( version >> 8 ), ( version & 0xff ) );
896
 
906
 
897
 	/* Copy out server random bytes */
907
 	/* Copy out server random bytes */
898
 	memcpy ( &tls->server_random, &hello_a->random,
908
 	memcpy ( &tls->server_random, &hello_a->random,
1208
 				   const void *data, size_t len,
1218
 				   const void *data, size_t len,
1209
 				   void *digest, size_t *plaintext_len ) {
1219
 				   void *digest, size_t *plaintext_len ) {
1210
 	size_t blocksize = tls->tx_cipherspec.cipher->blocksize;
1220
 	size_t blocksize = tls->tx_cipherspec.cipher->blocksize;
1211
-	size_t iv_len = blocksize;
1212
 	size_t mac_len = tls->tx_cipherspec.digest->digestsize;
1221
 	size_t mac_len = tls->tx_cipherspec.digest->digestsize;
1222
+	size_t iv_len;
1213
 	size_t padding_len;
1223
 	size_t padding_len;
1214
 	void *plaintext;
1224
 	void *plaintext;
1215
 	void *iv;
1225
 	void *iv;
1217
 	void *mac;
1227
 	void *mac;
1218
 	void *padding;
1228
 	void *padding;
1219
 
1229
 
1220
-	/* FIXME: TLSv1.1 has an explicit IV */
1221
-	iv_len = 0;
1230
+	/* TLSv1.1 and later use an explicit IV */
1231
+	iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? blocksize : 0 );
1222
 
1232
 
1223
 	/* Calculate block-ciphered struct length */
1233
 	/* Calculate block-ciphered struct length */
1224
 	padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
1234
 	padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
1234
 	padding = ( mac + mac_len );
1244
 	padding = ( mac + mac_len );
1235
 
1245
 
1236
 	/* Fill in block-ciphered struct */
1246
 	/* Fill in block-ciphered struct */
1237
-	memset ( iv, 0, iv_len );
1247
+	tls_generate_random ( tls, iv, iv_len );
1238
 	memcpy ( content, data, len );
1248
 	memcpy ( content, data, len );
1239
 	memcpy ( mac, digest, mac_len );
1249
 	memcpy ( mac, digest, mac_len );
1240
 	memset ( padding, padding_len, ( padding_len + 1 ) );
1250
 	memset ( padding, padding_len, ( padding_len + 1 ) );
1266
 
1276
 
1267
 	/* Construct header */
1277
 	/* Construct header */
1268
 	plaintext_tlshdr.type = type;
1278
 	plaintext_tlshdr.type = type;
1269
-	plaintext_tlshdr.version = htons ( TLS_VERSION_TLS_1_0 );
1279
+	plaintext_tlshdr.version = htons ( tls->version );
1270
 	plaintext_tlshdr.length = htons ( len );
1280
 	plaintext_tlshdr.length = htons ( len );
1271
 
1281
 
1272
 	/* Calculate MAC */
1282
 	/* Calculate MAC */
1304
 	/* Assemble ciphertext */
1314
 	/* Assemble ciphertext */
1305
 	tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) );
1315
 	tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) );
1306
 	tlshdr->type = type;
1316
 	tlshdr->type = type;
1307
-	tlshdr->version = htons ( TLS_VERSION_TLS_1_0 );
1317
+	tlshdr->version = htons ( tls->version );
1308
 	tlshdr->length = htons ( plaintext_len );
1318
 	tlshdr->length = htons ( plaintext_len );
1309
 	memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
1319
 	memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
1310
 		 cipherspec->cipher->ctxsize );
1320
 		 cipherspec->cipher->ctxsize );
1399
 	size_t padding_len;
1409
 	size_t padding_len;
1400
 	unsigned int i;
1410
 	unsigned int i;
1401
 
1411
 
1402
-	/* Decompose block-ciphered data */
1412
+	/* Sanity check */
1403
 	if ( plaintext_len < 1 ) {
1413
 	if ( plaintext_len < 1 ) {
1404
 		DBGC ( tls, "TLS %p received underlength record\n", tls );
1414
 		DBGC ( tls, "TLS %p received underlength record\n", tls );
1405
 		DBGC_HD ( tls, plaintext, plaintext_len );
1415
 		DBGC_HD ( tls, plaintext, plaintext_len );
1406
 		return -EINVAL;
1416
 		return -EINVAL;
1407
 	}
1417
 	}
1408
-	iv_len = tls->rx_cipherspec.cipher->blocksize;
1409
 
1418
 
1410
-	/* FIXME: TLSv1.1 uses an explicit IV */
1411
-	iv_len = 0;
1419
+	/* TLSv1.1 and later use an explicit IV */
1420
+	iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
1421
+		   tls->rx_cipherspec.cipher->blocksize : 0 );
1412
 
1422
 
1423
+	/* Decompose block-ciphered data */
1413
 	mac_len = tls->rx_cipherspec.digest->digestsize;
1424
 	mac_len = tls->rx_cipherspec.digest->digestsize;
1414
 	padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
1425
 	padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
1415
 	if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
1426
 	if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
1808
 	ref_init ( &tls->refcnt, free_tls );
1819
 	ref_init ( &tls->refcnt, free_tls );
1809
 	intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
1820
 	intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
1810
 	intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
1821
 	intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
1822
+	tls->version = TLS_VERSION_TLS_1_1;
1811
 	tls_clear_cipher ( tls, &tls->tx_cipherspec );
1823
 	tls_clear_cipher ( tls, &tls->tx_cipherspec );
1812
 	tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
1824
 	tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
1813
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
1825
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
1817
 			  ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
1829
 			  ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
1818
 		goto err_random;
1830
 		goto err_random;
1819
 	}
1831
 	}
1820
-	tls->pre_master_secret.version = htons ( TLS_VERSION_TLS_1_0 );
1832
+	tls->pre_master_secret.version = htons ( tls->version );
1821
 	if ( ( rc = tls_generate_random ( tls, &tls->pre_master_secret.random,
1833
 	if ( ( rc = tls_generate_random ( tls, &tls->pre_master_secret.random,
1822
 		      ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) {
1834
 		      ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) {
1823
 		goto err_random;
1835
 		goto err_random;

Loading…
Cancel
Save