Browse Source

[tls] Allow transmitted records to be scheduled independently

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
56a7981d58
2 changed files with 39 additions and 93 deletions
  1. 10
    10
      src/include/ipxe/tls.h
  2. 29
    83
      src/net/tls.c

+ 10
- 10
src/include/ipxe/tls.h View File

84
 	TLS_RX_DATA,
84
 	TLS_RX_DATA,
85
 };
85
 };
86
 
86
 
87
-/** TLS TX state machine state */
88
-enum tls_tx_state {
89
-	TLS_TX_NONE = 0,
90
-	TLS_TX_CLIENT_HELLO,
91
-	TLS_TX_CLIENT_KEY_EXCHANGE,
92
-	TLS_TX_CHANGE_CIPHER,
93
-	TLS_TX_FINISHED,
94
-	TLS_TX_DATA
87
+/** TLS TX pending flags */
88
+enum tls_tx_pending {
89
+	TLS_TX_CLIENT_HELLO = 0x0001,
90
+	TLS_TX_CLIENT_KEY_EXCHANGE = 0x0002,
91
+	TLS_TX_CHANGE_CIPHER = 0x0004,
92
+	TLS_TX_FINISHED = 0x0008,
95
 };
93
 };
96
 
94
 
97
 /** A TLS cipher specification */
95
 /** A TLS cipher specification */
172
 
170
 
173
 	/** TX sequence number */
171
 	/** TX sequence number */
174
 	uint64_t tx_seq;
172
 	uint64_t tx_seq;
175
-	/** TX state */
176
-	enum tls_tx_state tx_state;
173
+	/** TX pending transmissions */
174
+	unsigned int tx_pending;
177
 	/** TX process */
175
 	/** TX process */
178
 	struct process process;
176
 	struct process process;
177
+	/** TX ready for plaintext data */
178
+	int tx_ready;
179
 
179
 
180
 	/** RX sequence number */
180
 	/** RX sequence number */
181
 	uint64_t rx_seq;
181
 	uint64_t rx_seq;

+ 29
- 83
src/net/tls.c View File

596
 
596
 
597
 /******************************************************************************
597
 /******************************************************************************
598
  *
598
  *
599
- * TX state machine transitions
599
+ * Record handling
600
  *
600
  *
601
  ******************************************************************************
601
  ******************************************************************************
602
  */
602
  */
610
 	process_add ( &tls->process );
610
 	process_add ( &tls->process );
611
 }
611
 }
612
 
612
 
613
-/**
614
- * Enter TX state machine active state
615
- *
616
- * @v tls		TLS session
617
- * @v state		TX state
618
- */
619
-static void tls_tx_start ( struct tls_session *tls, enum tls_tx_state state ) {
620
-
621
-	/* Enter specified state */
622
-	tls->tx_state = state;
623
-
624
-	/* Resume state machine */
625
-	tls_tx_resume ( tls );
626
-}
627
-
628
-/**
629
- * Enter TX state machine idle state
630
- *
631
- * @v tls		TLS session
632
- */
633
-static void tls_tx_none ( struct tls_session *tls ) {
634
-
635
-	/* Enter idle state */
636
-	tls->tx_state = TLS_TX_NONE;
637
-}
638
-
639
-/**
640
- * Enter TX state machine data state
641
- *
642
- * @v tls		TLS session
643
- */
644
-static void tls_tx_data ( struct tls_session *tls ) {
645
-
646
-	/* Enter data state */
647
-	tls->tx_state = TLS_TX_DATA;
648
-
649
-	/* Send notification of a window change */
650
-	xfer_window_changed ( &tls->plainstream );
651
-}
652
-
653
-/******************************************************************************
654
- *
655
- * Record handling
656
- *
657
- ******************************************************************************
658
- */
659
-
660
 /**
613
 /**
661
  * Transmit Handshake record
614
  * Transmit Handshake record
662
  *
615
  *
1025
 		return -EINVAL;
978
 		return -EINVAL;
1026
 	}
979
 	}
1027
 
980
 
1028
-	/* Check that we are ready to send the Client Key Exchange */
1029
-	if ( tls->tx_state != TLS_TX_NONE ) {
1030
-		DBGC ( tls, "TLS %p received Server Hello Done while in "
1031
-		       "TX state %d\n", tls, tls->tx_state );
1032
-		return -EIO;
1033
-	}
1034
-
1035
-	/* Start sending the Client Key Exchange */
1036
-	tls_tx_start ( tls, TLS_TX_CLIENT_KEY_EXCHANGE );
981
+	/* Schedule Client Key Exchange, Change Cipher, and Finished */
982
+	tls->tx_pending |= ( TLS_TX_CLIENT_KEY_EXCHANGE |
983
+			     TLS_TX_CHANGE_CIPHER |
984
+			     TLS_TX_FINISHED );
985
+	tls_tx_resume ( tls );
1037
 
