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