aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-12-22 15:53:45 (GMT)
committerJouni Malinen <j@w1.fi>2015-12-22 15:53:45 (GMT)
commitbca0872dd5c72135827355c4be1f772cc9641a84 (patch)
treeb4e7ad31a50173cc86fced03d0118caed2759f07 /src/tls
parent8adce07a73e8eb53510190de6cf3eee86f5d0d87 (diff)
downloadhostap-bca0872dd5c72135827355c4be1f772cc9641a84.zip
hostap-bca0872dd5c72135827355c4be1f772cc9641a84.tar.gz
hostap-bca0872dd5c72135827355c4be1f772cc9641a84.tar.bz2
TLS server: OCSP stapling
This adds support for hostapd-as-authentication-server to be build with the internal TLS implementation and OCSP stapling server side support. This is more or less identical to the design used with OpenSSL, i.e., the cached response is read from the ocsp_stapling_response=<file> and sent as a response if the client requests it during the TLS handshake. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/tlsv1_cred.c1
-rw-r--r--src/tls/tlsv1_cred.h2
-rw-r--r--src/tls/tlsv1_server_i.h1
-rw-r--r--src/tls/tlsv1_server_read.c2
-rw-r--r--src/tls/tlsv1_server_write.c111
5 files changed, 116 insertions, 1 deletions
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 92f97c7..732ed4a 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -36,6 +36,7 @@ void tlsv1_cred_free(struct tlsv1_credentials *cred)
crypto_private_key_free(cred->key);
os_free(cred->dh_p);
os_free(cred->dh_g);
+ os_free(cred->ocsp_stapling_response);
os_free(cred);
}
diff --git a/src/tls/tlsv1_cred.h b/src/tls/tlsv1_cred.h
index b4bfe38..cbf4d39 100644
--- a/src/tls/tlsv1_cred.h
+++ b/src/tls/tlsv1_cred.h
@@ -24,6 +24,8 @@ struct tlsv1_credentials {
size_t dh_p_len;
u8 *dh_g; /* generator */
size_t dh_g_len;
+
+ char *ocsp_stapling_response;
};
diff --git a/src/tls/tlsv1_server_i.h b/src/tls/tlsv1_server_i.h
index 96d79b3..81439d1 100644
--- a/src/tls/tlsv1_server_i.h
+++ b/src/tls/tlsv1_server_i.h
@@ -55,6 +55,7 @@ struct tlsv1_server {
void *log_cb_ctx;
int use_session_ticket;
+ unsigned int status_request:1;
u8 *dh_secret;
size_t dh_secret_len;
diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c
index 8347d7a..5109b60 100644
--- a/src/tls/tlsv1_server_read.c
+++ b/src/tls/tlsv1_server_read.c
@@ -267,6 +267,8 @@ static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
ext_len);
conn->session_ticket_len = ext_len;
}
+ } else if (ext_type == TLS_EXT_STATUS_REQUEST) {
+ conn->status_request = 1;
}
pos += ext_len;
diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c
index e7c5e22..dafe3f9 100644
--- a/src/tls/tlsv1_server_write.c
+++ b/src/tls/tlsv1_server_write.c
@@ -42,7 +42,7 @@ static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn)
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;
@@ -97,6 +97,20 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
/* 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,
@@ -133,6 +147,11 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
*/
}
+ 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);
@@ -244,6 +263,85 @@ static int tls_write_server_certificate(struct tlsv1_server *conn,
}
+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)
{
@@ -814,6 +912,16 @@ static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
*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)
@@ -844,6 +952,7 @@ static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
/* 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) {