986
 
1038
 	return 0;
987
 	return 0;
1039
 }
988
 }
1050
 			      void *data, size_t len ) {
999
 			      void *data, size_t len ) {
1051
 
1000
 
1052
 	/* FIXME: Handle this properly */
1001
 	/* FIXME: Handle this properly */
1053
-	tls_tx_data ( tls );
1054
 	( void ) data;
1002
 	( void ) data;
1055
 	( void ) len;
1003
 	( void ) len;
1056
 
1004
 
1005
+	/* Mark session as ready to transmit plaintext data */
1006
+	tls->tx_ready = 1;
1007
+
1008
+	/* Send notification of a window change */
1009
+	xfer_window_changed ( &tls->plainstream );
1010
+
1057
 	return 0;
1011
 	return 0;
1058
 }
1012
 }
1059
 
1013
 
1561
 static size_t tls_plainstream_window ( struct tls_session *tls ) {
1515
 static size_t tls_plainstream_window ( struct tls_session *tls ) {
1562
 
1516
 
1563
 	/* Block window unless we are ready to accept data */
1517
 	/* Block window unless we are ready to accept data */
1564
-	if ( tls->tx_state != TLS_TX_DATA )
1518
+	if ( ! tls->tx_ready )
1565
 		return 0;
1519
 		return 0;
1566
 
1520
 
1567
 	return xfer_window ( &tls->cipherstream );
1521
 	return xfer_window ( &tls->cipherstream );
1581
 	int rc;
1535
 	int rc;
1582
 	
1536
 	
1583
 	/* Refuse unless we are ready to accept data */
1537
 	/* Refuse unless we are ready to accept data */
1584
-	if ( tls->tx_state != TLS_TX_DATA ) {
1538
+	if ( ! tls->tx_ready ) {
1585
 		rc = -ENOTCONN;
1539
 		rc = -ENOTCONN;
1586
 		goto done;
1540
 		goto done;
1587
 	}
1541
 	}
1757
 	if ( ! xfer_window ( &tls->cipherstream ) )
1711
 	if ( ! xfer_window ( &tls->cipherstream ) )
1758
 		return;
1712
 		return;
1759
 
1713
 
1760
-	switch ( tls->tx_state ) {
1761
-	case TLS_TX_NONE:
1762
-		/* Nothing to do */
1763
-		break;
1764
-	case TLS_TX_CLIENT_HELLO:
1714
+	/* Send first pending transmission */
1715
+	if ( tls->tx_pending & TLS_TX_CLIENT_HELLO ) {
1765
 		/* Send Client Hello */
1716
 		/* Send Client Hello */
1766
 		if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
1717
 		if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
1767
 			DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
1718
 			DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
1768
 			       tls, strerror ( rc ) );
1719
 			       tls, strerror ( rc ) );
1769
 			goto err;
1720
 			goto err;
1770
 		}
1721
 		}
