mirror of
https://github.com/espressif/openthread.git
synced 2026-08-11 21:27:46 +00:00
[crypto] add platform AES-CCM* one-shot hook (#13190)
When OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE is set, AesCcm::Engine::ProcessOneShot() calls the new weak platform hook: otPlatCryptoAesCcmProcessOneShot() The hook operates in-place on a contiguous [payload|tag] buffer, mapping to a one-shot PSA AEAD call or a packet-oriented hardware engine. Default weak implementations: - PSA path: psa_aead_encrypt / psa_aead_decrypt (one-shot). - mbedTLS path: mbedtls_ccm_encrypt_and_tag / mbedtls_ccm_auth_decrypt, both support in-place (input == output).
This commit is contained in:
@@ -107,6 +107,25 @@ jobs:
|
||||
cmake --build --preset simulation
|
||||
ctest --preset simulation
|
||||
|
||||
cmake-presets-ccm-one-shot:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
with:
|
||||
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
sudo apt-get --no-install-recommends install -y build-essential ninja-build libreadline-dev libncurses-dev
|
||||
- name: Build and test with platform CCM one-shot enabled
|
||||
run: |
|
||||
cmake --preset simulation -DOT_CRYPTO_CCM_ONE_SHOT=ON
|
||||
cmake --build --preset simulation
|
||||
ctest --preset simulation
|
||||
|
||||
cmake-version:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
|
||||
@@ -307,6 +307,7 @@ endif()
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
set(OT_CRYPTO_LIB_VALUES "MBEDTLS" "PSA" "PLATFORM")
|
||||
ot_multi_option(OT_CRYPTO_LIB OT_CRYPTO_LIB_VALUES OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_ "set Crypto backend library")
|
||||
ot_option(OT_CRYPTO_CCM_ONE_SHOT OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE "platform one-shot AES-CCM* hook")
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
set(OT_THREAD_VERSION_VALUES "1.1" "1.2" "1.3" "1.3.1" "1.4")
|
||||
|
||||
@@ -749,6 +749,51 @@ otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword,
|
||||
uint16_t aKeyLen,
|
||||
uint8_t *aKey);
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoAesCcmConfig
|
||||
*
|
||||
* Holds the parameters for a one-shot AES-CCM* operation passed to `otPlatCryptoAesCcmProcessOneShot`.
|
||||
*/
|
||||
typedef struct otPlatCryptoAesCcmConfig
|
||||
{
|
||||
otCryptoKey mKey; ///< The encryption key.
|
||||
const uint8_t *mNonce; ///< Pointer to the nonce buffer (IEEE 802.15.4 CCM* format, 13 bytes).
|
||||
uint8_t mNonceLength; ///< Length of @p mNonce in bytes.
|
||||
uint8_t mTagLength; ///< Authentication tag length in bytes (even)
|
||||
uint32_t mHeaderLength; ///< Length of the additional authenticated data (header) in bytes.
|
||||
uint32_t mPlainTextLength; ///< Payload length in bytes (excluding tag).
|
||||
} otPlatCryptoAesCcmConfig;
|
||||
|
||||
/**
|
||||
* Performs in-place AES-CCM* authenticated encryption or decryption in a single call.
|
||||
*
|
||||
* For encryption (@p aEncrypt == true):
|
||||
* - Plaintext at @p aData is replaced with ciphertext in-place.
|
||||
* - The authentication tag is written to @p aData + @p aConfig->mPlainTextLength.
|
||||
*
|
||||
* For decryption (@p aEncrypt == false):
|
||||
* - Ciphertext at @p aData is replaced with plaintext in-place.
|
||||
* - The tag to verify must be at @p aData + @p aConfig->mPlainTextLength.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE`.
|
||||
*
|
||||
* Default weak mbedTLS and PSA implementations are provided.
|
||||
*
|
||||
* @param[in] aEncrypt True to encrypt and generate tag; false to decrypt and verify tag.
|
||||
* @param[in] aConfig CCM* parameters (key, nonce, lengths).
|
||||
* @param[in] aHeader Additional authenticated data (not encrypted). May be NULL if header length is 0.
|
||||
* @param[in,out] aData Payload buffer (plaintext on encrypt entry, ciphertext on decrypt entry).
|
||||
* The buffer must hold @p aConfig->mPlainTextLength + @p aConfig->mTagLength bytes.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Success.
|
||||
* @retval OT_ERROR_SECURITY Tag mismatch (decrypt only).
|
||||
* @retval OT_ERROR_FAILED Operation failed.
|
||||
*/
|
||||
otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -196,6 +196,10 @@ build_all_features()
|
||||
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_BLE_TCAT=ON
|
||||
|
||||
# Build with platform CCM one-shot enabled
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_CRYPTO_CCM_ONE_SHOT=ON
|
||||
}
|
||||
|
||||
build_nest_common()
|
||||
|
||||
@@ -68,6 +68,19 @@
|
||||
#define OPENTHREAD_CONFIG_CRYPTO_PLATFORM_ALLOCS_CONTEXT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
*
|
||||
* Define to 1 to enable platform one-shot AES-CCM* acceleration.
|
||||
*
|
||||
* When enabled, `AesCcm::Engine::ProcessOneShot()` calls
|
||||
* `otPlatCryptoAesCcmProcessOneShot()` instead of the built-in
|
||||
* software CCM engine.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PLATFORM
|
||||
|
||||
/**
|
||||
|
||||
@@ -212,13 +212,11 @@ Error AesCcm::Engine::ProcessOneShot(Operation aOperation,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
// This method performs one-shot (single-part) AES-CCM processing.
|
||||
// Currently, it is implemented by calling the multi-part
|
||||
// streaming APIs sequentially. In the future, this can be
|
||||
// optimized to directly call platform-specific one-shot hardware
|
||||
// acceleration APIs if supported by the platform.
|
||||
Error error = kErrorNone;
|
||||
|
||||
Error error = kErrorNone;
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
error = otPlatCryptoAesCcmProcessOneShot(aOperation == kEncrypt, &aConfig, aHeader, aData);
|
||||
#else
|
||||
uint8_t tag[kMaxTagLength];
|
||||
|
||||
Start(aConfig);
|
||||
@@ -236,6 +234,7 @@ Error AesCcm::Engine::ProcessOneShot(Operation aOperation,
|
||||
error = (memcmp(aData + aConfig.mPlainTextLength, tag, aConfig.mTagLength) == 0) ? kErrorNone : kErrorSecurity;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -249,7 +248,7 @@ void AesCcm::Engine::Start(const Config &aConfig)
|
||||
|
||||
OT_ASSERT(aConfig.IsValid());
|
||||
|
||||
mEcb.SetKey(aConfig.mKey);
|
||||
mEcb.SetKey(aConfig.GetKey());
|
||||
|
||||
mNonceLength = aConfig.mNonceLength;
|
||||
mTagLength = aConfig.mTagLength;
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength Length of the key in bytes.
|
||||
*/
|
||||
void SetKey(const uint8_t *aKey, uint16_t aKeyLength) { mConfig.mKey.Set(aKey, aKeyLength); }
|
||||
void SetKey(const uint8_t *aKey, uint16_t aKeyLength) { mConfig.GetKey().Set(aKey, aKeyLength); }
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
*
|
||||
* @param[in] aMacKey Key Material for AES operation.
|
||||
*/
|
||||
void SetKey(const Mac::KeyMaterial &aMacKey) { aMacKey.ConvertToCryptoKey(mConfig.mKey); }
|
||||
void SetKey(const Mac::KeyMaterial &aMacKey) { aMacKey.ConvertToCryptoKey(mConfig.GetKey()); }
|
||||
|
||||
/**
|
||||
* Sets the Nonce.
|
||||
@@ -245,16 +245,11 @@ public:
|
||||
void *aTag);
|
||||
|
||||
private:
|
||||
struct Config : public Clearable<Config>
|
||||
struct Config : public otPlatCryptoAesCcmConfig, public Clearable<Config>
|
||||
{
|
||||
bool IsValid(void) const;
|
||||
|
||||
Key mKey;
|
||||
uint8_t mNonceLength;
|
||||
uint8_t mTagLength;
|
||||
uint32_t mHeaderLength;
|
||||
uint32_t mPlainTextLength;
|
||||
const uint8_t *mNonce;
|
||||
bool IsValid(void) const;
|
||||
Key &GetKey(void) { return AsCoreType(&mKey); }
|
||||
const Key &GetKey(void) const { return AsCoreType(&mKey); }
|
||||
};
|
||||
|
||||
class Engine
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/ccm.h>
|
||||
#include <mbedtls/cmac.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
@@ -152,6 +153,59 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_ccm_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_ccm_init(&ctx);
|
||||
|
||||
VerifyOrExit(aConfig != nullptr && aConfig->mNonce != nullptr && aData != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
{
|
||||
const LiteralKey key(*static_cast<const Key *>(&aConfig->mKey));
|
||||
|
||||
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key.GetBytes(), key.GetLength() * kBitsPerByte);
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
|
||||
if (aEncrypt)
|
||||
{
|
||||
ret = mbedtls_ccm_encrypt_and_tag(&ctx, aConfig->mPlainTextLength, aConfig->mNonce, aConfig->mNonceLength,
|
||||
aHeader, aConfig->mHeaderLength, aData, aData,
|
||||
aData + aConfig->mPlainTextLength, aConfig->mTagLength);
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MBEDTLS_ERR_CCM_AUTH_FAILED is the expected return on tag mismatch; map to kErrorSecurity.
|
||||
ret = mbedtls_ccm_auth_decrypt(&ctx, aConfig->mPlainTextLength, aConfig->mNonce, aConfig->mNonceLength,
|
||||
aHeader, aConfig->mHeaderLength, aData, aData,
|
||||
aData + aConfig->mPlainTextLength, aConfig->mTagLength);
|
||||
|
||||
if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED)
|
||||
{
|
||||
error = kErrorSecurity;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_ccm_free(&ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
// HMAC implementations
|
||||
|
||||
@@ -389,6 +389,49 @@ OT_TOOL_WEAK otError otPlatCryptoAesFree(otCryptoContext *aContext)
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
psa_status_t status;
|
||||
psa_algorithm_t algorithm;
|
||||
size_t outputLen = 0;
|
||||
|
||||
VerifyOrExit(aConfig != nullptr && aConfig->mNonce != nullptr && aData != nullptr, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aConfig->mKey.mKey == nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, aConfig->mTagLength);
|
||||
|
||||
if (aEncrypt)
|
||||
{
|
||||
// Output layout: ciphertext || tag, written in-place over the plaintext buffer.
|
||||
status = psa_aead_encrypt(aConfig->mKey.mKeyRef, algorithm, aConfig->mNonce, aConfig->mNonceLength, aHeader,
|
||||
aConfig->mHeaderLength, aData, aConfig->mPlainTextLength, aData,
|
||||
aConfig->mPlainTextLength + aConfig->mTagLength, &outputLen);
|
||||
SuccessOrExit(error = PsaToOtError(status));
|
||||
VerifyOrExit(outputLen == aConfig->mPlainTextLength + aConfig->mTagLength, error = kErrorFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Input layout: ciphertext || tag contiguous at aData. Output plaintext written in-place.
|
||||
status = psa_aead_decrypt(aConfig->mKey.mKeyRef, algorithm, aConfig->mNonce, aConfig->mNonceLength, aHeader,
|
||||
aConfig->mHeaderLength, aData, aConfig->mPlainTextLength + aConfig->mTagLength, aData,
|
||||
aConfig->mPlainTextLength, &outputLen);
|
||||
error = (status == PSA_ERROR_INVALID_SIGNATURE) ? kErrorSecurity : PsaToOtError(status);
|
||||
SuccessOrExit(error);
|
||||
VerifyOrExit(outputLen == aConfig->mPlainTextLength, error = kErrorFailed);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext)
|
||||
|
||||
@@ -339,6 +339,115 @@ void TestAesCcmMessageProcessing(void)
|
||||
printf("\nTestAesCcmMessageProcessing PASSED\n\n");
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
/**
|
||||
* Verifies `otPlatCryptoAesCcmProcessOneShot` directly and via `AesCcm::Process`,
|
||||
* using IEEE 802.15.4-2006 Annex C Section C.2.3
|
||||
* (MAC command frame: 29-byte header, 1-byte payload, 8-byte MIC).
|
||||
*/
|
||||
void TestPlatformCcmSinglePart(void)
|
||||
{
|
||||
static const uint8_t kKey[] = {
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
};
|
||||
|
||||
static const uint8_t kNonce[] = {
|
||||
0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
|
||||
};
|
||||
|
||||
static constexpr uint32_t kHeaderLength = 29;
|
||||
static constexpr uint32_t kPayloadLength = 1;
|
||||
static constexpr uint8_t kTagLength = 8;
|
||||
static constexpr uint32_t kFrameLength = kHeaderLength + kPayloadLength + kTagLength;
|
||||
|
||||
static const uint8_t kPlainFrame[kHeaderLength + kPayloadLength] = {
|
||||
0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0xFF, 0xFF,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00, 0x00, 0x00, 0x01, 0xCE,
|
||||
};
|
||||
|
||||
static const uint8_t kEncryptedFrame[kFrameLength] = {
|
||||
0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00,
|
||||
0x00, 0x00, 0x01, 0xD8, 0x4F, 0xDE, 0x52, 0x90, 0x61, 0xF9, 0xC6, 0xF1,
|
||||
};
|
||||
|
||||
otInstance *instance = testInitInstance();
|
||||
uint8_t frame[kFrameLength];
|
||||
otPlatCryptoAesCcmConfig config;
|
||||
|
||||
printf("TestPlatformCcmSinglePart\n");
|
||||
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
config.mKey.mKey = kKey;
|
||||
config.mKey.mKeyLength = sizeof(kKey);
|
||||
config.mKey.mKeyRef = 0;
|
||||
config.mNonce = kNonce;
|
||||
config.mNonceLength = sizeof(kNonce);
|
||||
config.mTagLength = kTagLength;
|
||||
config.mHeaderLength = kHeaderLength;
|
||||
config.mPlainTextLength = kPayloadLength;
|
||||
|
||||
// Direct encrypt/decrypt round-trip through the platform hook.
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
DumpBuffer("encrypted", frame, sizeof(frame));
|
||||
VerifyOrQuit(memcmp(frame, kEncryptedFrame, kFrameLength) == 0);
|
||||
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength));
|
||||
DumpBuffer("decrypted", frame, kHeaderLength + kPayloadLength);
|
||||
VerifyOrQuit(memcmp(frame, kPlainFrame, kHeaderLength + kPayloadLength) == 0);
|
||||
|
||||
// Tag corruption must be rejected.
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
frame[kHeaderLength + kPayloadLength] ^= 0xFF;
|
||||
VerifyOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength) == kErrorSecurity);
|
||||
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
frame[kFrameLength - 1] ^= 0x01;
|
||||
VerifyOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength) == kErrorSecurity);
|
||||
|
||||
// AesCcm::Process must produce the same result as the direct platform call.
|
||||
{
|
||||
uint8_t directResult[kFrameLength];
|
||||
uint8_t aesCcmResult[kFrameLength];
|
||||
Crypto::AesCcm aesCcm;
|
||||
|
||||
memcpy(directResult, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(directResult + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, directResult, directResult + kHeaderLength));
|
||||
|
||||
memcpy(aesCcmResult, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(aesCcmResult + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
aesCcm.SetKey(kKey, sizeof(kKey));
|
||||
aesCcm.SetNonce(kNonce, sizeof(kNonce));
|
||||
aesCcm.SetAuthData(aesCcmResult, kHeaderLength);
|
||||
aesCcm.SetTagLength(kTagLength);
|
||||
SuccessOrQuit(aesCcm.Process(Crypto::AesCcm::kEncrypt, aesCcmResult + kHeaderLength, kPayloadLength));
|
||||
VerifyOrQuit(memcmp(directResult, aesCcmResult, kFrameLength) == 0);
|
||||
VerifyOrQuit(memcmp(aesCcmResult, kEncryptedFrame, kFrameLength) == 0);
|
||||
|
||||
aesCcm.SetKey(kKey, sizeof(kKey));
|
||||
aesCcm.SetNonce(kNonce, sizeof(kNonce));
|
||||
aesCcm.SetAuthData(aesCcmResult, kHeaderLength);
|
||||
aesCcm.SetTagLength(kTagLength);
|
||||
SuccessOrQuit(aesCcm.Process(Crypto::AesCcm::kDecrypt, aesCcmResult + kHeaderLength, kPayloadLength));
|
||||
VerifyOrQuit(memcmp(aesCcmResult, kPlainFrame, kHeaderLength + kPayloadLength) == 0);
|
||||
}
|
||||
|
||||
testFreeInstance(instance);
|
||||
|
||||
printf("\nTestPlatformCcmSinglePart PASSED\n\n");
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -346,6 +455,9 @@ int main(void)
|
||||
ot::TestMacBeaconFrame();
|
||||
ot::TestMacCommandFrame();
|
||||
ot::TestAesCcmMessageProcessing();
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
ot::TestPlatformCcmSinglePart();
|
||||
#endif
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user