Browse Source

[tls] Split received records over multiple I/O buffers

TLS servers are not obliged to implement the RFC3546 maximum fragment
length extension, and many common servers (including OpenSSL, as used
in Apache's mod_ssl) do not do so.  iPXE may therefore have to cope
with TLS records of up to 16kB.  Allocations for 16kB have a
non-negligible chance of failing, causing the TLS connection to abort.

Fix by maintaining the received record as a linked list of I/O
buffers, rather than a single contiguous buffer.  To reduce memory
pressure, we also decrypt in situ, and deliver the decrypted data via
xfer_deliver_iob() rather than xfer_deliver_raw().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
72db14640c
2 changed files with 304 additions and 168 deletions
  1. 26
    4
      src/include/ipxe/tls.h
  2. 278
    164
      src/net/tls.c

+ 26
- 4
src/include/ipxe/tls.h View File

19
 #include <ipxe/sha256.h>
19
 #include <ipxe/sha256.h>
20
 #include <ipxe/x509.h>
20
 #include <ipxe/x509.h>
21
 #include <ipxe/pending.h>
21
 #include <ipxe/pending.h>
22
+#include <ipxe/iobuf.h>
22
 
23
 
23
 /** A TLS header */
24
 /** A TLS header */
24
 struct tls_header {
25
 struct tls_header {
264
 	uint64_t rx_seq;
265
 	uint64_t rx_seq;
265
 	/** RX state */
266
 	/** RX state */
266
 	enum tls_rx_state rx_state;
267
 	enum tls_rx_state rx_state;
267
-	/** Offset within current RX state */
268
-	size_t rx_rcvd;
269
 	/** Current received record header */
268
 	/** Current received record header */
270
 	struct tls_header rx_header;
269
 	struct tls_header rx_header;
271
-	/** Current received raw data buffer */
272
-	void *rx_data;
270
+	/** Current received record header (static I/O buffer) */
271
+	struct io_buffer rx_header_iobuf;
272
+	/** List of received data buffers */
273
+	struct list_head rx_data;
273
 };
274
 };
274
 
275
 
276
+/** RX I/O buffer size
277
+ *
278
+ * The maximum fragment length extension is optional, and many common
279
+ * implementations (including OpenSSL) do not support it.  We must
280
+ * therefore be prepared to receive records of up to 16kB in length.
281
+ * The chance of an allocation of this size failing is non-negligible,
282
+ * so we must split received data into smaller allocations.
283
+ */
284
+#define TLS_RX_BUFSIZE 4096
285
+
286
+/** Minimum RX I/O buffer size
287
+ *
288
+ * To simplify manipulations, we ensure that no RX I/O buffer is
289
+ * smaller than this size.  This allows us to assume that the MAC and
290
+ * padding are entirely contained within the final I/O buffer.
291
+ */
292
+#define TLS_RX_MIN_BUFSIZE 512
293
+
294
+/** RX I/O buffer alignment */
295
+#define TLS_RX_ALIGN 16
296
+
275
 extern int add_tls ( struct interface *xfer, const char *name,
297
 extern int add_tls ( struct interface *xfer, const char *name,
276
 		     struct interface **next );
298
 		     struct interface **next );
277
 
299
 

+ 278
- 164
src/net/tls.c View File

101
 #define EINFO_EINVAL_RX_STATE						\
101
 #define EINFO_EINVAL_RX_STATE						\
102
 	__einfo_uniqify ( EINFO_EINVAL, 0x0c,				\
102
 	__einfo_uniqify ( EINFO_EINVAL, 0x0c,				\
103
 			  "Invalid receive state" )
103
 			  "Invalid receive state" )
104
+#define EINVAL_MAC __einfo_error ( EINFO_EINVAL_MAC )
105
+#define EINFO_EINVAL_MAC						\
106
+	__einfo_uniqify ( EINFO_EINVAL, 0x0d,				\
107
+			  "Invalid MAC" )
108
+#define EINVAL_NON_DATA __einfo_error ( EINFO_EINVAL_NON_DATA )
109
+#define EINFO_EINVAL_NON_DATA						\
110
+	__einfo_uniqify ( EINFO_EINVAL, 0x0e,				\
111
+			  "Overlength non-data record" )
104
 #define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT )
112
 #define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT )
105
 #define EINFO_EIO_ALERT							\
113
 #define EINFO_EIO_ALERT							\
106
 	__einfo_uniqify ( EINFO_EINVAL, 0x01,				\
114
 	__einfo_uniqify ( EINFO_EINVAL, 0x01,				\
125
 #define EINFO_ENOMEM_TX_CIPHERTEXT					\
133
 #define EINFO_ENOMEM_TX_CIPHERTEXT					\
126
 	__einfo_uniqify ( EINFO_ENOMEM, 0x05,				\
134
 	__einfo_uniqify ( EINFO_ENOMEM, 0x05,				\
127
 			  "Not enough space for transmitted ciphertext" )
135
 			  "Not enough space for transmitted ciphertext" )
128
-#define ENOMEM_RX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_RX_PLAINTEXT )
129
-#define EINFO_ENOMEM_RX_PLAINTEXT					\
130
-	__einfo_uniqify ( EINFO_ENOMEM, 0x06,				\
131
-			  "Not enough space for received plaintext" )
132
 #define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA )
136
 #define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA )
133
 #define EINFO_ENOMEM_RX_DATA						\
137
 #define EINFO_ENOMEM_RX_DATA						\
134
 	__einfo_uniqify ( EINFO_ENOMEM, 0x07,				\
138
 	__einfo_uniqify ( EINFO_ENOMEM, 0x07,				\
159
 			  "Handshake verification failed" )
163
 			  "Handshake verification failed" )
160
 #define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION )
164
 #define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION )
161
 #define EINFO_EPROTO_VERSION						\
165
 #define EINFO_EPROTO_VERSION						\
162
-	__einfo_uniqify ( EINFO_EINVAL, 0x01,				\
166
+	__einfo_uniqify ( EINFO_EPROTO, 0x01,				\
163
 			  "Illegal protocol version upgrade" )
167
 			  "Illegal protocol version upgrade" )
164
 
168
 
165
 static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
169
 static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
295
 static void free_tls ( struct refcnt *refcnt ) {
299
 static void free_tls ( struct refcnt *refcnt ) {
296
 	struct tls_session *tls =
300
 	struct tls_session *tls =
297
 		container_of ( refcnt, struct tls_session, refcnt );
301
 		container_of ( refcnt, struct tls_session, refcnt );
302
+	struct io_buffer *iobuf;
303
+	struct io_buffer *tmp;
298
 
304
 
299
 	/* Free dynamically-allocated resources */
305
 	/* Free dynamically-allocated resources */
300
 	tls_clear_cipher ( tls, &tls->tx_cipherspec );
306
 	tls_clear_cipher ( tls, &tls->tx_cipherspec );
301
 	tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
307
 	tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
302
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
308
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
303
 	tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
309
 	tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
304
-	free ( tls->rx_data );
310
+	list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
311
+		list_del ( &iobuf->list );
312
+		free_iob ( iobuf );
313
+	}
305
 	x509_chain_put ( tls->chain );
314
 	x509_chain_put ( tls->chain );
306
 
315
 
307
 	/* Free TLS structure itself */
316
 	/* Free TLS structure itself */
1013
 	hello.extensions.max_fragment_length_len
1022
 	hello.extensions.max_fragment_length_len
1014
 		= htons ( sizeof ( hello.extensions.max_fragment_length ) );
1023
 		= htons ( sizeof ( hello.extensions.max_fragment_length ) );
1015
 	hello.extensions.max_fragment_length.max
1024
 	hello.extensions.max_fragment_length.max
1016
-		= TLS_MAX_FRAGMENT_LENGTH_2048;
1025
+		= TLS_MAX_FRAGMENT_LENGTH_4096;
1017
 
1026
 
1018
 	return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
1027
 	return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
1019
 }
1028
 }
1703
  *
1712
  *
1704
  * @v tls		TLS session
1713
  * @v tls		TLS session
1705
  * @v type		Record type
1714
  * @v type		Record type
1706
- * @v data		Plaintext record
1707
- * @v len		Length of plaintext record
1715
+ * @v rx_data		List of received data buffers
1708
  * @ret rc		Return status code
1716
  * @ret rc		Return status code
1709
  */
1717
  */
1710
 static int tls_new_record ( struct tls_session *tls, unsigned int type,
1718
 static int tls_new_record ( struct tls_session *tls, unsigned int type,
1711
-			    const void *data, size_t len ) {
1719
+			    struct list_head *rx_data ) {
1720
+	struct io_buffer *iobuf;
1721
+	int ( * handler ) ( struct tls_session *tls, const void *data,
1722
+			    size_t len );
1723
+	int rc;
1724
+
1725
+	/* Deliver data records to the plainstream interface */
1726
+	if ( type == TLS_TYPE_DATA ) {
1727
+
1728
+		/* Fail unless we are ready to receive data */
1729
+		if ( ! tls_ready ( tls ) )
1730
+			return -ENOTCONN;
1712
 
1731
 
1732
+		/* Deliver each I/O buffer in turn */
1733
+		while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
1734
+						     list ) ) ) {
1735
+			list_del ( &iobuf->list );
1736
+			if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
1737
+						       iobuf ) ) != 0 ) {
1738
+				DBGC ( tls, "TLS %p could not deliver data: "
1739
+				       "%s\n", tls, strerror ( rc ) );
1740
+				return rc;
1741
+			}
1742
+		}
1743
+		return 0;
1744
+	}
1745
+
1746
+	/* For all other records, fail unless we have exactly one I/O buffer */
1747
+	iobuf = list_first_entry ( rx_data, struct io_buffer, list );
1748
+	assert ( iobuf != NULL );
1749
+	list_del ( &iobuf->list );
1750
+	if ( ! list_empty ( rx_data ) ) {
1751
+		DBGC ( tls, "TLS %p overlength non-data record\n", tls );
1752
+		return -EINVAL_NON_DATA;
1753
+	}
1754
+
1755
+	/* Determine handler */
1713
 	switch ( type ) {
1756
 	switch ( type ) {
1714
 	case TLS_TYPE_CHANGE_CIPHER:
1757
 	case TLS_TYPE_CHANGE_CIPHER:
1715
-		return tls_new_change_cipher ( tls, data, len );
1758
+		handler = tls_new_change_cipher;
1759
+		break;
1716
 	case TLS_TYPE_ALERT:
1760
 	case TLS_TYPE_ALERT:
1717
-		return tls_new_alert ( tls, data, len );
1761
+		handler = tls_new_alert;
1762
+		break;
1718
 	case TLS_TYPE_HANDSHAKE:
1763
 	case TLS_TYPE_HANDSHAKE:
1719
-		return tls_new_handshake ( tls, data, len );
1720
-	case TLS_TYPE_DATA:
1721
-		if ( ! tls_ready ( tls ) )
1722
-			return -ENOTCONN;
1723
-		return xfer_deliver_raw ( &tls->plainstream, data, len );
1764
+		handler = tls_new_handshake;
1765
+		break;
1724
 	default:
1766
 	default:
1725
 		/* RFC4346 says that we should just ignore unknown
1767
 		/* RFC4346 says that we should just ignore unknown
1726
 		 * record types.
1768
 		 * record types.
1727
 		 */
1769
 		 */
1770
+		handler = NULL;
1728
 		DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
1771
 		DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
1729
-		return 0;
1772
+		break;
1730
 	}
1773
 	}