1771
-		tls_tx_none ( tls );
1772
-		break;
1773
-	case TLS_TX_CLIENT_KEY_EXCHANGE:
1722
+		tls->tx_pending &= ~TLS_TX_CLIENT_HELLO;
1723
+	} else if ( tls->tx_pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
1774
 		/* Send Client Key Exchange */
1724
 		/* Send Client Key Exchange */
1775
 		if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
1725
 		if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
1776
 			DBGC ( tls, "TLS %p could send Client Key Exchange: "
1726
 			DBGC ( tls, "TLS %p could send Client Key Exchange: "
1777
 			       "%s\n", tls, strerror ( rc ) );
1727
 			       "%s\n", tls, strerror ( rc ) );
1778
 			goto err;
1728
 			goto err;
1779
 		}
1729
 		}
1780
-		tls_tx_start ( tls, TLS_TX_CHANGE_CIPHER );
1781
-		break;
1782
-	case TLS_TX_CHANGE_CIPHER:
1730
+		tls->tx_pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE;
1731
+	} else if ( tls->tx_pending & TLS_TX_CHANGE_CIPHER ) {
1783
 		/* Send Change Cipher, and then change the cipher in use */
1732
 		/* Send Change Cipher, and then change the cipher in use */
1784
 		if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
1733
 		if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
1785
 			DBGC ( tls, "TLS %p could not send Change Cipher: "
1734
 			DBGC ( tls, "TLS %p could not send Change Cipher: "
1794
 			goto err;
1743
 			goto err;
1795
 		}
1744
 		}
1796
 		tls->tx_seq = 0;
1745
 		tls->tx_seq = 0;
1797
-		tls_tx_start ( tls, TLS_TX_FINISHED );
1798
-		break;
1799
-	case TLS_TX_FINISHED:
1746
+		tls->tx_pending &= ~TLS_TX_CHANGE_CIPHER;
1747
+	} else if ( tls->tx_pending & TLS_TX_FINISHED ) {
1800
 		/* Send Finished */
1748
 		/* Send Finished */
1801
 		if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
1749
 		if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
1802
 			DBGC ( tls, "TLS %p could not send Finished: %s\n",
1750
 			DBGC ( tls, "TLS %p could not send Finished: %s\n",
1803
 			       tls, strerror ( rc ) );
1751
 			       tls, strerror ( rc ) );
1804
 			goto err;
1752
 			goto err;
1805
 		}
1753
 		}
1806
-		tls_tx_none ( tls );
1807
-		break;
1808
-	case TLS_TX_DATA:
1809
-		/* Nothing to do */
1810
-		break;
1811
-	default:
1812
-		assert ( 0 );
1754
+		tls->tx_pending &= ~TLS_TX_FINISHED;
1813
 	}
1755
 	}
1814
 
1756
 
1757
+	/* Reschedule process if pending transmissions remain */
1758
+	if ( tls->tx_pending )
1759
+		tls_tx_resume ( tls );
1760
+
1815
 	return;
1761
 	return;
1816
 
1762
 
1817
  err:
1763
  err:
1862
 	}
1808
 	}
1863
 	digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
1809
 	digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
1864
 	digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
1810
 	digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
1865
-	process_init_stopped ( &tls->process, &tls_process_desc, &tls->refcnt );
1866
-	tls_tx_start ( tls, TLS_TX_CLIENT_HELLO );
1811
+	tls->tx_pending = TLS_TX_CLIENT_HELLO;
1812
+	process_init ( &tls->process, &tls_process_desc, &tls->refcnt );
1867
 
1813
 
1868
 	/* Attach to parent interface, mortalise self, and return */
1814
 	/* Attach to parent interface, mortalise self, and return */
1869
 	intf_plug_plug ( &tls->plainstream, xfer );
1815
 	intf_plug_plug ( &tls->plainstream, xfer );

Loading…
Cancel
Save