Compare commits

...

16 Commits

Author SHA1 Message Date
Ashish Sharma 7d4fa4223f switch to PSA crypto lib by default 2025-12-05 10:14:06 +08:00
zwx 291b7036b8 compatible with ESP platform 2025-12-04 19:30:16 +08:00
Łukasz Duda 2c0c3e84a3 [crypto] PSA API: support HKDF extraction with HMAC-SHA256 keys
The PSA platform now transparently handles HKDF operations when using
HMAC-SHA256 keys by exporting and re-importing them as volatile
HKDF-SHA256 keys. The export/import logic has been moved into the
platform layer. This change is required to support TREL and the PSA API
key usage restrictions.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:32 +01:00
Łukasz Duda b614af3a91 [crypto] PSA API: introduce platform API for crypto dynamic memory mgmt
This commit adds two new functions, `otPlatCryptoCAlloc` and
`otPlatCryptoFree`, which provide dynamic memory management for the
crypto subsystem. They are only enabled when
`OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE` is set.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:32 +01:00
Łukasz Duda 6b167f1cd3 [crypto] PSA API: remove otPlatCryptoInit API
This commit removes otPlatCryptoInit API and moves responsibility of
initializing the Crypto subsystem to the platform.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:32 +01:00
Łukasz Duda 3ed9fa8525 [crypto] PSA API: add basic unit, cert and expect testing in CI
This commit introduces initial CI testing of PSA Crypto variant.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:32 +01:00
Łukasz Duda aa3c2464d8 [crypto] PSA API: enable native ITS in build system
This commit enables PSA native ITS implementation in the build system
for simulation and test platforms.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:32 +01:00
Łukasz Duda bd36cf1ac5 [crypto] PSA API: set platform key references for PSA automatically
This commit configures the
OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE based on the chosen
crypto library.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:53:31 +01:00
Łukasz Duda 31cf8eac65 [crypto] PSA API: introduce example native ITS implementations
This commit implements two example native ITS for linux-based platform.
2025-11-04 21:53:31 +01:00
Łukasz Duda 24e0504b7d [crypto] PSA API: introduce support for simulation and test platform
This commit adds support for Crypto PSA library for simulation and test
platform and introduces initial CI check.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda cec709fcca [crypto] PSA API: align ECDSA unit tests
This commit allows running ECDSA unit tests using PSA Crypto API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda a71682d765 [crypto] PSA API: align HKDF-SHA256 unit tests
This commit allows running HKDF-SHA256 unit tests using PSA Crypto API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda 6f666901e3 [crypto] PSA API: align HMAC-SHA256 unit tests
This commit allows running HMAC-SHA256 unit tests using PSA Crypto API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda 2972fe884f [crypto] PSA API: align AES unit tests
This commit allows running AES unit tests using PSA Crypto API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda baed8372c3 [crypto] PSA API: introduce default OpenThread crypto platform port
This commit adds a default implementation of the OpenThread crypto
platform API for the PSA Crypto API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-04 21:48:29 +01:00
Łukasz Duda 3a6573fee8 [crypto] PSA API: extend Crypto platform API to support HKDF-SHA256
This commit adds PSA API support for HKDF-SHA256 for TREL in OpenThread
platform API.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2025-11-01 23:45:14 +01:00
47 changed files with 2501 additions and 421 deletions
+98
View File
@@ -419,6 +419,102 @@ jobs:
path: tmp/coverage.info
retention-days: 1
cli-psa:
runs-on: ubuntu-24.04
env:
COVERAGE: 1
THREAD_VERSION: 1.4
VIRTUAL_TIME: 1
INTER_OP_BBR: 1
steps:
- name: Harden Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: '3.12'
cache: pip
- name: Bootstrap
run: |
sudo apt-get update
sudo apt-get --no-install-recommends install -y g++-multilib lcov ninja-build
python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
- name: Build
run: |
OT_OPTIONS="-DOT_PLATFORM_KEY_REF=ON -DOT_CRYPTO_LIB=PSA" OT_NODE_TYPE=cli ./script/test build
- name: Run
run: |
./script/test unit
OT_NODE_TYPE=cli ./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
if: ${{ failure() }}
with:
name: cli-psa
path: ot_testing
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: cov-cli-psa
path: tmp/coverage.info
retention-days: 1
cli-psa-expects:
runs-on: ubuntu-24.04
env:
COVERAGE: 1
THREAD_VERSION: 1.4
VIRTUAL_TIME: 0
steps:
- name: Harden Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: '3.12'
cache: pip
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov
sudo bash script/install_socat
pip install bleak 'cryptography==43.0.0'
- name: Run CLI Mode
run: |
ulimit -c unlimited
./script/test prepare_coredump_upload
OT_OPTIONS="-DOT_PLATFORM_KEY_REF=ON -DOT_CRYPTO_LIB=PSA -DOT_TIME_SYNC=ON -DOT_BLE_TCAT=ON" OT_NODE_TYPE=cli ./script/test build expect
- name: Check Crash
if: ${{ failure() }}
run: |
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-cli-psa-expects-1-4
path: |
./ot-core-dump/*
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: cov-cli-psa-expects
path: tmp/coverage.info
retention-days: 1
upload-coverage:
needs:
- thread-1-4
@@ -426,6 +522,8 @@ jobs:
- packet-verification-1-1-on-1-4
- expects
- thread-1-4-posix
- cli-psa
- cli-psa-expects
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
-3
View File
@@ -180,9 +180,6 @@ jobs:
./tests/toranj/build.sh --log-level CRIT all
git clean -dfx
./tests/toranj/build.sh --log-level NONE all
#- - - - - - - - - - - - - - - - - - - - - - - - - - -
git clean -dfx
./tests/toranj/build.sh --enable-plat-key-ref all
toranj-macos:
name: toranj-macos
+5 -1
View File
@@ -300,6 +300,10 @@ if(ot_index EQUAL -1)
message(FATAL_ERROR "Invalid value for OT_PLATFORM - valid values are:" "${OT_PLATFORM_VALUES}")
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")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
set(OT_THREAD_VERSION_VALUES "1.1" "1.2" "1.3" "1.3.1" "1.4")
set(OT_THREAD_VERSION "1.4" CACHE STRING "set Thread version")
@@ -357,7 +361,7 @@ ot_int_option(OT_RCP_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(NOT OT_EXTERNAL_MBEDTLS)
set(OT_MBEDTLS mbedtls)
set(OT_MBEDTLS mbedtls mbedcrypto)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS=1")
else()
set(OT_MBEDTLS ${OT_EXTERNAL_MBEDTLS})
+1 -1
View File
@@ -48,9 +48,9 @@ target_link_libraries(ot-cli-ftd PRIVATE
openthread-cli-ftd
${OT_PLATFORM_LIB_FTD}
openthread-ftd
${OT_PLATFORM_LIB_FTD}
openthread-cli-ftd
${OT_MBEDTLS}
${OT_PLATFORM_LIB_FTD}
ot-config-ftd
ot-config
)
+1 -2
View File
@@ -56,8 +56,7 @@ extern void otAppCliInit(otInstance *aInstance);
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_TOOL_WEAK void *otPlatCAlloc(size_t aNum, size_t aSize) { return calloc(aNum, aSize); }
OT_TOOL_WEAK void otPlatFree(void *aPtr) { free(aPtr); }
OT_TOOL_WEAK void otPlatFree(void *aPtr) { free(aPtr); }
#endif
#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+1 -1
View File
@@ -48,9 +48,9 @@ target_link_libraries(ot-cli-mtd PRIVATE
openthread-cli-mtd
${OT_PLATFORM_LIB_MTD}
openthread-mtd
${OT_PLATFORM_LIB_MTD}
openthread-cli-mtd
${OT_MBEDTLS}
${OT_PLATFORM_LIB_MTD}
ot-config-mtd
ot-config
)
+1 -1
View File
@@ -41,9 +41,9 @@ target_link_libraries(ot-ncp-ftd PRIVATE
openthread-ncp-ftd
${OT_PLATFORM_LIB_FTD}
openthread-ftd
${OT_PLATFORM_LIB_FTD}
openthread-ncp-ftd
${OT_MBEDTLS}
${OT_PLATFORM_LIB_FTD}
ot-config-ftd
ot-config
)
+1 -2
View File
@@ -62,8 +62,7 @@ extern void otAppNcpInitMulti(otInstance **aInstances, uint8_t count);
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_TOOL_WEAK void *otPlatCAlloc(size_t aNum, size_t aSize) { return calloc(aNum, aSize); }
OT_TOOL_WEAK void otPlatFree(void *aPtr) { free(aPtr); }
OT_TOOL_WEAK void otPlatFree(void *aPtr) { free(aPtr); }
#endif
int main(int argc, char *argv[])
+1 -1
View File
@@ -41,9 +41,9 @@ target_link_libraries(ot-ncp-mtd PRIVATE
openthread-ncp-mtd
${OT_PLATFORM_LIB_MTD}
openthread-mtd
${OT_PLATFORM_LIB_MTD}
openthread-ncp-mtd
${OT_MBEDTLS}
${OT_PLATFORM_LIB_MTD}
ot-config-mtd
ot-config
)
+2 -1
View File
@@ -74,7 +74,6 @@ set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
add_library(openthread-simulation
alarm.c
ble.c
crypto.c
diag.c
dns.c
dnssd.c
@@ -104,6 +103,8 @@ endif()
target_link_libraries(openthread-simulation PRIVATE
openthread-platform
mbedtls
openthread-native-its-file
ot-simulation-config
ot-config
)
-121
View File
@@ -1,121 +0,0 @@
/*
* Copyright (c) 2021, 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.
*/
#include "platform-simulation.h"
#include <stdio.h>
#include <stdlib.h>
#include <openthread/config.h>
#include <openthread/platform/crypto.h>
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
// crypto key storage stubs
otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef,
otCryptoKeyType aKeyType,
otCryptoKeyAlgorithm aKeyAlgorithm,
int aKeyUsage,
otCryptoKeyStorage aKeyPersistence,
const uint8_t *aKey,
size_t aKeyLen)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aKeyType);
OT_UNUSED_VARIABLE(aKeyAlgorithm);
OT_UNUSED_VARIABLE(aKeyUsage);
OT_UNUSED_VARIABLE(aKeyPersistence);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aKeyLen);
return OT_ERROR_NOT_IMPLEMENTED;
}
otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aBuffer);
OT_UNUSED_VARIABLE(aBufferLen);
OT_UNUSED_VARIABLE(aKeyLen);
return OT_ERROR_NOT_IMPLEMENTED;
}
otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return OT_ERROR_NOT_IMPLEMENTED;
}
bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return false;
}
otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aPublicKey);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
const otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+34
View File
@@ -38,6 +38,10 @@
#include <openthread/platform/entropy.h>
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#include <psa/crypto.h>
#endif
#include "utils/code_utils.h"
#ifndef __SANITIZE_ADDRESS__
@@ -133,3 +137,33 @@ exit:
return error;
}
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/**
* When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no
* API to configure a dedicated non-default entropy source. It is documented that a future version of
* Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources.
*
* For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already
* uses CSPRNG, we will call it here as well.
*/
psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
OT_UNUSED_VARIABLE(context);
otError error;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
error = otPlatEntropyGet(output, (uint16_t)output_size);
if (error == OT_ERROR_NONE)
{
*output_length = output_size;
status = PSA_SUCCESS;
}
return status;
}
#endif
+18
View File
@@ -52,6 +52,10 @@
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#include <psa/crypto.h>
#endif
#include "simul_utils.h"
uint32_t gNodeId = 1;
@@ -61,6 +65,11 @@ extern otRadioCaps gRadioCaps;
static volatile bool gTerminate = false;
#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
static char sNativeItsFileNamePrefix[256];
extern const char *gItsFileNamePrefix;
#endif
static void handleSignal(int aSignal)
{
OT_UNUSED_VARIABLE(aSignal);
@@ -193,6 +202,15 @@ void otSysInit(int aArgCount, char *aArgVector[])
signal(SIGTERM, &handleSignal);
signal(SIGHUP, &handleSignal);
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
psa_crypto_init();
#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE
snprintf(sNativeItsFileNamePrefix, sizeof(sNativeItsFileNamePrefix), "%s/%s_%d_",
OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, getenv("PORT_OFFSET") ? getenv("PORT_OFFSET") : "0", gNodeId);
gItsFileNamePrefix = sNativeItsFileNamePrefix;
#endif
#endif
platformLoggingInit(basename(aArgVector[0]));
platformAlarmInit(speedUpFactor);
platformRadioInit();
@@ -50,6 +50,10 @@
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#include <psa/crypto.h>
#endif
#include "lib/platform/exit_code.h"
#include "utils/uart.h"
@@ -63,6 +67,11 @@ static bool sUseUnixSocket = false;
int gArgumentsCount = 0;
char **gArguments = NULL;
#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
static char sNativeItsFileNamePrefix[256];
extern const char *gItsFileNamePrefix;
#endif
uint64_t sNow = 0; // microseconds
int sSockFd;
uint16_t sPortBase = 9000;
@@ -273,6 +282,15 @@ void otSysInit(int argc, char *argv[])
DieNow(OT_EXIT_FAILURE);
}
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
psa_crypto_init();
#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE
snprintf(sNativeItsFileNamePrefix, sizeof(sNativeItsFileNamePrefix), "%s/%s_%d_",
OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, getenv("PORT_OFFSET") ? getenv("PORT_OFFSET") : "0", gNodeId);
gItsFileNamePrefix = sNativeItsFileNamePrefix;
#endif
#endif
socket_init();
platformAlarmInit(1);
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (548)
#define OPENTHREAD_API_VERSION (551)
/**
* @addtogroup api-instance
+34 -9
View File
@@ -60,10 +60,11 @@ extern "C" {
*/
typedef enum
{
OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data.
OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES.
OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC.
OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA.
OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data.
OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES.
OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC.
OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA.
OT_CRYPTO_KEY_TYPE_DERIVE, ///< Key Type: Derive.
} otCryptoKeyType;
/**
@@ -75,6 +76,7 @@ typedef enum
OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB.
OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256.
OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA.
OT_CRYPTO_KEY_ALG_HKDF_SHA256, ///< Key Algorithm: HKDF SHA-256.
} otCryptoKeyAlgorithm;
/**
@@ -88,6 +90,7 @@ enum
OT_CRYPTO_KEY_USAGE_DECRYPT = 1 << 2, ///< Key Usage: AES ECB.
OT_CRYPTO_KEY_USAGE_SIGN_HASH = 1 << 3, ///< Key Usage: Sign Hash.
OT_CRYPTO_KEY_USAGE_VERIFY_HASH = 1 << 4, ///< Key Usage: Verify Hash.
OT_CRYPTO_KEY_USAGE_DERIVE = 1 << 5, ///< Key Usage: Derive.
};
/**
@@ -212,11 +215,6 @@ typedef struct otPlatCryptoEcdsaSignature otPlatCryptoEcdsaSignature;
*/
#define OT_CRYPTO_PBDKF2_MAX_SALT_SIZE 30
/**
* Initialize the Crypto module.
*/
void otPlatCryptoInit(void);
/**
* Import a key into PSA ITS.
*
@@ -288,6 +286,33 @@ otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef);
*/
bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef);
/**
* Dynamically allocates new memory for Crypto subsystem. On platforms that support it, should just redirect to calloc.
* For those that don't support calloc, should support the same functionality:
*
* "The calloc() function contiguously allocates enough space for count objects that are size bytes of
* memory each and returns a pointer to the allocated memory. The allocated memory is filled with bytes
* of value zero."
*
* Is required for OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE.
*
* @param[in] aNum The number of blocks to allocate
* @param[in] aSize The size of each block to allocate
*
* @retval void* The pointer to the front of the memory allocated
* @retval NULL Failed to allocate the memory requested.
*/
void *otPlatCryptoCAlloc(size_t aNum, size_t aSize);
/**
* Frees memory that was dynamically allocated by otPlatCryptoCAlloc.
*
* Is required for OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE.
*
* @param[in] aPtr A pointer the memory blocks to free. The pointer may be NULL.
*/
void otPlatCryptoFree(void *aPtr);
/**
* Initialize the HMAC operation.
*
+4 -2
View File
@@ -481,7 +481,8 @@ openthread_core_files = [
"crypto/aes_ecb.cpp",
"crypto/aes_ecb.hpp",
"crypto/context_size.hpp",
"crypto/crypto_platform.cpp",
"crypto/crypto_platform_mbedtls.cpp",
"crypto/crypto_platform_psa.cpp",
"crypto/ecdsa.hpp",
"crypto/hkdf_sha256.cpp",
"crypto/hkdf_sha256.hpp",
@@ -803,7 +804,8 @@ openthread_radio_sources = [
"common/uptime.cpp",
"crypto/aes_ccm.cpp",
"crypto/aes_ecb.cpp",
"crypto/crypto_platform.cpp",
"crypto/crypto_platform_mbedtls.cpp",
"crypto/crypto_platform_psa.cpp",
"crypto/storage.cpp",
"diags/factory_diags.cpp",
"instance/instance.cpp",
+4 -2
View File
@@ -135,7 +135,8 @@ set(COMMON_SOURCES
common/uptime.cpp
crypto/aes_ccm.cpp
crypto/aes_ecb.cpp
crypto/crypto_platform.cpp
crypto/crypto_platform_mbedtls.cpp
crypto/crypto_platform_psa.cpp
crypto/hkdf_sha256.cpp
crypto/hmac_sha256.cpp
crypto/mbedtls.cpp
@@ -307,7 +308,8 @@ set(RADIO_COMMON_SOURCES
common/uptime.cpp
crypto/aes_ccm.cpp
crypto/aes_ecb.cpp
crypto/crypto_platform.cpp
crypto/crypto_platform_mbedtls.cpp
crypto/crypto_platform_psa.cpp
crypto/storage.cpp
diags/factory_diags.cpp
instance/instance.cpp
+1 -1
View File
@@ -49,7 +49,7 @@
* - @sa OPENTHREAD_CONFIG_CRYPTO_LIB_PLATFORM
*/
#ifndef OPENTHREAD_CONFIG_CRYPTO_LIB
#define OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
#define OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
#endif
/** Use mbedtls as crypto library */
+6 -2
View File
@@ -34,7 +34,7 @@
#ifndef CONFIG_PLATFORM_H_
#define CONFIG_PLATFORM_H_
#include "config/srp_server.h"
#include "config/crypto.h"
/**
* @addtogroup config-platform
@@ -154,9 +154,13 @@
* @def OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
*
* Define to 1 if you want to enable key ref usage support as defined by platform.
*
* This config is enabled by default for PSA Crypto backend.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 0
#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE \
(OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#endif
/**
@@ -47,6 +47,7 @@
#include <openthread/instance.h>
#include <openthread/platform/crypto.h>
#include <openthread/platform/entropy.h>
#include <openthread/platform/memory.h>
#include <openthread/platform/time.h>
#include "common/code_utils.hpp"
@@ -78,10 +79,10 @@ static constexpr uint16_t kEntropyMinThreshold = 16;
#endif
#endif
OT_TOOL_WEAK void otPlatCryptoInit(void)
{
// Intentionally empty.
}
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_TOOL_WEAK void *otPlatCryptoCAlloc(size_t aNum, size_t aSize) { return otPlatCAlloc(aNum, aSize); }
OT_TOOL_WEAK void otPlatCryptoFree(void *aPtr) { otPlatFree(aPtr); }
#endif
// AES Implementation
OT_TOOL_WEAK otError otPlatCryptoAesInit(otCryptoContext *aContext)
@@ -749,74 +750,4 @@ exit:
#endif // #if OPENTHREAD_FTD
#elif OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair)
{
OT_UNUSED_VARIABLE(aKeyPair);
return OT_ERROR_NOT_CAPABLE;
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair,
otPlatCryptoEcdsaPublicKey *aPublicKey)
{
OT_UNUSED_VARIABLE(aKeyPair);
OT_UNUSED_VARIABLE(aPublicKey);
return OT_ERROR_NOT_CAPABLE;
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair,
const otPlatCryptoSha256Hash *aHash,
otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aKeyPair);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NOT_CAPABLE;
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey,
const otPlatCryptoSha256Hash *aHash,
const otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aPublicKey);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NOT_CAPABLE;
}
#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE
#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_FTD
OT_TOOL_WEAK otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword,
uint16_t aPasswordLen,
const uint8_t *aSalt,
uint16_t aSaltLen,
uint32_t aIterationCounter,
uint16_t aKeyLen,
uint8_t *aKey)
{
OT_UNUSED_VARIABLE(aPassword);
OT_UNUSED_VARIABLE(aPasswordLen);
OT_UNUSED_VARIABLE(aSalt);
OT_UNUSED_VARIABLE(aSaltLen);
OT_UNUSED_VARIABLE(aIterationCounter);
OT_UNUSED_VARIABLE(aKeyLen);
OT_UNUSED_VARIABLE(aKey);
return OT_ERROR_NOT_CAPABLE;
}
#endif // #if OPENTHREAD_FTD
#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
+797
View File
@@ -0,0 +1,797 @@
/*
* Copyright (c) 2025, 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 default/weak Crypto platform APIs using ARM PSA API.
*/
#include "openthread-core-config.h"
#include <string.h>
#include <mbedtls/asn1.h>
#include <psa/crypto.h>
#include <openthread/instance.h>
#include <openthread/platform/crypto.h>
#include <openthread/platform/entropy.h>
#include <openthread/platform/memory.h>
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/new.hpp"
#include "config/crypto.h"
#include "crypto/ecdsa.hpp"
#include "crypto/hmac_sha256.hpp"
#include "crypto/storage.hpp"
#include "instance/instance.hpp"
using namespace ot;
using namespace Crypto;
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
//---------------------------------------------------------------------------------------------------------------------
// Default/weak implementation of crypto platform APIs
static otError psaToOtError(psa_status_t aStatus)
{
switch (aStatus)
{
case PSA_SUCCESS:
return kErrorNone;
case PSA_ERROR_INVALID_ARGUMENT:
return kErrorInvalidArgs;
case PSA_ERROR_BUFFER_TOO_SMALL:
return kErrorNoBufs;
default:
return kErrorFailed;
}
}
static psa_key_type_t toPsaKeyType(otCryptoKeyType aType)
{
switch (aType)
{
case OT_CRYPTO_KEY_TYPE_RAW:
return PSA_KEY_TYPE_RAW_DATA;
case OT_CRYPTO_KEY_TYPE_AES:
return PSA_KEY_TYPE_AES;
case OT_CRYPTO_KEY_TYPE_HMAC:
return PSA_KEY_TYPE_HMAC;
case OT_CRYPTO_KEY_TYPE_ECDSA:
return PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
case OT_CRYPTO_KEY_TYPE_DERIVE:
return PSA_KEY_TYPE_DERIVE;
default:
return PSA_KEY_TYPE_NONE;
}
}
static psa_algorithm_t toPsaAlgorithm(otCryptoKeyAlgorithm aAlgorithm)
{
switch (aAlgorithm)
{
case OT_CRYPTO_KEY_ALG_AES_ECB:
return PSA_ALG_ECB_NO_PADDING;
case OT_CRYPTO_KEY_ALG_HMAC_SHA_256:
return PSA_ALG_HMAC(PSA_ALG_SHA_256);
case OT_CRYPTO_KEY_ALG_ECDSA:
return PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256);
case OT_CRYPTO_KEY_ALG_HKDF_SHA256:
return PSA_ALG_HKDF(PSA_ALG_SHA_256);
default:
return PSA_ALG_NONE;
}
}
static psa_key_usage_t toPsaKeyUsage(int aUsage)
{
psa_key_usage_t usage = 0;
if (aUsage & OT_CRYPTO_KEY_USAGE_EXPORT)
{
usage |= PSA_KEY_USAGE_EXPORT;
}
if (aUsage & OT_CRYPTO_KEY_USAGE_ENCRYPT)
{
usage |= PSA_KEY_USAGE_ENCRYPT;
}
if (aUsage & OT_CRYPTO_KEY_USAGE_DECRYPT)
{
usage |= PSA_KEY_USAGE_DECRYPT;
}
if (aUsage & OT_CRYPTO_KEY_USAGE_SIGN_HASH)
{
usage |= PSA_KEY_USAGE_SIGN_HASH;
}
if (aUsage & OT_CRYPTO_KEY_USAGE_VERIFY_HASH)
{
usage |= PSA_KEY_USAGE_VERIFY_HASH;
}
if (aUsage & OT_CRYPTO_KEY_USAGE_DERIVE)
{
usage |= PSA_KEY_USAGE_DERIVE;
}
return usage;
}
static bool checkKeyUsage(int aUsage)
{
/* Check if only supported flags have been passed */
int supportedFlags = OT_CRYPTO_KEY_USAGE_EXPORT | OT_CRYPTO_KEY_USAGE_ENCRYPT | OT_CRYPTO_KEY_USAGE_DECRYPT |
OT_CRYPTO_KEY_USAGE_SIGN_HASH | OT_CRYPTO_KEY_USAGE_VERIFY_HASH | OT_CRYPTO_KEY_USAGE_DERIVE;
return (aUsage & ~supportedFlags) == 0;
}
static bool checkContext(otCryptoContext *aContext, size_t aMinSize)
{
/* Verify that the passed context is initialized and points to a big enough buffer */
return aContext != nullptr && aContext->mContext != nullptr && aContext->mContextSize >= aMinSize;
}
static otError extractPrivateKeyInfo(const uint8_t *aAsn1KeyPair,
size_t aAsn1KeyPairLen,
size_t *aKeyOffset,
size_t *aKeyLen)
{
Error error = kErrorNone;
unsigned char *p = const_cast<unsigned char *>(aAsn1KeyPair);
const unsigned char *end = p + aAsn1KeyPairLen;
size_t len;
// Parse the ASN.1 SEQUENCE headers
int ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
VerifyOrExit(ret == 0, error = kErrorInvalidArgs);
// Parse the version (INTEGER)
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
VerifyOrExit(ret == 0, error = kErrorInvalidArgs);
// Skip the version.
p += len;
// Parse the private key (OCTET STRING)
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
VerifyOrExit(ret == 0, error = kErrorInvalidArgs);
// Check if the private key includes a padding byte (0x00)
if (*p == 0x00)
{
p++;
len--; // Skip the padding byte and reduce length by 1
}
*aKeyOffset = (p - aAsn1KeyPair);
*aKeyLen = len;
exit:
return error;
}
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_TOOL_WEAK void *otPlatCryptoCAlloc(size_t aNum, size_t aSize) { return otPlatCAlloc(aNum, aSize); }
OT_TOOL_WEAK void otPlatCryptoFree(void *aPtr) { otPlatFree(aPtr); }
#endif
OT_TOOL_WEAK otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef,
otCryptoKeyType aKeyType,
otCryptoKeyAlgorithm aKeyAlgorithm,
int aKeyUsage,
otCryptoKeyStorage aKeyPersistence,
const uint8_t *aKey,
size_t aKeyLen)
{
Error error = kErrorNone;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_SUCCESS;
VerifyOrExit(checkKeyUsage(aKeyUsage), error = kErrorInvalidArgs);
VerifyOrExit(aKeyRef != nullptr && aKey != nullptr, error = kErrorInvalidArgs);
// PSA Crypto API expects the private key to be provided, not the full ASN1 buffer.
if (aKeyType == OT_CRYPTO_KEY_TYPE_ECDSA)
{
size_t pkOffset;
size_t pkLength;
SuccessOrExit(error = extractPrivateKeyInfo(aKey, aKeyLen, &pkOffset, &pkLength));
// Overwrite the content of the key.
aKey += pkOffset;
aKeyLen = pkLength;
psa_set_key_bits(&attributes, 256);
}
psa_set_key_type(&attributes, toPsaKeyType(aKeyType));
psa_set_key_algorithm(&attributes, toPsaAlgorithm(aKeyAlgorithm));
psa_set_key_usage_flags(&attributes, toPsaKeyUsage(aKeyUsage));
switch (aKeyPersistence)
{
case OT_CRYPTO_KEY_STORAGE_PERSISTENT:
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&attributes, *aKeyRef);
break;
case OT_CRYPTO_KEY_STORAGE_VOLATILE:
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
break;
default:
OT_ASSERT(false);
}
status = psa_import_key(&attributes, aKey, aKeyLen, aKeyRef);
exit:
psa_reset_key_attributes(&attributes);
if (error != kErrorNone)
{
return error;
}
return psaToOtError(status);
}
OT_TOOL_WEAK otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen)
{
Error error = kErrorNone;
VerifyOrExit(aBuffer != nullptr && aKeyLen != nullptr, error = kErrorInvalidArgs);
error = psaToOtError(psa_export_key(aKeyRef, aBuffer, aBufferLen, aKeyLen));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef) { return psaToOtError(psa_destroy_key(aKeyRef)); }
OT_TOOL_WEAK bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
status = psa_get_key_attributes(aKeyRef, &attributes);
psa_reset_key_attributes(&attributes);
return status == PSA_SUCCESS;
}
OT_TOOL_WEAK otError otPlatCryptoAesInit(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_key_id_t *keyRef;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs);
keyRef = static_cast<psa_key_id_t *>(aContext->mContext);
*keyRef = PSA_KEY_ID_NULL;
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCryptoKey *aKey)
{
Error error = kErrorNone;
psa_key_id_t *keyRef;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs);
VerifyOrExit(aKey != nullptr, error = kErrorInvalidArgs);
keyRef = static_cast<psa_key_id_t *>(aContext->mContext);
*keyRef = aKey->mKeyRef;
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoAesEncrypt(otCryptoContext *aContext, const uint8_t *aInput, uint8_t *aOutput)
{
Error error = kErrorNone;
const size_t blockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES);
psa_status_t status = PSA_SUCCESS;
psa_key_id_t *keyRef;
size_t cipherLen;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs);
VerifyOrExit(aInput != nullptr && aOutput != nullptr, error = kErrorInvalidArgs);
keyRef = static_cast<psa_key_id_t *>(aContext->mContext);
status = psa_cipher_encrypt(*keyRef, PSA_ALG_ECB_NO_PADDING, aInput, blockSize, aOutput, blockSize, &cipherLen);
error = psaToOtError(status);
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoAesFree(otCryptoContext *aContext)
{
OT_UNUSED_VARIABLE(aContext);
return kErrorNone;
}
#if !OPENTHREAD_RADIO
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_mac_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_mac_operation_t *>(aContext->mContext);
// Initialize the structure using memset as documented alternative for psa_mac_operation_init().
memset(operation, 0, sizeof(*operation));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Deinit(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_mac_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_mac_operation_t *>(aContext->mContext);
error = psaToOtError(psa_mac_abort(operation));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Start(otCryptoContext *aContext, const otCryptoKey *aKey)
{
Error error = kErrorNone;
psa_mac_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aKey != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_mac_operation_t *>(aContext->mContext);
error = psaToOtError(psa_mac_sign_setup(operation, aKey->mKeyRef, PSA_ALG_HMAC(PSA_ALG_SHA_256)));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength)
{
Error error = kErrorNone;
psa_mac_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_mac_operation_t *>(aContext->mContext);
error = psaToOtError(psa_mac_update(operation, static_cast<const uint8_t *>(aBuf), aBufLength));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, size_t aBufLength)
{
Error error = kErrorNone;
psa_mac_operation_t *operation;
size_t macLength;
VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_mac_operation_t *>(aContext->mContext);
error = psaToOtError(psa_mac_sign_finish(operation, aBuf, aBufLength, &macLength));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHkdfInit(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_key_derivation_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_key_derivation_operation_t *>(aContext->mContext);
*operation = PSA_KEY_DERIVATION_OPERATION_INIT;
error = psaToOtError(psa_key_derivation_setup(operation, PSA_ALG_HKDF(PSA_ALG_SHA_256)));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext,
const uint8_t *aSalt,
uint16_t aSaltLength,
const otCryptoKey *aInputKey)
{
Error error = kErrorNone;
psa_status_t status = PSA_SUCCESS;
psa_key_derivation_operation_t *operation = nullptr;
otCryptoKeyRef keyRef = PSA_KEY_ID_NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t keyAlg = PSA_ALG_NONE;
size_t keyLength = 0;
constexpr size_t kBufferSize = 128;
uint8_t keyBuffer[kBufferSize];
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aInputKey != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_key_derivation_operation_t *>(aContext->mContext);
status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLength);
SuccessOrExit(error = psaToOtError(status));
status = psa_get_key_attributes(aInputKey->mKeyRef, &attributes);
SuccessOrExit(error = psaToOtError(status));
keyAlg = psa_get_key_algorithm(&attributes);
// The PSA API enforces a policy that restricts each key to a single algorithm.
// If the key is already HKDF-SHA256, we can use it directly.
// Otherwise, export and re-import it as a volatile HKDF key.
if (keyAlg != toPsaAlgorithm(OT_CRYPTO_KEY_ALG_HKDF_SHA256))
{
SuccessOrExit(error = otPlatCryptoExportKey(aInputKey->mKeyRef, keyBuffer, sizeof(keyBuffer), &keyLength));
SuccessOrExit(error = otPlatCryptoImportKey(&keyRef, OT_CRYPTO_KEY_TYPE_DERIVE, OT_CRYPTO_KEY_ALG_HKDF_SHA256,
OT_CRYPTO_KEY_USAGE_DERIVE, OT_CRYPTO_KEY_STORAGE_VOLATILE,
keyBuffer, keyLength));
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, keyRef);
SuccessOrExit(error = psaToOtError(status));
}
else
{
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef);
SuccessOrExit(error = psaToOtError(status));
}
exit:
if (keyRef != PSA_KEY_ID_NULL)
{
otPlatCryptoDestroyKey(keyRef);
}
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHkdfExpand(otCryptoContext *aContext,
const uint8_t *aInfo,
uint16_t aInfoLength,
uint8_t *aOutputKey,
uint16_t aOutputKeyLength)
{
Error error = kErrorNone;
psa_status_t status = PSA_SUCCESS;
psa_key_derivation_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aOutputKey != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aOutputKeyLength != 0, error = kErrorInvalidArgs);
operation = static_cast<psa_key_derivation_operation_t *>(aContext->mContext);
status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_INFO, aInfo, aInfoLength);
SuccessOrExit(error = psaToOtError(status));
status = psa_key_derivation_output_bytes(operation, aOutputKey, aOutputKeyLength);
SuccessOrExit(error = psaToOtError(status));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoHkdfDeinit(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_key_derivation_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_key_derivation_operation_t *>(aContext->mContext);
error = psaToOtError(psa_key_derivation_abort(operation));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoSha256Init(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_hash_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_hash_operation_t *>(aContext->mContext);
// Initialize the structure using memset as documented alternative for psa_hash_operation_init().
memset(operation, 0, sizeof(*operation));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoSha256Deinit(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_hash_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_hash_operation_t *>(aContext->mContext);
error = psaToOtError(psa_hash_abort(operation));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoSha256Start(otCryptoContext *aContext)
{
Error error = kErrorNone;
psa_hash_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs);
operation = static_cast<psa_hash_operation_t *>(aContext->mContext);
error = psaToOtError(psa_hash_setup(operation, PSA_ALG_SHA_256));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength)
{
Error error = kErrorNone;
psa_hash_operation_t *operation;
VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_hash_operation_t *>(aContext->mContext);
error = psaToOtError(psa_hash_update(operation, static_cast<const uint8_t *>(aBuf), aBufLength));
exit:
return error;
}
OT_TOOL_WEAK otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize)
{
Error error = kErrorNone;
psa_hash_operation_t *operation;
size_t hashSize;
VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aHash != nullptr, error = kErrorInvalidArgs);
operation = static_cast<psa_hash_operation_t *>(aContext->mContext);
error = psaToOtError(psa_hash_finish(operation, aHash, aHashSize, &hashSize));
exit:
return error;
}
OT_TOOL_WEAK void otPlatCryptoRandomInit(void) { psa_crypto_init(); }
OT_TOOL_WEAK void otPlatCryptoRandomDeinit(void)
{
// Intentionally empty
}
OT_TOOL_WEAK otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize)
{
return psaToOtError(psa_generate_random(aBuffer, aSize));
}
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_key_id_t keyId = static_cast<psa_key_id_t>(aKeyRef);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&attributes, keyId);
psa_set_key_bits(&attributes, 256);
status = psa_generate_key(&attributes, &keyId);
VerifyOrExit(status == PSA_SUCCESS);
exit:
psa_reset_key_attributes(&attributes);
return psaToOtError(status);
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey)
{
psa_status_t status;
size_t exportedLen;
uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
status = psa_export_public_key(aKeyRef, buffer, sizeof(buffer), &exportedLen);
VerifyOrExit(status == PSA_SUCCESS);
OT_ASSERT(exportedLen == sizeof(buffer));
memcpy(aPublicKey->m8, buffer + 1, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE);
exit:
return psaToOtError(status);
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
otPlatCryptoEcdsaSignature *aSignature)
{
psa_status_t status;
size_t signatureLen;
status = psa_sign_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8, OT_CRYPTO_SHA256_HASH_SIZE,
aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE, &signatureLen);
VerifyOrExit(status == PSA_SUCCESS);
OT_ASSERT(signatureLen == OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
exit:
return psaToOtError(status);
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey,
const otPlatCryptoSha256Hash *aHash,
const otPlatCryptoEcdsaSignature *aSignature)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t keyId = PSA_KEY_ID_NULL;
psa_status_t status;
uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
/*
* `psa_import_key` expects a key format as specified by SEC1 &sect;2.3.3 for the
* uncompressed representation of the ECPoint.
*/
buffer[0] = 0x04;
memcpy(buffer + 1, aPublicKey->m8, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE);
status = psa_import_key(&attributes, buffer, sizeof(buffer), &keyId);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_verify_hash(keyId, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8, OT_CRYPTO_SHA256_HASH_SIZE,
aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
VerifyOrExit(status == PSA_SUCCESS);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(keyId);
return psaToOtError(status);
}
OT_TOOL_WEAK otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
const otPlatCryptoEcdsaSignature *aSignature)
{
psa_status_t status;
status = psa_verify_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8,
OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
VerifyOrExit(status == PSA_SUCCESS);
exit:
return psaToOtError(status);
}
#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE
#endif // #if !OPENTHREAD_RADIO
#if OPENTHREAD_FTD
OT_TOOL_WEAK otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword,
uint16_t aPasswordLen,
const uint8_t *aSalt,
uint16_t aSaltLen,
uint32_t aIterationCounter,
uint16_t aKeyLen,
uint8_t *aKey)
{
psa_status_t status = PSA_SUCCESS;
psa_key_id_t key_id = PSA_KEY_ID_NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t algorithm = PSA_ALG_PBKDF2_AES_CMAC_PRF_128;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, algorithm);
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(aPasswordLen));
status = psa_import_key(&attributes, aPassword, aPasswordLen, &key_id);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_key_derivation_setup(&operation, algorithm);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, aIterationCounter);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLen);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, key_id);
VerifyOrExit(status == PSA_SUCCESS);
status = psa_key_derivation_output_bytes(&operation, aKey, aKeyLen);
VerifyOrExit(status == PSA_SUCCESS);
exit:
psa_reset_key_attributes(&attributes);
psa_key_derivation_abort(&operation);
psa_destroy_key(key_id);
return psaToOtError(status);
}
#endif // #if OPENTHREAD_FTD
#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
+22 -22
View File
@@ -33,9 +33,9 @@
#include "mbedtls.hpp"
#include <mbedtls/ctr_drbg.h>
// #include <mbedtls/ctr_drbg.h>
#include <mbedtls/debug.h>
#include <mbedtls/entropy.h>
// #include <mbedtls/entropy.h>
#include <mbedtls/platform.h>
#include <mbedtls/threading.h>
@@ -57,9 +57,9 @@ MbedTls::MbedTls(void)
// mbedTLS's debug level is almost the same as OpenThread's
mbedtls_debug_set_threshold(OPENTHREAD_CONFIG_LOG_LEVEL);
#endif
#if OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
#if OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
mbedtls_platform_set_calloc_free(Heap::CAlloc, Heap::Free);
#endif // OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
#endif // OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
}
Error MbedTls::MapError(int aMbedTlsError)
@@ -69,8 +69,8 @@ Error MbedTls::MapError(int aMbedTlsError)
switch (aMbedTlsError)
{
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
// case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
// case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
case MBEDTLS_ERR_MPI_INVALID_CHARACTER:
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
@@ -84,7 +84,7 @@ Error MbedTls::MapError(int aMbedTlsError)
case MBEDTLS_ERR_PK_INVALID_PUBKEY:
case MBEDTLS_ERR_PK_INVALID_ALG:
case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE:
case MBEDTLS_ERR_PK_BAD_INPUT_DATA:
// case MBEDTLS_ERR_PK_BAD_INPUT_DATA:
case MBEDTLS_ERR_X509_SIG_MISMATCH:
case MBEDTLS_ERR_X509_BAD_INPUT_DATA:
case MBEDTLS_ERR_X509_FILE_IO_ERROR:
@@ -102,42 +102,42 @@ Error MbedTls::MapError(int aMbedTlsError)
case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
// case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
// case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
error = kErrorInvalidArgs;
break;
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
case MBEDTLS_ERR_MPI_ALLOC_FAILED:
// case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
// case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
// case MBEDTLS_ERR_MPI_ALLOC_FAILED:
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case MBEDTLS_ERR_PEM_ALLOC_FAILED:
// case MBEDTLS_ERR_PEM_ALLOC_FAILED:
case MBEDTLS_ERR_PK_ALLOC_FAILED:
case MBEDTLS_ERR_X509_BUFFER_TOO_SMALL:
case MBEDTLS_ERR_X509_ALLOC_FAILED:
// case MBEDTLS_ERR_X509_ALLOC_FAILED:
#endif
case MBEDTLS_ERR_SSL_ALLOC_FAILED:
// case MBEDTLS_ERR_SSL_ALLOC_FAILED:
case MBEDTLS_ERR_SSL_WANT_WRITE:
case MBEDTLS_ERR_ENTROPY_MAX_SOURCES:
// case MBEDTLS_ERR_ENTROPY_MAX_SOURCES:
error = kErrorNoBufs;
break;
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE:
case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH:
// case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH:
case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE:
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED:
case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED:
case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE:
// case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
// case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED:
// case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED:
// case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE:
#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED:
#endif
case MBEDTLS_ERR_THREADING_BAD_INPUT_DATA:
// case MBEDTLS_ERR_THREADING_BAD_INPUT_DATA:
case MBEDTLS_ERR_THREADING_MUTEX_ERROR:
error = kErrorSecurity;
break;
+7 -4
View File
@@ -57,10 +57,11 @@ namespace Storage {
*/
enum KeyType : uint8_t
{
kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data.
kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES.
kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC.
kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA.
kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data.
kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES.
kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC.
kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA.
kKeyTypeDerive = OT_CRYPTO_KEY_TYPE_DERIVE, ///< Key Type: Derive.
};
/**
@@ -72,6 +73,7 @@ enum KeyAlgorithm : uint8_t
kKeyAlgorithmAesEcb = OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB.
kKeyAlgorithmHmacSha256 = OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256.
kKeyAlgorithmEcdsa = OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA.
kKeyAlgorithmHkdfSha256 = OT_CRYPTO_KEY_ALG_HKDF_SHA256, ///< Key Algorithm: HKDF SHA-256.
};
constexpr uint8_t kUsageNone = OT_CRYPTO_KEY_USAGE_NONE; ///< Key Usage: Key Usage is empty.
@@ -80,6 +82,7 @@ constexpr uint8_t kUsageEncrypt = OT_CRYPTO_KEY_USAGE_ENCRYPT; ///< Key U
constexpr uint8_t kUsageDecrypt = OT_CRYPTO_KEY_USAGE_DECRYPT; ///< Key Usage: AES ECB.
constexpr uint8_t kUsageSignHash = OT_CRYPTO_KEY_USAGE_SIGN_HASH; ///< Key Usage: Sign Hash.
constexpr uint8_t kUsageVerifyHash = OT_CRYPTO_KEY_USAGE_VERIFY_HASH; ///< Key Usage: Verify Hash.
constexpr uint8_t kUsageDerive = OT_CRYPTO_KEY_USAGE_DERIVE; ///< Key Usage: Derive.
/**
* Defines the key storage types.
+2
View File
@@ -303,6 +303,7 @@ Instance::Instance(void)
, mIsInitialized(false)
, mId(Random::NonCrypto::GetUint32())
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
mCryptoStorageKeyRefManager.SetKeyRefExtraOffset(Crypto::Storage::KeyRefManager::kKeyRefExtraOffset * GetIdx(this));
@@ -311,6 +312,7 @@ Instance::Instance(void)
"The `KeyRef` values will be shared across different `Instance` objects"
#endif
#endif
#endif
}
#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+3 -2
View File
@@ -199,7 +199,7 @@ Error SecureSession::Setup(void)
}
#endif
mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr);
// mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr);
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
mbedtls_ssl_conf_min_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2);
mbedtls_ssl_conf_max_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2);
@@ -278,7 +278,8 @@ Error SecureSession::Setup(void)
if (mIsServer)
{
rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
// rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
rval = mbedtls_ssl_cookie_setup(&mCookieCtx);
VerifyOrExit(rval == 0);
mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx);
-2
View File
@@ -176,8 +176,6 @@ KeyManager::KeyManager(Instance &aInstance)
, mKekFrameCounter(0)
, mIsPskcSet(false)
{
otPlatCryptoInit();
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
{
NetworkKey networkKey;
+2
View File
@@ -42,6 +42,8 @@ add_library(ot-fake-platform
)
target_link_libraries(ot-fake-platform
ot-config
${OT_MBEDTLS}
openthread-native-its-ram
)
add_library(ot-fake-ftd INTERFACE)
+34
View File
@@ -50,6 +50,10 @@
#include <openthread/platform/trel.h>
#include <openthread/platform/udp.h>
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#include <psa/crypto.h>
#endif
using namespace ot;
bool operator<(const otExtAddress &aLeft, const otExtAddress &aRight)
@@ -482,6 +486,36 @@ otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
return error;
}
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/**
* When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no
* API to configure a dedicated non-default entropy source. It is documented that a future version of
* Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources.
*
* For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already
* uses CSPRNG, we will call it here as well.
*/
extern "C" psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
OT_UNUSED_VARIABLE(context);
otError error;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
error = otPlatEntropyGet(output, (uint16_t)output_size);
if (error == OT_ERROR_NONE)
{
*output_length = output_size;
status = PSA_SUCCESS;
}
return status;
}
#endif
void otPlatDiagSetOutputCallback(otInstance *, otPlatDiagOutputCallback, void *) {}
void otPlatDiagModeSet(bool) {}
+3 -1
View File
@@ -101,6 +101,7 @@ endif()
target_link_libraries(ot-test-platform-ftd
PRIVATE
ot-config
mbedtls
${OT_MBEDTLS}
)
@@ -116,10 +117,11 @@ set(COMMON_LIBS
ot-test-platform-ftd
openthread-ftd
ot-test-platform-ftd
${OT_MBEDTLS}
ot-config
openthread-ftd
openthread-url
${OT_MBEDTLS}
openthread-native-its-ram
)
set(COMMON_LIBS_RCP
+67 -9
View File
@@ -41,7 +41,7 @@ namespace ot {
*/
void TestMacBeaconFrame(void)
{
uint8_t key[] = {
uint8_t rawKey[] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
};
@@ -57,19 +57,34 @@ void TestMacBeaconFrame(void)
0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52,
0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53};
uint8_t nonce[] = {
0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02,
};
otInstance *instance = testInitInstance();
Crypto::AesCcm aesCcm;
uint32_t headerLength = sizeof(test) - 8;
uint32_t payloadLength = 0;
uint8_t tagLength = 8;
uint8_t nonce[] = {
0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02,
};
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Key key;
Crypto::Storage::KeyRef keyRef;
#endif
VerifyOrQuit(instance != nullptr);
aesCcm.SetKey(key, sizeof(key));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb,
Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, rawKey,
sizeof(rawKey)));
key.SetAsKeyRef(keyRef);
aesCcm.SetKey(key);
#else
aesCcm.SetKey(rawKey, sizeof(rawKey));
#endif
aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce));
aesCcm.Header(test, headerLength);
VerifyOrQuit(aesCcm.GetTagLength() == tagLength);
@@ -84,6 +99,10 @@ void TestMacBeaconFrame(void)
VerifyOrQuit(memcmp(test, decrypted, sizeof(decrypted)) == 0);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
testFreeInstance(instance);
}
@@ -92,7 +111,7 @@ void TestMacBeaconFrame(void)
*/
void TestMacCommandFrame(void)
{
uint8_t key[] = {
uint8_t rawKey[] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
};
@@ -128,9 +147,24 @@ void TestMacCommandFrame(void)
Message *message;
Crypto::AesCcm aesCcm;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Key key;
Crypto::Storage::KeyRef keyRef;
#endif
VerifyOrQuit(instance != nullptr);
aesCcm.SetKey(key, sizeof(key));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb,
Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, rawKey,
sizeof(rawKey)));
key.SetAsKeyRef(keyRef);
aesCcm.SetKey(key);
#else
aesCcm.SetKey(rawKey, sizeof(rawKey));
#endif
aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
aesCcm.Header(test, kHeaderLength);
aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt);
@@ -171,6 +205,11 @@ void TestMacCommandFrame(void)
VerifyOrQuit(message->Compare(0, decrypted));
message->Free();
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
testFreeInstance(instance);
}
@@ -182,7 +221,7 @@ void TestInPlaceAesCcmProcessing(void)
static constexpr uint16_t kTagLength = 4;
static constexpr uint32_t kHeaderLength = 19;
static const uint8_t kKey[] = {
static const uint8_t kRawKey[] = {
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
};
@@ -200,12 +239,26 @@ void TestInPlaceAesCcmProcessing(void)
Message *message;
Message *messageClone;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Key key;
Crypto::Storage::KeyRef keyRef;
#endif
VerifyOrQuit(instance != nullptr);
message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
VerifyOrQuit(message != nullptr);
aesCcm.SetKey(kKey, sizeof(kKey));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb,
Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, kRawKey,
sizeof(kRawKey)));
key.SetAsKeyRef(keyRef);
aesCcm.SetKey(key);
#else
aesCcm.SetKey(kRawKey, sizeof(kRawKey));
#endif
for (uint16_t msgLength : kMessageLengths)
{
@@ -251,6 +304,11 @@ void TestInPlaceAesCcmProcessing(void)
}
message->Free();
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
testFreeInstance(instance);
}
+3
View File
@@ -135,6 +135,9 @@ void otPlatFree(void *aPtr)
free(aPtr);
}
void *otPlatCryptoCAlloc(size_t aNum, size_t aSize) { return calloc(aNum, aSize); }
void otPlatCryptoFree(void *aPtr) { free(aPtr); }
#endif
#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
+29 -2
View File
@@ -77,7 +77,13 @@ void TestEcdsaVector(void)
Instance *instance = testInitInstance();
Ecdsa::P256::KeyPair keyPair;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Ecdsa::P256::KeyPairAsRef keyPair;
Crypto::Storage::KeyRef keyRef;
#else
Ecdsa::P256::KeyPair keyPair;
#endif
Ecdsa::P256::PublicKey publicKey;
Ecdsa::P256::Signature signature;
Sha256 sha256;
@@ -89,10 +95,18 @@ void TestEcdsaVector(void)
printf("Test ECDA with test vector from RFC 6979 (A.2.5)\n");
printf("\nLoading key-pair ----------------------------------------------------------\n");
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Storage::kKeyTypeEcdsa, Storage::kKeyAlgorithmEcdsa,
(Storage::kUsageSignHash | Storage::kUsageVerifyHash),
Storage::kTypeVolatile, kKeyPairInfo, sizeof(kKeyPairInfo)));
keyPair.SetKeyRef(keyRef);
#else
memcpy(keyPair.GetDerBytes(), kKeyPairInfo, sizeof(kKeyPairInfo));
keyPair.SetDerLength(sizeof(kKeyPairInfo));
DumpBuffer("KeyPair", keyPair.GetDerBytes(), keyPair.GetDerLength());
#endif
SuccessOrQuit(keyPair.GetPublicKey(publicKey));
DumpBuffer("PublicKey", publicKey.GetBytes(), Ecdsa::P256::PublicKey::kSize);
@@ -109,6 +123,7 @@ void TestEcdsaVector(void)
DumpBuffer("Hash", hash.GetBytes(), sizeof(hash));
printf("\nSign the message ----------------------------------------------------------\n");
SuccessOrQuit(keyPair.Sign(hash, signature));
DumpBuffer("Signature", signature.GetBytes(), sizeof(signature));
@@ -135,7 +150,13 @@ void TestEcdsaKeyGenerationSignAndVerify(void)
const char kMessage[] = "You are not a drop in the ocean. You are the entire ocean in a drop.";
Ecdsa::P256::KeyPair keyPair;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::KeyRef keyRef = 0x1234;
Ecdsa::P256::KeyPairAsRef keyPair(keyRef);
#else
Ecdsa::P256::KeyPair keyPair;
#endif
Ecdsa::P256::PublicKey publicKey;
Ecdsa::P256::Signature signature;
Sha256 sha256;
@@ -149,7 +170,9 @@ void TestEcdsaKeyGenerationSignAndVerify(void)
printf("\nGenerating key-pair -------------------------------------------------------\n");
SuccessOrQuit(keyPair.Generate());
#if !OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
DumpBuffer("KeyPair", keyPair.GetDerBytes(), keyPair.GetDerLength());
#endif
SuccessOrQuit(keyPair.GetPublicKey(publicKey));
DumpBuffer("PublicKey", publicKey.GetBytes(), Ecdsa::P256::PublicKey::kSize);
@@ -175,6 +198,10 @@ void TestEcdsaKeyGenerationSignAndVerify(void)
VerifyOrQuit(publicKey.Verify(hash, signature) != kErrorNone, "PublicKey::Verify() passed for invalid signature");
printf("\nSignature verification correctly failed with incorrect hash/signature.\n\n");
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
testFreeInstance(instance);
}
+42 -3
View File
@@ -50,7 +50,11 @@ struct TestVector
uint16_t mOutKeyLength;
};
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
void TestHkdfSha256(Crypto::Storage::KeyAlgorithm aAlgorithm)
#else
void TestHkdfSha256(void)
#endif
{
enum
{
@@ -134,6 +138,10 @@ void TestHkdfSha256(void)
uint8_t outKey[kMaxOuttKey];
Crypto::Key testInputKey;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::KeyRef keyRef;
#endif
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
DumpBuffer("\nInput Key", test->mInKey, test->mInKeyLength);
DumpBuffer("\nSalt", test->mSalt, test->mSaltLength);
@@ -141,9 +149,30 @@ void TestHkdfSha256(void)
DumpBuffer("\nExpected Output Key", test->mOutKey, test->mOutKeyLength);
memset(outKey, kFillByte, sizeof(outKey));
memset(&testInputKey, 0x00, sizeof(testInputKey));
testInputKey.mKey = test->mInKey;
testInputKey.mKeyLength = test->mInKeyLength;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
if (aAlgorithm == Crypto::Storage::kKeyAlgorithmHkdfSha256)
{
SuccessOrQuit(Crypto::Storage::ImportKey(
keyRef, Crypto::Storage::kKeyTypeDerive, Crypto::Storage::kKeyAlgorithmHkdfSha256,
Crypto::Storage::kUsageDerive, Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength));
}
else if (aAlgorithm == Crypto::Storage::kKeyAlgorithmHmacSha256)
{
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeHmac,
Crypto::Storage::kKeyAlgorithmHmacSha256,
Crypto::Storage::kUsageSignHash | Crypto::Storage::kUsageExport,
Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength));
}
else
{
VerifyOrQuit(false);
}
testInputKey.SetAsKeyRef(keyRef);
#else
testInputKey.Set(test->mInKey, test->mInKeyLength);
#endif
hkdf.Extract(test->mSalt, test->mSaltLength, testInputKey);
hkdf.Expand(test->mInfo, test->mInfoLength, outKey, test->mOutKeyLength);
@@ -156,6 +185,10 @@ void TestHkdfSha256(void)
{
VerifyOrQuit(outKey[i] == kFillByte, "HKDF-SHA-256 wrote beyond output key length");
}
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
}
testFreeInstance(instance);
@@ -165,7 +198,13 @@ void TestHkdfSha256(void)
int main(void)
{
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
ot::TestHkdfSha256(ot::Crypto::Storage::kKeyAlgorithmHkdfSha256);
ot::TestHkdfSha256(ot::Crypto::Storage::kKeyAlgorithmHmacSha256);
#else
ot::TestHkdfSha256();
#endif
printf("All tests passed\n");
return 0;
}
+38 -11
View File
@@ -141,10 +141,15 @@ void TestHmacSha256(void)
{
struct TestCase
{
otCryptoKey mKey;
const uint8_t *mKey;
uint16_t mKeyLength;
const void *mData;
uint16_t mDataLength;
otCryptoSha256Hash mHash;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::KeyRef mKeyRef;
#endif
};
// Test-cases from RFC 4231.
@@ -218,12 +223,12 @@ void TestHmacSha256(void)
0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
}};
static const TestCase kTestCases[] = {
{{&kKey1[0], sizeof(kKey1), 0}, kData1, sizeof(kData1) - 1, kHash1},
{{reinterpret_cast<const uint8_t *>(&kKey2[0]), sizeof(kKey2) - 1, 0}, kData2, sizeof(kData2) - 1, kHash2},
{{&kKey3[0], sizeof(kKey3), 0}, kData3, sizeof(kData3), kHash3},
{{&kKey4[0], sizeof(kKey4), 0}, kData4, sizeof(kData4), kHash4},
{{&kKey5[0], sizeof(kKey5), 0}, kData5, sizeof(kData5) - 1, kHash5},
static TestCase kTestCases[] = {
{kKey1, sizeof(kKey1), kData1, sizeof(kData1) - 1, kHash1},
{reinterpret_cast<const uint8_t *>(kKey2), sizeof(kKey2) - 1, kData2, sizeof(kData2) - 1, kHash2},
{kKey3, sizeof(kKey3), kData3, sizeof(kData3), kHash3},
{kKey4, sizeof(kKey4), kData4, sizeof(kData4), kHash4},
{kKey5, sizeof(kKey5), kData5, sizeof(kData5) - 1, kHash5},
};
Instance *instance = testInitInstance();
@@ -239,12 +244,23 @@ void TestHmacSha256(void)
messagePool = &instance->Get<MessagePool>();
VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
for (const TestCase &testCase : kTestCases)
for (TestCase &testCase : kTestCases)
{
Crypto::HmacSha256 hmac;
Crypto::HmacSha256::Hash hash;
Crypto::Key key;
hmac.Start(static_cast<const Crypto::Key &>(testCase.mKey));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
SuccessOrQuit(Crypto::Storage::ImportKey(
testCase.mKeyRef, Crypto::Storage::kKeyTypeHmac, Crypto::Storage::kKeyAlgorithmHmacSha256,
Crypto::Storage::kUsageSignHash, Crypto::Storage::kTypeVolatile, testCase.mKey, testCase.mKeyLength));
key.SetAsKeyRef(testCase.mKeyRef);
#else
key.Set(testCase.mKey, testCase.mKeyLength);
#endif
hmac.Start(key);
hmac.Update(testCase.mData, testCase.mDataLength);
hmac.Finish(hash);
@@ -255,7 +271,7 @@ void TestHmacSha256(void)
index = 0;
for (const TestCase &testCase : kTestCases)
for (TestCase &testCase : kTestCases)
{
SuccessOrQuit(message->Append("Hello"));
offsets[index++] = message->GetLength();
@@ -269,12 +285,23 @@ void TestHmacSha256(void)
{
Crypto::HmacSha256 hmac;
Crypto::HmacSha256::Hash hash;
Crypto::Key key;
hmac.Start(static_cast<const Crypto::Key &>(testCase.mKey));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
key.SetAsKeyRef(testCase.mKeyRef);
#else
key.Set(testCase.mKey, testCase.mKeyLength);
#endif
hmac.Start(key);
hmac.Update(*message, offsets[index++], testCase.mDataLength);
hmac.Finish(hash);
VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash));
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(testCase.mKeyRef);
#endif
}
message->Free();
+34 -85
View File
@@ -38,6 +38,10 @@
#include <openthread/platform/ble.h>
#endif
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA)
#include <psa/crypto.h>
#endif
enum
{
FLASH_SWAP_SIZE = 2048,
@@ -226,6 +230,36 @@ exit:
return error;
}
#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/**
* When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no
* API to configure a dedicated non-default entropy source. It is documented that a future version of
* Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources.
*
* For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already
* uses CSPRNG, we will call it here as well.
*/
extern "C" psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
OT_UNUSED_VARIABLE(context);
otError error;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
error = otPlatEntropyGet(output, (uint16_t)output_size);
if (error == OT_ERROR_NONE)
{
*output_length = output_size;
status = PSA_SUCCESS;
}
return status;
}
#endif
static void DiagOutput(const char *aFormat, ...)
{
va_list args;
@@ -512,91 +546,6 @@ OT_TOOL_WEAK void otPlatInfraIfDhcp6PdClientSend(otInstance *aInstance,
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef,
otCryptoKeyType aKeyType,
otCryptoKeyAlgorithm aKeyAlgorithm,
int aKeyUsage,
otCryptoKeyStorage aKeyPersistence,
const uint8_t *aKey,
size_t aKeyLen)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aKeyType);
OT_UNUSED_VARIABLE(aKeyAlgorithm);
OT_UNUSED_VARIABLE(aKeyUsage);
OT_UNUSED_VARIABLE(aKeyPersistence);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aKeyLen);
return OT_ERROR_NONE;
}
otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aBuffer);
OT_UNUSED_VARIABLE(aBufferLen);
*aKeyLen = 0;
return OT_ERROR_NONE;
}
otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return OT_ERROR_NONE;
}
bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return false;
}
otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aPublicKey);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NONE;
}
otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,
const otPlatCryptoSha256Hash *aHash,
const otPlatCryptoEcdsaSignature *aSignature)
{
OT_UNUSED_VARIABLE(aKeyRef);
OT_UNUSED_VARIABLE(aHash);
OT_UNUSED_VARIABLE(aSignature);
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
{
OT_UNUSED_VARIABLE(aInstance);
+3
View File
@@ -131,6 +131,9 @@ void otPlatFree(void *aPtr)
free(aPtr);
}
void *otPlatCryptoCAlloc(size_t aNum, size_t aSize) { return calloc(aNum, aSize); }
void otPlatCryptoFree(void *aPtr) { free(aPtr); }
#endif
#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
+1
View File
@@ -28,6 +28,7 @@
if(NOT OT_EXTERNAL_MBEDTLS)
add_subdirectory(mbedtls)
add_subdirectory(mbedtls/native_its)
endif()
add_subdirectory(tcplp)
+28 -6
View File
@@ -27,8 +27,10 @@
#
set(OT_MBEDTLS_DEFAULT_CONFIG_FILE \"openthread-mbedtls-config.h\")
set(OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE \"openthread-psa-crypto-config.h\")
set(OT_MBEDTLS_CONFIG_FILE "" CACHE STRING "The mbedTLS config file")
set(OT_PSA_CRYPTO_CONFIG_FILE "" CACHE STRING "The PSA Crypto config file")
set(ENABLE_TESTING OFF CACHE BOOL "Disable mbedtls test" FORCE)
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable mbetls program" FORCE)
@@ -42,6 +44,8 @@ if(UNIFDEF_EXE)
endif()
find_program(SED_EXE sed)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-but-set-variable")
string(REPLACE "-Wconversion" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REPLACE "-Wconversion" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
@@ -63,15 +67,29 @@ if(UNIFDEFALL_EXE AND SED_EXE AND UNIFDEF_VERSION VERSION_GREATER_EQUAL 2.10)
COMMAND_EXPAND_LISTS
)
add_custom_target(openthread-mbedtls-config
DEPENDS openthread-mbedtls-config.h)
add_custom_command(OUTPUT openthread-psa-crypto-config.h
COMMAND ${UNIFDEFALL_EXE}
"'-D$<JOIN:$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>,';'-D>'"
"-I$<JOIN:$<TARGET_PROPERTY:ot-config,INTERFACE_INCLUDE_DIRECTORIES>,;-I>"
"-I$<JOIN:${OT_PUBLIC_INCLUDES},;-I>"
"-I${CMAKE_CURRENT_SOURCE_DIR}/repo/include"
"${CMAKE_CURRENT_SOURCE_DIR}/psa-crypto-config.h" |
${SED_EXE} '/openthread-core-config\.h/d' >
openthread-psa-crypto-config.h
MAIN_DEPENDENCY psa-crypto-config.h
COMMAND_EXPAND_LISTS
)
add_dependencies(ot-config openthread-mbedtls-config)
add_dependencies(mbedtls openthread-mbedtls-config)
add_dependencies(mbedx509 openthread-mbedtls-config)
add_dependencies(mbedcrypto openthread-mbedtls-config)
add_custom_target(openthread-mbedtls-config
DEPENDS openthread-mbedtls-config.h openthread-psa-crypto-config.h)
add_dependencies(ot-config openthread-mbedtls-config openthread-psa-crypto-config)
add_dependencies(mbedtls openthread-mbedtls-config openthread-psa-crypto-config)
add_dependencies(mbedx509 openthread-mbedtls-config openthread-psa-crypto-config)
add_dependencies(mbedcrypto openthread-mbedtls-config openthread-psa-crypto-config)
else()
configure_file(mbedtls-config.h openthread-mbedtls-config.h COPYONLY)
configure_file(psa-crypto-config.h openthread-psa-crypto-config.h COPYONLY)
endif()
target_include_directories(ot-config SYSTEM
@@ -82,6 +100,7 @@ target_include_directories(ot-config SYSTEM
target_compile_definitions(mbedtls
PUBLIC
"MBEDTLS_CONFIG_FILE=$<IF:$<BOOL:${OT_MBEDTLS_CONFIG_FILE}>,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>"
"MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$<IF:$<BOOL:${OT_PSA_CRYPTO_CONFIG_FILE}>,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>"
PRIVATE
$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>
)
@@ -96,6 +115,7 @@ target_include_directories(mbedtls
target_compile_definitions(mbedx509
PUBLIC
"MBEDTLS_CONFIG_FILE=$<IF:$<BOOL:${OT_MBEDTLS_CONFIG_FILE}>,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>"
"MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$<IF:$<BOOL:${OT_PSA_CRYPTO_CONFIG_FILE}>,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>"
PRIVATE
$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>
)
@@ -110,6 +130,7 @@ target_include_directories(mbedx509
target_compile_definitions(mbedcrypto
PUBLIC
"MBEDTLS_CONFIG_FILE=$<IF:$<BOOL:${OT_MBEDTLS_CONFIG_FILE}>,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>"
"MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$<IF:$<BOOL:${OT_PSA_CRYPTO_CONFIG_FILE}>,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>"
PRIVATE
$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>
)
@@ -119,4 +140,5 @@ target_include_directories(mbedcrypto
PRIVATE
${OT_PUBLIC_INCLUDES}
$<TARGET_PROPERTY:ot-config,INTERFACE_INCLUDE_DIRECTORIES>
native_its/include
)
+104 -49
View File
@@ -40,7 +40,11 @@
#include <openthread/platform/logging.h>
#include <openthread/platform/memory.h>
#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
// ==============================================================================
// mbedTLS legacy/PSA configuration
// ==============================================================================
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
#define MBEDTLS_AES_C
#if (MBEDTLS_VERSION_NUMBER >= 0x03050000)
@@ -66,19 +70,46 @@
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
#define MBEDTLS_MD_C
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
#define MBEDTLS_SHA224_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA256_SMALLER
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_TLS_ENABLE
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#define MBEDTLS_GCM_C
#endif
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#define MBEDTLS_ECDSA_DETERMINISTIC
#endif
#endif
#elif OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
#define MBEDTLS_USE_PSA_CRYPTO
#define MBEDTLS_PSA_CRYPTO_C
#define MBEDTLS_PSA_CRYPTO_CLIENT
#define MBEDTLS_PSA_CRYPTO_STORAGE_C
#define MBEDTLS_PSA_CRYPTO_CONFIG
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
#endif
// ==============================================================================
// SSL configuration
// ==============================================================================
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
@@ -93,6 +124,12 @@
#define MBEDTLS_SSL_SRV_C
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#endif
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#endif
@@ -101,45 +138,6 @@
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#define MBEDTLS_GCM_C
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#endif
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#define MBEDTLS_ECDSA_DETERMINISTIC
#endif
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PK_WRITE_C
#endif
#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */
#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */
#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */
#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */
#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
#define MBEDTLS_PLATFORM_STD_CALLOC otPlatCAlloc /**< Default allocator to use, can be undefined */
#define MBEDTLS_PLATFORM_STD_FREE otPlatFree /**< Default free to use, can be undefined */
#else
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#define MBEDTLS_SSL_MAX_CONTENT_LEN 2000 /**< Maxium fragment length in bytes */
#elif OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
@@ -152,6 +150,63 @@
#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
// ==============================================================================
// x509 & PK configuration
// ==============================================================================
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_TLS_ENABLE
#define MBEDTLS_BASE64_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#endif
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PK_WRITE_C
#endif
// ==============================================================================
// MPI configuration
// ==============================================================================
#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */
#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */
// ==============================================================================
// ECP configuration
// ==============================================================================
#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */
#endif
#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */
// ==============================================================================
// Platform configuration
// ==============================================================================
#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
#define MBEDTLS_PLATFORM_STD_CALLOC otPlatCryptoCAlloc /**< Default allocator to use, can be undefined */
#define MBEDTLS_PLATFORM_STD_FREE otPlatCryptoFree /**< Default free to use, can be undefined */
#else
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
#endif
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
#define MBEDTLS_ENTROPY_MAX_SOURCES 1
// Spans multiple lines to avoid being processed by unifdef
#if defined(\
MBEDTLS_USER_CONFIG_FILE)
+58
View File
@@ -0,0 +1,58 @@
# Copyright (c) 2025, 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.
#
config("openthread-native-its-config") {
include_dirs = [
"include",
]
}
static_library("openthread-native-its-file") {
sources = [
"src/file/its_file.c"
]
configs += [
":openthread-native-its-config",
]
defines = [ "OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE=1" ]
}
static_library("openthread-native-its-ram") {
sources = [
"src/ram/its_ram.c"
]
configs += [
":openthread-native-its-config",
]
defines = [ "OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_RAM=1" ]
}
+60
View File
@@ -0,0 +1,60 @@
#
# Copyright (c) 2025, 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.
#
add_library(openthread-native-its-file STATIC)
target_sources(openthread-native-its-file PRIVATE
src/file/its_file.c
)
target_include_directories(openthread-native-its-file PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
${OT_PUBLIC_INCLUDES}
$<TARGET_PROPERTY:ot-config,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(openthread-native-its-file
PRIVATE
$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>
PUBLIC
OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE=1
)
add_library(openthread-native-its-ram STATIC)
target_sources(openthread-native-its-ram PRIVATE
src/ram/its_ram.c
)
target_include_directories(openthread-native-its-ram PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
${OT_PUBLIC_INCLUDES}
$<TARGET_PROPERTY:ot-config,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(openthread-native-its-ram
PRIVATE
$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>
PUBLIC
OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_RAM=1
)
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2025, 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.
*/
#ifndef PSA_ERROR_H__
#define PSA_ERROR_H__
#include <stdint.h>
typedef int32_t psa_status_t;
#define PSA_SUCCESS ((psa_status_t)0)
#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132)
#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133)
#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134)
#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135)
#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139)
#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140)
#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142)
#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146)
#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149)
#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152)
#endif /* PSA_ERROR_H__ */
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2025, 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.
*/
#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H__
#define PSA_INTERNAL_TRUSTED_STORAGE_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "psa/error.h"
/** \brief Flags used when creating a data entry
*/
typedef uint32_t psa_storage_create_flags_t;
/** \brief A type for UIDs used for identifying data
*/
typedef uint64_t psa_storage_uid_t;
#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */
#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/
/**
* \brief A container for metadata associated with a specific uid
*/
struct psa_storage_info_t {
uint32_t size; /**< The size of the data associated with a uid **/
psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/
};
/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */
#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0)
#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */
#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */
/**
* \brief Create a new or modify an existing uid/value pair
*
* \param[in] aUid The identifier for the data
* \param[in] aDataLength The size in bytes of the data in `p_data`
* \param[in] aData A buffer containing the data
* \param[in] aCreateFlags The flags that the data will be stored with
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE
* \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`)
* is invalid, for example is `NULL` or references memory the caller cannot access
*/
psa_status_t psa_its_set(psa_storage_uid_t aUid,
uint32_t aDataLength,
const void *aData,
psa_storage_create_flags_t aCreateFlags);
/**
* \brief Retrieve the value associated with a provided uid
*
* \param[in] aUid The uid value
* \param[in] aDataOffset The starting offset of the data requested
* \param[in] aDataLength The amount of data requested (and the minimum allocated size of the `p_data` buffer)
* \param[out] aData The buffer where the data will be placed upon successful completion
* \param[out] aDataLengthOut The amount of data returned in the p_data buffer
*
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
* \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
* is invalid. For example is `NULL` or references memory the caller cannot access.
* In addition, this can also happen if an invalid offset was provided.
*/
psa_status_t psa_its_get(psa_storage_uid_t aUid,
uint32_t aDataOffset,
uint32_t aDataLength,
void *aData,
size_t *aDataLengthOut);
/**
* \brief Retrieve the metadata about the provided uid
*
* \param[in] aUid The uid value
* \param[out] aInfo A pointer to the `psa_storage_info_t` struct that will be populated with the metadata
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage
* \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted
* \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`)
* is invalid, for example is `NULL` or references memory the caller cannot access
*/
psa_status_t psa_its_get_info(psa_storage_uid_t aUid,
struct psa_storage_info_t *aInfo);
/**
* \brief Remove the provided key and its associated data from the storage
*
* \param[in] aUid The uid value
*
* \return A status indicating the success/failure of the operation
*
* \retval #PSA_SUCCESS The operation completed successfully
* \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage
* \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE
* \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error)
*/
psa_status_t psa_its_remove(psa_storage_uid_t aUid);
#ifdef __cplusplus
}
#endif
#endif /* PSA_INTERNAL_TRUSTED_STORAGE_H__ */
+384
View File
@@ -0,0 +1,384 @@
/*
* Copyright (c) 2025, 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 an exemplary ITS working on files.
*/
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <sys/stat.h>
#include <unistd.h>
#define VerifyOrExit(aCondition, aAction) \
do \
{ \
if (!(aCondition)) \
{ \
aAction; \
goto exit; \
} \
} while (0)
/**
* @def ITS_FILE_DEFAULT_FILE_PREFIX
*
* The default directory prefix if the user does not override it by changing
* the global variable @c gItsFileNamePrefix.
*/
#define ITS_FILE_DEFAULT_FILE_PREFIX "tmp/"
/**
* @def ITS_FILE_PATH_MAX
*
* The maximum allowed length (in bytes) for file paths.
*/
#define ITS_FILE_PATH_MAX 256
/**
* @def ITS_DIR_MODE
*
* The mode used when creating directories (0777 gives full permissions to owner,
* group, and others).
*/
#define ITS_DIR_MODE 0777
/**
* @def ITS_FILE_HEADER_SIZE
*
* The size (in bytes) of the file header: 4 bytes for flags plus 4 bytes for total data length.
*/
#define ITS_FILE_HEADER_SIZE (sizeof(uint32_t) + sizeof(uint32_t))
/**
* @def ITS_FILE_NAME_FORMAT
*
* The format string for building the file path.
*/
#define ITS_FILE_NAME_FORMAT "%suid_%llu.psa_its"
/**
* A global variable that determines where PSA ITS files are stored.
*
* By default, it is @ref ITS_FILE_DEFAULT_FILE_PREFIX. You can override
* it at runtime:
* @code
* gItsFileNamePrefix = "tmp/its_node_3_offset_12";
* @endcode
*/
const char *gItsFileNamePrefix = ITS_FILE_DEFAULT_FILE_PREFIX;
/**
* Ensures that the directory (specified by `gItsFileNamePrefix`) exists.
*/
static bool ensureDirectoryExists(void)
{
bool success = true;
struct stat st;
char filePrefix[ITS_FILE_PATH_MAX];
char *dir;
// Copy prefix to local buffer, because dirname() modifies its argument
strncpy(filePrefix, gItsFileNamePrefix, sizeof(filePrefix));
filePrefix[sizeof(filePrefix) - 1] = '\0';
dir = dirname(filePrefix);
// 1) Check if path already exists
if (stat(dir, &st) == 0)
{
// Exists - must be a directory
if (!S_ISDIR(st.st_mode))
{
success = false;
}
}
else
{
// Path doesn't exist, attempt to create one.
if (mkdir(dir, ITS_DIR_MODE) != 0)
{
// Retry with stat again.
if (stat(dir, &st) != 0 || !S_ISDIR(st.st_mode))
{
success = false;
}
}
}
return success;
}
/**
* Builds the file path for a given UID.
* Returns 0 on success, -1 on error.
*/
static int buildFilePath(psa_storage_uid_t aUid, char *aPath, size_t aPathSize)
{
int result = 0;
// Attempt to format
int ret = snprintf(aPath, aPathSize, ITS_FILE_NAME_FORMAT,
gItsFileNamePrefix, (unsigned long long)aUid);
// If ret < 0 or ret >= aPathSize, return an error.
VerifyOrExit((ret >= 0) && ((size_t)ret < aPathSize), result = -1);
exit:
return result;
}
/**
* Reads an 8-byte header from the given file:
* - 4 bytes for flags (psa_storage_create_flags_t)
* - 4 bytes for data length
*
* Returns 0 on success, -1 on error.
*/
static int readHeader(FILE *aFile, psa_storage_create_flags_t *aFlags, uint32_t *aDataLen)
{
int result = 0;
uint32_t flagsTmp;
uint32_t lenTmp;
// Read flags
VerifyOrExit(fread(&flagsTmp, sizeof(flagsTmp), 1, aFile) == 1, result = -1);
// Read length
VerifyOrExit(fread(&lenTmp, sizeof(lenTmp), 1, aFile) == 1, result = -1);
*aFlags = flagsTmp;
*aDataLen = lenTmp;
exit:
return result;
}
/**
* Writes an 8-byte header to the given file:
* - 4 bytes for flags
* - 4 bytes for data length
*
* Returns 0 on success, -1 on error.
*/
static int writeHeader(FILE *aFile, psa_storage_create_flags_t aFlags, uint32_t aDataLen)
{
int result = 0;
// Write flags
VerifyOrExit(fwrite(&aFlags, sizeof(aFlags), 1, aFile) == 1, result = -1);
// Write length
VerifyOrExit(fwrite(&aDataLen, sizeof(aDataLen), 1, aFile) == 1, result = -1);
exit:
return result;
}
psa_status_t psa_its_set(psa_storage_uid_t aUid,
uint32_t aDataLength,
const void *aData,
psa_storage_create_flags_t aCreateFlags)
{
psa_status_t status = PSA_SUCCESS;
FILE *file = NULL;
char path[ITS_FILE_PATH_MAX];
// Validate arguments
VerifyOrExit((aData != NULL && aDataLength > 0), status = PSA_ERROR_INVALID_ARGUMENT);
// Only NONE or WRITE_ONCE => no other flags supported
VerifyOrExit((aCreateFlags & ~(PSA_STORAGE_FLAG_WRITE_ONCE)) == 0, status = PSA_ERROR_NOT_SUPPORTED);
// Ensure directory
VerifyOrExit(ensureDirectoryExists(), status = PSA_ERROR_GENERIC_ERROR);
// Build path
VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR);
// If file exists, check WRITE_ONCE
file = fopen(path, "rb");
if (file)
{
psa_storage_create_flags_t oldFlags;
uint32_t oldLen;
if (readHeader(file, &oldFlags, &oldLen) == 0)
{
VerifyOrExit(!(oldFlags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED);
}
fclose(file);
file = NULL;
}
// Create/overwrite
file = fopen(path, "wb");
VerifyOrExit(file != NULL, status = PSA_ERROR_GENERIC_ERROR);
// Write header
VerifyOrExit(writeHeader(file, aCreateFlags, aDataLength) == 0, status = PSA_ERROR_GENERIC_ERROR);
// Write data
if (aDataLength > 0 && aData != NULL)
{
size_t written = fwrite(aData, 1, aDataLength, file);
VerifyOrExit(written == aDataLength, status = PSA_ERROR_GENERIC_ERROR);
}
exit:
if (file)
{
fclose(file);
}
return status;
}
psa_status_t psa_its_get(psa_storage_uid_t aUid,
uint32_t aDataOffset,
uint32_t aDataLength,
void *aData,
size_t *aDataLengthOut)
{
psa_status_t status = PSA_SUCCESS;
FILE *file = NULL;
char path[ITS_FILE_PATH_MAX];
VerifyOrExit(aDataLengthOut != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
if (aDataLength > 0)
{
VerifyOrExit(aData != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
}
VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR);
file = fopen(path, "rb");
VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST);
{
psa_storage_create_flags_t flags;
uint32_t totalLen;
VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR);
VerifyOrExit(aDataOffset <= totalLen, status = PSA_ERROR_INVALID_ARGUMENT);
size_t available = totalLen - aDataOffset;
size_t toCopy = (aDataLength <= available) ? aDataLength : available;
VerifyOrExit(fseek(file, aDataOffset, SEEK_CUR) == 0, status = PSA_ERROR_GENERIC_ERROR);
if (toCopy > 0 && aData != NULL)
{
VerifyOrExit(fread(aData, 1, toCopy, file) == toCopy, status = PSA_ERROR_GENERIC_ERROR);
}
*aDataLengthOut = toCopy;
}
exit:
if (file)
{
fclose(file);
}
return status;
}
psa_status_t psa_its_get_info(psa_storage_uid_t aUid,
struct psa_storage_info_t *aInfo)
{
psa_status_t status = PSA_SUCCESS;
FILE *file = NULL;
char path[ITS_FILE_PATH_MAX];
psa_storage_create_flags_t flags;
uint32_t totalLen;
VerifyOrExit(aInfo != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR);
file = fopen(path, "rb");
VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST);
VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR);
aInfo->size = totalLen;
aInfo->flags = flags;
exit:
if (file)
{
fclose(file);
}
return status;
}
psa_status_t psa_its_remove(psa_storage_uid_t aUid)
{
psa_status_t status = PSA_SUCCESS;
FILE *file = NULL;
char path[ITS_FILE_PATH_MAX];
psa_storage_create_flags_t flags;
uint32_t totalLen;
VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR);
file = fopen(path, "rb");
VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST);
VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR);
// If WRITE_ONCE is set, we cannot remove it.
VerifyOrExit(!(flags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED);
fclose(file);
file = NULL;
VerifyOrExit((unlink(path) == 0), status = PSA_ERROR_GENERIC_ERROR);
exit:
if (file)
{
fclose(file);
}
return status;
}
#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
+265
View File
@@ -0,0 +1,265 @@
/*
* Copyright (c) 2025, 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 a simple in-RAM PSA ITS backend for demonstration and testing.
*
* All data is stored in memory and is not persisted after process termination.
*/
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#include <string.h>
#define VerifyOrExit(aCondition, aAction) \
do \
{ \
if (!(aCondition)) \
{ \
aAction; \
goto exit; \
} \
} while (0)
/**
* @def RAM_ITS_MAX_KEYS
*
* The maximum number of PSA ITS entries that can be stored in RAM.
*/
#define RAM_ITS_MAX_KEYS 64
/**
* @def RAM_ITS_MAX_DATA_SIZE
*
* The maximum size (in bytes) of data that can be stored for each entry.
*/
#define RAM_ITS_MAX_DATA_SIZE 128
/**
* Represents a single PSA ITS record stored in RAM.
*
*/
typedef struct
{
bool mInUse; // Whether this slot is occupied
psa_storage_uid_t mUid; // Unique ID
psa_storage_create_flags_t mFlags; // Storage flags (e.g. WRITE_ONCE)
uint32_t mDataLen; // Current size of stored data
uint8_t mData[RAM_ITS_MAX_DATA_SIZE]; // Raw data storage
} RamItsEntry;
/**
* Array of entries for RAM-based ITS storage.
*
*/
static RamItsEntry sRamItsEntries[RAM_ITS_MAX_KEYS];
/**
* Finds an existing entry by UID.
*
* @param[in] aUid The UID value to search for.
*
* @returns The index of the matching entry, or -1 if not found.
*
*/
static int RamItsFindEntry(psa_storage_uid_t aUid)
{
for (int i = 0; i < RAM_ITS_MAX_KEYS; i++)
{
if (sRamItsEntries[i].mInUse && (sRamItsEntries[i].mUid == aUid))
{
return i;
}
}
return -1;
}
/**
* Finds a free slot in the storage array.
*
* @returns The index of a free slot, or -1 if none is available.
*
*/
static int RamItsFindFreeSlot(void)
{
for (int i = 0; i < RAM_ITS_MAX_KEYS; i++)
{
if (!sRamItsEntries[i].mInUse)
{
return i;
}
}
return -1;
}
psa_status_t psa_its_set(psa_storage_uid_t aUid,
uint32_t aDataLength,
const void *aData,
psa_storage_create_flags_t aCreateFlags)
{
psa_status_t status = PSA_SUCCESS;
int idx = -1;
VerifyOrExit(!(aData == NULL && aDataLength > 0), status = PSA_ERROR_INVALID_ARGUMENT);
// Allow only NONE or WRITE_ONCE flags. Any others => Not supported.
VerifyOrExit((aCreateFlags & ~(PSA_STORAGE_FLAG_WRITE_ONCE)) == 0,
status = PSA_ERROR_NOT_SUPPORTED);
// Data length must not exceed our internal buffer size.
VerifyOrExit(aDataLength <= RAM_ITS_MAX_DATA_SIZE, status = PSA_ERROR_INVALID_ARGUMENT);
// Find existing entry, if any.
idx = RamItsFindEntry(aUid);
if (idx >= 0)
{
// Entry already exists.
// If WRITE_ONCE is set, we cannot overwrite it.
VerifyOrExit(!(sRamItsEntries[idx].mFlags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED);
// Overwrite existing entry.
sRamItsEntries[idx].mDataLen = aDataLength;
if (aDataLength > 0 && aData != NULL)
{
memcpy(sRamItsEntries[idx].mData, aData, aDataLength);
}
sRamItsEntries[idx].mFlags = aCreateFlags;
}
else
{
// Need a new entry.
idx = RamItsFindFreeSlot();
VerifyOrExit(idx >= 0, status = PSA_ERROR_INSUFFICIENT_STORAGE);
sRamItsEntries[idx].mInUse = true;
sRamItsEntries[idx].mUid = aUid;
sRamItsEntries[idx].mFlags = aCreateFlags;
sRamItsEntries[idx].mDataLen = aDataLength;
if (aDataLength > 0 && aData != NULL)
{
memcpy(sRamItsEntries[idx].mData, aData, aDataLength);
}
}
exit:
return status;
}
psa_status_t psa_its_get(psa_storage_uid_t aUid,
uint32_t aDataOffset,
uint32_t aDataLength,
void *aData,
size_t *aDataLengthOut)
{
psa_status_t status = PSA_SUCCESS;
int idx;
// Validate pointers.
VerifyOrExit(aDataLengthOut != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
if (aDataLength > 0)
{
VerifyOrExit(aData != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
}
idx = RamItsFindEntry(aUid);
VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST);
// Check offset validity.
VerifyOrExit(aDataOffset <= sRamItsEntries[idx].mDataLen, status = PSA_ERROR_INVALID_ARGUMENT);
// Determine how many bytes to copy.
{
size_t available = sRamItsEntries[idx].mDataLen - aDataOffset;
size_t toCopy = (aDataLength <= available) ? aDataLength : available;
if (toCopy > 0)
{
memcpy(aData, &sRamItsEntries[idx].mData[aDataOffset], toCopy);
}
*aDataLengthOut = toCopy;
}
exit:
return status;
}
psa_status_t psa_its_get_info(psa_storage_uid_t aUid,
struct psa_storage_info_t *aInfo)
{
psa_status_t status = PSA_SUCCESS;
int idx;
VerifyOrExit(aInfo != NULL, status = PSA_ERROR_INVALID_ARGUMENT);
idx = RamItsFindEntry(aUid);
VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST);
aInfo->size = sRamItsEntries[idx].mDataLen;
aInfo->flags = sRamItsEntries[idx].mFlags;
exit:
return status;
}
psa_status_t psa_its_remove(psa_storage_uid_t aUid)
{
psa_status_t status = PSA_SUCCESS;
int idx;
idx = RamItsFindEntry(aUid);
VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST);
// If WRITE_ONCE is set, we cannot remove it.
VerifyOrExit(!(sRamItsEntries[idx].mFlags & PSA_STORAGE_FLAG_WRITE_ONCE),
status = PSA_ERROR_NOT_PERMITTED);
// Clear the slot.
memset(sRamItsEntries[idx].mData, 0, sizeof(sRamItsEntries[idx].mData));
sRamItsEntries[idx].mDataLen = 0;
sRamItsEntries[idx].mUid = 0;
sRamItsEntries[idx].mFlags = 0;
sRamItsEntries[idx].mInUse = false;
exit:
return status;
}
#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2025, 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.
*/
// Spans multiple lines to avoid being processed by unifdef
#ifndef \
PSA_CRYPTO_CONFIG_H
#define PSA_CRYPTO_CONFIG_H
#include "openthread-core-config.h"
#include <openthread/config.h>
#define PSA_WANT_ALG_CBC_NO_PADDING 1
#define PSA_WANT_ALG_CBC_PKCS7 1
#define PSA_WANT_ALG_CCM 1
#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1
#define PSA_WANT_ALG_CMAC 1
#define PSA_WANT_ALG_CFB 1
#define PSA_WANT_ALG_CTR 1
#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
#define PSA_WANT_ALG_ECB_NO_PADDING 1
#define PSA_WANT_ALG_ECDH 1
#define PSA_WANT_ALG_ECDSA 1
#define PSA_WANT_ALG_JPAKE 1
#define PSA_WANT_ALG_GCM 1
#define PSA_WANT_ALG_HKDF 1
#define PSA_WANT_ALG_HKDF_EXTRACT 1
#define PSA_WANT_ALG_HKDF_EXPAND 1
#define PSA_WANT_ALG_HMAC 1
#define PSA_WANT_ALG_PBKDF2_HMAC 1
#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1
#define PSA_WANT_ALG_RIPEMD160 1
#define PSA_WANT_ALG_SHA_1 1
#define PSA_WANT_ALG_SHA_224 1
#define PSA_WANT_ALG_SHA_256 1
#define PSA_WANT_ALG_TLS12_PRF 1
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
#define PSA_WANT_ECC_SECP_K1_256 1
#define PSA_WANT_ECC_SECP_R1_256 1
#define PSA_WANT_KEY_TYPE_DERIVE 1
#define PSA_WANT_KEY_TYPE_PASSWORD 1
#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
#define PSA_WANT_KEY_TYPE_HMAC 1
#define PSA_WANT_KEY_TYPE_AES 1
#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
#endif /* PSA_CRYPTO_CONFIG_H */