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