summaryrefslogtreecommitdiffstats
path: root/src/net/tls.c
diff options
context:
space:
mode:
authorMichael Brown2012-03-03 23:47:16 +0100
committerMichael Brown2012-03-03 23:47:16 +0100
commit281f9aa7a6775e60c78469228fe3d1a3a1355db9 (patch)
treecc907a658c3891efc52555ef574bfbc81a154810 /src/net/tls.c
parent[tls] Verify the contents of the Finished record (diff)
downloadipxe-281f9aa7a6775e60c78469228fe3d1a3a1355db9.tar.gz
ipxe-281f9aa7a6775e60c78469228fe3d1a3a1355db9.tar.xz
ipxe-281f9aa7a6775e60c78469228fe3d1a3a1355db9.zip
[tls] Send empty Certificate record if requested by server
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/tls.c')
-rw-r--r--src/net/tls.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/net/tls.c b/src/net/tls.c
index 28a4ba4e..0249ed7c 100644
--- a/src/net/tls.c
+++ b/src/net/tls.c
@@ -685,6 +685,27 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
}
/**
+ * Transmit Certificate record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_certificate ( struct tls_session *tls ) {
+ struct {
+ uint32_t type_length;
+ uint8_t length[3];
+ } __attribute__ (( packed )) certificate;
+
+ memset ( &certificate, 0, sizeof ( certificate ) );
+ certificate.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE ) |
+ htonl ( sizeof ( certificate ) -
+ sizeof ( certificate.type_length)));
+
+ return tls_send_handshake ( tls, &certificate, sizeof ( certificate ) );
+}
+
+
+/**
* Transmit Client Key Exchange record
*
* @v tls TLS session
@@ -956,6 +977,30 @@ static int tls_new_certificate ( struct tls_session *tls,
}
/**
+ * Receive new Certificate Request handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_certificate_request ( struct tls_session *tls,
+ void *data __unused,
+ size_t len __unused ) {
+
+ /* We can only send an empty certificate (as mandated by
+ * TLSv1.2), so there is no point in parsing the Certificate
+ * Request.
+ */
+
+ /* Schedule Certificate transmission */
+ tls->tx_pending |= TLS_TX_CERTIFICATE;
+ tls_tx_resume ( tls );
+
+ return 0;
+}
+
+/**
* Receive new Server Hello Done handshake record
*
* @v tls TLS session
@@ -1070,6 +1115,10 @@ static int tls_new_handshake ( struct tls_session *tls,
case TLS_CERTIFICATE:
rc = tls_new_certificate ( tls, payload, payload_len );
break;
+ case TLS_CERTIFICATE_REQUEST:
+ rc = tls_new_certificate_request ( tls, payload,
+ payload_len );
+ break;
case TLS_SERVER_HELLO_DONE:
rc = tls_new_server_hello_done ( tls, payload,
payload_len );
@@ -1741,6 +1790,14 @@ static void tls_tx_step ( struct tls_session *tls ) {
goto err;
}
tls->tx_pending &= ~TLS_TX_CLIENT_HELLO;
+ } else if ( tls->tx_pending & TLS_TX_CERTIFICATE ) {
+ /* Send Certificate */
+ if ( ( rc = tls_send_certificate ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p cold not send Certificate: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_pending &= ~TLS_TX_CERTIFICATE;
} else if ( tls->tx_pending & TLS_TX_CLIENT_KEY_EXCHANGE ) {
/* Send Client Key Exchange */
if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {