diff --git a/src/crypto/tls.h b/src/crypto/tls.h index df0c7153a..81e588fb8 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -541,4 +541,10 @@ void tls_connection_set_log_cb(struct tls_connection *conn, void (*log_cb)(void *ctx, const char *msg), void *ctx); +#define TLS_BREAK_VERIFY_DATA BIT(0) +#define TLS_BREAK_SRV_KEY_X_HASH BIT(1) +#define TLS_BREAK_SRV_KEY_X_SIGNATURE BIT(2) + +void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags); + #endif /* TLS_H */ diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c index 7327b4b53..6563ed218 100644 --- a/src/crypto/tls_internal.c +++ b/src/crypto/tls_internal.c @@ -111,6 +111,17 @@ struct tls_connection * tls_connection_init(void *tls_ctx) } +#ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_TLS_INTERNAL_SERVER +void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags) +{ + if (conn->server) + tlsv1_server_set_test_flags(conn->server, flags); +} +#endif /* CONFIG_TLS_INTERNAL_SERVER */ +#endif /* CONFIG_TESTING_OPTIONS */ + + void tls_connection_set_log_cb(struct tls_connection *conn, void (*log_cb)(void *ctx, const char *msg), void *ctx) diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index f1eb46871..698a5ac0b 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -110,6 +110,10 @@ struct eap_config { const u8 *server_id; size_t server_id_len; + +#ifdef CONFIG_TESTING_OPTIONS + u32 tls_test_flags; +#endif /* CONFIG_TESTING_OPTIONS */ }; diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h index 0180aff4b..3a6802b7a 100644 --- a/src/eap_server/eap_i.h +++ b/src/eap_server/eap_i.h @@ -191,6 +191,10 @@ struct eap_sm { const u8 *server_id; size_t server_id_len; + +#ifdef CONFIG_TESTING_OPTIONS + u32 tls_test_flags; +#endif /* CONFIG_TESTING_OPTIONS */ }; int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c index 19997822f..65d00ddaf 100644 --- a/src/eap_server/eap_server.c +++ b/src/eap_server/eap_server.c @@ -1327,6 +1327,10 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx, sm->server_id = conf->server_id; sm->server_id_len = conf->server_id_len; +#ifdef CONFIG_TESTING_OPTIONS + sm->tls_test_flags = conf->tls_test_flags; +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); return sm; diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c index 0afb44b66..01853e689 100644 --- a/src/eap_server/eap_server_tls_common.c +++ b/src/eap_server/eap_server_tls_common.c @@ -63,6 +63,9 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, #ifdef CONFIG_TLS_INTERNAL tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm); +#ifdef CONFIG_TESTING_OPTIONS + tls_connection_set_test_flags(data->conn, sm->tls_test_flags); +#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TLS_INTERNAL */ if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index 958ddf97b..c929fe183 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -17,6 +17,7 @@ #include "eloop.h" #include "eap_server/eap.h" #include "ap/ap_config.h" +#include "crypto/tls.h" #include "radius_server.h" /** @@ -533,6 +534,51 @@ radius_server_new_session(struct radius_server_data *data, } +#ifdef CONFIG_TESTING_OPTIONS +static void radius_server_testing_options_tls(struct radius_session *sess, + const char *tls, + struct eap_config *eap_conf) +{ + int test = atoi(tls); + + switch (test) { + case 1: + srv_log(sess, "TLS test - break VerifyData"); + eap_conf->tls_test_flags = TLS_BREAK_VERIFY_DATA; + break; + case 2: + srv_log(sess, "TLS test - break ServerKeyExchange ServerParams hash"); + eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_HASH; + break; + case 3: + srv_log(sess, "TLS test - break ServerKeyExchange ServerParams Signature"); + eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_SIGNATURE; + break; + default: + srv_log(sess, "Unrecognized TLS test"); + break; + } +} +#endif /* CONFIG_TESTING_OPTIONS */ + +static void radius_server_testing_options(struct radius_session *sess, + struct eap_config *eap_conf) +{ +#ifdef CONFIG_TESTING_OPTIONS + const char *pos; + + pos = os_strstr(sess->username, "@test-"); + if (pos == NULL) + return; + pos += 6; + if (os_strncmp(pos, "tls-", 4) == 0) + radius_server_testing_options_tls(sess, pos + 4, eap_conf); + else + srv_log(sess, "Unrecognized test: %s", pos); +#endif /* CONFIG_TESTING_OPTIONS */ +} + + static struct radius_session * radius_server_get_new_session(struct radius_server_data *data, struct radius_client *client, @@ -605,6 +651,7 @@ radius_server_get_new_session(struct radius_server_data *data, eap_conf.pwd_group = data->pwd_group; eap_conf.server_id = (const u8 *) data->server_id; eap_conf.server_id_len = os_strlen(data->server_id); + radius_server_testing_options(sess, &eap_conf); sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, &eap_conf); if (sess->eap == NULL) { diff --git a/src/tls/tlsv1_server.c b/src/tls/tlsv1_server.c index 16e29cb0d..4aeccf6a9 100644 --- a/src/tls/tlsv1_server.c +++ b/src/tls/tlsv1_server.c @@ -315,6 +315,16 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn, return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if ((conn->test_flags && + (TLS_BREAK_VERIFY_DATA | TLS_BREAK_SRV_KEY_X_HASH | + TLS_BREAK_SRV_KEY_X_SIGNATURE)) && + !conn->test_failure_reported) { + tlsv1_server_log(conn, "TEST-FAILURE: Client ApplData received after invalid handshake"); + conn->test_failure_reported = 1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " @@ -656,3 +666,11 @@ void tlsv1_server_set_log_cb(struct tlsv1_server *conn, conn->log_cb = cb; conn->log_cb_ctx = ctx; } + + +#ifdef CONFIG_TESTING_OPTIONS +void tlsv1_server_set_test_flags(struct tlsv1_server *conn, u32 flags) +{ + conn->test_flags = flags; +} +#endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/tls/tlsv1_server.h b/src/tls/tlsv1_server.h index b20ff1aac..b2b28d1e1 100644 --- a/src/tls/tlsv1_server.h +++ b/src/tls/tlsv1_server.h @@ -48,4 +48,6 @@ void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, void tlsv1_server_set_log_cb(struct tlsv1_server *conn, void (*cb)(void *ctx, const char *msg), void *ctx); +void tlsv1_server_set_test_flags(struct tlsv1_server *conn, u32 flags); + #endif /* TLSV1_SERVER_H */ diff --git a/src/tls/tlsv1_server_i.h b/src/tls/tlsv1_server_i.h index 12c57fd4b..9a36d8f03 100644 --- a/src/tls/tlsv1_server_i.h +++ b/src/tls/tlsv1_server_i.h @@ -58,6 +58,11 @@ struct tlsv1_server { u8 *dh_secret; size_t dh_secret_len; + +#ifdef CONFIG_TESTING_OPTIONS + u32 test_flags; + int test_failure_reported; +#endif /* CONFIG_TESTING_OPTIONS */ }; diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c index cef4a7c30..04622b5e7 100644 --- a/src/tls/tlsv1_server_read.c +++ b/src/tls/tlsv1_server_read.c @@ -27,6 +27,23 @@ static int tls_process_change_cipher_spec(struct tlsv1_server *conn, size_t *in_len); +static int testing_cipher_suite_filter(struct tlsv1_server *conn, u16 suite) +{ +#ifdef CONFIG_TESTING_OPTIONS + if ((conn->test_flags & + (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) && + suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 && + suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA && + suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 && + suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA && + suite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) + return 1; +#endif /* CONFIG_TESTING_OPTIONS */ + + return 0; +} + + static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { @@ -137,6 +154,8 @@ static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, cipher_suite = 0; for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { + if (testing_cipher_suite_filter(conn, conn->cipher_suites[i])) + continue; c = pos; for (j = 0; j < num_suites; j++) { u16 tmp = WPA_GET_BE16(c); @@ -968,6 +987,15 @@ static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; +#ifdef CONFIG_TESTING_OPTIONS + if ((conn->test_flags & + (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) && + !conn->test_failure_reported) { + tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after invalid ServerKeyExchange"); + conn->test_failure_reported = 1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { tlsv1_server_log(conn, "Expected Finished; received content type 0x%x", ct); diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c index e56cb0f32..619b9ab8b 100644 --- a/src/tls/tlsv1_server_write.c +++ b/src/tls/tlsv1_server_write.c @@ -502,6 +502,12 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn, wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash", hash, hlen); +#ifdef CONFIG_TESTING_OPTIONS + if (conn->test_flags & TLS_BREAK_SRV_KEY_X_HASH) { + tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params hash"); + hash[hlen - 1] ^= 0x80; + } +#endif /* CONFIG_TESTING_OPTIONS */ /* * RFC 2246, 4.7: @@ -527,6 +533,12 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn, return -1; } WPA_PUT_BE16(signed_start, clen); +#ifdef CONFIG_TESTING_OPTIONS + if (conn->test_flags & TLS_BREAK_SRV_KEY_X_SIGNATURE) { + tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params signature"); + pos[clen - 1] ^= 0x80; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos += clen; } @@ -754,6 +766,12 @@ static int tls_write_server_finished(struct tlsv1_server *conn, } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); +#ifdef CONFIG_TESTING_OPTIONS + if (conn->test_flags & TLS_BREAK_VERIFY_DATA) { + tlsv1_server_log(conn, "TESTING: Break verify_data (server)"); + verify_data[1 + 3 + 1] ^= 0x80; + } +#endif /* CONFIG_TESTING_OPTIONS */ /* Handshake */ pos = hs_start = verify_data;