static int tls_write_server_hello(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
- u8 *pos, *rhdr, *hs_start, *hs_length;
+ u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start;
struct os_time now;
size_t rlen;
/* CompressionMethod compression_method */
*pos++ = TLS_COMPRESSION_NULL;
+ /* Extension */
+ ext_start = pos;
+ pos += 2;
+
+ if (conn->status_request) {
+ /* Add a status_request extension with empty extension_data */
+ /* ExtensionsType extension_type = status_request(5) */
+ WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 0);
+ pos += 2;
+ }
+
if (conn->session_ticket && conn->session_ticket_cb) {
int res = conn->session_ticket_cb(
conn->session_ticket_cb_ctx,
*/
}
+ if (pos == ext_start + 2)
+ pos -= 2; /* no extensions */
+ else
+ WPA_PUT_BE16(ext_start, pos - ext_start - 2);
+
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
}
+static int tls_write_server_certificate_status(struct tlsv1_server *conn,
+ u8 **msgpos, u8 *end)
+{
+ u8 *pos, *rhdr, *hs_start, *hs_length;
+ char *resp;
+ size_t rlen, len;
+
+ if (!conn->status_request)
+ return 0; /* Client did not request certificate status */
+ if (!conn->cred->ocsp_stapling_response)
+ return 0; /* No cached OCSP stapling response */
+ resp = os_readfile(conn->cred->ocsp_stapling_response, &len);
+ if (!resp)
+ return 0; /* No cached OCSP stapling response */
+
+ pos = *msgpos;
+ if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + len >
+ (unsigned int) (end - pos)) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ os_free(resp);
+ return -1;
+ }
+
+ tlsv1_server_log(conn, "Send CertificateStatus");
+ rhdr = pos;
+ pos += TLS_RECORD_HEADER_LEN;
+
+ /* opaque fragment[TLSPlaintext.length] */
+
+ /* Handshake */
+ hs_start = pos;
+ /* HandshakeType msg_type */
+ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS;
+ /* uint24 length (to be filled) */
+ hs_length = pos;
+ pos += 3;
+
+ /* body - CertificateStatus
+ *
+ * struct {
+ * CertificateStatusType status_type;
+ * select (status_type) {
+ * case ocsp: OCSPResponse;
+ * } response;
+ * } CertificateStatus;
+ *
+ * opaque OCSPResponse<1..2^24-1>;
+ */
+
+ /* CertificateStatusType status_type */
+ *pos++ = 1; /* ocsp(1) */
+ /* uint24 length of OCSPResponse */
+ WPA_PUT_BE24(pos, len);
+ pos += 3;
+ os_memcpy(pos, resp, len);
+ os_free(resp);
+ pos += len;
+
+ WPA_PUT_BE24(hs_length, pos - hs_length - 3);
+
+ if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
+ wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
+ pos = rhdr + rlen;
+
+ tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
+
+ *msgpos = pos;
+
+ return 0;
+}
+
+
static int tls_write_server_key_exchange(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
*out_len = 0;
msglen = 1000 + tls_server_cert_chain_der_len(conn);
+ if (conn->status_request && conn->cred->ocsp_stapling_response) {
+ char *resp;
+ size_t len;
+
+ resp = os_readfile(conn->cred->ocsp_stapling_response, &len);
+ if (resp) {
+ msglen += 10 + len;
+ os_free(resp);
+ }
+ }
msg = os_malloc(msglen);
if (msg == NULL)
/* Full handshake */
if (tls_write_server_certificate(conn, &pos, end) < 0 ||
+ tls_write_server_certificate_status(conn, &pos, end) < 0 ||
tls_write_server_key_exchange(conn, &pos, end) < 0 ||
tls_write_server_certificate_request(conn, &pos, end) < 0 ||
tls_write_server_hello_done(conn, &pos, end) < 0) {