1 /*
2  * Copyright (c) 2017-2023, Texas Instruments Incorporated
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
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /** ============================================================================
33  *  @file      CryptoKey.h
34  *
35  *  @brief     The CryptoKey type is an opaque representation of a cryptographic key.
36  *
37  *  @warning   This is a beta API. It may change in future releases.
38  *
39  *  Cryptographic keying material may be stored on an embedded system multiple ways.
40  *   - plaintext: in plaintext in flash or RAM
41  *   - key store: in a dedicated hardware database whose entries can not be directly
42  *     read out.
43  *
44  *  Each storage option requires different approaches to handling the keying material
45  *  when performing a crypto operation. In order to separate these concerns from
46  *  the API of the various crypto drivers available with TI-RTOS, the CryptoKey
47  *  type abstracts away from these details. It does not contain any cryptographic
48  *  keying material itself but instead contains the details necessary for drivers to use the
49  *  keying material. The driver implementation handles preparing and moving the keying
50  *  material as necessary to perform the desired crypto operation.
51  *
52  *  The same CryptoKey may be passed to crypto APIs of different modes subject to
53  *  restrictions placed on the key by their storage types. Plaintext keys may be used
54  *  without restriction while key store keys have their permitted uses
55  *  restricted when the keying material is loaded.
56  *  These restrictions are specified in a CryptoKey_SecurityPolicy that is device-specific
57  *  and depends on the hardware capability of the device.
58  *
59  *  An application should never access a field within a CryptoKey struct itself.
60  *  Where needed, helper functions are provided to do so.
61  *
62  *  Before using a CryptoKey in another crypto API call, it must be initialized
63  *  with a call to one of the initialization functions.
64  *   - CryptoKeyPlaintext_initKey()
65  *   - CryptoKeyPlaintext_initBlankKey()
66  *   - KeyStore_PSA_initKey()
67  *   - KeyStore_PSA_initBlankKey()
68  *
69  *  The keystore CryptoKeys may be used to load a key into a key store after
70  *  its respective _init call.
71  *
72  *  CryptoKeys can be initialized "blank", without keying material but with an empty buffer
73  *  or key store entry, to encode the destination of a key to be created in the
74  *  future. This way, keys may be generated securely within a key store
75  *  for example and never even be stored in RAM temporarily.
76  *
77  *  Not all devices support all CryptoKey functionality. This is hardware-dependent.
78  *
79  */
80 
81 #ifndef ti_drivers_cryptoutils_cyptokey_CryptoKey__include
82 #define ti_drivers_cryptoutils_cyptokey_CryptoKey__include
83 
84 #include <stdint.h>
85 #include <stdbool.h>
86 
87 #ifdef __cplusplus
88 extern "C" {
89 #endif
90 
91 /*!
92 
93  */
94 
95 /**
96  *  @defgroup CryptoKey_CONTROL Status codes
97  *  These CryptoKey macros are reservations for CryptoKey.h
98  *  @{
99  */
100 
101 /*!
102  *  Common CryptoKey_control status code reservation offset.
103  *  CryptoKey driver implementations should offset status codes with
104  *  CryptoKey_STATUS_RESERVED growing negatively.
105  *
106  *  Example implementation specific status codes:
107  *  @code
108  *  #define CryptoKeyXYZ_STATUS_ERROR0    CryptoKey_STATUS_RESERVED - 0
109  *  #define CryptoKeyXYZ_STATUS_ERROR1    CryptoKey_STATUS_RESERVED - 1
110  *  #define CryptoKeyXYZ_STATUS_ERROR2    CryptoKey_STATUS_RESERVED - 2
111  *  @endcode
112  */
113 #define CryptoKey_STATUS_RESERVED (-32)
114 
115 /**
116  *  @defgroup CryptoKey_STATUS Status Codes
117  *  CryptoKey_STATUS_*  macros are general status codes returned by CryptoKey_control()
118  *  @{
119  *  @ingroup CryptoKey_CONTROL
120  */
121 
122 /*!
123  *  @brief   Successful status code
124  *
125  *  CryptoKey_control() returns CryptoKey_STATUS_SUCCESS if the control code was executed
126  *  successfully.
127  */
128 #define CryptoKey_STATUS_SUCCESS (0)
129 
130 /*!
131  *  @brief   Generic error status code
132  *
133  *  CryptoKey_control() returns CryptoKey_STATUS_ERROR if the control code was not executed
134  *  successfully.
135  */
136 #define CryptoKey_STATUS_ERROR (-1)
137 
138 /*!
139  *  @brief   Returned if the encoding of a CryptoKey is not a CryptoKey_Encoding value
140  *
141  *  CryptoKey_control() returns CryptoKey_STATUS_ERROR if the control code was not executed
142  *  successfully.
143  */
144 #define CryptoKey_STATUS_UNDEFINED_ENCODING (-2)
145 
146 /** @}*/
147 
148 /** @}*/
149 
150 /*
151  * CRYPTOKEY_HSM is being used to mask bit 6 which determines which accelerator to use.
152  * Any encoding that is ORed with CRYPTOKEY_HSM indicates that the HSM is the engine of choice for the operation
153  */
154 #define CRYPTOKEY_HSM 0x20U
155 
156 #define CRYPTOKEY_PLAINTEXT       0x02U
157 #define CRYPTOKEY_BLANK_PLAINTEXT 0x04U
158 #define CRYPTOKEY_KEYSTORE        0x08U
159 #define CRYPTOKEY_BLANK_KEYSTORE  0x10U
160 
161 /*!
162  *  @brief  List of the different types of CryptoKey.
163  *  _HSM encodings are only available for select devices, CC27XX.
164  */
165 typedef uint8_t CryptoKey_Encoding;
166 static const CryptoKey_Encoding CryptoKey_PLAINTEXT       = CRYPTOKEY_PLAINTEXT;
167 static const CryptoKey_Encoding CryptoKey_BLANK_PLAINTEXT = CRYPTOKEY_BLANK_PLAINTEXT;
168 static const CryptoKey_Encoding CryptoKey_KEYSTORE        = CRYPTOKEY_KEYSTORE;
169 static const CryptoKey_Encoding CryptoKey_BLANK_KEYSTORE  = CRYPTOKEY_BLANK_KEYSTORE;
170 static const CryptoKey_Encoding CryptoKey_PLAINTEXT_HSM   = CRYPTOKEY_PLAINTEXT | CRYPTOKEY_HSM;
171 
172 /*!
173  *  @brief  Plaintext CryptoKey datastructure.
174  *
175  *  This structure contains all the information necessary to access keying material stored
176  *  in plaintext form in flash or RAM.
177  */
178 typedef struct
179 {
180     uint8_t *keyMaterial;
181     uint32_t keyLength;
182 } CryptoKey_Plaintext;
183 
184 /*!
185  *  @brief  Key store CryptoKey datastructure.
186  *
187  *  This structure contains all the information necessary to access keying material stored
188  *  in a dedicated key store or key database with memory access controls.
189  *  The application must ensure that the key attributes struct used to initialize the pointer
190  *  #keyAttributes must either be a global variable or it must be available in the context of the
191  *  function that makes the call to import the key associated with the same key attribute.
192  *  Otherwise, the keyAttributes pointer will point to a location in stack that could be deallocated.
193  */
194 typedef struct
195 {
196     uint32_t keyLength;
197     uint32_t keyID;
198     void *keyAttributes;
199 } CryptoKey_KeyStore;
200 
201 /*!
202  *  @brief  CryptoKey datastructure.
203  *
204  *  This structure contains a CryptoKey_Encoding and one of
205  * - CryptoKey_Plaintext
206  * - CryptoKey_KeyStore
207  */
208 typedef struct
209 {
210     CryptoKey_Encoding encoding;
211     union
212     {
213         CryptoKey_Plaintext plaintext;
214         CryptoKey_KeyStore keyStore;
215     } u;
216 } CryptoKey;
217 
218 /*!
219  *  @brief  Structure that specifies the restrictions on a CryptoKey
220  *
221  *  This structure is device-specific and declared here in incomplete form.
222  *  The structure is fully defined in CryptoKeyDEVICE.h. This creates a link-time binding
223  *  when using the structure with key store functions. If the instance
224  *  of the CryptoKey_SecurityPolicy is kept in a device-specific application-file,
225  *  the generic application code may still use references to it despite being
226  *  an incomplete type in the generic application file at compile time.
227  */
228 typedef struct CryptoKey_SecurityPolicy_ CryptoKey_SecurityPolicy;
229 
230 /*!
231  *  @brief Gets the key type of the CryptoKey
232  *
233  *  @param [in]     keyHandle   Pointer to a CryptoKey
234  *  @param [out]    keyType     Type of the CryptoKey
235  *
236  *  @return Returns a status code
237  */
238 int_fast16_t CryptoKey_getCryptoKeyType(const CryptoKey *keyHandle, CryptoKey_Encoding *keyType);
239 
240 /*!
241  *  @brief Whether the CryptoKey is 'blank' or represents valid keying material
242  *
243  *  @param [in]     keyHandle   Pointer to a CryptoKey
244  *  @param [out]    isBlank     Whether the CryptoKey is 'blank' or not
245  *
246  *  @return Returns a status code
247  */
248 int_fast16_t CryptoKey_isBlank(const CryptoKey *keyHandle, bool *isBlank);
249 
250 /*!
251  *  @brief Function to initialize the CryptoKey_SecurityPolicy struct to its defaults
252  *
253  *  This will zero-out all fields that cannot be set to safe defaults
254  *
255  *  @param [in]     policy   Pointer to a CryptoKey_SecurityPolicy
256  *
257  *  @return Returns a status code
258  */
259 int_fast16_t CryptoKey_initSecurityPolicy(CryptoKey_SecurityPolicy *policy);
260 
261 /*!
262  *  @brief Function to verify a secure CryptoKey
263  *
264  *  This will check that the key type is valid and verify plaintext key material
265  *  is located in non-secure read-access memory.
266  *
267  *  @note This function may not be available in all implementations
268  *
269  *  @param [in]     secureKey   Pointer to a CryptoKey struct located in secure memory
270  *
271  *  @retval CryptoKey_STATUS_SUCCESS  Key passes all verification checks
272  *  @retval CryptoKey_STATUS_ERROR    Key fails any verification check
273  */
274 int_fast16_t CryptoKey_verifySecureInputKey(const CryptoKey *secureKey);
275 
276 /*!
277  *  @brief Function to verify a secure output CryptoKey
278  *
279  *  This will check that the key type is valid and verify plaintext key material
280  *  is located in non-secure RW-access memory.
281  *
282  *  @note This function may not be available in all implementations
283  *
284  *  @param [in]     secureKey   Pointer to a CryptoKey struct located in secure memory
285  *
286  *  @retval CryptoKey_STATUS_SUCCESS  Key passes all verification checks
287  *  @retval CryptoKey_STATUS_ERROR    Key fails any verification check
288  */
289 int_fast16_t CryptoKey_verifySecureOutputKey(const CryptoKey *secureKey);
290 
291 /*!
292  *  @brief Function to copy and verify a secure input CryptoKey
293  *
294  *  This will check that the source CryptoKey struct is located in non-secure
295  *  read-access memory, copy the CryptoKey struct from the src to dst, and check
296  *  that the key type is valid and verify plaintext key material is located in
297  *  non-secure read-access memory.
298  *
299  *  @note This function may not be available in all implementations
300  *
301  *  @param [out]    dst         Pointer to the destination CryptoKey struct located in secure memory
302  *  @param [in,out] src         Pointer to a source CryptoKey struct pointer located in secure memory
303  *                              which will be updated to point to the destination CryptoKey struct
304  *
305  *  @retval CryptoKey_STATUS_SUCCESS  Key passes all verification checks
306  *  @retval CryptoKey_STATUS_ERROR    Key fails any verification check
307  */
308 int_fast16_t CryptoKey_copySecureInputKey(CryptoKey *dst, const CryptoKey **src);
309 
310 /*!
311  *  @brief Function to copy and verify a secure output CryptoKey
312  *
313  *  This will check that the source CryptoKey struct is located in non-secure
314  *  RW-access memory, copy the CryptoKey struct from the src to dst, and check
315  *  that the key type is valid and verify plaintext key material is located in
316  *  non-secure RW-access memory.
317  *
318  *  @note This function may not be available in all implementations
319  *
320  *  @param [out]    dst         Pointer to the destination CryptoKey struct located in secure memory
321  *  @param [in,out] src         Pointer to a source CryptoKey struct pointer located in secure memory
322  *                              which will be updated to point to the destination CryptoKey struct
323  *
324  *  @retval CryptoKey_STATUS_SUCCESS  Key passes all verification checks
325  *  @retval CryptoKey_STATUS_ERROR    Key fails any verification check
326  */
327 int_fast16_t CryptoKey_copySecureOutputKey(CryptoKey *dst, CryptoKey **src);
328 
329 #ifdef __cplusplus
330 }
331 #endif
332 
333 #endif /* ti_drivers_cryptoutils_cyptokey_CryptoKey__include */
334