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