• 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  * @brief
32  *   This file includes the platform abstraction for Crypto operations.
33  */
34 
35 #ifndef OPENTHREAD_PLATFORM_CRYPTO_H_
36 #define OPENTHREAD_PLATFORM_CRYPTO_H_
37 
38 #include <stdint.h>
39 #include <stdlib.h>
40 
41 #include <openthread/error.h>
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 /**
48  * @addtogroup plat-crypto
49  *
50  * @brief
51  *   This module includes the platform abstraction for Crypto.
52  *
53  * @{
54  *
55  */
56 
57 /**
58  * This enumeration defines the key types.
59  *
60  */
61 typedef enum
62 {
63     OT_CRYPTO_KEY_TYPE_RAW,  ///< Key Type: Raw Data.
64     OT_CRYPTO_KEY_TYPE_AES,  ///< Key Type: AES.
65     OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC.
66 } otCryptoKeyType;
67 
68 /**
69  * This enumeration defines the key algorithms.
70  *
71  */
72 typedef enum
73 {
74     OT_CRYPTO_KEY_ALG_VENDOR,       ///< Key Algorithm: Vendor Defined.
75     OT_CRYPTO_KEY_ALG_AES_ECB,      ///< Key Algorithm: AES ECB.
76     OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256.
77 } otCryptoKeyAlgorithm;
78 
79 /**
80  * This enumeration defines the key usage flags.
81  *
82  */
83 enum
84 {
85     OT_CRYPTO_KEY_USAGE_NONE      = 0,      ///< Key Usage: Key Usage is empty.
86     OT_CRYPTO_KEY_USAGE_EXPORT    = 1 << 0, ///< Key Usage: Key can be exported.
87     OT_CRYPTO_KEY_USAGE_ENCRYPT   = 1 << 1, ///< Key Usage: Encryption (vendor defined).
88     OT_CRYPTO_KEY_USAGE_DECRYPT   = 1 << 2, ///< Key Usage: AES ECB.
89     OT_CRYPTO_KEY_USAGE_SIGN_HASH = 1 << 3, ///< Key Usage: HMAC SHA-256.
90 };
91 
92 /**
93  * This enumeration defines the key storage types.
94  *
95  */
96 typedef enum
97 {
98     OT_CRYPTO_KEY_STORAGE_VOLATILE,   ///< Key Persistence: Key is volatile.
99     OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key Persistence: Key is persistent.
100 } otCryptoKeyStorage;
101 
102 /**
103  * This datatype represents the key reference.
104  *
105  */
106 typedef uint32_t otCryptoKeyRef;
107 
108 /**
109  * @struct otCryptoKey
110  *
111  * This structure represents the Key Material required for Crypto operations.
112  *
113  */
114 typedef struct otCryptoKey
115 {
116     const uint8_t *mKey;       ///< Pointer to the buffer containing key. NULL indicates to use `mKeyRef`.
117     uint16_t       mKeyLength; ///< The key length in bytes (applicable when `mKey` is not NULL).
118     uint32_t       mKeyRef;    ///< The PSA key ref (requires `mKey` to be NULL).
119 } otCryptoKey;
120 
121 /**
122  * @struct otCryptoContext
123  *
124  * This structure stores the context object for platform APIs.
125  *
126  */
127 typedef struct otCryptoContext
128 {
129     void *   mContext;     ///< Pointer to the context.
130     uint16_t mContextSize; ///< The length of the context in bytes.
131 } otCryptoContext;
132 
133 /**
134  * Initialize the Crypto module.
135  *
136  */
137 void otPlatCryptoInit(void);
138 
139 /**
140  * Import a key into PSA ITS.
141  *
142  * @param[in,out] aKeyRef           Pointer to the key ref to be used for crypto operations.
143  * @param[in]     aKeyType          Key Type encoding for the key.
144  * @param[in]     aKeyAlgorithm     Key algorithm encoding for the key.
145  * @param[in]     aKeyUsage         Key Usage encoding for the key (combinations of `OT_CRYPTO_KEY_USAGE_*`).
146  * @param[in]     aKeyPersistence   Key Persistence for this key
147  * @param[in]     aKey              Actual key to be imported.
148  * @param[in]     aKeyLen           Length of the key to be imported.
149  *
150  * @retval OT_ERROR_NONE          Successfully imported the key.
151  * @retval OT_ERROR_FAILED        Failed to import the key.
152  * @retval OT_ERROR_INVALID_ARGS  @p aKey was set to NULL.
153  *
154  * @note If OT_CRYPTO_KEY_STORAGE_PERSISTENT is passed for aKeyPersistence then @p aKeyRef is input and platform
155  *       should use the given aKeyRef and MUST not change it.
156  *
157  *       If OT_CRYPTO_KEY_STORAGE_VOLATILE is passed for aKeyPersistence then @p aKeyRef is output, the initial
158  *       value does not matter and platform API MUST update it to return the new key ref.
159  *
160  *       This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled.
161  *
162  */
163 otError otPlatCryptoImportKey(otCryptoKeyRef *     aKeyRef,
164                               otCryptoKeyType      aKeyType,
165                               otCryptoKeyAlgorithm aKeyAlgorithm,
166                               int                  aKeyUsage,
167                               otCryptoKeyStorage   aKeyPersistence,
168                               const uint8_t *      aKey,
169                               size_t               aKeyLen);
170 
171 /**
172  * Export a key stored in PSA ITS.
173  *
174  * @param[in]   aKeyRef           The key ref to be used for crypto operations.
175  * @param[out]  aBuffer           Pointer to the buffer where key needs to be exported.
176  * @param[in]   aBufferLen        Length of the buffer passed to store the exported key.
177  * @param[out]  aKeyLen           Pointer to return the length of the exported key.
178  *
179  * @retval OT_ERROR_NONE          Successfully exported  @p aKeyRef.
180  * @retval OT_ERROR_FAILED        Failed to export @p aKeyRef.
181  * @retval OT_ERROR_INVALID_ARGS  @p aBuffer was NULL
182  *
183  * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled.
184  *
185  */
186 otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen);
187 
188 /**
189  * Destroy a key stored in PSA ITS.
190  *
191  * @param[in]   aKeyRef          The key ref to be destroyed
192  *
193  * @retval OT_ERROR_NONE          Successfully destroyed the key.
194  * @retval OT_ERROR_FAILED        Failed to destroy the key.
195  *
196  * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled.
197  *
198  */
199 otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef);
200 
201 /**
202  * Check if the key ref passed has an associated key in PSA ITS.
203  *
204  * @param[in]  aKeyRef          The Key Ref to check.
205  *
206  * @retval TRUE                 There is an associated key with @p aKeyRef.
207  * @retval FALSE                There is no associated key with @p aKeyRef.
208  *
209  * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled.
210  *
211  */
212 bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef);
213 
214 /**
215  * Initialize the HMAC operation.
216  *
217  * @param[in]  aContext          Context for HMAC operation.
218  *
219  * @retval OT_ERROR_NONE          Successfully initialized HMAC operation.
220  * @retval OT_ERROR_FAILED        Failed to initialize HMAC operation.
221  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
222  *
223  * @note The platform driver shall point the context to the correct object such as psa_mac_operation_t or
224  *       mbedtls_md_context_t.
225  *
226  */
227 otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext);
228 
229 /**
230  * Uninitialize the HMAC operation.
231  *
232  * @param[in]  aContext          Context for HMAC operation.
233  *
234  * @retval OT_ERROR_NONE          Successfully uninitialized HMAC operation.
235  * @retval OT_ERROR_FAILED        Failed to uninitialized HMAC operation.
236  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
237  *
238  */
239 otError otPlatCryptoHmacSha256Deinit(otCryptoContext *aContext);
240 
241 /**
242  * Start HMAC operation.
243  *
244  * @param[in]  aContext           Context for HMAC operation.
245  * @param[in]  aKey               Key material to be used for for HMAC operation.
246  *
247  * @retval OT_ERROR_NONE          Successfully started HMAC operation.
248  * @retval OT_ERROR_FAILED        Failed to start HMAC operation.
249  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aKey was NULL
250  *
251  */
252 otError otPlatCryptoHmacSha256Start(otCryptoContext *aContext, const otCryptoKey *aKey);
253 
254 /**
255  * Update the HMAC operation with new input.
256  *
257  * @param[in]  aContext           Context for HMAC operation.
258  * @param[in]  aBuf               A pointer to the input buffer.
259  * @param[in]  aBufLength         The length of @p aBuf in bytes.
260  *
261  * @retval OT_ERROR_NONE          Successfully updated HMAC with new input operation.
262  * @retval OT_ERROR_FAILED        Failed to update HMAC operation.
263  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aBuf was NULL
264  *
265  */
266 otError otPlatCryptoHmacSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength);
267 
268 /**
269  * Complete the HMAC operation.
270  *
271  * @param[in]  aContext           Context for HMAC operation.
272  * @param[out] aBuf               A pointer to the output buffer.
273  * @param[in]  aBufLength         The length of @p aBuf in bytes.
274  *
275  * @retval OT_ERROR_NONE          Successfully completed HMAC operation.
276  * @retval OT_ERROR_FAILED        Failed to complete HMAC operation.
277  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aBuf was NULL
278  *
279  */
280 otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, size_t aBufLength);
281 
282 /**
283  * Initialise the AES operation.
284  *
285  * @param[in]  aContext           Context for AES operation.
286  *
287  * @retval OT_ERROR_NONE          Successfully Initialised AES operation.
288  * @retval OT_ERROR_FAILED        Failed to Initialise AES operation.
289  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
290  * @retval OT_ERROR_NO_BUFS       Cannot allocate the context.
291  *
292  * @note The platform driver shall point the context to the correct object such as psa_key_id
293  *       or mbedtls_aes_context_t.
294  *
295  */
296 otError otPlatCryptoAesInit(otCryptoContext *aContext);
297 
298 /**
299  * Set the key for AES operation.
300  *
301  * @param[in]  aContext           Context for AES operation.
302  * @param[out] aKey               Key to use for AES operation.
303  *
304  * @retval OT_ERROR_NONE          Successfully set the key for AES operation.
305  * @retval OT_ERROR_FAILED        Failed to set the key for AES operation.
306  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aKey was NULL
307  *
308  */
309 otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCryptoKey *aKey);
310 
311 /**
312  * Encrypt the given data.
313  *
314  * @param[in]  aContext           Context for AES operation.
315  * @param[in]  aInput             Pointer to the input buffer.
316  * @param[in]  aOutput            Pointer to the output buffer.
317  *
318  * @retval OT_ERROR_NONE          Successfully encrypted @p aInput.
319  * @retval OT_ERROR_FAILED        Failed to encrypt @p aInput.
320  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aKey or @p aOutput were NULL
321  *
322  */
323 otError otPlatCryptoAesEncrypt(otCryptoContext *aContext, const uint8_t *aInput, uint8_t *aOutput);
324 
325 /**
326  * Free the AES context.
327  *
328  * @param[in]  aContext           Context for AES operation.
329  *
330  * @retval OT_ERROR_NONE          Successfully freed AES context.
331  * @retval OT_ERROR_FAILED        Failed to free AES context.
332  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
333  *
334  */
335 otError otPlatCryptoAesFree(otCryptoContext *aContext);
336 
337 /**
338  * Initialise the HKDF context.
339  *
340  * @param[in]  aContext           Context for HKDF operation.
341  *
342  * @retval OT_ERROR_NONE          Successfully Initialised AES operation.
343  * @retval OT_ERROR_FAILED        Failed to Initialise AES operation.
344  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
345  *
346  * @note The platform driver shall point the context to the correct object such as psa_key_derivation_operation_t
347  *       or HmacSha256::Hash
348  *
349  */
350 otError otPlatCryptoHkdfInit(otCryptoContext *aContext);
351 
352 /**
353  * Perform HKDF Expand step.
354  *
355  * @param[in]  aContext           Operation context for HKDF operation.
356  * @param[in]  aInfo              Pointer to the Info sequence.
357  * @param[in]  aInfoLength        Length of the Info sequence.
358  * @param[out] aOutputKey         Pointer to the output Key.
359  * @param[in]  aOutputKeyLength   Size of the output key buffer.
360  *
361  * @retval OT_ERROR_NONE          HKDF Expand was successful.
362  * @retval OT_ERROR_FAILED        HKDF Expand failed.
363  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
364  *
365  */
366 otError otPlatCryptoHkdfExpand(otCryptoContext *aContext,
367                                const uint8_t *  aInfo,
368                                uint16_t         aInfoLength,
369                                uint8_t *        aOutputKey,
370                                uint16_t         aOutputKeyLength);
371 
372 /**
373  * Perform HKDF Extract step.
374  *
375  * @param[in]  aContext           Operation context for HKDF operation.
376  * @param[in]  aSalt              Pointer to the Salt for HKDF.
377  * @param[in]  aSaltLength        Length of Salt.
378  * @param[in]  aInputKey          Pointer to the input key.
379  *
380  * @retval OT_ERROR_NONE          HKDF Extract was successful.
381  * @retval OT_ERROR_FAILED        HKDF Extract failed.
382  *
383  */
384 otError otPlatCryptoHkdfExtract(otCryptoContext *  aContext,
385                                 const uint8_t *    aSalt,
386                                 uint16_t           aSaltLength,
387                                 const otCryptoKey *aInputKey);
388 
389 /**
390  * Uninitialize the HKDF context.
391  *
392  * @param[in]  aContext           Context for HKDF operation.
393  *
394  * @retval OT_ERROR_NONE          Successfully un-initialised HKDF operation.
395  * @retval OT_ERROR_FAILED        Failed to un-initialised HKDF operation.
396  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
397  *
398  */
399 otError otPlatCryptoHkdfDeinit(otCryptoContext *aContext);
400 
401 /**
402  * Initialise the SHA-256 operation.
403  *
404  * @param[in]  aContext           Context for SHA-256 operation.
405  *
406  * @retval OT_ERROR_NONE          Successfully initialised SHA-256 operation.
407  * @retval OT_ERROR_FAILED        Failed to initialise SHA-256 operation.
408  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
409  *
410  *
411  * @note The platform driver shall point the context to the correct object such as psa_hash_operation_t
412  *       or mbedtls_sha256_context.
413  */
414 otError otPlatCryptoSha256Init(otCryptoContext *aContext);
415 
416 /**
417  * Uninitialize the SHA-256 operation.
418  *
419  * @param[in]  aContext           Context for SHA-256 operation.
420  *
421  * @retval OT_ERROR_NONE          Successfully un-initialised SHA-256 operation.
422  * @retval OT_ERROR_FAILED        Failed to un-initialised SHA-256 operation.
423  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
424  *
425  */
426 otError otPlatCryptoSha256Deinit(otCryptoContext *aContext);
427 
428 /**
429  * Start SHA-256 operation.
430  *
431  * @param[in]  aContext           Context for SHA-256 operation.
432  *
433  * @retval OT_ERROR_NONE          Successfully started SHA-256 operation.
434  * @retval OT_ERROR_FAILED        Failed to start SHA-256 operation.
435  * @retval OT_ERROR_INVALID_ARGS  @p aContext was NULL
436  *
437  */
438 otError otPlatCryptoSha256Start(otCryptoContext *aContext);
439 
440 /**
441  * Update SHA-256 operation with new input.
442  *
443  * @param[in]  aContext           Context for SHA-256 operation.
444  * @param[in]  aBuf               A pointer to the input buffer.
445  * @param[in]  aBufLength         The length of @p aBuf in bytes.
446  *
447  * @retval OT_ERROR_NONE          Successfully updated SHA-256 with new input operation.
448  * @retval OT_ERROR_FAILED        Failed to update SHA-256 operation.
449  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aBuf was NULL
450  *
451  */
452 otError otPlatCryptoSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength);
453 
454 /**
455  * Finish SHA-256 operation.
456  *
457  * @param[in]  aContext           Context for SHA-256 operation.
458  * @param[in]  aHash              A pointer to the output buffer, where hash needs to be stored.
459  * @param[in]  aHashSize          The length of @p aHash in bytes.
460  *
461  * @retval OT_ERROR_NONE          Successfully completed the SHA-256 operation.
462  * @retval OT_ERROR_FAILED        Failed to complete SHA-256 operation.
463  * @retval OT_ERROR_INVALID_ARGS  @p aContext or @p aHash was NULL
464  *
465  */
466 otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize);
467 
468 /**
469  * Initialize cryptographically-secure pseudorandom number generator (CSPRNG).
470  *
471  */
472 void otPlatCryptoRandomInit(void);
473 
474 /**
475  * Deinitialize cryptographically-secure pseudorandom number generator (CSPRNG).
476  *
477  */
478 void otPlatCryptoRandomDeinit(void);
479 
480 /**
481  * Fills a given buffer with cryptographically secure random bytes.
482  *
483  * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
484  * @param[in]  aSize    Size of buffer (number of bytes to fill).
485  *
486  * @retval OT_ERROR_NONE     Successfully filled buffer with random values.
487  * @retval OT_ERROR_FAILED   Operation failed.
488  *
489  */
490 otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize);
491 
492 /**
493  * @}
494  *
495  */
496 
497 #ifdef __cplusplus
498 } // end of extern "C"
499 #endif
500 #endif // OPENTHREAD_PLATFORM_CRYPTO_H_
501