1 /* Copyright (c) 2023 Codecoup
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <zephyr/bluetooth/att.h>
6 #include <zephyr/bluetooth/bluetooth.h>
7 #include <zephyr/bluetooth/gatt.h>
8 #include <zephyr/bluetooth/l2cap.h>
9 #include <zephyr/sys/__assert.h>
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/logging/log.h>
12 
13 #include "../common_defs.h"
14 #include "../test_utils.h"
15 
16 #include <testlib/conn.h>
17 #include "testlib/scan.h"
18 #include "testlib/security.h"
19 
20 LOG_MODULE_REGISTER(client, LOG_LEVEL_DBG);
21 
22 DEFINE_FLAG(flag_attr_read_success);
23 
gatt_attr_read_cb(struct bt_conn * conn,uint8_t att_err,struct bt_gatt_read_params * params,const void * data,uint16_t len)24 static uint8_t gatt_attr_read_cb(struct bt_conn *conn, uint8_t att_err,
25 				 struct bt_gatt_read_params *params, const void *data, uint16_t len)
26 {
27 	__ASSERT_NO_MSG(!att_err);
28 
29 	SET_FLAG(flag_attr_read_success);
30 
31 	return BT_GATT_ITER_STOP;
32 }
33 
gatt_attr_read(struct bt_conn * conn)34 static void gatt_attr_read(struct bt_conn *conn)
35 {
36 	static struct bt_gatt_read_params params;
37 	static struct bt_uuid_128 uuid;
38 	int err;
39 
40 	memset(&params, 0, sizeof(params));
41 	params.func = gatt_attr_read_cb;
42 	params.by_uuid.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
43 	params.by_uuid.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
44 	memcpy(&uuid.uuid, TEST_CHRC_UUID, sizeof(uuid));
45 	params.by_uuid.uuid = &uuid.uuid;
46 
47 	err = bt_gatt_read(conn, &params);
48 	__ASSERT_NO_MSG(!err);
49 }
50 
51 DEFINE_FLAG(flag_conn_encrypted);
52 
security_changed_cb(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)53 static void security_changed_cb(struct bt_conn *conn, bt_security_t level,
54 				enum bt_security_err err)
55 {
56 	if (err != BT_SECURITY_ERR_SUCCESS || level < BT_SECURITY_L2) {
57 		return;
58 	}
59 
60 	SET_FLAG(flag_conn_encrypted);
61 }
62 
63 static struct bt_conn_cb conn_cb = {
64 	.security_changed = security_changed_cb,
65 };
66 
test_client(void)67 static void test_client(void)
68 {
69 	struct bt_conn *conn = NULL;
70 	bt_addr_le_t scan_result;
71 	int err;
72 
73 	err = bt_enable(NULL);
74 	__ASSERT_NO_MSG(!err);
75 
76 	bt_conn_cb_register(&conn_cb);
77 
78 	err = bt_testlib_scan_find_name(&scan_result, "d1");
79 	__ASSERT_NO_MSG(!err);
80 
81 	err = bt_testlib_connect(&scan_result, &conn);
82 	__ASSERT_NO_MSG(!err);
83 
84 	/* Read characteristic value that requires encryption */
85 	gatt_attr_read(conn);
86 
87 	/* Expect link encryption  */
88 	WAIT_FOR_FLAG(flag_conn_encrypted);
89 
90 	/* Wait for successful Read Response */
91 	WAIT_FOR_FLAG(flag_attr_read_success);
92 
93 	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
94 	__ASSERT_NO_MSG(!err);
95 
96 	bt_conn_unref(conn);
97 	conn = NULL;
98 
99 	PASS("PASS\n");
100 }
101 
102 DEFINE_FLAG(flag_pairing_in_progress);
103 
auth_cancel_cb(struct bt_conn * conn)104 static void auth_cancel_cb(struct bt_conn *conn)
105 {
106 
107 }
108 
auth_pairing_confirm_cb(struct bt_conn * conn)109 static void auth_pairing_confirm_cb(struct bt_conn *conn)
110 {
111 	SET_FLAG(flag_pairing_in_progress);
112 }
113 
114 static struct bt_conn_auth_cb auth_cb = {
115 	.cancel = auth_cancel_cb,
116 	.pairing_confirm = auth_pairing_confirm_cb,
117 };
118 
test_client_security_request(void)119 static void test_client_security_request(void)
120 {
121 	struct bt_conn *conn = NULL;
122 	bt_addr_le_t scan_result;
123 	int err;
124 
125 	err = bt_enable(NULL);
126 	__ASSERT_NO_MSG(!err);
127 
128 	bt_conn_cb_register(&conn_cb);
129 
130 	err = bt_conn_auth_cb_register(&auth_cb);
131 	__ASSERT_NO_MSG(!err);
132 
133 	err = bt_testlib_scan_find_name(&scan_result, "d1");
134 	__ASSERT_NO_MSG(!err);
135 
136 	err = bt_testlib_connect(&scan_result, &conn);
137 	__ASSERT_NO_MSG(!err);
138 
139 	/* Wait for peripheral to initaiate pairing */
140 	WAIT_FOR_FLAG(flag_pairing_in_progress);
141 
142 	/* Read characteristic value that requires encryption */
143 	gatt_attr_read(conn);
144 
145 	/* Accept pairing */
146 	err = bt_conn_auth_pairing_confirm(conn);
147 	__ASSERT_NO_MSG(!err);
148 
149 	/* Expect link encryption  */
150 	WAIT_FOR_FLAG(flag_conn_encrypted);
151 
152 	/* Wait for successful Read Response */
153 	WAIT_FOR_FLAG(flag_attr_read_success);
154 
155 	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
156 	__ASSERT_NO_MSG(!err);
157 
158 	bt_conn_unref(conn);
159 	conn = NULL;
160 
161 	PASS("PASS\n");
162 }
163 
164 static const struct bst_test_instance client_tests[] = {
165 	{
166 		.test_id = "test_client",
167 		.test_pre_init_f = test_init,
168 		.test_tick_f = test_tick,
169 		.test_main_f = test_client,
170 	},
171 	{
172 		.test_id = "test_client_security_request",
173 		.test_pre_init_f = test_init,
174 		.test_tick_f = test_tick,
175 		.test_main_f = test_client_security_request,
176 	},
177 	BSTEST_END_MARKER,
178 };
179 
client_tests_install(struct bst_test_list * tests)180 static struct bst_test_list *client_tests_install(struct bst_test_list *tests)
181 {
182 	return bst_add_tests(tests, client_tests);
183 };
184 
185 bst_test_install_t test_installers[] = {
186 	client_tests_install,
187 	NULL
188 };
189 
main(void)190 int main(void)
191 {
192 	bst_main();
193 
194 	return 0;
195 }
196