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