• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for Crypto Internal Trusted Storage (ITS) APIs.
32  */
33 
34 #ifndef STORAGE_HPP_
35 #define STORAGE_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/platform/crypto.h>
40 
41 #include "common/as_core_type.hpp"
42 #include "common/clearable.hpp"
43 #include "common/code_utils.hpp"
44 #include "common/error.hpp"
45 #include "common/locator.hpp"
46 #include "common/non_copyable.hpp"
47 
48 namespace ot {
49 namespace Crypto {
50 
51 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
52 
53 namespace Storage {
54 
55 /**
56  * Defines the key types.
57  */
58 enum KeyType : uint8_t
59 {
60     kKeyTypeRaw   = OT_CRYPTO_KEY_TYPE_RAW,   ///< Key Type: Raw Data.
61     kKeyTypeAes   = OT_CRYPTO_KEY_TYPE_AES,   ///< Key Type: AES.
62     kKeyTypeHmac  = OT_CRYPTO_KEY_TYPE_HMAC,  ///< Key Type: HMAC.
63     kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA.
64 };
65 
66 /**
67  * Defines the key algorithms.
68  */
69 enum KeyAlgorithm : uint8_t
70 {
71     kKeyAlgorithmVendor     = OT_CRYPTO_KEY_ALG_VENDOR,       ///< Key Algorithm: Vendor Defined.
72     kKeyAlgorithmAesEcb     = OT_CRYPTO_KEY_ALG_AES_ECB,      ///< Key Algorithm: AES ECB.
73     kKeyAlgorithmHmacSha256 = OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256.
74     kKeyAlgorithmEcdsa      = OT_CRYPTO_KEY_ALG_ECDSA,        ///< Key Algorithm: ECDSA.
75 };
76 
77 constexpr uint8_t kUsageNone       = OT_CRYPTO_KEY_USAGE_NONE;        ///< Key Usage: Key Usage is empty.
78 constexpr uint8_t kUsageExport     = OT_CRYPTO_KEY_USAGE_EXPORT;      ///< Key Usage: Key can be exported.
79 constexpr uint8_t kUsageEncrypt    = OT_CRYPTO_KEY_USAGE_ENCRYPT;     ///< Key Usage: Encrypt (vendor defined).
80 constexpr uint8_t kUsageDecrypt    = OT_CRYPTO_KEY_USAGE_DECRYPT;     ///< Key Usage: AES ECB.
81 constexpr uint8_t kUsageSignHash   = OT_CRYPTO_KEY_USAGE_SIGN_HASH;   ///< Key Usage: Sign Hash.
82 constexpr uint8_t kUsageVerifyHash = OT_CRYPTO_KEY_USAGE_VERIFY_HASH; ///< Key Usage: Verify Hash.
83 
84 /**
85  * Defines the key storage types.
86  */
87 enum StorageType : uint8_t
88 {
89     kTypeVolatile   = OT_CRYPTO_KEY_STORAGE_VOLATILE,   ///< Key is volatile.
90     kTypePersistent = OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key is persistent.
91 };
92 
93 /**
94  * This datatype represents the key reference.
95  */
96 typedef otCryptoKeyRef KeyRef;
97 
98 constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
99 
100 #if OPENTHREAD_FTD || OPENTHREAD_MTD
101 
102 /**
103  * Manages and selects the `KeyRef` values.
104  */
105 class KeyRefManager : public InstanceLocator
106 {
107 public:
108     /**
109      * Represents difference `KeyRef` types.
110      */
111     enum Type : uint8_t
112     {
113         kNetworkKey               = 1,
114         kPskc                     = 2,
115         kActiveDatasetNetworkKey  = 3,
116         kActiveDatasetPskc        = 4,
117         kPendingDatasetNetworkKey = 5,
118         kPendingDatasetPskc       = 6,
119         kEcdsa                    = 7,
120     };
121 
122     /**
123      * Initializes the `KeyRefManager`.
124      *
125      * @param[in]  aInstance     A reference to the OpenThread instance.
126      */
KeyRefManager(Instance & aInstance)127     explicit KeyRefManager(Instance &aInstance)
128         : InstanceLocator(aInstance)
129 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
130         , mExtraOffset(0)
131 #endif
132     {
133     }
134 
135     /**
136      * Determines the `KeyRef` to use for a given `Type`.
137      *
138      * @param[in] aType  The key ref type.
139      *
140      * @returns The `KeyRef` associated with @p aType.
141      */
KeyRefFor(Type aType)142     KeyRef KeyRefFor(Type aType)
143     {
144         KeyRef keyRef = kPsaItsNvmOffset + aType;
145 
146 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
147         keyRef += mExtraOffset;
148 #endif
149         return keyRef;
150     }
151 
152     /**
153      * Delete all the persistent keys.
154      */
155     void DestroyPersistentKeys(void);
156 
157 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
158     static constexpr uint32_t kKeyRefExtraOffset = 32; ///< Recommended extra offset to use.
159 
160     /**
161      * Sets the additional `KeyRef` offset value to use when determining the `KeyRef`s.
162      *
163      * This is intended for when `MULTIPLE_INSTANCE_ENABLE` is enabled to ensure different `ot::Instance`s use
164      * different `KeyRef` value ranges.
165      *
166      * @param[in] aOffset  The offset value.
167      */
SetKeyRefExtraOffset(uint32_t aOffset)168     void SetKeyRefExtraOffset(uint32_t aOffset) { mExtraOffset = aOffset; }
169 #endif
170 
171 private:
172     static constexpr KeyRef kPsaItsNvmOffset = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET;
173 
174 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
175     uint32_t mExtraOffset;
176 #endif
177 };
178 
179 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
180 
181 /**
182  * Determine if a given `KeyRef` is valid or not.
183  *
184  * @param[in] aKeyRef   The `KeyRef` to check.
185  *
186  * @retval TRUE   If @p aKeyRef is valid.
187  * @retval FALSE  If @p aKeyRef is not valid.
188  */
IsKeyRefValid(KeyRef aKeyRef)189 inline bool IsKeyRefValid(KeyRef aKeyRef) { return (aKeyRef < kInvalidKeyRef); }
190 
191 /**
192  * Import a key into PSA ITS.
193  *
194  * @param[in,out] aKeyRef          Reference to the key ref to be used for crypto operations.
195  * @param[in]     aKeyType         Key Type encoding for the key.
196  * @param[in]     aKeyAlgorithm    Key algorithm encoding for the key.
197  * @param[in]     aKeyUsage        Key Usage encoding for the key.
198  * @param[in]     aStorageType     Key storage type.
199  * @param[in]     aKey             Actual key to be imported.
200  * @param[in]     aKeyLen          Length of the key to be imported.
201  *
202  * @retval kErrorNone          Successfully imported the key.
203  * @retval kErrorFailed        Failed to import the key.
204  * @retval kErrorInvalidArgs   @p aKey was set to `nullptr`.
205  */
ImportKey(KeyRef & aKeyRef,KeyType aKeyType,KeyAlgorithm aKeyAlgorithm,int aKeyUsage,StorageType aStorageType,const uint8_t * aKey,size_t aKeyLen)206 inline Error ImportKey(KeyRef        &aKeyRef,
207                        KeyType        aKeyType,
208                        KeyAlgorithm   aKeyAlgorithm,
209                        int            aKeyUsage,
210                        StorageType    aStorageType,
211                        const uint8_t *aKey,
212                        size_t         aKeyLen)
213 {
214     return otPlatCryptoImportKey(&aKeyRef, static_cast<otCryptoKeyType>(aKeyType),
215                                  static_cast<otCryptoKeyAlgorithm>(aKeyAlgorithm), aKeyUsage,
216                                  static_cast<otCryptoKeyStorage>(aStorageType), aKey, aKeyLen);
217 }
218 
219 /**
220  * Export a key stored in PSA ITS.
221  *
222  * @param[in]   aKeyRef        The key ref to be used for crypto operations.
223  * @param[out]  aBuffer        Pointer to the buffer where key needs to be exported.
224  * @param[in]   aBufferLen     Length of the buffer passed to store the exported key.
225  * @param[out]  aKeyLen        Reference to variable to return the length of the exported key.
226  *
227  * @retval kErrorNone          Successfully exported  @p aKeyRef.
228  * @retval kErrorFailed        Failed to export @p aKeyRef.
229  * @retval kErrorInvalidArgs   @p aBuffer was `nullptr`.
230  */
ExportKey(KeyRef aKeyRef,uint8_t * aBuffer,size_t aBufferLen,size_t & aKeyLen)231 inline Error ExportKey(KeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t &aKeyLen)
232 {
233     return otPlatCryptoExportKey(aKeyRef, aBuffer, aBufferLen, &aKeyLen);
234 }
235 
236 /**
237  * Destroy a key stored in PSA ITS.
238  *
239  * @param[in]   aKeyRef   The key ref to be removed.
240  */
DestroyKey(KeyRef aKeyRef)241 inline void DestroyKey(KeyRef aKeyRef)
242 {
243     if (IsKeyRefValid(aKeyRef))
244     {
245         IgnoreError(otPlatCryptoDestroyKey(aKeyRef));
246     }
247 }
248 
249 /**
250  * Check if the keyRef passed has an associated key in PSA ITS.
251  *
252  * @param[in]  aKeyRef          The Key Ref for to check.
253  *
254  * @retval true                 Key Ref passed has a key associated in PSA.
255  * @retval false                Key Ref passed is invalid and has no key associated in PSA.
256  */
HasKey(KeyRef aKeyRef)257 inline bool HasKey(KeyRef aKeyRef) { return otPlatCryptoHasKey(aKeyRef); }
258 
259 } // namespace Storage
260 
261 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
262 
263 /**
264  * Represents a crypto key.
265  *
266  * The `Key` can represent a literal key (i.e., a pointer to a byte array containing the key along with a key length)
267  * or a `KeyRef` (if `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled).
268  */
269 class Key : public otCryptoKey, public Clearable<Key>
270 {
271 public:
272     /**
273      * Sets the `Key` as a literal key from a given byte array and length.
274      *
275      * @param[in] aKeyBytes   A pointer to buffer containing the key.
276      * @param[in] aKeyLength  The key length (number of bytes in @p aKeyBytes).
277      */
Set(const uint8_t * aKeyBytes,uint16_t aKeyLength)278     void Set(const uint8_t *aKeyBytes, uint16_t aKeyLength)
279     {
280         mKey       = aKeyBytes;
281         mKeyLength = aKeyLength;
282     }
283 
284     /**
285      * Gets the pointer to the bye array containing the key.
286      *
287      * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this
288      * method returns `nullptr`.
289      *
290      * @returns The pointer to the byte array containing the key, or `nullptr` if the `Key` represents a `KeyRef`
291      */
GetBytes(void) const292     const uint8_t *GetBytes(void) const { return mKey; }
293 
294     /**
295      * Gets the key length (number of bytes).
296      *
297      * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this
298      * method returns zero.
299      *
300      * @returns The key length (number of bytes in the byte array from `GetBytes()`), or zero if `Key` represents a
301      *          `keyRef`.
302      */
GetLength(void) const303     uint16_t GetLength(void) const { return mKeyLength; }
304 
305 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
306     /**
307      * Indicates whether or not the key is represented as a `KeyRef`.
308      *
309      * @retval TRUE  The `Key` represents a `KeyRef`
310      * @retval FALSE The `Key` represents a literal key.
311      */
IsKeyRef(void) const312     bool IsKeyRef(void) const { return (mKey == nullptr); }
313 
314     /**
315      * Gets the `KeyRef`.
316      *
317      * MUST be used when `IsKeyRef()` returns `true`, otherwise its behavior is undefined.
318      *
319      * @returns The `KeyRef` associated with `Key`.
320      */
GetKeyRef(void) const321     Storage::KeyRef GetKeyRef(void) const { return mKeyRef; }
322 
323     /**
324      * Sets the `Key` as a `KeyRef`.
325      *
326      * @param[in] aKeyRef   The `KeyRef` to set from.
327      */
SetAsKeyRef(Storage::KeyRef aKeyRef)328     void SetAsKeyRef(Storage::KeyRef aKeyRef)
329     {
330         mKey       = nullptr;
331         mKeyLength = 0;
332         mKeyRef    = aKeyRef;
333     }
334 
335     /**
336      * Extracts and return the literal key when the key is represented as a `KeyRef`
337      *
338      * MUST be used when `IsKeyRef()` returns `true`.
339      *
340      * @param[out]     aKeyBuffer  Pointer to a byte array buffer to place the extracted key.
341      * @param[in,out]  aKeyLength  On input, the size of @p aKeyBuffer.
342      *                             On exit, returns the key length (number of bytes written in @p aKeyBuffer).
343      *
344      * @retval kErrorNone    Successfully extracted the key, @p aKeyBuffer and @p aKeyLength are updated.
345      * @retval kErrorNoBufs  Key does not fit in @p aKeyBuffer (extracted key length is larger than @p aKeyLength).
346      */
347     Error ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const;
348 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
349 };
350 
351 /**
352  * Represents a literal key derived from a `Key`.
353  */
354 class LiteralKey : public Clearable<LiteralKey>, private NonCopyable
355 {
356 public:
357     static constexpr uint16_t kMaxSize = 32; ///< Maximum size of the key.
358 
359     /**
360      * Initializes the `LiteralKey` from a given `Key`.
361      *
362      * If the @p aKey is itself represents a literal key the same key buffer pointers are used. If the @p aKey is
363      * a `KeyRef` then the literal key is extracted. In this case, the extracted key MUST be smaller than `kMaxSize`.
364      *
365      * @param[in] aKey   The key to convert from.
366      */
367     explicit LiteralKey(const Key &aKey);
368 
369     /*
370      * Gets the pointer to the byte array containing the literal key.
371      *
372      * @returns The pointer to the byte array containing the literal key.
373      */
GetBytes(void) const374     const uint8_t *GetBytes(void) const { return mKey; }
375 
376     /**
377      * Gets the key length.
378      *
379      * @returns The key length (number of bytes in the byte array from `GetBytes()`).
380      */
GetLength(void) const381     uint16_t GetLength(void) const { return mLength; }
382 
383 private:
384     const uint8_t *mKey;
385     uint16_t       mLength;
386 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
387     uint8_t mBuffer[kMaxSize];
388 #endif
389 };
390 
391 } // namespace Crypto
392 
393 DefineCoreType(otCryptoKey, Crypto::Key);
394 
395 } // namespace ot
396 
397 #endif // STORAGE_HPP_
398