Skip to content

Commit

Permalink
[tcat] Implement new tcat General commands.
Browse files Browse the repository at this point in the history
New General TLV's implemented:
	- Get network name
	- Get device id
	- Get ext pan ID
	- get provisioning URL
  • Loading branch information
canisLupus1313 committed Jul 22, 2024
1 parent 602167f commit a763b60
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 7 deletions.
18 changes: 18 additions & 0 deletions src/cli/cli_tcat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ otTcatDeviceId sVendorDeviceIds[OT_TCAT_DEVICE_ID_MAX];
const char kPskdVendor[] = "JJJJJJ";
const char kUrl[] = "dummy_url";

static bool IsDeviceIdSet(void)
{
for (otTcatDeviceId &vendorDeviceId : sVendorDeviceIds)
{
if (vendorDeviceId.mDeviceIdType != OT_TCAT_DEVICE_ID_EMPTY)
{
return true;
}
}

return false;
}

static void HandleBleSecureReceive(otInstance *aInstance,
const otMessage *aMessage,
int32_t aOffset,
Expand Down Expand Up @@ -210,6 +223,11 @@ template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
mVendorInfo.mPskdString = kPskdVendor;
mVendorInfo.mProvisioningUrl = kUrl;

if (IsDeviceIdSet())
{
mVendorInfo.mDeviceIds = sVendorDeviceIds;
}

otBleSecureSetCertificate(GetInstancePtr(), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_X509_CERT),
sizeof(OT_CLI_TCAT_X509_CERT), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_PRIV_KEY),
sizeof(OT_CLI_TCAT_PRIV_KEY));
Expand Down
18 changes: 18 additions & 0 deletions src/core/common/code_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,22 @@
*/
static inline void IgnoreError(otError aError) { OT_UNUSED_VARIABLE(aError); }

/**
* Executes the `statement` and performs action on success.
*
* Checks for the specified status, which is expected to commonly be successful, and executes action if
* status was successful.
*
* @param[in] aStatus A scalar status to be evaluated against zero (0).
*
*/
#define OnSuccess(...) \
do \
{ \
if ((OT_FIRST_ARG(__VA_ARGS__)) == 0) \
{ \
OT_SECOND_ARG(__VA_ARGS__); \
} \
} while (false)

#endif // CODE_UTILS_HPP_
110 changes: 104 additions & 6 deletions src/core/meshcop/tcat_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,17 +414,24 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutg
error = HandleDecomission();
break;
case kTlvPing:
error = HandlePing(aIncomingMessage, aOutgoingMessage, offset, length);
if (error == kErrorNone)
{
response = true;
}
OnSuccess(error = HandlePing(aIncomingMessage, aOutgoingMessage, offset, length), response = true);
break;
case kTlvGetNetworkName:
OnSuccess(error = HandleGetNetworkName(aOutgoingMessage), response = true);
break;
case kTlvGetDeviceId:
OnSuccess(error = HandleGetDeviceId(aOutgoingMessage), response = true);
break;
case kTlvGetExtendedPanID:
OnSuccess(error = HandleGetExtPanId(aOutgoingMessage), response = true);
break;
case kTlvGetProvisioningURL:
OnSuccess(error = HandleGetProvisioningUrl(aOutgoingMessage), response = true);
break;
default:
error = kErrorInvalidCommand;
}
}