1774
+
1775
+	/* Handle record and free I/O buffer */
1776
+	if ( handler )
1777
+		rc = handler ( tls, iobuf->data, iob_len ( iobuf ) );
1778
+	free_iob ( iobuf );
1779
+	return rc;
1731
 }
1780
 }
1732
 
1781
 
1733
 /******************************************************************************
1782
 /******************************************************************************
1737
  ******************************************************************************
1786
  ******************************************************************************
1738
  */
1787
  */
1739
 
1788
 
1789
+/**
1790
+ * Initialise HMAC
1791
+ *
1792
+ * @v cipherspec	Cipher specification
1793
+ * @v ctx		Context
1794
+ * @v seq		Sequence number
1795
+ * @v tlshdr		TLS header
1796
+ */
1797
+static void tls_hmac_init ( struct tls_cipherspec *cipherspec, void *ctx,
1798
+			    uint64_t seq, struct tls_header *tlshdr ) {
1799
+	struct digest_algorithm *digest = cipherspec->suite->digest;
1800
+
1801
+	hmac_init ( digest, ctx, cipherspec->mac_secret, &digest->digestsize );
1802
+	seq = cpu_to_be64 ( seq );
1803
+	hmac_update ( digest, ctx, &seq, sizeof ( seq ) );
1804
+	hmac_update ( digest, ctx, tlshdr, sizeof ( *tlshdr ) );
1805
+}
1806
+
1807
+/**
1808
+ * Update HMAC
1809
+ *
1810
+ * @v cipherspec	Cipher specification
1811
+ * @v ctx		Context
1812
+ * @v data		Data
1813
+ * @v len		Length of data
1814
+ */
1815
+static void tls_hmac_update ( struct tls_cipherspec *cipherspec, void *ctx,
1816
+			      const void *data, size_t len ) {
1817
+	struct digest_algorithm *digest = cipherspec->suite->digest;
1818
+
1819
+	hmac_update ( digest, ctx, data, len );
1820
+}
1821
+
1822
+/**
1823
+ * Finalise HMAC
1824
+ *
1825
+ * @v cipherspec	Cipher specification
1826
+ * @v ctx		Context
1827
+ * @v mac		HMAC to fill in
1828
+ */
1829
+static void tls_hmac_final ( struct tls_cipherspec *cipherspec, void *ctx,
1830
+			     void *hmac ) {
1831
+	struct digest_algorithm *digest = cipherspec->suite->digest;
1832
+
1833
+	hmac_final ( digest, ctx, cipherspec->mac_secret,
1834
+		     &digest->digestsize, hmac );
1835
+}
1836
+
1740
 /**
1837
 /**
1741
  * Calculate HMAC
1838
  * Calculate HMAC
1742
  *
1839
  *
1743
- * @v tls		TLS session
1744
  * @v cipherspec	Cipher specification
1840
  * @v cipherspec	Cipher specification
1745
  * @v seq		Sequence number
1841
  * @v seq		Sequence number
1746
  * @v tlshdr		TLS header
1842
  * @v tlshdr		TLS header
1748
  * @v len		Length of data
1844
  * @v len		Length of data
1749
  * @v mac		HMAC to fill in
1845
  * @v mac		HMAC to fill in
1750
  */
