void tlsv1_server_get_dh_p(struct tlsv1_server *conn, const u8 **dh_p, size_t *dh_p_len) { *dh_p = conn->cred->dh_p; *dh_p_len = conn->cred->dh_p_len; #ifdef CONFIG_TESTING_OPTIONS if (conn->test_flags & TLS_DHE_PRIME_511B) { tlsv1_server_log(conn, "TESTING: Use short 511-bit prime with DHE"); *dh_p = test_tls_prime511b; *dh_p_len = sizeof(test_tls_prime511b); } else if (conn->test_flags & TLS_DHE_PRIME_767B) { tlsv1_server_log(conn, "TESTING: Use short 767-bit prime with DHE"); *dh_p = test_tls_prime767b; *dh_p_len = sizeof(test_tls_prime767b); } else if (conn->test_flags & TLS_DHE_PRIME_15) { tlsv1_server_log(conn, "TESTING: Use bogus 15 \"prime\" with DHE"); *dh_p = test_tls_prime15; *dh_p_len = sizeof(test_tls_prime15); } else if (conn->test_flags & TLS_DHE_PRIME_58B) { tlsv1_server_log(conn, "TESTING: Use short 58-bit prime in long container with DHE"); *dh_p = test_tls_prime58; *dh_p_len = sizeof(test_tls_prime58); } else if (conn->test_flags & TLS_DHE_NON_PRIME) { tlsv1_server_log(conn, "TESTING: Use claim non-prime as the DHE prime"); *dh_p = test_tls_non_prime; *dh_p_len = sizeof(test_tls_non_prime); } #endif /* CONFIG_TESTING_OPTIONS */ }
static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end, *c; size_t left, len, i, j; u16 cipher_suite; u16 num_suites; int compr_null_found; u16 ext_type, ext_len; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) goto decode_error; /* HandshakeType msg_type */ if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientHello)", *pos); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } tlsv1_server_log(conn, "Received ClientHello"); pos++; /* uint24 length */ len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) goto decode_error; /* body - ClientHello */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); end = pos + len; /* ProtocolVersion client_version */ if (end - pos < 2) goto decode_error; conn->client_version = WPA_GET_BE16(pos); tlsv1_server_log(conn, "Client version %d.%d", conn->client_version >> 8, conn->client_version & 0xff); if (conn->client_version < TLS_VERSION_1) { tlsv1_server_log(conn, "Unexpected protocol version in ClientHello %u.%u", conn->client_version >> 8, conn->client_version & 0xff); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION); return -1; }
/** * tlsv1_server_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ int tlsv1_server_decrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; int used; u8 alert, *out_end, *out_pos, ct; size_t olen; pos = in_data; in_end = in_data + in_len; out_pos = out_data; out_end = out_data + out_len; while (pos < in_end) { ct = pos[0]; olen = out_end - out_pos; used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, out_pos, &olen, &alert); if (used < 0) { tlsv1_server_log(conn, "Record layer processing failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } if (used == 0) { /* need more data */ wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " "yet supported"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } if (ct == TLS_CONTENT_TYPE_ALERT) { if (olen < 2) { tlsv1_server_log(conn, "Alert underflow"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } tlsv1_server_log(conn, "Received alert %d:%d", out_pos[0], out_pos[1]); if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { /* Continue processing */ pos += used; continue; } tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, out_pos[1]); return -1; } if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { tlsv1_server_log(conn, "Unexpected content type 0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); 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 " "for processing the received record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos += used; } return out_pos - out_data; }