* 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 "gap_le.h"
#include "gap_internal.h"
#include <securec.h>
#include "allocator.h"
#include "log.h"
#include "thread.h"
#include "btm.h"
#include "btm/btm_thread.h"
typedef enum {
SIGNATURE_GENERATION,
SIGNATURE_CONFIRMATION,
} SignatureType;
typedef struct {
uint16_t handle;
uint8_t type;
uint32_t counter;
uint8_t signature[GAP_SIGNATURE_SIZE];
GAP_SignatureResult result;
bool processing;
void *callback;
void *context;
} SignatureRequestInfo;
typedef struct {
GapLePairCallback callback;
void *context;
} LePairCallback;
typedef struct {
GapLeSecurityCallback callback;
void *context;
} LeSecurityCallback;
static LePairCallback g_lePairCallback;
static LeSecurityCallback g_leSecurityCallback;
static int GapLePair(const BtAddr *addr);
static bool GapLeSecurityNeedAuthentication(const LeLocalInfo *localInfo)
{
return localInfo->mode1Level >= LE_MODE_1_LEVEL_3 || localInfo->mode2Level >= LE_MODE_2_LEVEL_2;
}
void GapDoLeSecurityCallback(const void *data)
{
uint16_t handle = 0;
GapLeRequestSecurityResult callback = NULL;
void *context = NULL;
uint8_t result;
uint8_t encryptionStatus = GAP_LE_NO_ENCRYPTION;
if (data == NULL) {
return;
} else {
handle = *(const uint16_t *)data;
}
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL && deviceInfo->securityReq != NULL) {
callback = deviceInfo->securityReq->callback;
context = deviceInfo->securityReq->context;
result = deviceInfo->securityReq->result;
MEM_MALLOC.free(deviceInfo->securityReq);
deviceInfo->securityReq = NULL;
}
if (deviceInfo != NULL) {
encryptionStatus = deviceInfo->encryptionStatus;
if (callback != NULL) {
callback(&deviceInfo->addr, result, encryptionStatus, context);
}
}
}
static void GapLePasskeyRequestProcess(
const BtAddr *addr, uint16_t handle, uint8_t pairMethod, const void *displayValue)
{
int ret;
if (pairMethod == SMP_PAIR_METHOD_PASSKEY_DISPLAY) {
if (g_lePairCallback.callback.lePairPassKeyNotification) {
g_lePairCallback.callback.lePairPassKeyNotification(
addr, *(uint32_t *)displayValue, g_lePairCallback.context);
ret = SMP_AuthenticationRequestReply(handle, true, 0x00, pairMethod, displayValue);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
} else {
ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
} else if (pairMethod == SMP_PAIR_METHOD_PASSKEY_ENTRY) {
if (g_lePairCallback.callback.lePairPassKeyReq) {
g_lePairCallback.callback.lePairPassKeyReq(addr, g_lePairCallback.context);
} else {
ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
}
}
static void GapLeUserConfirmProcess(const BtAddr *addr, uint16_t handle, uint8_t pairMethod, const void *displayValue)
{
if (g_lePairCallback.callback.lePairScUserConfirmReq) {
g_lePairCallback.callback.lePairScUserConfirmReq(addr, *(uint32_t *)displayValue, g_lePairCallback.context);
} else {
int ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
}
static void GapLeLegacyOOBProcess(const BtAddr *addr, uint16_t handle, uint8_t pairMethod, const void *displayValue)
{
if (g_lePairCallback.callback.lePairOobReq) {
g_lePairCallback.callback.lePairOobReq(addr, g_lePairCallback.context);
} else {
int ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
}
static void GapLeSecureConnectionOOBProcess(
const BtAddr *addr, uint16_t handle, uint8_t pairMethod, const void *displayValue)
{
int ret;
bool accept = true;
if (pairMethod == SMP_PAIR_METHOD_OOB_SC_LOCAL_SEND_PEER_RECV ||
pairMethod == SMP_PAIR_METHOD_OOB_SC_BOTH_SIDE_SEND_RECV) {
if (g_lePairCallback.callback.lePairScOobNotification) {
GapOOBData oobData;
const uint8_t *data = displayValue;
if (memcpy_s(oobData.R,
GAP_OOB_DATA_RANDOM_SIZE, data + BT_ADDRESS_SIZE, GAP_OOB_DATA_RANDOM_SIZE) != EOK) {
LOG_WARN("%{public}s: memcpy_s oobData.R fail.", __FUNCTION__);
return;
}
if (memcpy_s(oobData.C,
GAP_OOB_DATA_CONFIRM_SIZE,
data + BT_ADDRESS_SIZE + GAP_OOB_DATA_RANDOM_SIZE,
GAP_OOB_DATA_CONFIRM_SIZE) != EOK) {
LOG_WARN("%{public}s: memcpy_s fail.", __FUNCTION__);
return;
}
g_lePairCallback.callback.lePairScOobNotification(addr, &oobData, g_lePairCallback.context);
} else {
accept = false;
}
}
if (pairMethod == SMP_PAIR_METHOD_OOB_SC_LOCAL_RECV_PEER_SEND ||
pairMethod == SMP_PAIR_METHOD_OOB_SC_BOTH_SIDE_SEND_RECV) {
if (g_lePairCallback.callback.lePairScOobReq) {
g_lePairCallback.callback.lePairScOobReq(addr, g_lePairCallback.context);
} else {
accept = false;
}
}
if (accept) {
if (pairMethod == SMP_PAIR_METHOD_OOB_SC_LOCAL_SEND_PEER_RECV) {
ret = SMP_AuthenticationRequestReply(handle, accept, 0x00, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
} else {
ret = SMP_AuthenticationRequestReply(handle, accept, 0x00, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
}
static void GapLeAuthenticationRequestProcess(
BtAddr addr, uint16_t handle, uint8_t pairMethod, const uint8_t *displayValue)
{
int ret;
switch (pairMethod) {
case SMP_PAIR_METHOD_PASSKEY_DISPLAY:
case SMP_PAIR_METHOD_PASSKEY_ENTRY:
GapLePasskeyRequestProcess(&addr, handle, pairMethod, displayValue);
break;
case SMP_PAIR_METHOD_NUMERIC_COMPARISON:
GapLeUserConfirmProcess(&addr, handle, pairMethod, displayValue);
break;
case SMP_PAIR_METHOD_OOB_LEGACY:
GapLeLegacyOOBProcess(&addr, handle, pairMethod, displayValue);
break;
case SMP_PAIR_METHOD_JUST_WORK:
ret = SMP_AuthenticationRequestReply(handle, true, 0x00, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
break;
case SMP_PAIR_METHOD_OOB_SC_LOCAL_SEND_PEER_RECV:
case SMP_PAIR_METHOD_OOB_SC_LOCAL_RECV_PEER_SEND:
case SMP_PAIR_METHOD_OOB_SC_BOTH_SIDE_SEND_RECV:
GapLeSecureConnectionOOBProcess(&addr, handle, pairMethod, displayValue);
break;
default:
LOG_WARN("%{public}s:Invalid pair method:%hhu.", __FUNCTION__, pairMethod);
break;
}
}
void GapLeAuthenticationRequest(uint16_t handle, uint8_t pairMethod, const uint8_t *displayValue)
{
BtAddr addr = {0};
int ret;
LeLocalInfo *localInfo = GapGetLeLocalInfo();
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
deviceInfo->pairMethod = pairMethod;
}
if (deviceInfo != NULL) {
if (GapLeSecurityNeedAuthentication(localInfo) && pairMethod == SMP_PAIR_METHOD_JUST_WORK) {
ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_AUTH_REQ, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
return;
}
if (g_lePairCallback.callback.lePairMethodNotify) {
g_lePairCallback.callback.lePairMethodNotify(&addr, pairMethod, g_lePairCallback.context);
}
GapLeAuthenticationRequestProcess(addr, handle, pairMethod, displayValue);
} else {
ret = SMP_AuthenticationRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION, pairMethod, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:pairMethod:%{public}d Call SMP failed:%{public}d.", __FUNCTION__, pairMethod, ret);
}
}
}
static void GapLePairKeyConvert(const SMP_PairResult *result, LePairedKeys *keys)
{
if (result->peerKeyDist | SMP_KEY_DIST_BIT_ENC_KEY) {
(void)memcpy_s(keys->remoteEncKey->ltk, GAP_LTK_SIZE, result->peerLTK, GAP_LTK_SIZE);
(void)memcpy_s(&keys->remoteEncKey->rand,
sizeof(keys->remoteEncKey->rand),
result->peerRandom,
sizeof(result->peerRandom));
keys->remoteEncKey->ediv = result->peerEdiv;
keys->remoteEncKey->keySize = result->encKeySize;
} else {
keys->remoteEncKey = NULL;
}
if (result->peerKeyDist | SMP_KEY_DIST_BIT_ID_KEY) {
(void)memcpy_s(&keys->remoteIdKey->identityAddr, sizeof(BtAddr), &result->peerIdentAddr, sizeof(BtAddr));
(void)memcpy_s(keys->remoteIdKey->irk, GAP_IRK_SIZE, result->peerIRK, GAP_IRK_SIZE);
} else {
keys->remoteIdKey = NULL;
}
if (result->peerKeyDist | SMP_KEY_DIST_BIT_SIGN_KEY) {
(void)memcpy_s(keys->remoteSignKey->csrk, GAP_CSRK_SIZE, result->peerCSRK, GAP_CSRK_SIZE);
keys->remoteSignKey->counter = 0;
} else {
keys->remoteSignKey = NULL;
}
if (result->localKeyDist | SMP_KEY_DIST_BIT_ENC_KEY) {
(void)memcpy_s(keys->localEncKey->ltk, GAP_LTK_SIZE, result->localLTK, GAP_LTK_SIZE);
(void)memcpy_s(&keys->localEncKey->rand,
sizeof(keys->localEncKey->rand),
result->localRandom,
sizeof(result->localRandom));
keys->localEncKey->ediv = result->localEdiv;
keys->localEncKey->keySize = result->encKeySize;
} else {
keys->localEncKey = NULL;
}
if (result->localKeyDist | SMP_KEY_DIST_BIT_SIGN_KEY) {
(void)memcpy_s(keys->localSignKey->csrk, GAP_CSRK_SIZE, result->localCSRK, GAP_CSRK_SIZE);
keys->localSignKey->counter = 0;
} else {
keys->localSignKey = NULL;
}
}
static void GapCallbackKeyNotify(const BtAddr *addr, const SMP_PairResult *result)
{
LeEncKey remoteEncKey;
LeIdKey remoteIdKey;
LeSignKey remoteSignKey;
LeEncKey localEncKey;
LeSignKey localSignKey;
LePairedKeys keys;
keys.remoteEncKey = &remoteEncKey;
keys.remoteIdKey = &remoteIdKey;
keys.remoteSignKey = &remoteSignKey;
keys.localEncKey = &localEncKey;
keys.localSignKey = &localSignKey;
GapLePairKeyConvert(result, &keys);
if (g_lePairCallback.callback.lePairKeyNotify) {
g_lePairCallback.callback.lePairKeyNotify(addr, keys, g_lePairCallback.context);
}
}
static void GapSetLeSigningInfo(uint16_t handle, const SMP_PairResult *result)
{
LeDeviceInfo *deviceInfo =
ListForEachData(GapGetLeConnectionInfoBlock()->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
if (result->localKeyDist & SMP_KEY_DIST_BIT_SIGN_KEY) {
deviceInfo->localSigningExists = true;
(void)memcpy_s(deviceInfo->localSigningInfo.csrk, GAP_CSRK_SIZE, result->localCSRK, GAP_CSRK_SIZE);
deviceInfo->localSigningInfo.counter = 0;
} else {
deviceInfo->localSigningExists = false;
}
if (result->peerKeyDist & SMP_KEY_DIST_BIT_SIGN_KEY) {
deviceInfo->remoteSigningExists = true;
(void)memcpy_s(deviceInfo->remoteSigningInfo.csrk, GAP_CSRK_SIZE, result->peerCSRK, GAP_CSRK_SIZE);
deviceInfo->remoteSigningInfo.counter = 0;
} else {
deviceInfo->remoteSigningExists = false;
}
}
}
static void GapSetEncryptionStatusForPairEnd(LeDeviceInfo *deviceInfo, uint8_t status, const SMP_PairResult *result)
{
if (status == SMP_PAIR_STATUS_SUCCESS) {
if (deviceInfo->encryptionStatus == GAP_LE_UNAUTHENTICATED_ENCRYPTION && result->authFlag) {
deviceInfo->encryptionStatus = GAP_LE_AUTHENTICATED_ENCRYPTION;
}
} else {
deviceInfo->encryptionStatus = GAP_LE_NO_ENCRYPTION;
}
}
void GapDoPairResultCallback(const BtAddr *addr, uint8_t status)
{
if (g_lePairCallback.callback.lePairComplete) {
g_lePairCallback.callback.lePairComplete(addr, status, 0, g_lePairCallback.context);
}
}
void GapLePairResult(uint16_t handle, uint8_t status, const SMP_PairResult *result)
{
BtAddr addr = {0};
LeDeviceInfo *deviceInfo =
ListForEachData(GapGetLeConnectionInfoBlock()->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
if (deviceInfo->securityStatus == GAP_LE_SECURITY_STATUS_PAIR) {
deviceInfo->securityStatus = GAP_LE_SECURITY_STATUS_IDLE;
}
GapSetEncryptionStatusForPairEnd(deviceInfo, status, result);
if (deviceInfo->securityReq != NULL) {
deviceInfo->securityReq->result = status;
GapDoLeSecurityCallback(&deviceInfo->handle);
}
}
bool isPairing = GapGetLeBondBlock()->isPairing;
if (deviceInfo == NULL && isPairing == true) {
(void)memcpy_s(&addr, sizeof(BtAddr), &GapGetLeBondBlock()->addr, sizeof(BtAddr));
}
GapClearPairingStatus(&addr);
if (deviceInfo != NULL || isPairing) {
if (status == SMP_PAIR_STATUS_SUCCESS && result->bondedFlag == SMP_BONDED_FLAG_YES) {
GapCallbackKeyNotify(&addr, result);
GapSetLeSigningInfo(handle, result);
}
if (g_lePairCallback.callback.lePairComplete) {
g_lePairCallback.callback.lePairComplete(&addr, status, result->authFlag, g_lePairCallback.context);
}
}
}
void GapLeRemotePairRequest(uint16_t handle, const SMP_PairParam *param)
{
BtAddr addr = {0};
int ret;
if (GapGetLeLocalInfo()->minEncKeySize > param->maxEncKeySize) {
SMP_RemotePairRequestReply(handle, SMP_PAIR_FAILED_ENC_KEY_SIZE, NULL, NULL, NULL);
return;
}
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
}
if (deviceInfo != NULL) {
if (g_lePairCallback.callback.lePairFeatureReq) {
g_lePairCallback.callback.lePairFeatureReq(
&deviceInfo->addr, deviceInfo->isLocalSecurityRequest, g_lePairCallback.context);
} else {
ret = SMP_RemotePairRequestReply(handle, SMP_PAIR_FAILED_UNSPECIFIED_REASION, NULL, NULL, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:SMP_RemotePairRequestReply failed:%{public}d.", __FUNCTION__, ret);
}
}
} else {
ret = SMP_RemotePairRequestReply(handle, SMP_PAIR_FAILED_UNSPECIFIED_REASION, NULL, NULL, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:SMP_RemotePairRequestReply failed:%{public}d.", __FUNCTION__, ret);
}
}
}
void GapLeRemotePairResponse(uint16_t handle, const SMP_PairParam *param)
{
if (GapGetLeLocalInfo()->minEncKeySize > param->maxEncKeySize) {
SMP_RemotePairResponseReply(handle, false, SMP_PAIR_FAILED_ENC_KEY_SIZE);
return;
}
LeLocalInfo *localInfo = GapGetLeLocalInfo();
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
if (GapLeSecurityNeedAuthentication(localInfo) && !(param->authReq & SMP_AUTH_REQ_BIT_MITM)) {
SMP_RemotePairResponseReply(handle, false, SMP_PAIR_FAILED_AUTH_REQ);
} else {
SMP_RemotePairResponseReply(handle, true, 0x00);
}
} else {
SMP_RemotePairResponseReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION);
}
}
void GapLeRemoteSecurityRequest(uint16_t handle, uint8_t authReq)
{
BtAddr addr = {0};
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
deviceInfo->isRemoteSecurityRequest = true;
}
if (g_leSecurityCallback.callback.leRemoteEncryptionKeyReqEvent) {
g_leSecurityCallback.callback.leRemoteEncryptionKeyReqEvent(&addr, g_leSecurityCallback.context);
} else {
int ret = SMP_RemoteSecurityRequestReply(handle, false, SMP_PAIR_FAILED_UNSPECIFIED_REASION);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:SMP_RemoteSecurityRequestReply failed:%{public}d.", __FUNCTION__, ret);
}
}
}
void GapLeLongTermKeyRequest(uint16_t handle, const uint8_t *random, uint16_t ediv)
{
BtAddr addr = {0};
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
}
if (g_leSecurityCallback.callback.leLocalEncryptionKeyReqEvent) {
g_leSecurityCallback.callback.leLocalEncryptionKeyReqEvent(
&addr, *(uint64_t *)random, ediv, g_leSecurityCallback.context);
} else {
int ret = SMP_LongTermKeyRequestReply(handle, false, NULL);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:SMP_LongTermKeyRequestReply failed:%{public}d.", __FUNCTION__, ret);
}
}
}
void GapLeEncryptionComplete(uint16_t handle, uint8_t status)
{
BtAddr addr = {0};
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByHandle, &handle);
if (deviceInfo != NULL) {
(void)memcpy_s(&addr, sizeof(BtAddr), &deviceInfo->addr, sizeof(BtAddr));
if (status != HCI_SUCCESS) {
deviceInfo->encryptionStatus = GAP_LE_NO_ENCRYPTION;
if (deviceInfo->securityReq != NULL) {
deviceInfo->securityReq->result = GAP_STATUS_FAILED;
GapDoLeSecurityCallback(&handle);
}
} else {
if (deviceInfo->keyType == LE_KEY_TYPE_AUTHENTICATION) {
deviceInfo->encryptionStatus = GAP_LE_AUTHENTICATED_ENCRYPTION;
} else {
deviceInfo->encryptionStatus = GAP_LE_UNAUTHENTICATED_ENCRYPTION;
}
}
}
if (deviceInfo != NULL && g_leSecurityCallback.callback.encryptionComplete) {
g_leSecurityCallback.callback.encryptionComplete(status, &addr, g_leSecurityCallback.context);
}
}
int GAP_RegisterLeSecurityCallback(const GapLeSecurityCallback *callback, void *context)
{
LOG_INFO("%{public}s:%{public}s", __FUNCTION__, callback ? "register" : "NULL");
if (callback == NULL) {
(void)memset_s(&g_leSecurityCallback.callback,
sizeof(g_leSecurityCallback.callback),
0x00,
sizeof(g_leSecurityCallback.callback));
} else {
g_leSecurityCallback.callback = *callback;
}
g_leSecurityCallback.context = context;
return GAP_SUCCESS;
}
int GAP_DeregisterLeSecurityCallback(void)
{
(void)memset_s(&g_leSecurityCallback.callback,
sizeof(g_leSecurityCallback.callback),
0x00,
sizeof(g_leSecurityCallback.callback));
g_leSecurityCallback.context = NULL;
return GAP_SUCCESS;
}
int GAP_LeRemoteEncryptionKeyRsp(const BtAddr *addr, uint8_t accept, LeEncKey encKey, uint8_t keyType)
{
LOG_INFO("%{public}s:" BT_ADDR_FMT "accept:%hhu keyType:%hhu",
__FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr), accept, keyType);
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
int ret = GAP_ERR_INVAL_PARAM;
LeLocalInfo *localInfo = GapGetLeLocalInfo();
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
deviceInfo->keyType = keyType;
deviceInfo->keySize = encKey.keySize;
if (deviceInfo->isRemoteSecurityRequest) {
ret = SMP_RemoteSecurityRequestReply(deviceInfo->handle, true, 0x00);
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s:SMP_RemoteSecurityRequestReply failed:%{public}d.", __FUNCTION__, ret);
}
}
if (keyType == LE_KEY_TYPE_AUTHENTICATION) {
ret = SMP_StartEncryption(deviceInfo->handle, (uint8_t *)&encKey.rand, encKey.ediv, encKey.ltk);
} else if (GapLeSecurityNeedAuthentication(localInfo)) {
ret = GapLePair(addr);
GapGetLeBondBlock()->isPairing = true;
(void)memcpy_s(&GapGetLeBondBlock()->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
} else {
ret = SMP_StartEncryption(deviceInfo->handle, (uint8_t *)&encKey.rand, encKey.ediv, encKey.ltk);
}
} else if (accept == GAP_NOT_ACCEPT) {
ret = GapLePair(addr);
GapGetLeBondBlock()->isPairing = true;
(void)memcpy_s(&GapGetLeBondBlock()->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
} else {
ret = GAP_ERR_INVAL_PARAM;
}
}
return ret;
}
int GAP_LeLocalEncryptionKeyRsp(const BtAddr *addr, uint8_t accept, LeEncKey encKey, uint8_t keyType)
{
LOG_INFO("%{public}s:" BT_ADDR_FMT "accept:%hhu keyType:%hhu",
__FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr), accept, keyType);
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
int ret = GAP_ERR_INVAL_PARAM;
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
deviceInfo->keyType = keyType;
deviceInfo->keySize = encKey.keySize;
if (accept == GAP_ACCEPT) {
ret = SMP_LongTermKeyRequestReply(deviceInfo->handle, true, encKey.ltk);
} else if (accept == GAP_NOT_ACCEPT) {
ret = SMP_LongTermKeyRequestReply(deviceInfo->handle, false, NULL);
} else {
ret = GAP_ERR_INVAL_PARAM;
}
}
return ret;
}
int GAP_RequestSigningAlgorithmInfoRsp(const BtAddr *addr, uint8_t accept, GapSigningAlgorithmInfo info)
{
int ret = GAP_SUCCESS;
LOG_INFO("%{public}s:" BT_ADDR_FMT "accept:%hhu", __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr), accept);
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
if (info.localKey != NULL) {
deviceInfo->localSigningExists = true;
deviceInfo->localSigningInfo = *info.localKey;
}
if (info.remoteKey != NULL) {
deviceInfo->remoteSigningExists = true;
deviceInfo->remoteSigningInfo = *info.remoteKey;
}
} else if (accept == GAP_NOT_ACCEPT) {
deviceInfo->localSigningExists = false;
deviceInfo->remoteSigningExists = false;
} else {
ret = GAP_ERR_INVAL_PARAM;
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
static int GapLeRequestSecurityMaster(const LeDeviceInfo *deviceInfo)
{
int ret = GAP_SUCCESS;
bool isCalled = false;
const BtAddr *addr = &deviceInfo->addr;
if (deviceInfo->encryptionStatus >= deviceInfo->securityReq->secReqStatus) {
deviceInfo->securityReq->callback(
&deviceInfo->addr, GAP_STATUS_SUCCESS, deviceInfo->encryptionStatus, deviceInfo->securityReq->context);
return ret;
}
if (!isCalled) {
if (g_leSecurityCallback.callback.leRemoteEncryptionKeyReqEvent) {
g_leSecurityCallback.callback.leRemoteEncryptionKeyReqEvent(addr, g_leSecurityCallback.context);
isCalled = true;
}
}
if (!isCalled) {
if (g_lePairCallback.callback.lePairFeatureReq) {
g_lePairCallback.callback.lePairFeatureReq(
addr, !deviceInfo->isRemoteSecurityRequest, g_lePairCallback.context);
isCalled = true;
}
}
if (!isCalled) {
ret = GAP_ERR_NOT_SUPPORT;
}
return ret;
}
int GapLeRequestSecurityProcess(LeDeviceInfo *deviceInfo)
{
int ret = GAP_SUCCESS;
uint8_t authReq = AUTH_REQ_DEFAULT;
if (deviceInfo->securityStatus != GAP_LE_SECURITY_STATUS_IDLE) {
return ret;
}
if (deviceInfo->role == LE_CONNECTION_ROLE_MASTER) {
ret = GapLeRequestSecurityMaster(deviceInfo);
} else {
if (deviceInfo->securityReq != NULL && deviceInfo->securityReq->secReqStatus == GAP_LE_NO_ENCRYPTION) {
deviceInfo->securityReq->result = GAP_STATUS_SUCCESS;
GapDoLeSecurityCallback(&deviceInfo->handle);
} else if (deviceInfo->securityReq != NULL &&
deviceInfo->securityReq->secReqStatus == GAP_LE_UNAUTHENTICATED_ENCRYPTION) {
authReq &= GapIsLeBondableMode() ? ~0 : ~SMP_AUTH_REQ_BONDING;
} else {
authReq &= GapIsLeBondableMode() ? ~0 : ~SMP_AUTH_REQ_BONDING;
authReq &= SMP_AUTH_REQ_BIT_MITM;
}
deviceInfo->isLocalSecurityRequest = true;
ret = SMP_SendSecurityRequestToRemote(deviceInfo->handle, authReq);
}
return ret;
}
int GAP_LeRequestSecurity(
const BtAddr *addr, GAP_LeSecurityStatus status, GapLeRequestSecurityResult callback, void *context)
{
LOG_INFO("%{public}s:" BT_ADDR_FMT " status:%{public}d", __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr), status);
int ret;
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
LeDeviceInfo *deviceInfo =
ListForEachData(GapGetLeConnectionInfoBlock()->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL && deviceInfo->securityReq == NULL) {
deviceInfo->securityReq = MEM_MALLOC.alloc(sizeof(LeSecurityReq));
if (deviceInfo->securityReq != NULL) {
deviceInfo->securityReq->secReqStatus = status;
deviceInfo->securityReq->callback = callback;
deviceInfo->securityReq->context = context;
ret = GapLeRequestSecurityProcess(deviceInfo);
} else {
ret = GAP_ERR_OUT_OF_RES;
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
static void GapDoLePairFeatureReqCallback(void *data)
{
LeDeviceInfo *deviceInfo = data;
if (g_lePairCallback.callback.lePairFeatureReq) {
g_lePairCallback.callback.lePairFeatureReq(
&deviceInfo->addr, !deviceInfo->isRemoteSecurityRequest, g_lePairCallback.context);
}
}
int GAP_RegisterLePairCallback(const GapLePairCallback *callback, void *context)
{
LOG_INFO("%{public}s:%{public}s", __FUNCTION__, callback ? "register" : "NULL");
if (callback == NULL) {
(void)memset_s(
&g_lePairCallback.callback, sizeof(g_lePairCallback.callback), 0x00, sizeof(g_lePairCallback.callback));
} else {
g_lePairCallback.callback = *callback;
}
g_lePairCallback.context = context;
return GAP_SUCCESS;
}
int GAP_DeregisterLePairCallback(void)
{
(void)memset_s(
&g_lePairCallback.callback, sizeof(g_lePairCallback.callback), 0x00, sizeof(g_lePairCallback.callback));
g_lePairCallback.context = NULL;
return GAP_SUCCESS;
}
void GapClearPairingStatus(const BtAddr *addr)
{
LeBondBlock *leBondBlock = GapGetLeBondBlock();
if (GapAddrCompare(addr, &leBondBlock->addr)) {
leBondBlock->isPairing = false;
}
}
static int GapLePair(const BtAddr *addr)
{
int ret = GAP_SUCCESS;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
uint8_t authReq = AUTH_REQ_DEFAULT;
BtmLocalVersionInformation version;
BTM_GetLocalVersionInformation(&version);
if (version.hciVersion < BLUETOOTH_CORE_SPECIFICATION_4_2) {
authReq &= ~SMP_AUTH_REQ_BIT_SC;
}
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (deviceInfo->securityStatus == GAP_LE_SECURITY_STATUS_IDLE) {
deviceInfo->securityStatus = GAP_LE_SECURITY_STATUS_PAIR;
if (deviceInfo->role == LE_CONNECTION_ROLE_MASTER) {
GapDoLePairFeatureReqCallback(deviceInfo);
} else {
deviceInfo->isLocalSecurityRequest = true;
SMP_SendSecurityRequestToRemote(deviceInfo->handle, authReq);
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
} else {
ret = GAP_ERR_INVAL_PARAM;
}
return ret;
}
void GapLeDoPair(const void *addr)
{
int ret = GapLePair(addr);
if (ret != BT_SUCCESS) {
LOG_WARN("GapLePair ret = %{public}d", ret);
}
}
int GAP_LePair(const BtAddr *addr)
{
int ret;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
LeBondBlock *leBondBlock = GapGetLeBondBlock();
if (leBondBlock->isPairing) {
ret = GAP_ERR_INVAL_STATE;
} else {
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
ret = GapLePair(addr);
} else {
ret = BTM_LeConnect(addr);
}
leBondBlock->isPairing = true;
(void)memcpy_s(&leBondBlock->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
}
return ret;
}
int GAP_LeCancelPair(const BtAddr *addr)
{
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
LeBondBlock *leBondBlock = GapGetLeBondBlock();
if (!leBondBlock->isPairing) {
LOG_WARN("%{public}s: invalid state", __FUNCTION__);
}
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
return SMP_CancelPair(deviceInfo->handle);
} else {
return BTM_LeCancelConnect(addr);
}
}
int GAP_LeSetMinEncKeySize(uint8_t minSize)
{
LeLocalInfo *localInfo = NULL;
LOG_INFO("%{public}s: min key size:%hhu", __FUNCTION__, minSize);
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
localInfo = GapGetLeLocalInfo();
localInfo->minEncKeySize = minSize;
return GAP_SUCCESS;
}
int GAP_LePairFeatureRsp(const BtAddr *addr, GapLePairFeature localFeature)
{
int ret;
LeLocalInfo *localInfo = NULL;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
localInfo = GapGetLeLocalInfo();
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (localInfo->bondableMode == GAP_BONDABLE_MODE_NON) {
localFeature.authReq &= ~SMP_AUTH_REQ_BONDING;
localFeature.initKeyDis &= (deviceInfo->role == LE_CONNECTION_ROLE_MASTER) ? GAP_LE_KEY_DIST_ID_KEY : 0;
localFeature.respKeyDis &= (deviceInfo->role == LE_CONNECTION_ROLE_SLAVE) ? GAP_LE_KEY_DIST_ID_KEY : 0;
}
if (deviceInfo->securityReq && deviceInfo->securityReq->secReqStatus == GAP_LE_AUTHENTICATED_ENCRYPTION) {
localFeature.authReq |= SMP_AUTH_REQ_BIT_MITM;
}
BtmLocalVersionInformation version;
BTM_GetLocalVersionInformation(&version);
if (version.hciVersion < BLUETOOTH_CORE_SPECIFICATION_4_2) {
localFeature.authReq &= ~SMP_AUTH_REQ_BIT_SC;
}
SMP_PairParam pairParam = {
.ioCapability = localFeature.ioCapability,
.oobDataFlag = localFeature.oobDataFlag,
.authReq = localFeature.authReq,
.maxEncKeySize = localFeature.maxEncKeySize,
.initKeyDist = localFeature.initKeyDis,
.respKeyDist = localFeature.respKeyDis,
};
if (deviceInfo->role == LE_CONNECTION_ROLE_MASTER) {
ret = SMP_StartPair(deviceInfo->handle, &deviceInfo->ownAddr, &deviceInfo->peerAddr, &pairParam);
} else {
ret = SMP_RemotePairRequestReply(
deviceInfo->handle, SMP_PAIR_FAILED_NO_FAILED, &deviceInfo->ownAddr, &deviceInfo->peerAddr, &pairParam);
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
int GAP_LePairPassKeyRsp(const BtAddr *addr, uint8_t accept, uint32_t number)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
ret = SMP_AuthenticationRequestReply(
deviceInfo->handle, true, 0x00, deviceInfo->pairMethod, (uint8_t *)&number);
} else if (accept == GAP_NOT_ACCEPT) {
ret = SMP_AuthenticationRequestReply(
deviceInfo->handle, false, SMP_PAIR_FAILED_PASSKEY_ENTRY, deviceInfo->pairMethod, NULL);
} else {
ret = GAP_ERR_INVAL_PARAM;
}
} else {
ret = GAP_ERR_INVAL_PARAM;
}
return ret;
}
int GAP_LePairOobRsp(const BtAddr *addr, uint8_t accept, uint8_t oobData[GAP_OOB_DATA_SIZE])
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
ret = SMP_AuthenticationRequestReply(deviceInfo->handle, true, 0x00, deviceInfo->pairMethod, oobData);
} else if (accept == GAP_NOT_ACCEPT) {
ret = SMP_AuthenticationRequestReply(
deviceInfo->handle, false, SMP_PAIR_FAILED_OOB_NOT_AVAILABLE, deviceInfo->pairMethod, NULL);
} else {
ret = GAP_ERR_INVAL_PARAM;
}
} else {
ret = GAP_ERR_INVAL_PARAM;
}
return ret;
}
int GAP_LePairScOobRsp(const BtAddr *addr, uint8_t accept, const uint8_t oobDataC[GAP_OOB_DATA_SIZE],
const uint8_t oobDataR[GAP_OOB_DATA_SIZE])
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
const int length = BT_ADDRESS_SIZE + GAP_OOB_DATA_RANDOM_SIZE + GAP_OOB_DATA_CONFIRM_SIZE;
uint8_t smData[BT_ADDRESS_SIZE + GAP_OOB_DATA_RANDOM_SIZE + GAP_OOB_DATA_CONFIRM_SIZE] = {0};
int offset = 0;
(void)memcpy_s(smData + offset, length - offset, deviceInfo->peerAddr.addr, BT_ADDRESS_SIZE);
offset += BT_ADDRESS_SIZE;
(void)memcpy_s(smData + offset, length - offset, oobDataR, GAP_OOB_DATA_RANDOM_SIZE);
offset += GAP_OOB_DATA_RANDOM_SIZE;
(void)memcpy_s(smData + offset, length - offset, oobDataC, GAP_OOB_DATA_CONFIRM_SIZE);
ret = SMP_AuthenticationRequestReply(deviceInfo->handle, true, 0x00, deviceInfo->pairMethod, smData);
} else if (accept == GAP_NOT_ACCEPT) {
ret = SMP_AuthenticationRequestReply(
deviceInfo->handle, false, SMP_PAIR_FAILED_NUMERIC_COMPARISON, deviceInfo->pairMethod, NULL);
} else {
ret = GAP_ERR_INVAL_PARAM;
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
int GAP_LePairScUserConfirmRsp(const BtAddr *addr, uint8_t accept)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret;
LeConnectionInfoBlock *connectionInfoBlock = NULL;
LeDeviceInfo *deviceInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
connectionInfoBlock = GapGetLeConnectionInfoBlock();
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL) {
if (accept == GAP_ACCEPT) {
ret = SMP_AuthenticationRequestReply(deviceInfo->handle, true, 0x00, deviceInfo->pairMethod, NULL);
} else if (accept == GAP_NOT_ACCEPT) {
ret = SMP_AuthenticationRequestReply(
deviceInfo->handle, false, SMP_PAIR_FAILED_NUMERIC_COMPARISON, deviceInfo->pairMethod, NULL);
} else {
ret = GAP_ERR_INVAL_PARAM;
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
void GapDoSignatureCallback(void *data)
{
SignatureRequestInfo *info = data;
if (info->type == SIGNATURE_GENERATION) {
GAPSignatureGenerationResult callback = info->callback;
callback(info->result, info->signature, info->context);
} else if (info->type == SIGNATURE_CONFIRMATION) {
GAPSignatureConfirmationResult callback = info->callback;
callback(info->result, info->context);
}
ListRemoveNode(GapGetLeSignatureBlock()->RequestList, data);
}
static SignatureRequestInfo *GapAllocSignatureRequestInfo(
uint16_t handle, SignatureType type, uint32_t counter, void *callback, void *context)
{
SignatureRequestInfo *info = MEM_MALLOC.alloc(sizeof(SignatureRequestInfo));
if (info != NULL) {
info->handle = handle;
info->callback = callback;
info->context = context;
info->type = type;
info->processing = true;
info->counter = counter;
}
return info;
}
int GAP_LeDataSignatureGeneration(
const BtAddr *addr, GapSignatureData dataInfo, GAPSignatureGenerationResult callback, void *context)
{
if (callback == NULL) {
return GAP_ERR_INVAL_PARAM;
}
uint8_t signature[GAP_SIGNATURE_SIZE] = {0};
if (GapIsLeEnable() == false) {
callback(GAP_SIGNATURE_ERR_EXECUTION, signature, context);
return GAP_ERR_NOT_ENABLE;
}
if (addr == NULL) {
callback(GAP_SIGNATURE_ERR_EXECUTION, signature, context);
return GAP_ERR_INVAL_PARAM;
}
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
int ret = GAP_ERR_INVAL_STATE;
LeConnectionInfoBlock *connectionInfoBlock = GapGetLeConnectionInfoBlock();
LeDeviceInfo *deviceInfo = NULL;
deviceInfo = ListForEachData(connectionInfoBlock->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL && deviceInfo->localSigningExists) {
uint32_t counter = deviceInfo->localSigningInfo.counter;
SignatureRequestInfo *info =
GapAllocSignatureRequestInfo(deviceInfo->handle, SIGNATURE_GENERATION, counter, callback, context);
if (info != NULL) {
ListAddLast(GapGetLeSignatureBlock()->RequestList, info);
ret = SMP_GenerateSignature(deviceInfo->localSigningInfo.csrk, counter, dataInfo.data, dataInfo.dataLen);
if (ret != BT_SUCCESS) {
ListRemoveLast(GapGetLeSignatureBlock()->RequestList);
}
} else {
ret = GAP_ERR_OUT_OF_RES;
}
}
if (ret != BT_SUCCESS) {
LOG_INFO("%{public}s: ret = %{public}d", __FUNCTION__, ret);
callback(GAP_SIGNATURE_ERR_EXECUTION, signature, context);
}
return ret;
}
int GAP_LeDataSignatureConfirmation(const BtAddr *addr, GapSignatureData dataInfo,
const uint8_t signature[GAP_SIGNATURE_SIZE], GAPSignatureConfirmationResult callback, void *context)
{
int ret = GAP_SUCCESS;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
if (GapIsLeEnable() == false) {
callback(GAP_SIGNATURE_ERR_EXECUTION, context);
return GAP_ERR_NOT_ENABLE;
}
LeDeviceInfo *deviceInfo =
ListForEachData(GapGetLeConnectionInfoBlock()->deviceList, GapFindLeConnectionDeviceByAddr, (void *)addr);
if (deviceInfo != NULL && deviceInfo->remoteSigningExists) {
uint32_t counter = *(uint32_t *)signature;
SignatureRequestInfo *info =
GapAllocSignatureRequestInfo(deviceInfo->handle, SIGNATURE_CONFIRMATION, counter, callback, context);
if (info != NULL) {
(void)memcpy_s(info->signature, GAP_SIGNATURE_SIZE, signature, GAP_SIGNATURE_SIZE);
ListAddLast(GapGetLeSignatureBlock()->RequestList, info);
if (deviceInfo->remoteSigningInfo.counter > counter) {
info->processing = false;
info->result = GAP_SIGNATURE_ERR_COUNTER;
GapDoSignatureCallback(info);
} else {
ret =
SMP_GenerateSignature(deviceInfo->remoteSigningInfo.csrk, counter, dataInfo.data, dataInfo.dataLen);
}
if (ret != BT_SUCCESS) {
ListRemoveLast(GapGetLeSignatureBlock()->RequestList);
}
}
} else {
ret = GAP_ERR_INVAL_STATE;
}
if (ret != BT_SUCCESS) {
LOG_INFO("%{public}s: ret = %{public}d", __FUNCTION__, ret);
callback(GAP_SIGNATURE_ERR_EXECUTION, context);
}
return ret;
}
static void GapDoCallbackSignCounterChange(SignatureRequestInfo *info)
{
LeSignKey *signKey = NULL;
GAP_SignCounterType signCounterType = LOCAL_SIGN_COUNTER;
LeDeviceInfo *deviceInfo =
ListForEachData(GapGetLeConnectionInfoBlock()->deviceList, GapFindLeConnectionDeviceByHandle, &info->handle);
if (deviceInfo != NULL) {
if (info->type == SIGNATURE_GENERATION) {
signKey = &deviceInfo->localSigningInfo;
signCounterType = LOCAL_SIGN_COUNTER;
} else if (info->type == SIGNATURE_CONFIRMATION) {
signKey = &deviceInfo->remoteSigningInfo;
signCounterType = REMOTE_SIGN_COUNTER;
}
if (signKey == NULL) {
return;
}
signKey->counter = info->counter + 1;
if (g_leSecurityCallback.callback.leSignCounterChangeNotification) {
g_leSecurityCallback.callback.leSignCounterChangeNotification(
&deviceInfo->addr, signCounterType, signKey->counter, g_leSecurityCallback.context);
}
}
}
void GapLeGenerateSignatureResult(uint8_t status, const uint8_t *sign)
{
LOG_INFO("%{public}s: status:0x%02x", __FUNCTION__, status);
List *list = GapGetLeSignatureBlock()->RequestList;
ListNode *node = ListGetFirstNode(list);
SignatureRequestInfo *info = NULL;
while (node != 0) {
info = ListGetNodeData(node);
if (info != NULL && info->processing) {
info->processing = false;
break;
}
node = ListGetNextNode(node);
}
if (node != NULL) {
if (status != SMP_GENERATE_SIGN_STATUS_SUCCESS) {
info->result = GAP_SIGNATURE_ERR_EXECUTION;
} else {
if (info->type == SIGNATURE_CONFIRMATION && memcmp(sign, info->signature, GAP_SIGNATURE_SIZE)) {
info->result = GAP_SIGNATURE_ERR_ALGORITHM;
} else {
(void)memcpy_s(info->signature, GAP_SIGNATURE_SIZE, sign, GAP_SIGNATURE_SIZE);
info->result = GAP_SIGNATURE_OK;
GapDoCallbackSignCounterChange(info);
}
}
GapDoSignatureCallback(info);
}
}
int GapRequestSigningAlgorithmInfo(const BtAddr *addr)
{
int ret;
if (g_leSecurityCallback.callback.GapRequestSigningAlgorithmInfo) {
g_leSecurityCallback.callback.GapRequestSigningAlgorithmInfo(addr, g_leSecurityCallback.context);
ret = GAP_SUCCESS;
} else {
ret = GAP_ERR_NOT_SUPPORT;
}
return ret;
}