/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "rfcomm_defs.h" typedef struct { uint16_t result; GapServiceSecurityInfo serviceInfo; void *context; } RfcommSecurityResultInfo; static void RfcommRecvChannelSecurityResultTsk(void *context) { LOG_INFO("%{public}s", __func__); RfcommSecurityResultInfo *ctx = context; if (ctx == NULL) { LOG_ERROR("%{public}s context is NULL.", __func__); return; } RfcommRecvChannelSecurityResult(ctx->result, ctx->serviceInfo, ctx->context); free(ctx); } /** * @brief This is the callback function registered when GAPIF_RequestSecurityAsync is called * to receive the result of the security check. * * @param result The result of the security check. * @param serviceInfo server information. * @param context The context passed in when calling GAPIF_RequestSecurityAsync. */ static void RfcommRecvChannelSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context) { LOG_INFO("%{public}s result:%hu", __func__, result); if (context == NULL) { LOG_ERROR("%{public}s:DLC is closed.", __func__); return; } RfcommSecurityResultInfo *ctx = malloc(sizeof(RfcommSecurityResultInfo)); if (ctx == NULL) { return; } (void)memset_s(ctx, sizeof(RfcommSecurityResultInfo), 0x00, sizeof(RfcommSecurityResultInfo)); ctx->result = result; ctx->context = context; (void)memcpy_s(&ctx->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo)); int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvChannelSecurityResultTsk, ctx); if (ret != BT_SUCCESS) { free(ctx); } } static void RfcommRecvSessionSecurityResultTsk(void *context) { LOG_INFO("%{public}s", __func__); RfcommSecurityResultInfo *ctx = context; if (ctx == NULL) { LOG_ERROR("%{public}s context is NULL.", __func__); return; } RfcommRecvSessionSecurityResult(ctx->result, ctx->serviceInfo, ctx->context); free(ctx); } static void RfcommRecvSessionSecurityResultCallback(uint16_t result, GapServiceSecurityInfo serviceInfo, void *context) { LOG_INFO("%{public}s result:%hu", __func__, result); if (context == NULL) { LOG_ERROR("%{public}s:Session is closed.", __func__); return; } RfcommSecurityResultInfo *ctx = malloc(sizeof(RfcommSecurityResultInfo)); if (ctx == NULL) { return; } (void)memset_s(ctx, sizeof(RfcommSecurityResultInfo), 0x00, sizeof(RfcommSecurityResultInfo)); ctx->result = result; ctx->context = context; (void)memcpy_s(&ctx->serviceInfo, sizeof(GapServiceSecurityInfo), &serviceInfo, sizeof(GapServiceSecurityInfo)); int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvSessionSecurityResultTsk, ctx); if (ret != BT_SUCCESS) { free(ctx); } } /** * @brief Before initiating a connection or accepting a connection, * the GAP interface is called to perform a security check. * * @param channel The pointer of the channel in the channel list. * @param isServer Server side:true, client side:false. * @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails. */ int RfcommCheckChannelSecurity(RfcommChannelInfo *channel, bool isServer) { LOG_INFO("%{public}s isServer:%{public}d", __func__, isServer); GapRequestSecurityParam param; (void)memset_s(¶m, sizeof(GapRequestSecurityParam), 0x00, sizeof(GapRequestSecurityParam)); param.callback = RfcommRecvChannelSecurityResultCallback; param.info.channelId.rfcommChannel = channel->dlci >> RFCOMM_DLCI_SHIFT_SCN; param.info.direction = isServer ? INCOMING : OUTGOING; param.info.protocolId = SEC_PROTOCOL_RFCOMM; param.info.serviceId = UNKNOWN_SERVICE; param.context = channel; int ret = GAPIF_RequestSecurityAsync(&(channel->session->btAddr), ¶m); if (ret != BT_SUCCESS) { LOG_DEBUG("%{public}s return error.", __func__); } return ret; } /** * @brief Before initiating a connection or accepting a L2CAP connection, * the GAP interface is called to perform a security check. * * @param session The pointer of the session in the session list. * @param scn The rfcomm server channel number(Valid if this is initiator). * @param isServer Server side:true, client side:false. * @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails. */ int RfcommCheckSessionSecurity(RfcommSessionInfo *session, uint8_t scn, bool isServer) { LOG_INFO("%{public}s isServer:%{public}d", __func__, isServer); GapRequestSecurityParam param; (void)memset_s(¶m, sizeof(GapRequestSecurityParam), 0x00, sizeof(GapRequestSecurityParam)); param.callback = RfcommRecvSessionSecurityResultCallback; param.context = (void*)session; if (isServer) { param.info.direction = INCOMING; param.info.serviceId = RFCOMM; param.info.protocolId = SEC_PROTOCOL_L2CAP; param.info.channelId.l2capPsm = BT_PSM_RFCOMM; } else { param.info.direction = OUTGOING; param.info.serviceId = UNKNOWN_SERVICE; param.info.protocolId = SEC_PROTOCOL_RFCOMM; param.info.channelId.rfcommChannel = scn; } int ret = GAPIF_RequestSecurityAsync(&(session->btAddr), ¶m); if (ret != BT_SUCCESS) { LOG_DEBUG("%{public}s return error.", __func__); } return ret; } /** * @brief Register security information to GAP. * */ void RfcommRegisterSecurity() { LOG_INFO("%{public}s", __func__); GapServiceSecurityInfo serviceInfo = {INCOMING, RFCOMM, SEC_PROTOCOL_L2CAP, {BT_PSM_RFCOMM}}; int ret = GAPIF_RegisterServiceSecurityAsync(NULL, &serviceInfo, 0); if (ret != BT_SUCCESS) { LOG_DEBUG("%{public}s return error.", __func__); } } /** * @brief Deregister security information to GAP. * */ void RfcommDeregisterSecurity() { LOG_INFO("%{public}s", __func__); GapServiceSecurityInfo serviceInfo = {INCOMING, RFCOMM, SEC_PROTOCOL_L2CAP, {BT_PSM_RFCOMM}}; int ret = GAPIF_DeregisterServiceSecurityAsync(NULL, &serviceInfo); if (ret != BT_SUCCESS) { LOG_DEBUG("%{public}s return error.", __func__); } }