/* * 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. */ /** * @file * This file includes definitions for Crypto Internal Trusted Storage (ITS) APIs. */ #ifndef STORAGE_HPP_ #define STORAGE_HPP_ #include "openthread-core-config.h" #include #include "common/as_core_type.hpp" #include "common/clearable.hpp" #include "common/code_utils.hpp" #include "common/error.hpp" #include "common/non_copyable.hpp" namespace ot { namespace Crypto { #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE namespace Storage { /** * This enumeration defines the key types. * */ 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. }; /** * This enumeration defines the key algorithms. * */ enum KeyAlgorithm : uint8_t { kKeyAlgorithmVendor = OT_CRYPTO_KEY_ALG_VENDOR, ///< Key Algorithm: Vendor Defined. kKeyAlgorithmAesEcb = OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB. kKeyAlgorithmHmacSha256 = OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256. }; constexpr uint8_t kUsageNone = OT_CRYPTO_KEY_USAGE_NONE; ///< Key Usage: Key Usage is empty. constexpr uint8_t kUsageExport = OT_CRYPTO_KEY_USAGE_EXPORT; ///< Key Usage: Key can be exported. constexpr uint8_t kUsageEncrypt = OT_CRYPTO_KEY_USAGE_ENCRYPT; ///< Key Usage: Encrypt (vendor defined). 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: HMAC SHA-256. /** * This enumeration defines the key storage types. * */ enum StorageType : uint8_t { kTypeVolatile = OT_CRYPTO_KEY_STORAGE_VOLATILE, ///< Key is volatile. kTypePersistent = OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key is persistent. }; /** * This datatype represents the key reference. * */ typedef otCryptoKeyRef KeyRef; constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1). constexpr KeyRef kNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1; constexpr KeyRef kPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2; constexpr KeyRef kActiveDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 3; constexpr KeyRef kActiveDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 4; constexpr KeyRef kPendingDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 5; constexpr KeyRef kPendingDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 6; /** * Determine if a given `KeyRef` is valid or not. * * @param[in] aKeyRef The `KeyRef` to check. * * @retval TRUE If @p aKeyRef is valid. * @retval FALSE If @p aKeyRef is not valid. * */ inline bool IsKeyRefValid(KeyRef aKeyRef) { return (aKeyRef < kInvalidKeyRef); } /** * Import a key into PSA ITS. * * @param[in,out] aKeyRef Reference to the key ref to be used for crypto operations. * @param[in] aKeyType Key Type encoding for the key. * @param[in] aKeyAlgorithm Key algorithm encoding for the key. * @param[in] aKeyUsage Key Usage encoding for the key. * @param[in] aStorageType Key storage type. * @param[in] aKey Actual key to be imported. * @param[in] aKeyLen Length of the key to be imported. * * @retval kErrorNone Successfully imported the key. * @retval kErrorFailed Failed to import the key. * @retval kErrorInvalidArgs @p aKey was set to `nullptr`. * */ inline Error ImportKey(KeyRef & aKeyRef, KeyType aKeyType, KeyAlgorithm aKeyAlgorithm, int aKeyUsage, StorageType aStorageType, const uint8_t *aKey, size_t aKeyLen) { return otPlatCryptoImportKey(&aKeyRef, static_cast(aKeyType), static_cast(aKeyAlgorithm), aKeyUsage, static_cast(aStorageType), aKey, aKeyLen); } /** * Export a key stored in PSA ITS. * * @param[in] aKeyRef The key ref to be used for crypto operations. * @param[out] aBuffer Pointer to the buffer where key needs to be exported. * @param[in] aBufferLen Length of the buffer passed to store the exported key. * @param[out] aKeyLen Reference to variable to return the length of the exported key. * * @retval kErrorNone Successfully exported @p aKeyRef. * @retval kErrorFailed Failed to export @p aKeyRef. * @retval kErrorInvalidArgs @p aBuffer was `nullptr`. * */ inline Error ExportKey(KeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t &aKeyLen) { return otPlatCryptoExportKey(aKeyRef, aBuffer, aBufferLen, &aKeyLen); } /** * Destroy a key stored in PSA ITS. * * @param[in] aKeyRef The key ref to be removed. * */ inline void DestroyKey(KeyRef aKeyRef) { if (IsKeyRefValid(aKeyRef)) { IgnoreError(otPlatCryptoDestroyKey(aKeyRef)); } } /** * Check if the keyRef passed has an associated key in PSA ITS. * * @param[in] aKeyRef The Key Ref for to check. * * @retval true Key Ref passed has a key associated in PSA. * @retval false Key Ref passed is invalid and has no key associated in PSA. * */ inline bool HasKey(KeyRef aKeyRef) { return otPlatCryptoHasKey(aKeyRef); } } // namespace Storage #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE /** * This class represents a crypto key. * * The `Key` can represent a literal key (i.e., a pointer to a byte array containing the key along with a key length) * or a `KeyRef` (if `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled). * */ class Key : public otCryptoKey, public Clearable { public: /** * This method sets the `Key` as a literal key from a given byte array and length. * * @param[in] aKeyBytes A pointer to buffer containing the key. * @param[in] aKeyLength The key length (number of bytes in @p akeyBytes). * */ void Set(const uint8_t *aKeyBytes, uint16_t aKeyLength) { mKey = aKeyBytes; mKeyLength = aKeyLength; } /** * This method gets the pointer to the bye array containing the key. * * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this * method returns `nullptr`. * * @returns The pointer to the byte array containing the key, or `nullptr` if the `Key` represents a `KeyRef` * */ const uint8_t *GetBytes(void) const { return mKey; } /** * This method gets the key length (number of bytes). * * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this * method returns zero. * * @returns The key length (number of bytes in the byte array from `GetBytes()`), or zero if `Key` represents a * `keyRef`. * */ uint16_t GetLength(void) const { return mKeyLength; } #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE /** * This method indicates whether or not the key is represented as a `KeyRef`. * * @retval TRUE The `Key` represents a `KeyRef` * @retval FALSE The `Key` represents a literal key. * */ bool IsKeyRef(void) const { return (mKey == nullptr); } /** * This method gets the `KeyRef`. * * This method MUST be used when `IsKeyRef()` returns `true`, otherwise its behavior is undefined. * * @returns The `KeyRef` associated with `Key`. * */ Storage::KeyRef GetKeyRef(void) const { return mKeyRef; } /** * This method sets the `Key` as a `KeyRef`. * * @param[in] aKeyRef The `KeyRef` to set from. * */ void SetAsKeyRef(Storage::KeyRef aKeyRef) { mKey = nullptr; mKeyLength = 0; mKeyRef = aKeyRef; } /** * This method extracts and return the literal key when the key is represented as a `KeyRef` * * This method MUST be used when `IsKeyRef()` returns `true`. * * @param[out] aKeyBuffer Pointer to a byte array buffer to place the extracted key. * @param[in,out] aKeyLength On input, the size of @p aKeyBuffer. * On exit, returns the key length (number of bytes written in @p aKeyBuffer). * * @retval kErrorNone Successfully extracted the key, @p aKeyBuffer and @p aKeyLength are updated. * @retval kErrorNoBufs Key does not fit in @p aKeyBuffer (extracted key length is larger than @p aKeyLength). * */ Error ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const; #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE }; /** * This class represents a literal key derived from a `Key`. * */ class LiteralKey : public Clearable, private NonCopyable { public: static constexpr uint16_t kMaxSize = 32; ///< Maximum size of the key. /** * This constructor initializes the `LiteralKey` from a given `Key`. * * If the @p aKey is itself represents a literal key the same key buffer pointers are used. If the @p aKey is * a `KeyRef` then the literal key is extracted. In this case, the extracted key MUST be smaller than `kMaxSize`. * * @param[in] aKey The key to convert from. * */ explicit LiteralKey(const Key &aKey); /* * This method gets the pointer to the byte array containing the literal key. * * @returns The pointer to the byte array containing the literal key. * */ const uint8_t *GetBytes(void) const { return mKey; } /** * This method gets the key length. * * @returns The key length (number of bytes in the byte array from `GetBytes()`). * */ uint16_t GetLength(void) const { return mLength; } private: const uint8_t *mKey; uint16_t mLength; #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE uint8_t mBuffer[kMaxSize]; #endif }; } // namespace Crypto DefineCoreType(otCryptoKey, Crypto::Key); } // namespace ot #endif // STORAGE_HPP_