1846
  */
1751
-static void tls_hmac ( struct tls_session *tls __unused,
1752
-		       struct tls_cipherspec *cipherspec,
1847
+static void tls_hmac ( struct tls_cipherspec *cipherspec,
1753
 		       uint64_t seq, struct tls_header *tlshdr,
1848
 		       uint64_t seq, struct tls_header *tlshdr,
1754
 		       const void *data, size_t len, void *hmac ) {
1849
 		       const void *data, size_t len, void *hmac ) {
1755
 	struct digest_algorithm *digest = cipherspec->suite->digest;
1850
 	struct digest_algorithm *digest = cipherspec->suite->digest;
1756
-	uint8_t digest_ctx[digest->ctxsize];
1851
+	uint8_t ctx[digest->ctxsize];
1757
 
1852
 
1758
-	hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
1759
-		    &digest->digestsize );
1760
-	seq = cpu_to_be64 ( seq );
1761
-	hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) );
1762
-	hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) );
1763
-	hmac_update ( digest, digest_ctx, data, len );
1764
-	hmac_final ( digest, digest_ctx, cipherspec->mac_secret,
1765
-		     &digest->digestsize, hmac );
1853
+	tls_hmac_init ( cipherspec, ctx, seq, tlshdr );
1854
+	tls_hmac_update ( cipherspec, ctx, data, len );
1855
+	tls_hmac_final ( cipherspec, ctx, hmac );
1766
 }
