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