1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rfcomm_defs.h"
17
18 typedef struct {
19 uint16_t result;
20 GapServiceSecurityInfo serviceInfo;
21 void *context;
22 } RfcommSecurityResultInfo;
23
RfcommRecvChannelSecurityResultTsk(void * context)24 static void RfcommRecvChannelSecurityResultTsk(void *context)
25 {
26 LOG_INFO("%{public}s", __func__);
27
28 RfcommSecurityResultInfo *ctx = context;
29
30 if (ctx == NULL) {
31 LOG_ERROR("%{public}s context is NULL.", __func__);
32 return;
33 }
34
35 RfcommRecvChannelSecurityResult(ctx->result, ctx->serviceInfo, ctx->context);
36
37 free(ctx);
38 }
39
40 /**
41 * @brief This is the callback function registered when GAPIF_RequestSecurityAsync is called
42 * to receive the result of the security check.
43 *
44 * @param result The result of the security check.
45 * @param serviceInfo server information.
46 * @param context The context passed in when calling GAPIF_RequestSecurityAsync.
47 */
RfcommRecvChannelSecurityResultCallback(uint16_t result,GapServiceSecurityInfo serviceInfo,void * context)48 static void RfcommRecvChannelSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
49 {
50 LOG_INFO("%{public}s result:%hu", __func__, result);
51
52 if (context == NULL) {
53 LOG_ERROR("%{public}s:DLC is closed.", __func__);
54 return;
55 }
56
57 RfcommSecurityResultInfo *ctx = malloc(sizeof(RfcommSecurityResultInfo));
58 if (ctx == NULL) {
59 return;
60 }
61
62 (void)memset_s(ctx, sizeof(RfcommSecurityResultInfo), 0x00, sizeof(RfcommSecurityResultInfo));
63 ctx->result = result;
64 ctx->context = context;
65 (void)memcpy_s(&ctx->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo));
66
67 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvChannelSecurityResultTsk, ctx);
68 if (ret != BT_SUCCESS) {
69 free(ctx);
70 }
71 }
72
RfcommRecvSessionSecurityResultTsk(void * context)73 static void RfcommRecvSessionSecurityResultTsk(void *context)
74 {
75 LOG_INFO("%{public}s", __func__);
76
77 RfcommSecurityResultInfo *ctx = context;
78
79 if (ctx == NULL) {
80 LOG_ERROR("%{public}s context is NULL.", __func__);
81 return;
82 }
83
84 RfcommRecvSessionSecurityResult(ctx->result, ctx->serviceInfo, ctx->context);
85
86 free(ctx);
87 }
88
RfcommRecvSessionSecurityResultCallback(uint16_t result,GapServiceSecurityInfo serviceInfo,void * context)89 static void RfcommRecvSessionSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context)
90 {
91 LOG_INFO("%{public}s result:%hu", __func__, result);
92
93 if (context == NULL) {
94 LOG_ERROR("%{public}s:Session is closed.", __func__);
95 return;
96 }
97
98 RfcommSecurityResultInfo *ctx = malloc(sizeof(RfcommSecurityResultInfo));
99 if (ctx == NULL) {
100 return;
101 }
102
103 (void)memset_s(ctx, sizeof(RfcommSecurityResultInfo), 0x00, sizeof(RfcommSecurityResultInfo));
104 ctx->result = result;
105 ctx->context = context;
106 (void)memcpy_s(&ctx->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo));
107
108 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvSessionSecurityResultTsk, ctx);
109 if (ret != BT_SUCCESS) {
110 free(ctx);
111 }
112 }
113
114 /**
115 * @brief Before initiating a connection or accepting a connection,
116 * the GAP interface is called to perform a security check.
117 *
118 * @param channel The pointer of the channel in the channel list.
119 * @param isServer Server side:true, client side:false.
120 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
121 */
RfcommCheckChannelSecurity(RfcommChannelInfo * channel,bool isServer)122 int RfcommCheckChannelSecurity(RfcommChannelInfo *channel, bool isServer)
123 {
124 LOG_INFO("%{public}s isServer:%{public}d", __func__, isServer);
125
126 GapRequestSecurityParam param;
127 (void)memset_s(¶m, sizeof(GapRequestSecurityParam), 0x00, sizeof(GapRequestSecurityParam));
128
129 param.callback = RfcommRecvChannelSecurityResultCallback;
130 param.info.channelId.rfcommChannel = channel->dlci >> RFCOMM_DLCI_SHIFT_SCN;
131 param.info.direction = isServer ? INCOMING : OUTGOING;
132 param.info.protocolId = SEC_PROTOCOL_RFCOMM;
133 param.info.serviceId = UNKNOWN_SERVICE;
134 param.context = channel;
135
136 int ret = GAPIF_RequestSecurityAsync(&(channel->session->btAddr), ¶m);
137 if (ret != BT_SUCCESS) {
138 LOG_DEBUG("%{public}s return error.", __func__);
139 }
140
141 return ret;
142 }
143
144 /**
145 * @brief Before initiating a connection or accepting a L2CAP connection,
146 * the GAP interface is called to perform a security check.
147 *
148 * @param session The pointer of the session in the session list.
149 * @param scn The rfcomm server channel number(Valid if this is initiator).
150 * @param isServer Server side:true, client side:false.
151 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
152 */
RfcommCheckSessionSecurity(RfcommSessionInfo * session,uint8_t scn,bool isServer)153 int RfcommCheckSessionSecurity(RfcommSessionInfo *session, uint8_t scn, bool isServer)
154 {
155 LOG_INFO("%{public}s isServer:%{public}d", __func__, isServer);
156
157 GapRequestSecurityParam param;
158 (void)memset_s(¶m, sizeof(GapRequestSecurityParam), 0x00, sizeof(GapRequestSecurityParam));
159
160 param.callback = RfcommRecvSessionSecurityResultCallback;
161 param.context = (void*)session;
162 if (isServer) {
163 param.info.direction = INCOMING;
164 param.info.serviceId = RFCOMM;
165 param.info.protocolId = SEC_PROTOCOL_L2CAP;
166 param.info.channelId.l2capPsm = BT_PSM_RFCOMM;
167 } else {
168 param.info.direction = OUTGOING;
169 param.info.serviceId = UNKNOWN_SERVICE;
170 param.info.protocolId = SEC_PROTOCOL_RFCOMM;
171 param.info.channelId.rfcommChannel = scn;
172 }
173
174 int ret = GAPIF_RequestSecurityAsync(&(session->btAddr), ¶m);
175 if (ret != BT_SUCCESS) {
176 LOG_DEBUG("%{public}s return error.", __func__);
177 }
178
179 return ret;
180 }
181
182 /**
183 * @brief Register security information to GAP.
184 *
185 */
RfcommRegisterSecurity()186 void RfcommRegisterSecurity()
187 {
188 LOG_INFO("%{public}s", __func__);
189
190 GapServiceSecurityInfo serviceInfo = {INCOMING, RFCOMM, SEC_PROTOCOL_L2CAP, {BT_PSM_RFCOMM}};
191
192 int ret = GAPIF_RegisterServiceSecurityAsync(NULL, &serviceInfo, 0);
193 if (ret != BT_SUCCESS) {
194 LOG_DEBUG("%{public}s return error.", __func__);
195 }
196 }
197
198 /**
199 * @brief Deregister security information to GAP.
200 *
201 */
RfcommDeregisterSecurity()202 void RfcommDeregisterSecurity()
203 {
204 LOG_INFO("%{public}s", __func__);
205
206 GapServiceSecurityInfo serviceInfo = {INCOMING, RFCOMM, SEC_PROTOCOL_L2CAP, {BT_PSM_RFCOMM}};
207
208 int ret = GAPIF_DeregisterServiceSecurityAsync(NULL, &serviceInfo);
209 if (ret != BT_SUCCESS) {
210 LOG_DEBUG("%{public}s return error.", __func__);
211 }
212 }