OOB是啥?
OOB就是OutofBand的缩写,指安全数据不经过自己通信的信道进行传输。OOB允许两个蓝牙设备通过设备的带外通道发送认证信息,比如:串口、NFC、UWB等。OOB的目的是允许两个设备在没有输入输出能力的情况下创建认证配对,认证需要发送3个认证参数:deviceaddress、randomnumber、股票量化交易软件,confirmvalue。它这种认证配对方式能很好的反MITM攻击。方法就是在主机或者从机中产生一个密钥,然后OOB数据通过蓝牙通信之外的方式发送给其他设备。OOB数据可以选择使用椭圆曲线加密算法生成。流程大致是这样的: 创建存放OOB数据的变量,有两个,一个是用于存放设备自己本身的OOB数据,另一个是用于存放对端设备的OOB数据。 定义配对状态的回调函数。 要用ECC密钥产生OOB数据,先调用GAPBondMgr_GenerateEccKeys产生ECC密钥,然后在ECC密钥产生的事件中再调用GAPBondMgr_SCGetLocalOOBParameters获取OOB数据。当协议栈的ECC密钥准备好了之后,协议栈会发送事件GAPBOND_GENERATE_ECC_DONE给应用层,该事件在配对状态回调里面处理。上面提到的两个API函数可以在蓝牙连接建立前或者后调用,但是必须是在配对开始前被调用。如果不调用GAPBondMgr_GenerateEccKeys,那么OOB数据是没使用ECC密钥生成的。 在OOB数据生成之后,设备应该将它发送到对端设备,对端设备的配对特性必须是使能了OOB配对绑定的。如果两个设备都产生和分享OOB数据,那么这两个设备的配对特性都必须使能OOB配对绑定。 对端设备接收到OOB数据之后,应使用函数接口GAPBondMgr_SCSetRemoteOOBParameters记录下接收到的OOB数据到绑定管理器中。 设备发起配对请求,走配对流程,整个过程两设备不存在输入输出显示操作,配对完成之后两设备BLE协议栈会向应用层发出事件GAPBOND_PAIRING_STATE_COMPLETE。
OOB配对实践
下面我们先做两个实验: 一个设备产生OOB数据,另一个设备不产生OOB数据,实现OOB配对。 两个设备都产生OOB数据,实现OOB配对。 在中,做法可以是这样: 在IAR中导入CC26XX的SimpleCentral例程。-1-先定义两个变量:
#ifdef USING_OOB_PAIR
// This is needed for the device that generates OOB data
gapBondOOBData_t localOobData;
// This is needed to store the OOB data this device receives
gapBondOOBData_t remoteOobData;
#endif
-2-在GAP_DEVICE_INIT_DONE_EVENT事件中添加ECC密钥产生函数,该函数调用成功之后会产生一个事件:GAPBOND_GENERATE_ECC_DONE
GAPBondMgr_GenerateEccKeys();
-3-在SimpleCentral_processPairState函数里面添加一个事件:
static void SimpleCentral_processPairState(uint8_t state,
scPairStateData_t* pPairData)
{
uint8_t status = pPairData->status;
uint8_t pairMode = 0;
if (state == GAPBOND_GENERATE_ECC_DONE)
{
if (status == SUCCESS)
{
//After we get the ECC key, we can get the OOB data which is generated by ECC
GAPBondMgr_SCGetLocalOOBParameters(&localOobData);
uint8_t i;
for (i = 0; i < KEYLEN; i++)
{
Display_printf(dispHandle, SC_ROW_CUR_CONN+i+5, 0, "OOB data 股票量化交易软件,confirm[%d]: 0x%2x", i, localOobData.confirm[i]);
Display_printf(dispHandle, SC_ROW_CUR_CONN+KEYLEN+i+5, 0, "OOB data rand[%d]: 0x%2x", i, localOobData.rand[i]);
}
}
}
else if (state == GAPBOND_PAIRING_STATE_STARTED)
...
}
-4-编译运行Central例程,使用串口助手查看Central打印出的OOB数据,包括了Confirm值和随机数。-5-至此,Central例程的代码已经改完了,现在改从机代码,从机代码我使用的是ProjectZero,同样,建一个变量:
#ifdef USING_OOB_PAIR
// This is needed for the device that generates OOB data
gapBondOOBData_t localOobData;
// This is needed to store the OOB data this device receives
gapBondOOBData_t remoteOobData;//we"ll use
#endif
-6-直接将Central串口打印出来的Confirm值和随机数赋值到remoteOobData,然后存储到配对管理器中:
#ifdef USING_OOB_PAIR
void oob_ready(void)
{
uint8_t u8OOB_Enable = true;
GAPBondMgr_SetParameter(GAPBOND_OOB_ENABLED, sizeof(uint8_t), &u8OOB_Enable);
remoteOobData.confirm[0] = 0xe0;
remoteOobData.confirm[1] = 0xa6;
remoteOobData.confirm[2] = 0xb5;
remoteOobData.confirm[3] = 0x76;
remoteOobData.confirm[4] = 0x3d;
remoteOobData.confirm[5] = 0x30;
remoteOobData.confirm[6] = 0xe6;
remoteOobData.confirm[7] = 0xa1;
remoteOobData.confirm[8] = 0x9f;
remoteOobData.confirm[9] = 0xa1;
remoteOobData.confirm[10] = 0x9f;
remoteOobData.confirm[11] = 0x89;
remoteOobData.confirm[12] = 0xb0;
remoteOobData.confirm[13] = 0xa2;
remoteOobData.confirm[14] = 0x1f;
remoteOobData.confirm[15] = 0x94;
remoteOobData.rand[0] = 0xec;
remoteOobData.rand[1] = 0x04;
remoteOobData.rand[2] = 0xf8;
remoteOobData.rand[3] = 0xa4;
remoteOobData.rand[4] = 0xd8;
remoteOobData.rand[5] = 0x69;
remoteOobData.rand[6] = 0x39;
remoteOobData.rand[7] = 0x94;
remoteOobData.rand[8] = 0xce;
remoteOobData.rand[9] = 0xf9;
remoteOobData.rand[10] = 0xf0;
remoteOobData.rand[11] = 0x1d;
remoteOobData.rand[12] = 0x1e;
remoteOobData.rand[13] = 0xfb;
remoteOobData.rand[14] = 0x45;
remoteOobData.rand[15] = 0x1c;
GAPBondMgr_SCSetRemoteOOBParameters(&remoteOobData, 1);
}
#endif
-7-在ProjectZero的GAP_DEVICE_INIT_DONE_EVENT事件之中添加该函数
static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg)
{
...
case GAP_DEVICE_INIT_DONE_EVENT:
{
...
oob_ready();
break;
...
-8-注意,这个期间,Central不要复位,复位后OOB数据就不一样啦。编译运行ProjectZero,这里建议把ProjectZero的蓝牙地址模式设置成Public,方便Central那边扫描连接。使用Central连接ProjectZero,如果不知道怎么操作的话,可以看下工程里边的Readme。-9-扫描到从机设备之后connectto它,由于Central是配对请求发起端,在建立连接之后马上发起配对,这个时候我们可以在Central的串口助手上看到“Pairingsuccess”和“Bondsavesuccess”信息,表示OOB配对成功。
-10-断开连接,重新扫描连接,你可以看到“Encryptionsuccess”信息,表示之后的连接都是加密的,也从侧面表示配对成功了。
-1-先把L2CAPCoc通信打通,我们需要做四件事: 双方都把L2CAPConnectionOrientedChannel…勾选上 对于Central,需要把配对模式改成不允许配对,这样在建立连接之后就不会立即配对了。 下面是两个设备注册SPSM的代码段:
#define APP_SPSM 0x0080
void L2CAP_vidConfig_Init( void )
{
l2capPsm_t psm;
l2capPsmInfo_t psmInfo;
if(L2CAP_PsmInfo(APP_SPSM, &psmInfo) == INVALIDPARAMETER)
{
psm.initPeerCredits = 0xFFFF;
psm.maxNumChannels = MAX_NUM_BLE_CONNS;
psm.mtu = MAX_PDU_SIZE;
psm.peerCreditThreshold = 0;
psm.pfnVerifySecCB = NULL;
psm.psm = APP_SPSM;
psm.taskId = ICall_getLocalMsgEntityId(ICALL_SERVICE_CLASS_BLE_MSG, selfEntity);
L2CAP_RegisterPsm(&psm);
}
else
{
//Failed
}
}
-1-在Central一方的建立连接事件里添加L2CAP连接请求
// Send out L2CAP_LE_CREDIT_BASED_CONNECTION_REQ
L2CAP_ConnectReq(connHandle, App_SPSM, App_SPSM);
两个设备都可以发送L2CAPCoc建立连接请求,但是不需要两个设备都发起。-2-在Central一方添加下面的代码段,"…"是我省略了一些例程本来就有的代码。
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点