• 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/non_copyable.hpp"
46 
47 namespace ot {
48 namespace Crypto {
49 
50 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
51 
52 namespace Storage {
53 
54 /**
55  * This enumeration defines the key types.
56  *
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 };
64 
65 /**
66  * This enumeration defines the key algorithms.
67  *
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 };
75 
76 constexpr uint8_t kUsageNone     = OT_CRYPTO_KEY_USAGE_NONE;      ///< Key Usage: Key Usage is empty.
77 constexpr uint8_t kUsageExport   = OT_CRYPTO_KEY_USAGE_EXPORT;    ///< Key Usage: Key can be exported.
78 constexpr uint8_t kUsageEncrypt  = OT_CRYPTO_KEY_USAGE_ENCRYPT;   ///< Key Usage: Encrypt (vendor defined).
79 constexpr uint8_t kUsageDecrypt  = OT_CRYPTO_KEY_USAGE_DECRYPT;   ///< Key Usage: AES ECB.
80 constexpr uint8_t kUsageSignHash = OT_CRYPTO_KEY_USAGE_SIGN_HASH; ///< Key Usage: HMAC SHA-256.
81 
82 /**
83  * This enumeration defines the key storage types.
84  *
85  */
86 enum StorageType : uint8_t
87 {
88     kTypeVolatile   = OT_CRYPTO_KEY_STORAGE_VOLATILE,   ///< Key is volatile.
89     kTypePersistent = OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key is persistent.
90 };
91 
92 /**
93  * This datatype represents the key reference.
94  *
95  */
96 typedef otCryptoKeyRef KeyRef;
97 
98 constexpr KeyRef kInvalidKeyRef               = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
99 constexpr KeyRef kNetworkKeyRef               = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1;
100 constexpr KeyRef kPskcRef                     = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2;
101 constexpr KeyRef kActiveDatasetNetworkKeyRef  = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 3;
102 constexpr KeyRef kActiveDatasetPskcRef        = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 4;
103 constexpr KeyRef kPendingDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 5;
104 constexpr KeyRef kPendingDatasetPskcRef       = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 6;
105 
106 /**
107  * Determine if a given `KeyRef` is valid or not.
108  *
109  * @param[in] aKeyRef   The `KeyRef` to check.
110  *
111  * @retval TRUE   If @p aKeyRef is valid.
112  * @retval FALSE  If @p aKeyRef is not valid.
113  *
114  */
IsKeyRefValid(KeyRef aKeyRef)115 inline bool IsKeyRefValid(KeyRef aKeyRef)
116 {
117     return (aKeyRef < kInvalidKeyRef);
118 }
119 
120 /**
121  * Import a key into PSA ITS.
122  *
123  * @param[in,out] aKeyRef          Reference to the key ref to be used for crypto operations.
124  * @param[in]     aKeyType         Key Type encoding for the key.
125  * @param[in]     aKeyAlgorithm    Key algorithm encoding for the key.
126  * @param[in]     aKeyUsage        Key Usage encoding for the key.
127  * @param[in]     aStorageType     Key storage type.
128  * @param[in]     aKey             Actual key to be imported.
129  * @param[in]     aKeyLen          Length of the key to be imported.
130  *
131  * @retval kErrorNone          Successfully imported the key.
132  * @retval kErrorFailed        Failed to import the key.
133  * @retval kErrorInvalidArgs   @p aKey was set to `nullptr`.
134  *
135  */
ImportKey(KeyRef & aKeyRef,KeyType aKeyType,KeyAlgorithm aKeyAlgorithm,int aKeyUsage,StorageType aStorageType,const uint8_t * aKey,size_t aKeyLen)136 inline Error ImportKey(KeyRef &       aKeyRef,
137                        KeyType        aKeyType,
138                        KeyAlgorithm   aKeyAlgorithm,
139                        int            aKeyUsage,
140                        StorageType    aStorageType,
141                        const uint8_t *aKey,
142                        size_t         aKeyLen)
143 {
144     return otPlatCryptoImportKey(&aKeyRef, static_cast<otCryptoKeyType>(aKeyType),
145                                  static_cast<otCryptoKeyAlgorithm>(aKeyAlgorithm), aKeyUsage,
146                                  static_cast<otCryptoKeyStorage>(aStorageType), aKey, aKeyLen);
147 }
148 
149 /**
150  * Export a key stored in PSA ITS.
151  *
152  * @param[in]   aKeyRef        The key ref to be used for crypto operations.
153  * @param[out]  aBuffer        Pointer to the buffer where key needs to be exported.
154  * @param[in]   aBufferLen     Length of the buffer passed to store the exported key.
155  * @param[out]  aKeyLen        Reference to variable to return the length of the exported key.
156  *
157  * @retval kErrorNone          Successfully exported  @p aKeyRef.
158  * @retval kErrorFailed        Failed to export @p aKeyRef.
159  * @retval kErrorInvalidArgs   @p aBuffer was `nullptr`.
160  *
161  */
ExportKey(KeyRef aKeyRef,uint8_t * aBuffer,size_t aBufferLen,size_t & aKeyLen)162 inline Error ExportKey(KeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t &aKeyLen)
163 {
164     return otPlatCryptoExportKey(aKeyRef, aBuffer, aBufferLen, &aKeyLen);
165 }
166 
167 /**
168  * Destroy a key stored in PSA ITS.
169  *
170  * @param[in]   aKeyRef   The key ref to be removed.
171  *
172  */
DestroyKey(KeyRef aKeyRef)173 inline void DestroyKey(KeyRef aKeyRef)
174 {
175     if (IsKeyRefValid(aKeyRef))
176     {
177         IgnoreError(otPlatCryptoDestroyKey(aKeyRef));
178     }
179 }
180 
181 /**
182  * Check if the keyRef passed has an associated key in PSA ITS.
183  *
184  * @param[in]  aKeyRef          The Key Ref for to check.
185  *
186  * @retval true                 Key Ref passed has a key associated in PSA.
187  * @retval false                Key Ref passed is invalid and has no key associated in PSA.
188  *
189  */
HasKey(KeyRef aKeyRef)190 inline bool HasKey(KeyRef aKeyRef)
191 {
192     return otPlatCryptoHasKey(aKeyRef);
193 }
194 
195 } // namespace Storage
196 
197 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
198 
199 /**
200  * This class represents a crypto key.
201  *
202  * The `Key` can represent a literal key (i.e., a pointer to a byte array containing the key along with a key length)
203  * or a `KeyRef` (if `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled).
204  *
205  */
206 class Key : public otCryptoKey, public Clearable<Key>
207 {
208 public:
209     /**
210      * This method sets the `Key` as a literal key from a given byte array and length.
211      *
212      * @param[in] aKeyBytes   A pointer to buffer containing the key.
213      * @param[in] aKeyLength  The key length (number of bytes in @p akeyBytes).
214      *
215      */
Set(const uint8_t * aKeyBytes,uint16_t aKeyLength)216     void Set(const uint8_t *aKeyBytes, uint16_t aKeyLength)
217     {
218         mKey       = aKeyBytes;
219         mKeyLength = aKeyLength;
220     }
221 
222     /**
223      * This method gets the pointer to the bye array containing the key.
224      *
225      * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this
226      * method returns `nullptr`.
227      *
228      * @returns The pointer to the byte array containing the key, or `nullptr` if the `Key` represents a `KeyRef`
229      *
230      */
GetBytes(void) const231     const uint8_t *GetBytes(void) const { return mKey; }
232 
233     /**
234      * This method gets the key length (number of bytes).
235      *
236      * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this
237      * method returns zero.
238      *
239      * @returns The key length (number of bytes in the byte array from `GetBytes()`), or zero if `Key` represents a
240      *          `keyRef`.
241      *
242      */
GetLength(void) const243     uint16_t GetLength(void) const { return mKeyLength; }
244 
245 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
246     /**
247      * This method indicates whether or not the key is represented as a `KeyRef`.
248      *
249      * @retval TRUE  The `Key` represents a `KeyRef`
250      * @retval FALSE The `Key` represents a literal key.
251      *
252      */
IsKeyRef(void) const253     bool IsKeyRef(void) const { return (mKey == nullptr); }
254 
255     /**
256      * This method gets the `KeyRef`.
257      *
258      * This method MUST be used when `IsKeyRef()` returns `true`, otherwise its behavior is undefined.
259      *
260      * @returns The `KeyRef` associated with `Key`.
261      *
262      */
GetKeyRef(void) const263     Storage::KeyRef GetKeyRef(void) const { return mKeyRef; }
264 
265     /**
266      * This method sets the `Key` as a `KeyRef`.
267      *
268      * @param[in] aKeyRef   The `KeyRef` to set from.
269      *
270      */
SetAsKeyRef(Storage::KeyRef aKeyRef)271     void SetAsKeyRef(Storage::KeyRef aKeyRef)
272     {
273         mKey       = nullptr;
274         mKeyLength = 0;
275         mKeyRef    = aKeyRef;
276     }
277 
278     /**
279      * This method extracts and return the literal key when the key is represented as a `KeyRef`
280      *
281      * This method MUST be used when `IsKeyRef()` returns `true`.
282      *
283      * @param[out]     aKeyBuffer  Pointer to a byte array buffer to place the extracted key.
284      * @param[in,out]  aKeyLength  On input, the size of @p aKeyBuffer.
285      *                             On exit, returns the key length (number of bytes written in @p aKeyBuffer).
286      *
287      * @retval kErrorNone    Successfully extracted the key, @p aKeyBuffer and @p aKeyLength are updated.
288      * @retval kErrorNoBufs  Key does not fit in @p aKeyBuffer (extracted key length is larger than @p aKeyLength).
289      *
290      */
291     Error ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const;
292 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
293 };
294 
295 /**
296  * This class represents a literal key derived from a `Key`.
297  *
298  */
299 class LiteralKey : public Clearable<LiteralKey>, private NonCopyable
300 {
301 public:
302     static constexpr uint16_t kMaxSize = 32; ///< Maximum size of the key.
303 
304     /**
305      * This constructor initializes the `LiteralKey` from a given `Key`.
306      *
307      * If the @p aKey is itself represents a literal key the same key buffer pointers are used. If the @p aKey is
308      * a `KeyRef` then the literal key is extracted. In this case, the extracted key MUST be smaller than `kMaxSize`.
309      *
310      * @param[in] aKey   The key to convert from.
311      *
312      */
313     explicit LiteralKey(const Key &aKey);
314 
315     /*
316      * This method gets the pointer to the byte array containing the literal key.
317      *
318      * @returns The pointer to the byte array containing the literal key.
319      *
320      */
GetBytes(void) const321     const uint8_t *GetBytes(void) const { return mKey; }
322 
323     /**
324      * This method gets the key length.
325      *
326      * @returns The key length (number of bytes in the byte array from `GetBytes()`).
327      *
328      */
GetLength(void) const329     uint16_t GetLength(void) const { return mLength; }
330 
331 private:
332     const uint8_t *mKey;
333     uint16_t       mLength;
334 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
335     uint8_t mBuffer[kMaxSize];
336 #endif
337 };
338 
339 } // namespace Crypto
340 
341 DefineCoreType(otCryptoKey, Crypto::Key);
342 
343 } // namespace ot
344 
345 #endif // STORAGE_HPP_
346