1 /*--------------------------------------------------------------------------*/
2 /* Copyright 2020-2021 NXP                                                  */
3 /*                                                                          */
4 /* NXP Confidential. This software is owned or controlled by NXP and may    */
5 /* only be used strictly in accordance with the applicable license terms.   */
6 /* By expressly accepting such terms or by downloading, installing,         */
7 /* activating and/or otherwise using the software, you are agreeing that    */
8 /* you have read, and that you agree to comply with and are bound by, such  */
9 /* license terms. If you do not agree to be bound by the applicable license */
10 /* terms, then you may not retain, install, activate or otherwise use the   */
11 /* software.                                                                */
12 /*--------------------------------------------------------------------------*/
13 
14 /** @file  mcuxClCss_KeyManagement.c
15  *  @brief CSSv2 implementation for key management.
16  * This file implements the functions declared in mcuxClCss_KeyManagement.h. */
17 
18 #include <mcuxClCss_KeyManagement.h>    // Implement mcuxClCss interface "KeyManagement"
19 #include <mcuxCsslFlowProtection.h>
20 #include <platform_specific_headers.h>
21 #include <mcuxClCss.h>
22 #include <mcuxClMemory.h>
23 #include <internal/mcuxClCss_Internal.h>
24 
25 
26 // Implementation of mcuxClCss interface "KeyManagement"
27 
MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyDelete_Async)28 MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyDelete_Async)
29 MCUXCLCSS_API mcuxClCss_Status_Protected_t mcuxClCss_KeyDelete_Async(
30         mcuxClCss_KeyIndex_t keyIdx)
31 {
32     MCUX_CSSL_FP_FUNCTION_ENTRY(mcuxClCss_KeyDelete_Async);
33     MCUXCLCSS_INPUT_PARAM_CHECK_PROTECTED(mcuxClCss_KeyDelete_Async, (CSS_KS_CNT <= keyIdx));
34 
35     /* CSS SFRs are not cached => Tell SW to wait for CSS to come back from BUSY state before modifying the SFRs */
36     if (MCUXCLCSS_ISBUSY)
37     {
38         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyDelete_Async, MCUXCLCSS_STATUS_SW_CANNOT_INTERRUPT);
39     }
40 
41     MCUXCLCSS_SETKEYSTOREINDEX0(keyIdx);
42     MCUXCLCSS_STARTCOMMAND(ID_CFG_CSS_CMD_KDELETE, 0U, CSS_CMD_BIG_ENDIAN);
43 
44     MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyDelete_Async, MCUXCLCSS_STATUS_OK_WAIT);
45 }
46 
47 
48 
MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyImport_Async)49 MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyImport_Async)
50 MCUXCLCSS_API mcuxClCss_Status_Protected_t mcuxClCss_KeyImport_Async(
51     mcuxClCss_KeyImportOption_t options,
52     uint8_t const * pImportKey,
53     size_t importKeyLength,
54     mcuxClCss_KeyIndex_t wrappingKeyIdx,
55     mcuxClCss_KeyIndex_t targetKeyIdx)
56 {
57     MCUX_CSSL_FP_FUNCTION_ENTRY(mcuxClCss_KeyImport_Async);
58     /* Key indices out of bounds or the source key pointer is NULL although the key format indicates that it should be imported from memory */
59     MCUXCLCSS_INPUT_PARAM_CHECK_PROTECTED(mcuxClCss_KeyImport_Async,
60                                          (wrappingKeyIdx >= CSS_KS_CNT)
61                                          || (targetKeyIdx >= CSS_KS_CNT)
62                                          || ((options.bits.kfmt == MCUXCLCSS_KEYIMPORT_KFMT_RFC3394) && (importKeyLength == 0u)));
63 
64     /* CSS SFRs are not cached => Tell SW to wait for CSS to come back from BUSY state before modifying the SFRs */
65     if (MCUXCLCSS_ISBUSY)
66     {
67         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyImport_Async, MCUXCLCSS_STATUS_SW_CANNOT_INTERRUPT);
68     }
69 
70     MCUXCLCSS_SETKEYSTOREINDEX0(wrappingKeyIdx);
71     MCUXCLCSS_SETKEYSTOREINDEX1(targetKeyIdx);
72     MCUXCLCSS_SETCSSINPUT0(pImportKey, importKeyLength);
73     MCUXCLCSS_STARTCOMMAND(ID_CFG_CSS_CMD_KEYIN, options.word.value, CSS_CMD_BIG_ENDIAN);
74 
75     MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyImport_Async, MCUXCLCSS_STATUS_OK_WAIT);
76 }
77 
78 
handleKeyExportError(uint8_t * pOutput,size_t key_length,mcuxClCss_InterruptOptionEn_t interrupt_state_old)79 static mcuxClCss_Status_Protected_t handleKeyExportError(uint8_t *pOutput, size_t key_length, mcuxClCss_InterruptOptionEn_t interrupt_state_old)
80 {
81     /* Clear the interrupt state */
82     mcuxClCss_InterruptOptionRst_t interrupt_options_1 = {0U};
83     interrupt_options_1.bits.cssint = MCUXCLCSS_CSS_RESET_CLEAR;
84     // no FP in this call since mcuxClCss_ResetIntFlags always returns OK
85     (void)mcuxClCss_ResetIntFlags(interrupt_options_1);
86 
87     /* Restore the CSS interrupt settings */
88     // no FP in this call since mcuxClCss_SetIntEnableFlags always returns OK
89     (void)mcuxClCss_SetIntEnableFlags(interrupt_state_old);
90 
91     /* clear the memory to which the key was exported */
92     // no FP in this call since MCUXCLCSS_STATUS_SW_FAULT gets returned anyway
93     (void)mcuxClMemory_set(pOutput, 0x00, key_length, key_length);
94 
95     return MCUXCLCSS_STATUS_SW_FAULT;
96 }
97 
MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyExport_Async)98 MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_KeyExport_Async)
99 MCUXCLCSS_API mcuxClCss_Status_Protected_t mcuxClCss_KeyExport_Async(
100     mcuxClCss_KeyIndex_t wrappingKeyIdx,
101     mcuxClCss_KeyIndex_t exportKeyIdx,
102     uint8_t * pOutput)
103 {
104     MCUX_CSSL_FP_FUNCTION_ENTRY(mcuxClCss_KeyExport_Async);
105     /* Key indices out of bounds or the source key pointer is NULL although the key format indicates that it should be imported from memory */
106     MCUXCLCSS_INPUT_PARAM_CHECK_PROTECTED(mcuxClCss_KeyExport_Async, wrappingKeyIdx >= CSS_KS_CNT || exportKeyIdx >= CSS_KS_CNT);
107 
108     /* CSS SFRs are not cached => Tell SW to wait for CSS to come back from BUSY state before modifying the SFRs */
109     if (MCUXCLCSS_ISBUSY)
110     {
111         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_SW_CANNOT_INTERRUPT);
112     }
113 
114     /* CSS KEYOUT */
115     MCUXCLCSS_SETKEYSTOREINDEX0(wrappingKeyIdx);
116     MCUXCLCSS_SETKEYSTOREINDEX1(exportKeyIdx);
117     MCUXCLCSS_SETCSSOUTPUT_FIXEDSIZE(pOutput);
118 
119     MCUX_CSSL_FP_EXPECT(
120         MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_GetIntEnableFlags),
121         MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_SetIntEnableFlags));
122 
123     /* Save current CSS interrupts state */
124     mcuxClCss_InterruptOptionEn_t interrupt_state;
125 
126     MCUX_CSSL_FP_FUNCTION_CALL(status_get, mcuxClCss_GetIntEnableFlags(&interrupt_state));
127 
128     if(MCUXCLCSS_STATUS_OK != status_get)
129     {
130         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_SW_FAULT);
131     }
132 
133     /* Disable CSS interrupts */
134     mcuxClCss_InterruptOptionEn_t interrupt_state_new = interrupt_state;
135     interrupt_state_new.bits.cssint = MCUXCLCSS_CSS_INTERRUPT_DISABLE;
136 
137     MCUX_CSSL_FP_FUNCTION_CALL(status_set, mcuxClCss_SetIntEnableFlags(interrupt_state_new));
138 
139     if(MCUXCLCSS_STATUS_OK != status_set)
140     {
141         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_SW_FAULT);
142     }
143 
144     /* Start KEYOUT command */
145     MCUXCLCSS_STARTCOMMAND(ID_CFG_CSS_CMD_KEYOUT, 0U, CSS_CMD_BIG_ENDIAN);
146 
147 
148     MCUX_CSSL_FP_EXPECT(
149         MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation));
150 
151     /* Wait for operation CSS KEYOUT */
152     MCUX_CSSL_FP_FUNCTION_CALL(status_wait, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_KEEP)); // flags not cleared because the error is caught in the wait for operation after this function exits
153 
154     if(MCUXCLCSS_STATUS_OK != status_wait)
155     {
156         // no FP in this call since mcuxClCss_SetIntEnableFlags always returns OK
157         // In case of interrupt driven operation the error will be caught by the interrupt handler since re-enabling the interrupt when CSS_IRQ is set will immediately trigger an interrupt
158         (void)mcuxClCss_SetIntEnableFlags(interrupt_state);
159 
160         // OK_WAIT is returned here so that the error can be captured by the wait for operation following this function
161         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_OK_WAIT);
162     }
163 
164     MCUX_CSSL_FP_EXPECT(
165             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_GetKeyProperties),
166             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_KeyDelete_Async),
167             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation),
168             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_KeyImport_Async),
169             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation),
170             MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_SetIntEnableFlags));
171 
172     /* Save key properties */
173     mcuxClCss_KeyProp_t key_properties;
174 
175     MCUX_CSSL_FP_FUNCTION_CALL(status_keyprop, mcuxClCss_GetKeyProperties(exportKeyIdx, &key_properties));
176 
177     if(MCUXCLCSS_STATUS_OK != status_keyprop)
178     {
179         // no FP in this call since mcuxClCss_SetIntEnableFlags always returns OK
180         (void)mcuxClCss_SetIntEnableFlags(interrupt_state);
181 
182         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_SW_FAULT);
183     }
184 
185     size_t key_length = (key_properties.bits.ksize == MCUXCLCSS_KEYPROPERTY_KEY_SIZE_128) ? MCUXCLCSS_RFC3394_CONTAINER_SIZE_128 : MCUXCLCSS_RFC3394_CONTAINER_SIZE_256;
186 
187     /* CSS KDELETE */
188     MCUX_CSSL_FP_FUNCTION_CALL(status_delete, mcuxClCss_KeyDelete_Async(exportKeyIdx));
189 
190     if(MCUXCLCSS_STATUS_OK_WAIT != status_delete)
191     {
192         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async,
193                                   handleKeyExportError(pOutput, key_length, interrupt_state),
194                                   MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClMemory_set));
195     }
196 
197     /* wait for CSS KDELETE */
198     MCUX_CSSL_FP_FUNCTION_CALL(status_wait1, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
199 
200     if(MCUXCLCSS_STATUS_OK != status_wait1)
201     {
202         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async,
203                                   handleKeyExportError(pOutput, key_length, interrupt_state),
204                                   MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClMemory_set));
205     }
206 
207     /* CSS KEYIN */
208     mcuxClCss_KeyImportOption_t import_options;
209     import_options.word.value = 0U;
210     import_options.bits.kfmt = MCUXCLCSS_KEYIMPORT_KFMT_RFC3394;
211 
212     MCUX_CSSL_FP_FUNCTION_CALL(status_import,
213                     mcuxClCss_KeyImport_Async(
214                         import_options,
215                         pOutput,
216                         key_length,
217                         wrappingKeyIdx,
218                         exportKeyIdx
219                     ));
220 
221     if(MCUXCLCSS_STATUS_OK_WAIT != status_import)
222     {
223         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async,
224                                   handleKeyExportError(pOutput, key_length, interrupt_state),
225                                   MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClMemory_set));
226     }
227 
228     /* wait for CSS KEYIN */
229     MCUX_CSSL_FP_FUNCTION_CALL(status_wait2, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
230 
231     if(MCUXCLCSS_STATUS_OK != status_wait2)
232     {
233         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async,
234                                   handleKeyExportError(pOutput, key_length, interrupt_state),
235                                   MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClMemory_set));
236     }
237 
238     /* Restore CSS interrupt state - will trigger an interrupt immediately if interrupt is enabled since CSS_IRQ is expected to be set at this point */
239     MCUX_CSSL_FP_FUNCTION_CALL(status_set1, mcuxClCss_SetIntEnableFlags(interrupt_state));
240     if(MCUXCLCSS_STATUS_OK != status_set1)
241     {
242         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_SW_FAULT);
243     }
244 
245 
246     /* Exit function */
247     MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_KeyExport_Async, MCUXCLCSS_STATUS_OK_WAIT);
248 }
249 
250 /** Exports the properties of the keys stored in the CSS internal keystore */
MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_GetKeyProperties)251 MCUX_CSSL_FP_FUNCTION_DEF(mcuxClCss_GetKeyProperties)
252 MCUXCLCSS_API mcuxClCss_Status_Protected_t mcuxClCss_GetKeyProperties(
253     mcuxClCss_KeyIndex_t keyIdx,
254     mcuxClCss_KeyProp_t * pKeyProp
255     )
256 {
257     MCUX_CSSL_FP_FUNCTION_ENTRY(mcuxClCss_GetKeyProperties);
258     MCUXCLCSS_INPUT_PARAM_CHECK_PROTECTED(mcuxClCss_GetKeyProperties, (CSS_KS_CNT <= keyIdx));
259 
260     /* CSS SFRs are not cached => Tell SW to wait for CSS to come back from BUSY state before modifying the SFRs */
261     if (MCUXCLCSS_ISBUSY)
262     {
263         MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_GetKeyProperties, MCUXCLCSS_STATUS_SW_CANNOT_INTERRUPT);
264     }
265 
266     pKeyProp->word.value = ((const volatile uint32_t *) (&IP_CSS->CSS_KS0))[keyIdx];
267 
268     MCUX_CSSL_FP_FUNCTION_EXIT(mcuxClCss_GetKeyProperties, MCUXCLCSS_STATUS_OK);
269 }
270