mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 18:07:47 +00:00
[utils] implement Verhoeff checksum calculation and validation (#9966)
This commit adds `Utils::VerhoeffChecksum` class along with public OT APIs and related CLI commands for Verhoeff checksum calculation and validation. Unit test `test_checksum` is updated to test the new module.
This commit is contained in:
@@ -154,6 +154,7 @@
|
||||
* @}
|
||||
*
|
||||
* @defgroup api-sntp SNTP
|
||||
* @defgroup api-verhoeff-checksum Verhoeff Checksum
|
||||
*
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -249,6 +249,7 @@ ot_option(OT_TX_BEACON_PAYLOAD OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENA
|
||||
ot_option(OT_TX_QUEUE_STATS OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE "tx queue statistics")
|
||||
ot_option(OT_UDP_FORWARD OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE "UDP forward")
|
||||
ot_option(OT_UPTIME OPENTHREAD_CONFIG_UPTIME_ENABLE "uptime")
|
||||
ot_option(OT_VERHOEFF_CHECKSUM OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE "verhoeff checksum")
|
||||
|
||||
option(OT_DOC "build OpenThread documentation")
|
||||
message(STATUS "- - - - - - - - - - - - - - - - ")
|
||||
|
||||
@@ -125,6 +125,7 @@ source_set("openthread") {
|
||||
"thread_ftd.h",
|
||||
"trel.h",
|
||||
"udp.h",
|
||||
"verhoeff_checksum.h",
|
||||
]
|
||||
|
||||
public_deps = [ ":openthread_config" ]
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (402)
|
||||
#define OPENTHREAD_API_VERSION (403)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines APIs for Verhoeff checksum calculation and validation.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_VERHOEFF_CHECKSUM_H_
|
||||
#define OPENTHREAD_VERHOEFF_CHECKSUM_H_
|
||||
|
||||
#include <openthread/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-verhoeff-checksum
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for Verhoeff checksum calculation and validation.
|
||||
*
|
||||
* The functions in this module are available when `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE` is enabled.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies the maximum length of decimal string input in `otVerhoeffChecksum` functions.
|
||||
*
|
||||
*/
|
||||
#define OT_VERHOEFF_CHECKSUM_MAX_STRING_LENGTH 128
|
||||
|
||||
/**
|
||||
* Calculates the Verhoeff checksum for a given decimal string.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
|
||||
*
|
||||
* @param[in] aDecimalString The string containing decimal digits.
|
||||
* @param[out] aChecksum Pointer to a `char` to return the calculated checksum.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully calculated the checksum, @p aChecksum is updated.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aDecimalString is not valid, i.e. it either contains chars other than
|
||||
* ['0'-'9'], or is longer than `OT_VERHOEFF_CHECKSUM_MAX_STRING_LENGTH`.
|
||||
*
|
||||
*/
|
||||
otError otVerhoeffChecksumCalculate(const char *aDecimalString, char *aChecksum);
|
||||
|
||||
/**
|
||||
* Validates the Verhoeff checksum for a given decimal string.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
|
||||
*
|
||||
* @param[in] aDecimalString The string containing decimal digits (last char is treated as checksum).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully validated the checksum in @p aDecimalString.
|
||||
* @retval OT_ERROR_FAILED Checksum validation failed.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aDecimalString is not valid, i.e. it either contains chars other than
|
||||
* ['0'-'9'], or is longer than `OT_VERHOEFF_CHECKSUM_MAX_STRING_LENGTH`.
|
||||
*
|
||||
*/
|
||||
otError otVerhoeffChecksumValidate(const char *aDecimalString);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_VERHOEFF_CHECKSUM_H_
|
||||
@@ -130,6 +130,7 @@ Done
|
||||
- [unsecureport](#unsecureport-add-port)
|
||||
- [uptime](#uptime)
|
||||
- [vendor](#vendor-name)
|
||||
- [verhoeff](#verhoeff-calculate)
|
||||
- [version](#version)
|
||||
|
||||
## OpenThread Command Details
|
||||
@@ -3964,6 +3965,35 @@ Set the vendor SW version (requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_
|
||||
Done
|
||||
```
|
||||
|
||||
### verhoeff calculate
|
||||
|
||||
Calculates the Verhoeff checksum for a given decimal string.
|
||||
|
||||
Requires `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
|
||||
|
||||
The input string MUST consist of characters in `['0'-'9']`.
|
||||
|
||||
```bash
|
||||
> verhoeff calculate 30731842
|
||||
1
|
||||
Done
|
||||
```
|
||||
|
||||
### verhoeff validate
|
||||
|
||||
Validates the Verhoeff checksum for a given decimal string.
|
||||
|
||||
Requires `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
|
||||
|
||||
The input string MUST consist of characters in `['0'-'9']`. The last digit is treated as checksum.
|
||||
|
||||
```bash
|
||||
> verhoeff validate 307318421
|
||||
Done
|
||||
> verhoeff validate 307318425
|
||||
Error 1: Failed
|
||||
```
|
||||
|
||||
### version
|
||||
|
||||
Print the build version information.
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <openthread/logging.h>
|
||||
#include <openthread/ncp.h>
|
||||
#include <openthread/thread.h>
|
||||
#include <openthread/verhoeff_checksum.h>
|
||||
#include "common/num_utils.hpp"
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
#include <openthread/network_time.h>
|
||||
@@ -8355,6 +8356,57 @@ void Interpreter::HandleIp6Receive(otMessage *aMessage, void *aContext)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
template <> otError Interpreter::Process<Cmd("verhoeff")>(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
|
||||
/**
|
||||
* @cli verhoeff calculate
|
||||
* @code
|
||||
* verhoeff calculate 30731842
|
||||
* 1
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam verhoeff calculate @ca{decimalstring}
|
||||
* @par api_copy
|
||||
* #otVerhoeffChecksumCalculate
|
||||
*/
|
||||
if (aArgs[0] == "calculate")
|
||||
{
|
||||
char checksum;
|
||||
|
||||
VerifyOrExit(!aArgs[1].IsEmpty() && aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = otVerhoeffChecksumCalculate(aArgs[1].GetCString(), &checksum));
|
||||
OutputLine("%c", checksum);
|
||||
}
|
||||
/**
|
||||
* @cli verhoeff validate
|
||||
* @code
|
||||
* verhoeff validate 307318421
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam verhoeff validate @ca{decimalstring}
|
||||
* @par api_copy
|
||||
* #otVerhoeffChecksumValidate
|
||||
*/
|
||||
else if (aArgs[0] == "validate")
|
||||
{
|
||||
VerifyOrExit(!aArgs[1].IsEmpty() && aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
error = otVerhoeffChecksumValidate(aArgs[1].GetCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
void Interpreter::Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
|
||||
@@ -8653,6 +8705,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
|
||||
CmdEntry("uptime"),
|
||||
#endif
|
||||
CmdEntry("vendor"),
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
CmdEntry("verhoeff"),
|
||||
#endif
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
CmdEntry("version"),
|
||||
};
|
||||
|
||||
@@ -360,6 +360,7 @@ openthread_core_files = [
|
||||
"api/thread_ftd_api.cpp",
|
||||
"api/trel_api.cpp",
|
||||
"api/udp_api.cpp",
|
||||
"api/verhoeff_checksum_api.cpp",
|
||||
"backbone_router/backbone_tmf.cpp",
|
||||
"backbone_router/backbone_tmf.hpp",
|
||||
"backbone_router/bbr_leader.cpp",
|
||||
@@ -736,6 +737,8 @@ openthread_core_files = [
|
||||
"utils/slaac_address.hpp",
|
||||
"utils/srp_client_buffers.cpp",
|
||||
"utils/srp_client_buffers.hpp",
|
||||
"utils/verhoeff_checksum.cpp",
|
||||
"utils/verhoeff_checksum.hpp",
|
||||
]
|
||||
|
||||
openthread_radio_sources = [
|
||||
|
||||
@@ -86,6 +86,7 @@ set(COMMON_SOURCES
|
||||
api/thread_ftd_api.cpp
|
||||
api/trel_api.cpp
|
||||
api/udp_api.cpp
|
||||
api/verhoeff_checksum_api.cpp
|
||||
backbone_router/backbone_tmf.cpp
|
||||
backbone_router/bbr_leader.cpp
|
||||
backbone_router/bbr_local.cpp
|
||||
@@ -257,6 +258,7 @@ set(COMMON_SOURCES
|
||||
utils/power_calibration.cpp
|
||||
utils/slaac_address.cpp
|
||||
utils/srp_client_buffers.cpp
|
||||
utils/verhoeff_checksum.cpp
|
||||
)
|
||||
|
||||
set(RADIO_COMMON_SOURCES
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the Verhoeff Checksum public APIs.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
#include <openthread/verhoeff_checksum.h>
|
||||
|
||||
#include "common/debug.hpp"
|
||||
#include "utils/verhoeff_checksum.hpp"
|
||||
|
||||
using namespace ot::Utils;
|
||||
|
||||
otError otVerhoeffChecksumCalculate(const char *aDecimalString, char *aChecksum)
|
||||
{
|
||||
AssertPointerIsNotNull(aDecimalString);
|
||||
AssertPointerIsNotNull(aChecksum);
|
||||
|
||||
return VerhoeffChecksum::Calculate(aDecimalString, *aChecksum);
|
||||
}
|
||||
|
||||
otError otVerhoeffChecksumValidate(const char *aDecimalString)
|
||||
{
|
||||
AssertPointerIsNotNull(aDecimalString);
|
||||
|
||||
return VerhoeffChecksum::Validate(aDecimalString);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
@@ -141,6 +141,16 @@
|
||||
#define OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Verhoeff checksum utility module.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
#define OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
|
||||
*
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements Verhoeff checksum calculation and validation.
|
||||
*/
|
||||
|
||||
#include "verhoeff_checksum.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/string.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
|
||||
uint8_t VerhoeffChecksum::Lookup(uint8_t aIndex, const uint8_t aCompressedArray[])
|
||||
{
|
||||
// The values in the array are [0-9]. To save space, two
|
||||
// entries are saved as a single byte in @p aCompressedArray,
|
||||
// such that higher 4-bit corresponds to one entry, and the
|
||||
// lower 4-bit to the next entry.
|
||||
|
||||
uint8_t result = aCompressedArray[aIndex / 2];
|
||||
|
||||
if ((aIndex & 1) == 0)
|
||||
{
|
||||
result >>= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
result &= 0x0f;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t VerhoeffChecksum::Multiply(uint8_t aFirst, uint8_t aSecond)
|
||||
{
|
||||
static uint8_t kMultiplication[][5] = {{0x01, 0x23, 0x45, 0x67, 0x89}, {0x12, 0x34, 0x06, 0x78, 0x95},
|
||||
{0x23, 0x40, 0x17, 0x89, 0x56}, {0x34, 0x01, 0x28, 0x95, 0x67},
|
||||
{0x40, 0x12, 0x39, 0x56, 0x78}, {0x59, 0x87, 0x60, 0x43, 0x21},
|
||||
{0x65, 0x98, 0x71, 0x04, 0x32}, {0x76, 0x59, 0x82, 0x10, 0x43},
|
||||
{0x87, 0x65, 0x93, 0x21, 0x04}, {0x98, 0x76, 0x54, 0x32, 0x10}};
|
||||
|
||||
return Lookup(aSecond, kMultiplication[aFirst]);
|
||||
}
|
||||
|
||||
uint8_t VerhoeffChecksum::Permute(uint8_t aPosition, uint8_t aValue)
|
||||
{
|
||||
static uint8_t kPermutation[][5] = {{0x01, 0x23, 0x45, 0x67, 0x89}, {0x15, 0x76, 0x28, 0x30, 0x94},
|
||||
{0x58, 0x03, 0x79, 0x61, 0x42}, {0x89, 0x16, 0x04, 0x35, 0x27},
|
||||
{0x94, 0x53, 0x12, 0x68, 0x70}, {0x42, 0x86, 0x57, 0x39, 0x01},
|
||||
{0x27, 0x93, 0x80, 0x64, 0x15}, {0x70, 0x46, 0x91, 0x32, 0x58}};
|
||||
|
||||
return Lookup(aValue, kPermutation[aPosition]);
|
||||
}
|
||||
|
||||
uint8_t VerhoeffChecksum::InverseOf(uint8_t aValue)
|
||||
{
|
||||
static uint8_t kInverse[] = {0x04, 0x32, 0x15, 0x67, 0x89};
|
||||
|
||||
return Lookup(aValue, kInverse);
|
||||
}
|
||||
|
||||
Error VerhoeffChecksum::Calculate(const char *aDecimalString, char &aChecksum)
|
||||
{
|
||||
Error error;
|
||||
uint8_t code;
|
||||
|
||||
SuccessOrExit(error = ComputeCode(aDecimalString, code, /* aValidate */ false));
|
||||
aChecksum = static_cast<char>('0' + InverseOf(code));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error VerhoeffChecksum::Validate(const char *aDecimalString)
|
||||
{
|
||||
Error error;
|
||||
uint8_t code;
|
||||
|
||||
SuccessOrExit(error = ComputeCode(aDecimalString, code, /* aValidate */ true));
|
||||
VerifyOrExit(code == 0, error = kErrorFailed);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error VerhoeffChecksum::ComputeCode(const char *aDecimalString, uint8_t &aCode, bool aValidate)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t code = 0;
|
||||
uint16_t index = 0;
|
||||
uint16_t length = StringLength(aDecimalString, kMaxStringLength + 1);
|
||||
|
||||
VerifyOrExit(length <= kMaxStringLength, error = kErrorInvalidArgs);
|
||||
|
||||
if (!aValidate)
|
||||
{
|
||||
length++;
|
||||
index++;
|
||||
}
|
||||
|
||||
for (; index < length; ++index)
|
||||
{
|
||||
char digit = aDecimalString[length - index - 1];
|
||||
|
||||
VerifyOrExit(digit >= '0' && digit <= '9', error = kErrorInvalidArgs);
|
||||
code = Multiply(code, Permute(index % 8, static_cast<uint8_t>(digit - '0')));
|
||||
}
|
||||
|
||||
aCode = code;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for Verhoeff checksum calculation and validation.
|
||||
*/
|
||||
|
||||
#ifndef VERHOEFF_CHECKSUM_HPP_
|
||||
#define VERHOEFF_CHECKSUM_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
#include <openthread/verhoeff_checksum.h>
|
||||
|
||||
#include "common/error.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
|
||||
class VerhoeffChecksum
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Specifies the maximum length of decimal string input.
|
||||
*
|
||||
*/
|
||||
static constexpr uint16_t kMaxStringLength = OT_VERHOEFF_CHECKSUM_MAX_STRING_LENGTH;
|
||||
|
||||
/**
|
||||
* Calculates the Verhoeff checksum for a given decimal string.
|
||||
*
|
||||
*
|
||||
* @param[in] a DecimalString The string containing decimal digits.
|
||||
* @param[out] aChecksum Reference to a `char` to return the calculated checksum.
|
||||
*
|
||||
* @retval kErrorNone Successfully calculated the checksum, @p aChecksum is updated.
|
||||
* @retval kErrorInvalidArgs The @p aDecimalString is not valid, i.e. it either contains chars other than
|
||||
* ['0'-'9'], or is longer than `kMaxStringLength`.
|
||||
*
|
||||
*/
|
||||
static Error Calculate(const char *aDecimalString, char &aChecksum);
|
||||
|
||||
/**
|
||||
* Validates the Verhoeff checksum for a given decimal string.
|
||||
*
|
||||
* @param[in] aDecimalString The string containing decimal digits (last char is treated as checksum).
|
||||
*
|
||||
* @retval kErrorNone Successfully validated the checksum in @p aDecimalString.
|
||||
* @retval kErrorFailed Checksum is not valid.
|
||||
* @retval kErrorInvalidArgs The @p aDecimalString is not valid, i.e. it either contains chars other than
|
||||
* ['0'-'9'], or is longer than `kMaxStringLength`.
|
||||
*
|
||||
*/
|
||||
static Error Validate(const char *aDecimalString);
|
||||
|
||||
VerhoeffChecksum(void) = delete;
|
||||
|
||||
private:
|
||||
static Error ComputeCode(const char *aDecimalString, uint8_t &aCode, bool aValidate);
|
||||
static uint8_t Lookup(uint8_t aIndex, const uint8_t aCompressedArray[]);
|
||||
static uint8_t Multiply(uint8_t aFirst, uint8_t aSecond);
|
||||
static uint8_t Permute(uint8_t aPosition, uint8_t aValue);
|
||||
static uint8_t InverseOf(uint8_t aValue);
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
#endif // VERHOEFF_CHECKSUM_HPP_
|
||||
@@ -30,11 +30,13 @@
|
||||
#include "common/message.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
#include "net/checksum.hpp"
|
||||
#include "net/icmp6.hpp"
|
||||
#include "net/ip4_types.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "utils/verhoeff_checksum.hpp"
|
||||
|
||||
#include "test_platform.h"
|
||||
#include "test_util.hpp"
|
||||
@@ -467,6 +469,62 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
void TestVerhoeffChecksum(void)
|
||||
{
|
||||
static constexpr uint16_t kMaxStringSize = 50;
|
||||
|
||||
const char *kExamples[] = {"307318421", "487300178", "123455672", "0", "15",
|
||||
"999999994", "000000001", "100000000", "2363"};
|
||||
|
||||
const char *kInvalidFormats[] = {
|
||||
"307 318421",
|
||||
"307318421 ",
|
||||
" 307318421",
|
||||
"ABCDE",
|
||||
};
|
||||
|
||||
char string[kMaxStringSize];
|
||||
char checksum;
|
||||
char expectedChecksum;
|
||||
|
||||
printf("\nVerhoeffChecksum\n");
|
||||
|
||||
for (const char *example : kExamples)
|
||||
{
|
||||
uint16_t length = StringLength(example, kMaxStringSize - 1);
|
||||
|
||||
memcpy(string, example, length + 1);
|
||||
|
||||
printf("- \"%s\"\n", string);
|
||||
|
||||
SuccessOrQuit(Utils::VerhoeffChecksum::Validate(string));
|
||||
|
||||
expectedChecksum = string[length - 1];
|
||||
|
||||
string[length - 1] = (expectedChecksum == '0') ? '9' : (expectedChecksum - 1);
|
||||
VerifyOrQuit(Utils::VerhoeffChecksum::Validate(string) == kErrorFailed);
|
||||
|
||||
string[length - 1] = '\0';
|
||||
SuccessOrQuit(Utils::VerhoeffChecksum::Calculate(string, checksum));
|
||||
VerifyOrQuit(checksum == expectedChecksum);
|
||||
|
||||
string[length - 1] = expectedChecksum == '0' ? '9' : (expectedChecksum - 1);
|
||||
}
|
||||
|
||||
printf("\nInvalid format:\n");
|
||||
|
||||
for (const char *example : kInvalidFormats)
|
||||
{
|
||||
printf("- \"%s\"\n", example);
|
||||
VerifyOrQuit(Utils::VerhoeffChecksum::Validate(example) == kErrorInvalidArgs);
|
||||
VerifyOrQuit(Utils::VerhoeffChecksum::Calculate(example, checksum) == kErrorInvalidArgs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -477,6 +535,10 @@ int main(void)
|
||||
ot::TestTcp4MessageChecksum();
|
||||
ot::TestUdp4MessageChecksum();
|
||||
ot::TestIcmp4MessageChecksum();
|
||||
#if OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
|
||||
ot::TestVerhoeffChecksum();
|
||||
#endif
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user