]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Send empty Certificate record if requested by server
authorMichael Brown <mcb30@ipxe.org>
Sat, 3 Mar 2012 22:47:16 +0000 (22:47 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 3 Mar 2012 22:47:16 +0000 (22:47 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/tls.h
src/net/tls.c

index 2aa2b06dab0256d8290d6ee945a8a00eb9a41f30..49401e6bf715b0625f434942a4f34afa8ece9730 100644 (file)
@@ -87,9 +87,10 @@ enum tls_rx_state {
 /** TLS TX pending flags */
 enum tls_tx_pending {
        TLS_TX_CLIENT_HELLO = 0x0001,
-       TLS_TX_CLIENT_KEY_EXCHANGE = 0x0002,
-       TLS_TX_CHANGE_CIPHER = 0x0004,
-       TLS_TX_FINISHED = 0x0008,
+       TLS_TX_CERTIFICATE = 0x0002,
+       TLS_TX_CLIENT_KEY_EXCHANGE = 0x0004,
+       TLS_TX_CHANGE_CIPHER = 0x0008,
+       TLS_TX_FINISHED = 0x0010,
 };
 
 /** A TLS cipher specification */
index 28a4ba4ecc6876f58a14ebd92439102a76affc8a..0249ed7cbd8bb9b4504e4bddbd98f29fcd0ad733 100644 (file)
@@ -684,6 +684,27 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
        return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
 }
 
+/**
+ * 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
  *
@@ -955,6 +976,30 @@ static int tls_new_certificate ( struct tls_session *tls,
        return -EINVAL;
 }
 
+/**
+ * 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
  *
@@ -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 ) {