From f9aeacfd4dc4b62e5d762e7597f07a0f1bec5af7 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 12 Jan 2026 10:35:47 -0800 Subject: [PATCH] [cli] add commands for ephemeral key TAP generation and validation (#12267) This change introduces two new CLI commands to the Border Agent module for managing Thread Administration One-Time Passcodes (TAPs). The new commands are: - `ba ephemeralkey generate-tap`: This command generates and outputs a cryptographically secure random TAP string. Note that it does not start ephemeral key use with this TAP string. - `ba ephemeralkey validate-tap `: This command validates a given TAP string by checking its length, character set, and the Verhoeff checksum. The change also includes documentation updates and a new test case to verify the functionality. --- src/cli/README.md | 30 +++++++++ src/cli/cli_ba.cpp | 62 ++++++++++++++++++- tests/toranj/cli/cli.py | 6 ++ .../test-028-border-agent-ephemeral-key.py | 13 ++++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/cli/README.md b/src/cli/README.md index 50ca489ed..f89df8439 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -596,6 +596,36 @@ Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`. Done ``` +### ba ephemeralkey generate-tap + +Generates a cryptographically secure random Thread Administration One-Time Passcode (TAP) string. + +Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`. + +The TAP is a string of 9 characters, generated as a sequence of eight cryptographically secure random numeric digits [`0`-`9`] followed by a single check digit determined using the Verhoeff algorithm. + +Note that this command simply generates and outputs a TAP. It does not start ephemeral key use with this TAP on the Border Agent. + +```bash +> ba ephemeralkey generate-tap +989710128 +Done +``` + +### ba ephemeralkey validate-tap \ + +Validates a given Thread Administration One-Time Passcode (TAP) string. + +Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`. + +Validates that the TAP string has the proper length, contains digit characters [`0`-`9`], and validates the Verhoeff checksum. + +```bash +> ba ephemeralkey validate-tap 989710128 +validated +Done +``` + ### ba counters Get the border agent counter values. diff --git a/src/cli/cli_ba.cpp b/src/cli/cli_ba.cpp index c9ac9eb6d..509f87169 100644 --- a/src/cli/cli_ba.cpp +++ b/src/cli/cli_ba.cpp @@ -389,7 +389,7 @@ template <> otError Ba::Process(Arg aArgs[]) { } /** - * @cli ba ephemeralkey start [timeout-in-msec] [port] + * @cli ba ephemeralkey start * @code * ba ephemeralkey start Z10X20g3J15w1000P60m16 5000 1234 * Done @@ -481,6 +481,66 @@ template <> otError Ba::Process(Arg aArgs[]) otBorderAgentEphemeralKeySetCallback(GetInstancePtr(), nullptr, nullptr); } } +#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE + /** + * @cli ba ephemeralkey generate-tap + * @code + * ba ephemeralkey generate-tap + * 989710128 + * Done + * @endcode + * @par + * Generates a cryptographically secure random Thread Administration One-Time Passcode (TAP) string. + * @par + * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`. + * @par + * The TAP is a string of 9 characters, generated as a sequence of eight cryptographically secure random + * numeric digits [`0`-`9`] followed by a single check digit determined using the Verhoeff algorithm. + * @par + * Note that this command simply generates and outputs a TAP. It does not start ephemeral key use with this TAP on + * the Border Agent. + * @sa otBorderAgentEphemeralKeyGenerateTap + */ + else if (aArgs[0] == "generate-tap") + { + otBorderAgentEphemeralKeyTap tap; + + VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + + SuccessOrExit(error = otBorderAgentEphemeralKeyGenerateTap(&tap)); + OutputLine("%s", tap.mTap); + } + /** + * @cli ba ephemeralkey validate-tap + * @code + * ba ephemeralkey validate-tap 989710128 + * validated + * Done + * @endcode + * @cparam ba ephemeralkey validate-tap @ca{tapstring} + * @par + * Validates a given Thread Administration One-Time Passcode (TAP) string. + * @par + * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`. + * @par + * Validates that the TAP string has the proper length, contains digit characters [`0`-`9`], and validates the + * Verhoeff checksum. + * @sa otBorderAgentEphemeralKeyValidateTap + */ + else if (aArgs[0] == "validate-tap") + { + otBorderAgentEphemeralKeyTap tap; + + ClearAllBytes(tap); + + VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + VerifyOrExit(aArgs[1].GetLength() <= OT_BORDER_AGENT_EPHEMERAL_KEY_TAP_STRING_LENGTH, + error = OT_ERROR_INVALID_ARGS); + memcpy(tap.mTap, aArgs[1].GetCString(), aArgs[1].GetLength()); + SuccessOrExit(error = otBorderAgentEphemeralKeyValidateTap(&tap)); + OutputLine("validated"); + } +#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE else { error = OT_ERROR_INVALID_ARGS; diff --git a/tests/toranj/cli/cli.py b/tests/toranj/cli/cli.py index 1887d954e..183575baa 100644 --- a/tests/toranj/cli/cli.py +++ b/tests/toranj/cli/cli.py @@ -545,6 +545,12 @@ class Node(object): def ba_ephemeral_key_get_port(self): return self._cli_single_output('ba ephemeralkey port') + def ba_ephemeral_key_generate_tap(self): + return self._cli_single_output('ba ephemeralkey generate-tap') + + def ba_ephemeral_key_validate_tap(self, tapstring): + return self._cli_single_output('ba ephemeralkey validate-tap', tapstring) + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # UDP diff --git a/tests/toranj/cli/test-028-border-agent-ephemeral-key.py b/tests/toranj/cli/test-028-border-agent-ephemeral-key.py index ba0608042..077c37e44 100755 --- a/tests/toranj/cli/test-028-border-agent-ephemeral-key.py +++ b/tests/toranj/cli/test-028-border-agent-ephemeral-key.py @@ -70,6 +70,19 @@ verify(int(leader.ba_ephemeral_key_get_port()) == 1234) leader.ba_ephemeral_key_stop() verify(leader.ba_ephemeral_key_get_state() == 'Stopped') +tap = leader.ba_ephemeral_key_generate_tap() +verify(leader.ba_ephemeral_key_validate_tap(tap) == 'validated') + +errored = False + +try: + leader.ba_ephemeral_key_validate_tap("123456789") +except cli.CliError as e: + verify(e.message == 'Failed') + errored = True + +verify(errored) + # ----------------------------------------------------------------------------------------------------------------------- # Test finished