if (!response)
{
StatusCode statusCode;
Expand Down Expand Up @@ -540,6 +547,97 @@ Error TcatAgent::HandlePing(const Message &aIncomingMessage,
return error;
}

Error TcatAgent::HandleGetNetworkName(Message &aOutgoingMessage)
{
Error error = kErrorNone;
const char *name = otThreadGetNetworkName(&GetInstance());
uint16_t length = static_cast<uint16_t>(strlen(name));
ot::Tlv tlv;

VerifyOrExit(Get<ActiveDatasetManager>().IsCommissioned(), error = kErrorInvalidState);
VerifyOrExit(length > 0, error = kErrorInvalidState);

tlv.SetType(kTlvResponseWithPayload);
tlv.SetLength(static_cast<uint8_t>(length));
SuccessOrExit(error = aOutgoingMessage.Append(tlv));
SuccessOrExit(error = aOutgoingMessage.AppendBytes(name, length));

exit:
return error;
}

Error TcatAgent::HandleGetDeviceId(Message &aOutgoingMessage)
{
uint8_t deviceId[OT_EXT_ADDRESS_SIZE];
uint16_t length = 0;
ot::Tlv tlv;
Error error = kErrorNone;

static_assert(OT_EXT_ADDRESS_SIZE > OT_TCAT_MAX_VENDORID_SIZE, "Size of TCAT vendor id is greater than extaddr.");

if (mVendorInfo->mDeviceIds != nullptr)
{
// If array is not null return first set device ID.
for (uint8_t i = 0; mVendorInfo->mDeviceIds[i].mDeviceIdType != OT_TCAT_DEVICE_ID_EMPTY; i++)
{
length = mVendorInfo->mDeviceIds->mDeviceIdLen;
memcpy(deviceId, mVendorInfo->mDeviceIds[i].mDeviceId, length);
break;
}
}

if (length == 0)
{
// If array is null or contains only empty entries return EUI64.
otPlatRadioGetIeeeEui64(&GetInstance(), deviceId);
length = OT_EXT_ADDRESS_SIZE;
}

tlv.SetType(kTlvResponseWithPayload);
tlv.SetLength(static_cast<uint8_t>(length));
SuccessOrExit(error = aOutgoingMessage.Append(tlv));
SuccessOrExit(error = aOutgoingMessage.AppendBytes(deviceId, length));

exit:
return error;
}

Error TcatAgent::HandleGetExtPanId(Message &aOutgoingMessage)
{
Error error = kErrorNone;
const otExtendedPanId *name =
otThreadGetExtendedPanId(&GetInstance()); // is it possible to check if i't not set ask during review.
uint16_t length = OT_EXT_PAN_ID_SIZE;
ot::Tlv tlv;

VerifyOrExit(Get<ActiveDatasetManager>().IsCommissioned(), error = kErrorInvalidState);

tlv.SetType(kTlvResponseWithPayload);
tlv.SetLength(static_cast<uint8_t>(length));
SuccessOrExit(error = aOutgoingMessage.Append(tlv));
SuccessOrExit(error = aOutgoingMessage.AppendBytes(name, length));

exit:
return error;
}

Error TcatAgent::HandleGetProvisioningUrl(Message &aOutgoingMessage)
{
Error error = kErrorNone;
uint16_t length = static_cast<uint16_t>(strlen(mVendorInfo->mProvisioningUrl));
ot::Tlv tlv;

VerifyOrExit(length != 0, error = kErrorInvalidState);

tlv.SetType(kTlvResponseWithPayload);
tlv.SetLength(static_cast<uint8_t>(length));
SuccessOrExit(error = aOutgoingMessage.Append(tlv));
SuccessOrExit(error = aOutgoingMessage.AppendBytes(mVendorInfo->mProvisioningUrl, length));

exit:
return error;
}

Error TcatAgent::HandleStartThreadInterface(void)
{
Error error;
Expand Down
5 changes: 5 additions & 0 deletions src/core/meshcop/tcat_agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class TcatAgent : public InstanceLocator, private NonCopyable
kTlvPing = 10, ///< TCAT ping request TLV
kTlvGetDeviceId = 11, ///< TCAT device ID query TLV
kTlvGetExtendedPanID = 12, ///< TCAT extended PAN ID query TLV
kTlvGetProvisioningURL = 13, ///< TCAT provisioning URL query TLV
kTlvPresentPskdHash = 16, ///< TCAT commissioner rights elevation request TLV using PSKd hash
kTlvPresentPskcHash = 17, ///< TCAT commissioner rights elevation request TLV using PSKc hash
kTlvPresentInstallCodeHash = 18, ///< TCAT commissioner rights elevation request TLV using install code
Expand Down Expand Up @@ -354,6 +355,10 @@ class TcatAgent : public InstanceLocator, private NonCopyable
Error HandleSetActiveOperationalDataset(const Message &aIncomingMessage, uint16_t aOffset, uint16_t aLength);
Error HandleDecomission(void);
Error HandlePing(const Message &aIncomingMessage, Message &aOutgoingMessage, uint16_t aOffset, uint16_t aLength);
Error HandleGetNetworkName(Message &aOutgoingMessage);
Error HandleGetDeviceId(Message &aOutgoingMessage);
Error HandleGetExtPanId(Message &aOutgoingMessage);
Error HandleGetProvisioningUrl(Message &aOutgoingMessage);
Error HandleStartThreadInterface(void);

bool CheckCommandClassAuthorizationFlags(CommandClassFlags aCommissionerCommandClassFlags,
Expand Down
25 changes: 25 additions & 0 deletions tests/scripts/expect/cli-tcat.exp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ expect_line "Done"
spawn python "tools/tcat_ble_client/bbtc.py" --simulation 1 --cert_path "tools/tcat_ble_client/auth"
set py_client "$spawn_id"
expect_line "Done"

send "network_name\n"
expect_line "\tTYPE:\tRESPONSE_W_STATUS"
expect_line "\tVALUE:\t0x06"

send "commission\n"
expect_line "\tTYPE:\tRESPONSE_W_STATUS"
expect_line "\tVALUE:\t0x00"
Expand All @@ -58,6 +63,26 @@ send "ping 512\n"
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
expect_line "\tLEN:\t512"

send "network_name\n"
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
expect_line "\tLEN:\t15"
expect_line "\tVALUE:\t0x4f70656e5468726561642d63363465"

send "device_id\n"
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
expect_line "\tLEN:\t8"
expect_line "\tVALUE:\t0x18b4300000000001"

send "ext_panid\n"
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
expect_line "\tLEN:\t8"
expect_line "\tVALUE:\t0xef1398c2fd504b67"

send "provisioning_url\n"
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
expect_line "\tLEN:\t9"
expect_line "\tVALUE:\t0x64756d6d795f75726c"

send "exit\n"
expect eof

Expand Down
62 changes: 62 additions & 0 deletions tools/tcat_ble_client/cli/base_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,68 @@ async def execute_default(self, args, context):
return CommandResultTLV(tlv_response)


class GetDeviceIdCommand(Command):

def get_help_string(self) -> str:
return 'Get unique identifier for the TCAT device.'

async def execute_default(self, args, context):
bless: BleStreamSecure = context['ble_sstream']
data = (TLV(TcatTLVType.GET_DEVICE_ID.value, bytes()).to_bytes())
response = await bless.send_with_resp(data)
if not response:
return
tlv_response = TLV.from_bytes(response)
return CommandResultTLV(tlv_response)


class GetExtPanIDCommand(Command):

def get_help_string(self) -> str:
return 'Get a URL for an application suited to commission device.'

async def execute_default(self, args, context):
bless: BleStreamSecure = context['ble_sstream']
data = (TLV(TcatTLVType.GET_EXT_PAN_ID.value, bytes()).to_bytes())
response = await bless.send_with_resp(data)
if not response:
return
tlv_response = TLV.from_bytes(response)
return CommandResultTLV(tlv_response)


class GetProvisioningUrlCommand(Command):

def get_help_string(self) -> str:
return 'Get a URL for an application suited to commission device.'

async def execute_default(self, args, context):
bless: BleStreamSecure = context['ble_sstream']
data = (TLV(TcatTLVType.GET_PROVISIONING_URL.value, bytes()).to_bytes())
response = await bless.send_with_resp(data)
if not response:
return
tlv_response = TLV.from_bytes(response)
print(f'Provisioning URL: "{str(tlv_response.value)}".')
return CommandResultTLV(tlv_response)


class GetNetworkNameCommand(Command):

def get_help_string(self) -> str:
return 'Get the network name that is commissioned in the active dataset.'

async def execute_default(self, args, context):
bless: BleStreamSecure = context['ble_sstream']
data = (TLV(TcatTLVType.GET_NETWORK_NAME.value, bytes()).to_bytes())
response = await bless.send_with_resp(data)
if not response:
return
tlv_response = TLV.from_bytes(response)
print(f'Network name: "{str(tlv_response.value)}".')
return CommandResultTLV(tlv_response)


class PingCommand(Command):

def get_help_string(self) -> str:
Expand Down
7 changes: 6 additions & 1 deletion tools/tcat_ble_client/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
import readline
import shlex
from ble.ble_stream_secure import BleStreamSecure
from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, DecommissionCommand, PingCommand,
from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, DecommissionCommand, GetDeviceIdCommand,
GetExtPanIDCommand, GetNetworkNameCommand, GetProvisioningUrlCommand, PingCommand,
ThreadStateCommand, ScanCommand)
from cli.dataset_commands import (DatasetCommand)
from dataset.dataset import ThreadDataset
Expand All @@ -44,6 +45,10 @@ def __init__(self, dataset: ThreadDataset, ble_sstream: Optional[BleStreamSecure
'hello': HelloCommand(),
'commission': CommissionCommand(),
'decommission': DecommissionCommand(),
'device_id': GetDeviceIdCommand(),
'ext_panid': GetExtPanIDCommand(),
'provisioning_url': GetProvisioningUrlCommand(),
'network_name': GetNetworkNameCommand(),
'ping': PingCommand(),
'dataset': DatasetCommand(),
'thread': ThreadStateCommand(),
Expand Down
4 changes: 4 additions & 0 deletions tools/tcat_ble_client/tlv/tcat_tlv.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@
class TcatTLVType(Enum):
RESPONSE_W_STATUS = 0x01
RESPONSE_W_PAYLOAD = 0x02
GET_NETWORK_NAME = 0x08
DISCONNECT = 0x09
PING = 0x0A
GET_DEVICE_ID = 0x0B
GET_EXT_PAN_ID = 0x0C
GET_PROVISIONING_URL = 0x0D
ACTIVE_DATASET = 0x20
DECOMMISSION = 0x60
APPLICATION = 0x82
Expand Down

0 comments on commit a763b60

Please sign in to comment.