blob: 725ab27553a7002092f295a2788110c32218f885 [file] [log] [blame]
/*
* 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 <openthread/platform/crypto.h>
#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<otCryptoKeyType>(aKeyType),
static_cast<otCryptoKeyAlgorithm>(aKeyAlgorithm), aKeyUsage,
static_cast<otCryptoKeyStorage>(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<Key>
{
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<LiteralKey>, 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_