/** 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 */
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
*
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
*
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 );
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 ) {