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;
}