1856
 }
1767
 
1857
 
1768
 /**
1858
 /**
1877
 	plaintext_tlshdr.length = htons ( len );
1967
 	plaintext_tlshdr.length = htons ( len );
1878
 
1968
 
1879
 	/* Calculate MAC */
1969
 	/* Calculate MAC */
1880
-	tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
1881
-		   data, len, mac );
1970
+	tls_hmac ( cipherspec, tls->tx_seq, &plaintext_tlshdr, data, len, mac );
1882
 
1971
 
1883
 	/* Allocate and assemble plaintext struct */
1972
 	/* Allocate and assemble plaintext struct */
1884
 	if ( is_stream_cipher ( cipher ) ) {
1973
 	if ( is_stream_cipher ( cipher ) ) {
1945
  * Split stream-ciphered record into data and MAC portions
2034
  * Split stream-ciphered record into data and MAC portions
1946
  *
2035
  *
1947
  * @v tls		TLS session
2036
  * @v tls		TLS session
1948
- * @v plaintext		Plaintext record
1949
- * @v plaintext_len	Length of record
1950
- * @ret data		Data
1951
- * @ret len		Length of data
1952
- * @ret digest		MAC digest
2037
+ * @v rx_data		List of received data buffers
2038
+ * @v mac		MAC to fill in
1953
  * @ret rc		Return status code
2039
  * @ret rc		Return status code
1954
  */
2040
  */
1955
 static int tls_split_stream ( struct tls_session *tls,
2041
 static int tls_split_stream ( struct tls_session *tls,
1956
-			      void *plaintext, size_t plaintext_len,
1957
-			      void **data, size_t *len, void **digest ) {
1958
-	void *content;
1959
-	size_t content_len;
1960
-	void *mac;
1961
-	size_t mac_len;
1962
-
1963
-	/* Decompose stream-ciphered data */
1964
-	mac_len = tls->rx_cipherspec.suite->digest->digestsize;
1965
-	if ( plaintext_len < mac_len ) {
1966
-		DBGC ( tls, "TLS %p received underlength record\n", tls );
1967
-		DBGC_HD ( tls, plaintext, plaintext_len );
2042
+			      struct list_head *rx_data, void **mac ) {
2043
+	size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize;
2044
+	struct io_buffer *iobuf;
2045
+
2046
+	/* Extract MAC */
2047
+	iobuf = list_last_entry ( rx_data, struct io_buffer, list );
2048
+	assert ( iobuf != NULL );
2049
+	if ( iob_len ( iobuf ) < mac_len ) {
2050
+		DBGC ( tls, "TLS %p received underlength MAC\n", tls );
2051
+		DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
1968
 		return -EINVAL_STREAM;
2052
 		return -EINVAL_STREAM;
1969
 	}
2053
 	}
1970
-	content_len = ( plaintext_len - mac_len );
1971
-	content = plaintext;
1972
-	mac = ( content + content_len );
1973
-
1974
-	/* Fill in return values */
1975
-	*data = content;
1976
-	*len = content_len;
1977
-	*digest = mac;
2054
+	iob_unput ( iobuf, mac_len );
2055
+	*mac = iobuf->tail;
1978
 
2056
 
1979
 	return 0;
2057
 	return 0;
1980
 }
2058
 }
1983
  * Split block-ciphered record into data and MAC portions
2061
  * Split block-ciphered record into data and MAC portions
1984
  *
2062
  *
1985
  * @v tls		TLS session
2063
  * @v tls		TLS session
1986
- * @v plaintext		Plaintext record
1987
- * @v plaintext_len	Length of record
1988
- * @ret data		Data
1989
- * @ret len		Length of data
1990
- * @ret digest		MAC digest
2064
+ * @v rx_data		List of received data buffers
2065
+ * @v mac		MAC to fill in
1991
  * @ret rc		Return status code
2066
  * @ret rc		Return status code
1992
  */
2067
  */
1993
 static int tls_split_block ( struct tls_session *tls,
2068
 static int tls_split_block ( struct tls_session *tls,
1994
-			     void *plaintext, size_t plaintext_len,
1995
-			     void **data, size_t *len,
1996
-			     void **digest ) {
1997
-	void *iv;
2069
+			     struct list_head *rx_data, void **mac ) {
2070
+	size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize;
2071
+	struct io_buffer *iobuf;
1998
 	size_t iv_len;
2072
 	size_t iv_len;
1999
-	void *content;
2000
-	size_t content_len;
2001
-	void *mac;
2002
-	size_t mac_len;
2003
-	void *padding;
2073
+	uint8_t *padding_final;
2074
+	uint8_t *padding;
2004
 	size_t padding_len;
2075
 	size_t padding_len;
2005
-	unsigned int i;
2006
-
2007
-	/* Sanity check */
2008
-	if ( plaintext_len < 1 ) {
2009
-		DBGC ( tls, "TLS %p received underlength record\n", tls );
2010
-		DBGC_HD ( tls, plaintext, plaintext_len );
2011
-		return -EINVAL_BLOCK;
2012
-	}
2013
 
2076
 
2014
 	/* TLSv1.1 and later use an explicit IV */
2077
 	/* TLSv1.1 and later use an explicit IV */
2078
+	iobuf = list_first_entry ( rx_data, struct io_buffer, list );
2015
 	iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
2079
 	iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
2016
 		   tls->rx_cipherspec.suite->cipher->blocksize : 0 );
2080
 		   tls->rx_cipherspec.suite->cipher->blocksize : 0 );
2017
-
2018
-	/* Decompose block-ciphered data */
2019
-	mac_len = tls->rx_cipherspec.suite->digest->digestsize;
2020
-	padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
2021
-	if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
2022
-		DBGC ( tls, "TLS %p received underlength record\n", tls );
2023
-		DBGC_HD ( tls, plaintext, plaintext_len );
2081
+	if ( iob_len ( iobuf ) < iv_len ) {
2082
+		DBGC ( tls, "TLS %p received underlength IV\n", tls );
2083
+		DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
2024
 		return -EINVAL_BLOCK;
2084
 		return -EINVAL_BLOCK;
2025
 	}
2085
 	}
2026
-	content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
2027
-	iv = plaintext;
2028
-	content = ( iv + iv_len );
2029
-	mac = ( content + content_len );
2030
-	padding = ( mac + mac_len );
2031
-
2032
-	/* Verify padding bytes */
2033
-	for ( i = 0 ; i < padding_len ; i++ ) {
2034
-		if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
2086
+	iob_pull ( iobuf, iv_len );
2087
+
2088
+	/* Extract and verify padding */
2089
+	iobuf = list_last_entry ( rx_data, struct io_buffer, list );
2090
+	padding_final = ( iobuf->tail - 1 );
2091
+	padding_len = *padding_final;
2092
+	if ( ( padding_len + 1 ) > iob_len ( iobuf ) ) {
2093
+		DBGC ( tls, "TLS %p received underlength padding\n", tls );
2094
+		DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
2095
+		return -EINVAL_BLOCK;
2096
+	}
2097
+	iob_unput ( iobuf, ( padding_len + 1 ) );
2098
+	for ( padding = iobuf->tail ; padding < padding_final ; padding++ ) {
2099
+		if ( *padding != padding_len ) {
2035
 			DBGC ( tls, "TLS %p received bad padding\n", tls );
2100
 			DBGC ( tls, "TLS %p received bad padding\n", tls );
2036
-			DBGC_HD ( tls, plaintext, plaintext_len );
2101
+			DBGC_HD ( tls, padding, padding_len );
2037
 			return -EINVAL_PADDING;
2102
 			return -EINVAL_PADDING;
2038
 		}
2103
 		}
2039
 	}
2104
 	}
