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>
This commit is contained in:
parent
8adce07a73
commit
bca0872dd5
6 changed files with 120 additions and 1 deletions
|
@ -331,6 +331,10 @@ int tls_global_set_params(void *tls_ctx,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (params->ocsp_stapling_response)
|
||||
cred->ocsp_stapling_response =
|
||||
os_strdup(params->ocsp_stapling_response);
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue