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(&param, 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), &param);
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(&param, 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), &param);
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 }