2040
 
2105
 
2041
-	/* Fill in return values */
2042
-	*data = content;
2043
-	*len = content_len;
2044
-	*digest = mac;
2106
+	/* Extract MAC */
2107
+	if ( iob_len ( iobuf ) < mac_len ) {
2108
+		DBGC ( tls, "TLS %p received underlength MAC\n", tls );
2109
+		DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
2110
+		return -EINVAL_BLOCK;
2111
+	}
2112
+	iob_unput ( iobuf, mac_len );
2113
+	*mac = iobuf->tail;
2045
 
2114
 
2046
 	return 0;
2115
 	return 0;
2047
 }
2116
 }
2051
  *
2120
  *
2052
  * @v tls		TLS session
2121
  * @v tls		TLS session
2053
  * @v tlshdr		Record header
2122
  * @v tlshdr		Record header
2054
- * @v ciphertext	Ciphertext record
2123
+ * @v rx_data		List of received data buffers
2055
  * @ret rc		Return status code
2124
  * @ret rc		Return status code
2056
  */
2125
  */
2057
 static int tls_new_ciphertext ( struct tls_session *tls,
2126
 static int tls_new_ciphertext ( struct tls_session *tls,
2058
 				struct tls_header *tlshdr,
2127
 				struct tls_header *tlshdr,
2059
-				const void *ciphertext ) {
2128
+				struct list_head *rx_data ) {
2060
 	struct tls_header plaintext_tlshdr;
2129
 	struct tls_header plaintext_tlshdr;
2061
 	struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
2130
 	struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
2062
 	struct cipher_algorithm *cipher = cipherspec->suite->cipher;
2131
 	struct cipher_algorithm *cipher = cipherspec->suite->cipher;
2063
-	size_t record_len = ntohs ( tlshdr->length );
2064
-	void *plaintext = NULL;
2065
-	void *data;
2066
-	size_t len;
2132
+	struct digest_algorithm *digest = cipherspec->suite->digest;
2133
+	uint8_t ctx[digest->ctxsize];
2134
+	uint8_t verify_mac[digest->digestsize];
2135
+	struct io_buffer *iobuf;
2067
 	void *mac;
2136
 	void *mac;
2068
-	size_t mac_len = cipherspec->suite->digest->digestsize;
2069
-	uint8_t verify_mac[mac_len];
2137
+	size_t len = 0;
2070
 	int rc;
2138
 	int rc;
2071
 
2139
 
2072
-	/* Allocate buffer for plaintext */
2073
-	plaintext = malloc ( record_len );
2074
-	if ( ! plaintext ) {
2075
-		DBGC ( tls, "TLS %p could not allocate %zd bytes for "
2076
-		       "decryption buffer\n", tls, record_len );
2077
-		rc = -ENOMEM_RX_PLAINTEXT;
2078
-		goto done;
2140
+	/* Decrypt the received data */
2141
+	list_for_each_entry ( iobuf, &tls->rx_data, list ) {
2142
+		cipher_decrypt ( cipher, cipherspec->cipher_ctx,
2143
+				 iobuf->data, iobuf->data, iob_len ( iobuf ) );
2079
 	}
2144
 	}
2080
 
2145
 
2081
-	/* Decrypt the record */
2082
-	cipher_decrypt ( cipher, cipherspec->cipher_ctx,
2083
-			 ciphertext, plaintext, record_len );
2084
-
2085
 	/* Split record into content and MAC */
2146
 	/* Split record into content and MAC */
2086
 	if ( is_stream_cipher ( cipher ) ) {
2147
 	if ( is_stream_cipher ( cipher ) ) {
2087
-		if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
2088
-					       &data, &len, &mac ) ) != 0 )
2089
-			goto done;
2148
+		if ( ( rc = tls_split_stream ( tls, rx_data, &mac ) ) != 0 )
2149
+			return rc;
2090
 	} else {
2150
 	} else {
2091
-		if ( ( rc = tls_split_block ( tls, plaintext, record_len,
2092
-					      &data, &len, &mac ) ) != 0 )
2093
-			goto done;
2151
+		if ( ( rc = tls_split_block ( tls, rx_data, &mac ) ) != 0 )
2152
+			return rc;
2153
+	}
2154
+
2155
+	/* Calculate total length */
2156
+	DBGC2 ( tls, "Received plaintext data:\n" );
2157
+	list_for_each_entry ( iobuf, rx_data, list ) {
2158
+		DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
2159
+		len += iob_len ( iobuf );
2094
 	}
2160
 	}
2095
 
2161
 
2096
 	/* Verify MAC */
2162
 	/* Verify MAC */
2097
 	plaintext_tlshdr.type = tlshdr->type;
2163
 	plaintext_tlshdr.type = tlshdr->type;
2098
 	plaintext_tlshdr.version = tlshdr->version;
2164
 	plaintext_tlshdr.version = tlshdr->version;
2099
 	plaintext_tlshdr.length = htons ( len );
2165
 	plaintext_tlshdr.length = htons ( len );
2100
-	tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr,
2101
-		   data, len, verify_mac);
2102
-	if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) {
2166
+	tls_hmac_init ( cipherspec, ctx, tls->rx_seq, &plaintext_tlshdr );
2167
+	list_for_each_entry ( iobuf, rx_data, list ) {
2168
+		tls_hmac_update ( cipherspec, ctx, iobuf->data,
2169
+				  iob_len ( iobuf ) );
2170
+	}
2171
+	tls_hmac_final ( cipherspec, ctx, verify_mac );
2172
+	if ( memcmp ( mac, verify_mac, sizeof ( verify_mac ) ) != 0 ) {
2103
 		DBGC ( tls, "TLS %p failed MAC verification\n", tls );
2173
 		DBGC ( tls, "TLS %p failed MAC verification\n", tls );
2104
-		DBGC_HD ( tls, plaintext, record_len );
2105
-		goto done;
2174
+		return -EINVAL_MAC;
2106
 	}
2175
 	}
2107
 
2176
 
2108
-	DBGC2 ( tls, "Received plaintext data:\n" );
2109
-	DBGC2_HD ( tls, data, len );
2110
-
2111
 	/* Process plaintext record */
2177
 	/* Process plaintext record */
2112
-	if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
2113
-		goto done;
2178
+	if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
2179
+		return rc;
2114
 
2180
 
2115
-	rc = 0;
2116
- done:
2117
-	free ( plaintext );
2118
-	return rc;
2181
+	return 0;
2119
 }
2182
 }
2120
 
2183
 
2121
 /******************************************************************************
2184
 /******************************************************************************
2195
  */
2258
  */
2196
 static int tls_newdata_process_header ( struct tls_session *tls ) {
2259
 static int tls_newdata_process_header ( struct tls_session *tls ) {
2197
 	size_t data_len = ntohs ( tls->rx_header.length );
2260
 	size_t data_len = ntohs ( tls->rx_header.length );
2261
+	size_t remaining = data_len;
2262
+	size_t frag_len;
2263
+	struct io_buffer *iobuf;
2264
+	struct io_buffer *tmp;
2265
+	int rc;
2198
 
2266
 
2199
-	/* Allocate data buffer now that we know the length */
2200
-	assert ( tls->rx_data == NULL );
2201
-	tls->rx_data = malloc ( data_len );
2202
-	if ( ! tls->rx_data ) {
2203
-		DBGC ( tls, "TLS %p could not allocate %zd bytes "
2204
-		       "for receive buffer\n", tls, data_len );
2205
-		return -ENOMEM_RX_DATA;
2267
+	/* Allocate data buffers now that we know the length */
2268
+	assert ( list_empty ( &tls->rx_data ) );
2269
+	while ( remaining ) {
2270
+
2271
+		/* Calculate fragment length.  Ensure that no block is
2272
+		 * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
2273
+		 * allocation length if necessary).
2274
+		 */
2275
+		frag_len = remaining;
2276
+		if ( frag_len > TLS_RX_BUFSIZE )
2277
+			frag_len = TLS_RX_BUFSIZE;
2278
+		remaining -= frag_len;
2279
+		if ( remaining < TLS_RX_MIN_BUFSIZE ) {
2280
+			frag_len += remaining;
2281
+			remaining = 0;
2282
+		}
2283
+
2284
+		/* Allocate buffer */
2285
+		iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
2286
+		if ( ! iobuf ) {
2287
+			DBGC ( tls, "TLS %p could not allocate %zd of %zd "
2288
+			       "bytes for receive buffer\n", tls,
2289
+			       remaining, data_len );
2290
+			rc = -ENOMEM_RX_DATA;
2291
+			goto err;
2292
+		}
2293
+
2294
+		/* Ensure tailroom is exactly what we asked for.  This
2295
+		 * will result in unaligned I/O buffers when the
2296
+		 * fragment length is unaligned, which can happen only
2297
+		 * before we switch to using a block cipher.
2298
+		 */
2299
+		iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
2300
+
2301
+		/* Add I/O buffer to list */
2302
+		list_add_tail ( &iobuf->list, &tls->rx_data );
2206
 	}
2303
 	}
2207
 
2304
 
2208
 	/* Move to data state */
2305
 	/* Move to data state */
2209
 	tls->rx_state = TLS_RX_DATA;
2306
 	tls->rx_state = TLS_RX_DATA;
2210
 
2307
 
2211
 	return 0;
2308
 	return 0;
2309
+
2310
+ err:
2311
+	list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
2312
+		list_del ( &iobuf->list );
2313
+		free_iob ( iobuf );
2314
+	}
2315
+	return rc;
2212
 }
2316
 }
2213
 
2317
 
2214
 /**
2318
 /**
2218
  * @ret rc		Returned status code
2322
  * @ret rc		Returned status code
2219
  */
2323
  */
2220
 static int tls_newdata_process_data ( struct tls_session *tls ) {
2324
 static int tls_newdata_process_data ( struct tls_session *tls ) {
2325
+	struct io_buffer *iobuf;
2221
 	int rc;
2326
 	int rc;
2222
 
2327
 
2328
+	/* Move current buffer to end of list */
2329
+	iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
2330
+	list_del ( &iobuf->list );
2331
+	list_add_tail ( &iobuf->list, &tls->rx_data );
2332
+
2333
+	/* Continue receiving data if any space remains */
2334
+	iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
2335
+	if ( iob_tailroom ( iobuf ) )
2336
+		return 0;
2337
+
2223
 	/* Process record */
2338
 	/* Process record */
2224
 	if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
2339
 	if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
2225
-					 tls->rx_data ) ) != 0 )
2340
+					 &tls->rx_data ) ) != 0 )
2226
 		return rc;
2341
 		return rc;
2227
 
2342
 
2228
 	/* Increment RX sequence number */
2343
 	/* Increment RX sequence number */
2229
 	tls->rx_seq += 1;
2344
 	tls->rx_seq += 1;
2230
 
2345
 
2231
-	/* Free data buffer */
2232
-	free ( tls->rx_data );
2233
-	tls->rx_data = NULL;
2234
-
2235
 	/* Return to header state */
2346
 	/* Return to header state */
2347
+	assert ( list_empty ( &tls->rx_data ) );
2236
 	tls->rx_state = TLS_RX_HEADER;
2348
 	tls->rx_state = TLS_RX_HEADER;
2349
+	iob_unput ( &tls->rx_header_iobuf, sizeof ( tls->rx_header ) );
2237
 
2350
 
2238
 	return 0;
2351
 	return 0;
2239
 }
2352
 }
2250
 				      struct io_buffer *iobuf,
2363
 				      struct io_buffer *iobuf,
2251
 				      struct xfer_metadata *xfer __unused ) {
2364
 				      struct xfer_metadata *xfer __unused ) {
2252
 	size_t frag_len;
2365
 	size_t frag_len;
2253
-	void *buf;
2254
-	size_t buf_len;
2255
 	int ( * process ) ( struct tls_session *tls );
2366
 	int ( * process ) ( struct tls_session *tls );
2367
+	struct io_buffer *dest;
2256
 	int rc;
2368
 	int rc;
2257
 
2369
 
2258
 	while ( iob_len ( iobuf ) ) {
2370
 	while ( iob_len ( iobuf ) ) {
2371
+
2259
 		/* Select buffer according to current state */
2372
 		/* Select buffer according to current state */
2260
 		switch ( tls->rx_state ) {
2373
 		switch ( tls->rx_state ) {
2261
 		case TLS_RX_HEADER:
2374
 		case TLS_RX_HEADER:
2262
-			buf = &tls->rx_header;
2263
-			buf_len = sizeof ( tls->rx_header );
2375
+			dest = &tls->rx_header_iobuf;
2264
 			process = tls_newdata_process_header;
2376
 			process = tls_newdata_process_header;
2265
 			break;
2377
 			break;
2266
 		case TLS_RX_DATA:
2378
 		case TLS_RX_DATA:
2267
-			buf = tls->rx_data;
2268
-			buf_len = ntohs ( tls->rx_header.length );
2379
+			dest = list_first_entry ( &tls->rx_data,
2380
+						  struct io_buffer, list );
2381
+			assert ( dest != NULL );
2269
 			process = tls_newdata_process_data;
2382
 			process = tls_newdata_process_data;
2270
 			break;
2383
 			break;
2271
 		default:
2384
 		default:
2275
 		}
2388
 		}
2276
 
2389
 
2277
 		/* Copy data portion to buffer */
2390
 		/* Copy data portion to buffer */
2278
-		frag_len = ( buf_len - tls->rx_rcvd );
2279
-		if ( frag_len > iob_len  ( iobuf ) )
2280
-			frag_len = iob_len ( iobuf );
2281
-		memcpy ( ( buf + tls->rx_rcvd ), iobuf->data, frag_len );
2282
-		tls->rx_rcvd += frag_len;
2391
+		frag_len = iob_len ( iobuf );
2392
+		if ( frag_len > iob_tailroom ( dest ) )
2393
+			frag_len = iob_tailroom ( dest );
2394
+		memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
2283
 		iob_pull ( iobuf, frag_len );
2395
 		iob_pull ( iobuf, frag_len );
2284
 
2396
 
2285
 		/* Process data if buffer is now full */
2397
 		/* Process data if buffer is now full */
2286
-		if ( tls->rx_rcvd == buf_len ) {
2398
+		if ( iob_tailroom ( dest ) == 0 ) {
2287
 			if ( ( rc = process ( tls ) ) != 0 ) {
2399
 			if ( ( rc = process ( tls ) ) != 0 ) {
2288
 				tls_close ( tls, rc );
2400
 				tls_close ( tls, rc );
2289
 				goto done;
2401
 				goto done;
2290
 			}
2402
 			}
2291
-			tls->rx_rcvd = 0;
2292
 		}
2403
 		}
2293
 	}
2404
 	}
2294
 	rc = 0;
2405
 	rc = 0;
2521
 	tls->handshake_digest = &sha256_algorithm;
2632
 	tls->handshake_digest = &sha256_algorithm;
2522
 	tls->handshake_ctx = tls->handshake_sha256_ctx;
2633
 	tls->handshake_ctx = tls->handshake_sha256_ctx;
2523
 	tls->tx_pending = TLS_TX_CLIENT_HELLO;
2634
 	tls->tx_pending = TLS_TX_CLIENT_HELLO;
2635
+	iob_populate ( &tls->rx_header_iobuf, &tls->rx_header, 0,
2636
+		       sizeof ( tls->rx_header ) );
2637
+	INIT_LIST_HEAD ( &tls->rx_data );
2524
 
2638
 
2525
 	/* Add pending operations for server and client Finished messages */
2639
 	/* Add pending operations for server and client Finished messages */
2526
 	pending_get ( &tls->client_negotiation );
2640
 	pending_get ( &tls->client_negotiation );

Loading…
Cancel
Save