1 /***************************************************************************//**
2 * @file
3 * @brief Secure Element API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #include "em_se.h"
32
33 #if defined(SLI_EM_SE_HOST) || defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
34
35 #if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
36
37 #include "em_core.h"
38 #include "sl_assert.h"
39 #include "em_system.h"
40
41 #endif
42
43 /***************************************************************************//**
44 * @addtogroup se
45 * @{
46 ******************************************************************************/
47
48 /*******************************************************************************
49 ****************************** DEFINES ***********************************
50 ******************************************************************************/
51 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
52 /* OTP initialization structure defines. */
53 #define SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_ENABLE (1 << 16)
54 #define SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_VERIFY_CERTIFICATE (1 << 17)
55 #define SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_ANTI_ROLLBACK (1 << 18)
56 #define SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_PAGE_LOCK_NARROW (1 << 19)
57 #define SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_PAGE_LOCK_FULL (1 << 20)
58
59 #if defined(CRYPTOACC_PRESENT)
60
61 /// Signal that OTP version is incorporated into the status field of the output
62 #define SE_VSE_REPLY_STATUS_OTP_VERSION_SET (1 << 21)
63 /// Mask defining the region of the status field that contains the OTP version
64 /// number.
65 #define SE_VSE_REPLY_STATUS_OTP_VERSION_MASK (0xFF000000UL)
66 /// Shift to insert a number into the otp version part of the status field
67 #define SE_VSE_REPLY_STATUS_OTP_VERSION_SHIFT (24)
68
69 /* Size of VSE Mailbox instance.
70 There are two instances, input and output. */
71 #define ROOT_MAILBOX_SIZE (512UL)
72
73 /* Base addresses of the VSE Input and Output Mailbox data structures.
74 (Must be stored in a RAM area which is not used by the VSE)
75 We use the upper 1KB of FRC RAM for the VSE mailboxes. */
76 #define ROOT_MAILBOX_OUTPUT_S_BASE (RDMEM_FRCRAM_S_MEM_END + 1 - ROOT_MAILBOX_SIZE)
77 #define ROOT_MAILBOX_INPUT_S_BASE (ROOT_MAILBOX_OUTPUT_S_BASE - ROOT_MAILBOX_SIZE)
78
79 // SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S is defined in sl_trustzone_secure_config.h
80 #if ((defined(SL_TRUSTZONE_SECURE) && !defined(SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S)) \
81 || (defined(SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S) && SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S))
82
83 #define RDMEM_FRCRAM_MEM_BASE RDMEM_FRCRAM_S_MEM_BASE
84
85 #define ROOT_MAILBOX_OUTPUT_BASE SYSCFG->ROOTDATA1;
86 #define ROOT_MAILBOX_OUTPUT_BASE_EXPECTED ROOT_MAILBOX_OUTPUT_S_BASE
87 #else
88 #define RDMEM_FRCRAM_MEM_BASE RDMEM_FRCRAM_NS_MEM_BASE
89
90 // VSE will always output the secure address, if NS is desired, caculate the NS address.
91 #define ROOT_MAILBOX_OUTPUT_BASE (SYSCFG->ROOTDATA1 - RDMEM_FRCRAM_S_MEM_BASE + RDMEM_FRCRAM_NS_MEM_BASE);
92 #define ROOT_MAILBOX_OUTPUT_BASE_EXPECTED (RDMEM_FRCRAM_NS_MEM_END + 1 - ROOT_MAILBOX_SIZE)
93 #endif
94 #define ROOT_MAILBOX_INPUT_BASE (ROOT_MAILBOX_OUTPUT_BASE_EXPECTED - ROOT_MAILBOX_SIZE)
95
96 /* Position of parameter number field in VSE Input Mailbox LENGTH field.*/
97 #define ROOT_MB_LENGTH_PARAM_NUM_SHIFT (24)
98
99 /* Done flag indicating that the VSE Mailbox handler has completed
100 processing the mailbox command. */
101 #define ROOT_MB_DONE (1 << 23)
102
103 /* VSE Configuration Status bits mask */
104 #define ROOT_MB_OUTPUT_STATUS_CONFIG_BITS_MASK (0xFFFF)
105
106 #endif // #if defined(CRYPTOACC_PRESENT)
107 /** @endcond */
108
109 /*******************************************************************************
110 ****************************** TYPEDEFS ***********************************
111 ******************************************************************************/
112 #if defined(CRYPTOACC_PRESENT)
113 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
114 // VSE Input Mailbox structure
115 typedef struct {
116 volatile uint32_t magic;
117 volatile uint32_t command;
118 volatile uint32_t length;
119 volatile uint32_t data[0];
120 } root_InputMailbox_t;
121
122 // VSE Output Mailbox structure
123 typedef struct {
124 volatile uint32_t magic;
125 volatile uint32_t version;
126 volatile uint32_t status;
127 volatile uint32_t command;
128 volatile uint32_t length;
129 volatile uint32_t data[0];
130 } root_OutputMailbox_t;
131 /** @endcond */
132
133 #endif // #if defined(CRYPTOACC_PRESENT)
134
135 /*******************************************************************************
136 ************************** STATIC FUNCTIONS *******************************
137 ******************************************************************************/
138
139 #if defined(SEMAILBOX_PRESENT)
140 /***************************************************************************//**
141 * @brief
142 * Write to FIFO
143 *
144 * @param value
145 * Value to write to FIFO
146 ******************************************************************************/
147 #if defined(_SEMAILBOX_FIFO_RESETVALUE)
writeToFifo(uint32_t value)148 __STATIC_INLINE void writeToFifo(uint32_t value)
149 {
150 SEMAILBOX_HOST->FIFO = value;
151 }
152 #else
writeToFifo(uint32_t value)153 __STATIC_INLINE void writeToFifo(uint32_t value)
154 {
155 SEMAILBOX_HOST->FIFO[0].DATA = value;
156 }
157 #endif
158
159 #endif // SEMAILBOX_PRESENT
160
161 /*******************************************************************************
162 ************************** GLOBAL FUNCTIONS *******************************
163 ******************************************************************************/
164
165 /***************************************************************************//**
166 * @brief
167 * Add input data to a command
168 *
169 * @details
170 * This function adds a buffer of input data to the given SE command structure
171 * The buffer gets appended by reference at the end of the list of already
172 * added buffers.
173 *
174 * @note
175 * Note that this function does not copy either the data buffer or the buffer
176 * structure, so make sure to keep the data object in scope until the command
177 * has been executed by the secure element.
178 *
179 * @param[in] command
180 * Pointer to an SE command structure.
181 *
182 * @param[in] data
183 * Pointer to a data transfer structure.
184 ******************************************************************************/
SE_addDataInput(SE_Command_t * command,SE_DataTransfer_t * data)185 void SE_addDataInput(SE_Command_t *command, SE_DataTransfer_t *data)
186 {
187 if (command->data_in == NULL) {
188 command->data_in = data;
189 } else {
190 SE_DataTransfer_t *next = command->data_in;
191 while (next->next != (void*)SE_DATATRANSFER_STOP) {
192 next = (SE_DataTransfer_t*)next->next;
193 }
194 next->next = data;
195 }
196 }
197
198 /***************************************************************************//**
199 * @brief
200 * Add output data to a command
201 *
202 * @details
203 * This function adds a buffer of output data to the given command structure
204 * The buffer gets appended by reference at the end of the list of already
205 * added buffers.
206 *
207 * @note
208 * Note that this function does not copy either the data buffer or the buffer
209 * structure, so make sure to keep the data object in scope until the command
210 * has been executed by the secure element.
211 *
212 * @param[in] command
213 * Pointer to an SE command structure.
214 *
215 * @param[in] data
216 * Pointer to a data transfer structure.
217 ******************************************************************************/
SE_addDataOutput(SE_Command_t * command,SE_DataTransfer_t * data)218 void SE_addDataOutput(SE_Command_t *command,
219 SE_DataTransfer_t *data)
220 {
221 if (command->data_out == NULL) {
222 command->data_out = data;
223 } else {
224 SE_DataTransfer_t *next = command->data_out;
225 while (next->next != (void*)SE_DATATRANSFER_STOP) {
226 next = (SE_DataTransfer_t*)next->next;
227 }
228 next->next = data;
229 }
230 }
231
232 /***************************************************************************//**
233 * @brief
234 * Add a parameter to a command
235 *
236 * @details
237 * This function adds a parameter word to the passed command.
238 *
239 * @note
240 * Make sure to not exceed @ref SE_MAX_PARAMETERS.
241 *
242 * @param[in] command
243 * Pointer to a filled-out SE command structure.
244 * @param[in] parameter
245 * Parameter to add.
246 ******************************************************************************/
SE_addParameter(SE_Command_t * command,uint32_t parameter)247 void SE_addParameter(SE_Command_t *command, uint32_t parameter)
248 {
249 if (command->num_parameters >= SE_MAX_PARAMETERS) {
250 EFM_ASSERT(command->num_parameters < SE_MAX_PARAMETERS);
251 return;
252 }
253
254 command->parameters[command->num_parameters] = parameter;
255 command->num_parameters += 1;
256 }
257
258 #if !defined(SLI_EM_SE_HOST)
259 /***************************************************************************//**
260 * @brief
261 * Execute the passed command
262 *
263 * @details
264 * This function starts the execution of the passed command by the secure
265 * element. When started, wait for the RXINT interrupt flag, or call
266 * @ref SE_waitCommandCompletion to busy-wait. After completion, you have to
267 * call @ref SE_readCommandResponse to get the command's execution status.
268 *
269 * @param[in] command
270 * Pointer to a filled-out SE command structure.
271 ******************************************************************************/
SE_executeCommand(SE_Command_t * command)272 void SE_executeCommand(SE_Command_t *command)
273 {
274 // Don't overflow our struct
275 if (command->num_parameters > SE_MAX_PARAMETERS) {
276 EFM_ASSERT(command->num_parameters <= SE_MAX_PARAMETERS);
277 return;
278 }
279
280 #if defined(SEMAILBOX_PRESENT)
281
282 // Wait for room available in the mailbox
283 while (!(SEMAILBOX_HOST->TX_STATUS & SEMAILBOX_TX_STATUS_TXINT)) ;
284
285 // Write header to start transaction
286 SEMAILBOX_HOST->TX_HEADER = sizeof(uint32_t) * (4 + command->num_parameters);
287
288 // Write command into FIFO
289 writeToFifo(command->command);
290
291 // Write DMA descriptors into FIFO
292 writeToFifo((uint32_t)command->data_in);
293 writeToFifo((uint32_t)command->data_out);
294
295 // Write applicable parameters into FIFO
296 for (size_t i = 0; i < command->num_parameters; i++) {
297 writeToFifo(command->parameters[i]);
298 }
299
300 #elif defined(CRYPTOACC_PRESENT)
301 // Prepare the VSE Mailbox within a critical section to prevent
302 // the process from getting interrupted. At this point, the only option
303 // we have is to go through a reset, so it is safe to enter the critical section.
304 (void)CORE_EnterCritical();
305
306 // Setup pointer to the VSE Mailbox Input data structure
307 // (must be stored in a RAM area which is not used by the VSE)
308 root_InputMailbox_t *rootInMb = (root_InputMailbox_t*)ROOT_MAILBOX_INPUT_BASE;
309 uint32_t *mbData;
310 unsigned int mbDataLen, inDataLen, i;
311 SE_DataTransfer_t *inDataDesc;
312 uint32_t *inData;
313 uint32_t checksum;
314 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
315 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
316
317 // Store the secure memory base addresses for VSE to be able to read from the address
318 // Set base of Mailbox Input data structure in SYSCFG register in order
319 // for VSE to find it.
320 SYSCFG->ROOTDATA0 = ROOT_MAILBOX_INPUT_S_BASE;
321 // Set base of Mailbox Output data structure in SYSCFG register in order
322 // for VSE to know where to write output data.
323 // Write command into FIFO
324 SYSCFG->ROOTDATA1 = ROOT_MAILBOX_OUTPUT_S_BASE;
325
326 if (!sysCfgClkWasEnabled) {
327 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
328 }
329
330 rootInMb->magic = SE_RESPONSE_MAILBOX_VALID;
331 rootInMb->command = command->command;
332
333 // Write applicable parameters into Mailbox DATA array
334 mbData = (uint32_t*) rootInMb->data;
335 for (mbDataLen = 0; mbDataLen < command->num_parameters; mbDataLen++) {
336 mbData[mbDataLen] = command->parameters[mbDataLen];
337 }
338
339 // Write input data into Mailbox DATA array
340 inDataLen = 0;
341 for (inDataDesc = command->data_in; inDataDesc; inDataDesc = (SE_DataTransfer_t*) inDataDesc->next) {
342 inData = (uint32_t*) inDataDesc->data;
343 for (i = 0; i < (inDataDesc->length & SE_DATATRANSFER_LENGTH_MASK) / sizeof(uint32_t); i++) {
344 // Make sure we do not overflow the input mailbox.
345 EFM_ASSERT(mbDataLen < ROOT_MAILBOX_SIZE);
346 mbData[mbDataLen++] = inData[i];
347 inDataLen++;
348 }
349 if (inDataDesc->next == (void*)SE_DATATRANSFER_STOP) {
350 break;
351 }
352 }
353
354 // Write number of parameters and data words to 'length' field of mailbox.
355 rootInMb->length =
356 inDataLen | (command->num_parameters << ROOT_MB_LENGTH_PARAM_NUM_SHIFT);
357
358 // Calculate checksum using bitwise XOR over the all words in the mailbox
359 // data structure, minus the CHECKSUM word (32bit = 4bytes ) at the end.
360 checksum = rootInMb->magic;
361 checksum ^= rootInMb->command;
362 checksum ^= rootInMb->length;
363 for (i = 0; i < mbDataLen; i++) {
364 checksum ^= mbData[i];
365 }
366
367 // Finally, write the calculated checksum to mailbox checksum field
368 mbData[mbDataLen] = checksum;
369
370 __NVIC_SystemReset();
371
372 #endif // #if defined(SEMAILBOX_PRESENT)
373 }
374
375 #endif // #if !defined(SLI_EM_SE_HOST)
376
377 #if defined(CRYPTOACC_PRESENT)
378 /***************************************************************************//**
379 * @brief
380 * Check whether the VSE Output Mailbox is valid.
381 *
382 * @return True if the VSE Output Mailbox is valid (magic and checksum OK)
383 ******************************************************************************/
rootIsOutputMailboxValid(void)384 bool rootIsOutputMailboxValid(void)
385 {
386 // Setup pointer to the VSE Output Mailbox data structure
387 // (must be stored in a RAM area which is not used by the VSE)
388 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
389 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
390 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
391 if ((uint32_t)rootOutMb > ROOT_MAILBOX_OUTPUT_BASE_EXPECTED
392 || (uint32_t)rootOutMb < RDMEM_FRCRAM_MEM_BASE) {
393 return false;
394 }
395
396 if (!sysCfgClkWasEnabled) {
397 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
398 }
399
400 uint32_t *mbPtr = (uint32_t*) rootOutMb;
401 uint32_t checksum;
402 unsigned int mbLen, cnt;
403
404 // Verify magic word of mailbox
405 if (rootOutMb->magic != SE_RESPONSE_MAILBOX_VALID) {
406 return false;
407 }
408
409 // Get length of mailbox
410 mbLen = sizeof(root_OutputMailbox_t) / sizeof(uint32_t) + rootOutMb->length;
411 if (mbLen >= ROOT_MAILBOX_SIZE) {
412 return false;
413 }
414 // Calculate checksum using bitwise XOR over all words in the mailbox
415 // data structure, minus the CHECKSUM word at the end.
416 for (checksum = 0, cnt = 0; cnt < mbLen; cnt++) {
417 checksum ^= mbPtr[cnt];
418 }
419
420 // Verify that the calculated checksum is equal to the mailbox checksum.
421 return (mbPtr[mbLen] == checksum);
422 }
423
424 /***************************************************************************//**
425 * @brief
426 * Get current SE version
427 *
428 * @details
429 * This function returns the current VSE version
430 *
431 * @param[in] version
432 * Pointer to location where to copy the version of VSE to.
433 *
434 * @return
435 * One of the SE_RESPONSE return codes:
436 * SE_RESPONSE_OK when the command was executed successfully
437 * SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
438 * SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
439 ******************************************************************************/
SE_getVersion(uint32_t * version)440 SE_Response_t SE_getVersion(uint32_t *version)
441 {
442 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
443 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
444 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
445 if (!sysCfgClkWasEnabled) {
446 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
447 }
448
449 if (version == NULL) {
450 return SE_RESPONSE_INVALID_PARAMETER;
451 }
452
453 // First verify that the response is ok.
454 if (!rootIsOutputMailboxValid()) {
455 return SE_RESPONSE_MAILBOX_INVALID;
456 }
457
458 // Return the 'version' from the Output Mailbox
459 *version = rootOutMb->version;
460
461 return SE_RESPONSE_OK;
462 }
463
464 /***************************************************************************//**
465 * @brief
466 * Get VSE configuration and status bits
467 *
468 * @details
469 * This function returns the current VSE configuration and status bits.
470 * The following list explains what the different bits in cfgStatus indicate.
471 * A bit value of 1 means enabled, while 0 means disabled:
472 * * [0]: Secure boot
473 * * [1]: Verify secure boot certificate
474 * * [2]: Anti-rollback
475 * * [3]: Narrow page lock
476 * * [4]: Full page lock
477 * The following status bits can be read with VSE versions
478 * higher than 1.2.2.
479 * * [10]: Debug port lock
480 * * [11]: Device erase enabled
481 * * [12]: Secure debug enabled
482 * * [15]: Debug port register state, 1 if the debug port is locked.
483 *
484 * @param[out] cfgStatus
485 * Pointer to location to copy Configuration Status bits into.
486 *
487 * @note
488 * This function will check that the mailbox content is valid before
489 * reading the status bits. If the command response has already been read
490 * with a call to @ref SE_ackCommand(), the validity check will fail, and
491 * the config status bits cannot be read before a reset has occurred.
492 *
493 * @return
494 * One of the SE_RESPONSE return codes:
495 * SE_RESPONSE_OK when the command was executed successfully
496 * SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
497 * SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
498 ******************************************************************************/
SE_getConfigStatusBits(uint32_t * cfgStatus)499 SE_Response_t SE_getConfigStatusBits(uint32_t *cfgStatus)
500 {
501 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
502 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
503 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
504 if (!sysCfgClkWasEnabled) {
505 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
506 }
507
508 if (cfgStatus == NULL) {
509 return SE_RESPONSE_INVALID_PARAMETER;
510 }
511
512 // First verify that the response is ok.
513 if (!rootIsOutputMailboxValid()) {
514 return SE_RESPONSE_MAILBOX_INVALID;
515 }
516
517 // Return the configuration status bits
518 *cfgStatus = rootOutMb->status & ROOT_MB_OUTPUT_STATUS_CONFIG_BITS_MASK;
519
520 return SE_RESPONSE_OK;
521 }
522
523 /***************************************************************************//**
524 * @brief
525 * Get the version number of the OTP from the status field of the output
526 * mailbox
527 * @details
528 * This function checks if the OTP version number flag is set in the output
529 * mailbox. If it is, the version number is writen to @ref otpVersion pointer
530 * location. If not, it returns error response.
531 *
532 * @param[out] otpVersion
533 * Pointer to location to copy OTP version number into.
534 * @return
535 * One of the SE_RESPONSE return codes.
536 * @retval SE_RESPONSE_OK when the command was executed successfully
537 ******************************************************************************/
SE_getOTPVersion(uint32_t * otpVersion)538 SE_Response_t SE_getOTPVersion(uint32_t *otpVersion)
539 {
540 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
541 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
542 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
543 if (!sysCfgClkWasEnabled) {
544 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
545 }
546
547 if (otpVersion == NULL) {
548 return SE_RESPONSE_INVALID_PARAMETER;
549 }
550
551 // First verify that the response is ok.
552 if (!rootIsOutputMailboxValid()) {
553 return SE_RESPONSE_MAILBOX_INVALID;
554 }
555
556 bool isOTPVersionSet = rootOutMb->status & SE_VSE_REPLY_STATUS_OTP_VERSION_SET;
557 if (isOTPVersionSet) {
558 // Return the OTP version from the status field.
559 *otpVersion = (rootOutMb->status & SE_VSE_REPLY_STATUS_OTP_VERSION_MASK) >> SE_VSE_REPLY_STATUS_OTP_VERSION_SHIFT;
560 } else {
561 return SE_RESPONSE_INVALID_COMMAND;
562 }
563
564 return SE_RESPONSE_OK;
565 }
566
567 /***************************************************************************//**
568 * @brief
569 * Check whether the running command has completed.
570 *
571 * @details
572 * This function polls the SE-to-host mailbox interrupt flag.
573 *
574 * @return True if a command has completed and the result is available
575 ******************************************************************************/
SE_isCommandCompleted(void)576 bool SE_isCommandCompleted(void)
577 {
578 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
579 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
580 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
581 if (!sysCfgClkWasEnabled) {
582 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
583 }
584
585 // First verify that the response is ok
586 if (!rootIsOutputMailboxValid()) {
587 return false;
588 }
589
590 // Check status MB_DONE flag of the mailbox
591 return ((rootOutMb->status & ROOT_MB_DONE) == ROOT_MB_DONE);
592 }
593
594 /***************************************************************************//**
595 * @brief
596 * Read the previously executed command.
597 *
598 * @details
599 * This function reads the previously executed command.
600 *
601 * @return
602 * One of the SE command words.
603 * SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid.
604 ******************************************************************************/
SE_readExecutedCommand(void)605 uint32_t SE_readExecutedCommand(void)
606 {
607 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
608 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
609 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
610 if (!sysCfgClkWasEnabled) {
611 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
612 }
613
614 // First verify that the Output Mailbox includes a valid response.
615 if (!SE_isCommandCompleted()) {
616 return SE_RESPONSE_MAILBOX_INVALID;
617 }
618
619 return rootOutMb->command;
620 }
621
622 /***************************************************************************//**
623 * @brief
624 * Read the status of the previously executed command.
625 *
626 * @details
627 * This function reads the status of the previously executed command.
628 *
629 * @return
630 * One of the SE_RESPONSE return codes:
631 * SE_RESPONSE_OK when the command was executed successfully or a signature
632 * was successfully verified,
633 * SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
634 * SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
635 * SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
636 * SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command, e.g.
637 * because of conflicting Secure/Non-Secure memory accesses,
638 * SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
639 * SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
640 * SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
641 ******************************************************************************/
SE_readCommandResponse(void)642 SE_Response_t SE_readCommandResponse(void)
643 {
644 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
645 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
646 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
647 if (!sysCfgClkWasEnabled) {
648 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
649 }
650
651 // First verify that the Output Mailbox includes a valid response.
652 if (!SE_isCommandCompleted()) {
653 return SE_RESPONSE_MAILBOX_INVALID;
654 }
655
656 return (SE_Response_t)(rootOutMb->status & SE_RESPONSE_MASK);
657 }
658
659 /***************************************************************************//**
660 * @brief
661 * Acknowledge and get status and output data of a completed command.
662 *
663 * @details
664 * This function acknowledges and gets the status and output data of a
665 * completed mailbox command.
666 * The mailbox command is acknowledged by inverting all bits in the checksum
667 * (XOR with 0xFFFFFFFF).
668 * The output data is copied into the linked list of output buffers pointed
669 * to in the given command data structure.
670 *
671 * @param[in] command
672 * Pointer to an SE command structure.
673 *
674 * @return
675 * One of the SE_RESPONSE return codes.
676 * @retval SE_RESPONSE_OK when the command was executed successfully or a
677 * signature was successfully verified,
678 * @retval SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
679 * @retval SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
680 * @retval SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
681 * @retval SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command,
682 * e.g. because of conflicting Secure/Non-Secure
683 * memory accesses,
684 * @retval SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
685 * @retval SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
686 * @retval SE_RESPONSE_MAILBOX_INVALID when mailbox command not done or invalid
687 ******************************************************************************/
SE_ackCommand(SE_Command_t * command)688 SE_Response_t SE_ackCommand(SE_Command_t *command)
689 {
690 // Setup pointer to the VSE Output Mailbox data structure
691 // (must be stored in a RAM area which is not used by the VSE)
692 bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
693 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
694 root_OutputMailbox_t *rootOutMb = (root_OutputMailbox_t *) ROOT_MAILBOX_OUTPUT_BASE;
695 if (!sysCfgClkWasEnabled) {
696 CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
697 }
698 uint32_t *mbData = (uint32_t*) rootOutMb->data;
699 SE_DataTransfer_t *outDataDesc = command->data_out;
700 unsigned int outDataLen, outDataCnt, i, outDescLen;
701 uint32_t *outData;
702
703 // First verify that the Output Mailbox includes a valid response.
704 if (!SE_isCommandCompleted()) {
705 return SE_RESPONSE_MAILBOX_INVALID;
706 }
707
708 // Get output data length
709 outDataLen = rootOutMb->length;
710
711 // Acknowledge the output mailbox response by invalidating checksum
712 mbData[outDataLen] ^= 0xFFFFFFFFUL;
713
714 // Check command status code
715 if ((rootOutMb->status & SE_RESPONSE_MASK) != SE_RESPONSE_OK) {
716 return rootOutMb->status & SE_RESPONSE_MASK;
717 }
718
719 // Copy data from the Output Mailbox to the linked list of output
720 // buffers provided by the user
721 outDataCnt = 0;
722 while (outDataDesc && (outDataCnt < outDataLen)) {
723 outData = (uint32_t*) outDataDesc->data;
724 outDescLen =
725 (outDataDesc->length & SE_DATATRANSFER_LENGTH_MASK) / sizeof(uint32_t);
726 for (i = 0; (i < outDescLen) && (outDataCnt < outDataLen); i++) {
727 outData[i] = mbData[outDataCnt++];
728 }
729 // If we have reached the end of a buffer, go to next buffer descriptor
730 if (i == outDescLen) {
731 outDataDesc = (SE_DataTransfer_t*)
732 ((uint32_t)outDataDesc->next & ~SE_DATATRANSFER_STOP);
733 }
734 }
735
736 // Check if the output data list is too small to copy all output data in
737 // mailbox.
738 if ((outDataDesc == 0) && (outDataCnt < outDataLen)) {
739 return SE_RESPONSE_INVALID_PARAMETER;
740 }
741
742 return SE_RESPONSE_OK;
743 }
744
745 #endif // #if defined(CRYPTOACC_PRESENT)
746
747 /*******************************************************************************
748 ***************************** DEPRECATED *********************************
749 ******************************************************************************/
750
751 /***************************************************************************//**
752 * @addtogroup se_deprecated
753 *
754 * @{
755 ******************************************************************************/
756
757 /*******************************************************************************
758 * The following functions have been deprecated and will be removed in a future
759 * version of emlib. All high-level functionality have been moved to the SE
760 * manager.
761 *******************************************************************************/
762
763 #if !defined(SLI_EM_SE_HOST)
764 /***************************************************************************//**
765 * @brief
766 *
767 * @deprecated
768 * This function has been moved to the SE manager, and will be removed in a
769 * future version of emlib.
770 *
771 * Init pubkey or pubkey signature.
772 *
773 * @details
774 * Initialize public key stored in the SE, or its corresponding signature. The
775 * command can be used to write:
776 * * SE_KEY_TYPE_BOOT -- public key used to perform secure boot
777 * * SE_KEY_TYPE_AUTH -- public key used to perform secure debug
778 *
779 * @note
780 * These keys can not be overwritten, so this command can only be issued once
781 * per key per part.
782 *
783 * @param[in] key_type
784 * ID of key type to initialize.
785 *
786 * @param[in] pubkey
787 * Pointer to a buffer that contains the public key or signature.
788 * Must be word aligned and have a length of 64 bytes.
789 *
790 * @param[in] numBytes
791 * Length of pubkey buffer (64 bytes).
792 *
793 * @param[in] signature
794 * If true, initialize signature for the specified key type instead of the
795 * public key itself.
796 *
797 * @return
798 * One of the SE_RESPONSE return codes.
799 * @retval SE_RESPONSE_OK when the command was executed successfully
800 * @retval SE_RESPONSE_TEST_FAILED when the pubkey is not set
801 * @retval SE_RESPONSE_INVALID_PARAMETER when an invalid type is passed
802 ******************************************************************************/
SE_initPubkey(uint32_t key_type,void * pubkey,uint32_t numBytes,bool signature)803 SE_Response_t SE_initPubkey(uint32_t key_type, void *pubkey, uint32_t numBytes, bool signature)
804 {
805 uint32_t commandWord = SE_COMMAND_INIT_PUBKEY;
806 SE_Response_t res = SE_RESPONSE_INVALID_COMMAND;
807
808 EFM_ASSERT((key_type == SE_KEY_TYPE_BOOT)
809 || (key_type == SE_KEY_TYPE_AUTH));
810
811 EFM_ASSERT(numBytes == 64);
812 EFM_ASSERT(!((size_t)pubkey & 3U));
813
814 // Find parity word
815 volatile uint32_t parity = 0;
816 for (size_t i = 0; i < numBytes / 4; i++) {
817 parity = parity ^ ((uint32_t *)pubkey)[i];
818 }
819
820 // SE command structures
821 #if defined(SEMAILBOX_PRESENT)
822 commandWord =
823 (signature) ? SE_COMMAND_INIT_PUBKEY_SIGNATURE : SE_COMMAND_INIT_PUBKEY;
824 #elif defined(CRYPTOACC_PRESENT)
825 (void)signature;
826 #endif
827 SE_Command_t command = SE_COMMAND_DEFAULT(commandWord | key_type);
828
829 SE_DataTransfer_t parityData = SE_DATATRANSFER_DEFAULT(&parity, 4);
830 SE_addDataInput(&command, &parityData);
831
832 SE_DataTransfer_t pubkeyData = SE_DATATRANSFER_DEFAULT(pubkey, numBytes);
833 SE_addDataInput(&command, &pubkeyData);
834
835 SE_executeCommand(&command);
836 #if defined(SEMAILBOX_PRESENT)
837 res = SE_readCommandResponse();
838 #endif
839 return res;
840 }
841
842 /***************************************************************************//**
843 * @brief
844 *
845 * @deprecated
846 * This function has been moved to the SE manager, and will be removed in a
847 * future version of emlib.
848 *
849 * Initialize SE one-time-programmable (OTP) configuration.
850 *
851 * @details
852 * Configuration is performed by setting the desired options in the
853 * @ref SE_OTPInit_t structure.
854 *
855 * This function can be used to enable secure boot, to configure flash page
856 * locking, and to enable anti-rollback protection when using the SE to
857 * perform an application upgrade, typically a Gecko bootloader upgrade.
858 *
859 * Before secure boot can be enabled, the public key used for secure boot
860 * verification must be uploaded using @ref SE_initPubkey().
861 *
862 * @warning
863 * This command can only be executed once per device! When the configuration
864 * has been programmed it is not possible to update any of the fields.
865 *
866 * @param[in] otp_init
867 * @ref SE_OTPInit_t structure containing the SE configuration.
868 *
869 * @return
870 * One of the SE_RESPONSE return codes.
871 * @retval SE_RESPONSE_OK when the command was executed successfully
872 ******************************************************************************/
SE_initOTP(SE_OTPInit_t * otp_init)873 SE_Response_t SE_initOTP(SE_OTPInit_t *otp_init)
874 {
875 uint32_t mcuSettingsFlags = 0;
876
877 SE_Response_t res = SE_RESPONSE_INVALID_COMMAND;
878
879 if (otp_init->enableSecureBoot) {
880 mcuSettingsFlags |= SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_ENABLE;
881
882 #if defined(SEMAILBOX_PRESENT)
883 uint8_t pubkey[64];
884 {
885 EFM_ASSERT(!((size_t)pubkey & 3U));
886 // SE command structures
887 SE_Command_t commandPubkeyRead = SE_COMMAND_DEFAULT(SE_COMMAND_READ_PUBKEY | SE_KEY_TYPE_BOOT);
888 SE_DataTransfer_t pubkeyData = SE_DATATRANSFER_DEFAULT(pubkey, sizeof(pubkey));
889 SE_addDataOutput(&commandPubkeyRead, &pubkeyData);
890 SE_executeCommand(&commandPubkeyRead);
891 res = SE_readCommandResponse();
892 if (res != SE_RESPONSE_OK) {
893 return SE_RESPONSE_ABORT;
894 }
895 res = SE_RESPONSE_INVALID_COMMAND;
896 }
897 #endif
898 }
899 if (otp_init->verifySecureBootCertificate) {
900 mcuSettingsFlags |= SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_VERIFY_CERTIFICATE;
901 }
902 if (otp_init->enableAntiRollback) {
903 mcuSettingsFlags |= SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_ANTI_ROLLBACK;
904 }
905
906 if (otp_init->secureBootPageLockNarrow && otp_init->secureBootPageLockFull) {
907 return SE_RESPONSE_ABORT;
908 }
909 if (otp_init->secureBootPageLockNarrow) {
910 mcuSettingsFlags |= SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_PAGE_LOCK_NARROW;
911 }
912 if (otp_init->secureBootPageLockFull) {
913 mcuSettingsFlags |= SE_OTP_MCU_SETTINGS_FLAG_SECURE_BOOT_PAGE_LOCK_FULL;
914 }
915
916 // Find parity word
917 volatile uint32_t parity = 0;
918 parity = parity ^ mcuSettingsFlags;
919
920 volatile uint32_t parameters[2] = {
921 parity,
922 sizeof(mcuSettingsFlags)
923 };
924
925 // SE command structures
926 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_INIT_OTP);
927
928 #if defined(SEMAILBOX_PRESENT)
929 static struct ReservedSettings {
930 uint8_t reserved1[16];
931 uint8_t reserved2[2];
932 uint8_t reserved3[2];
933 } reservedSettings = {
934 { 0x00 },
935 { 0xFF },
936 { 0x00 }
937 };
938
939 for (size_t i = 0; i < 5; i++) {
940 parity = parity ^ ((uint32_t*)(&reservedSettings))[i];
941 }
942 parameters[0] = parity;
943 parameters[1] = parameters[1] + sizeof(reservedSettings);
944
945 SE_DataTransfer_t parametersData = SE_DATATRANSFER_DEFAULT(¶meters, 8);
946 SE_addDataInput(&command, ¶metersData);
947
948 SE_DataTransfer_t mcuSettingsFlagsData = SE_DATATRANSFER_DEFAULT((volatile void *)&mcuSettingsFlags, sizeof(mcuSettingsFlags));
949 SE_addDataInput(&command, &mcuSettingsFlagsData);
950
951 SE_DataTransfer_t reservedSettingsData = SE_DATATRANSFER_DEFAULT((volatile void *)&reservedSettings, sizeof(reservedSettings));
952 SE_addDataInput(&command, &reservedSettingsData);
953
954 SE_executeCommand(&command);
955
956 res = SE_readCommandResponse();
957 #elif defined(CRYPTOACC_PRESENT)
958 SE_DataTransfer_t parametersData = SE_DATATRANSFER_DEFAULT(¶meters, 8);
959 SE_addDataInput(&command, ¶metersData);
960
961 SE_DataTransfer_t mcuSettingsFlagsData = SE_DATATRANSFER_DEFAULT((volatile void *)&mcuSettingsFlags, sizeof(mcuSettingsFlags));
962 SE_addDataInput(&command, &mcuSettingsFlagsData);
963
964 SE_executeCommand(&command);
965 #else
966 (void)command;
967 (void)parameters;
968 #endif
969
970 return res;
971 }
972
973 #if defined(SEMAILBOX_PRESENT)
974
975 /***************************************************************************//**
976 * @brief
977 * @deprecated
978 * This function has been moved to the SE manager, and will be removed in a
979 * future version of emlib.
980 *
981 * Writes data to User Data section in MTP. Write data must be aligned to
982 * word size and contain a number of bytes that is divisable by four.
983 *
984 * @note
985 * It is recommended to erase the flash page before performing a write.
986 *
987 * @param[in] offset
988 * Offset to the flash word to write to. Must be aligned to words.
989 * @param[in] data
990 * Data to write to flash.
991 * @param[in] numBytes
992 * Number of bytes to write to flash. NB: Must be divisable by four.
993 * @return
994 * One of the SE_RESPONSE return codes.
995 * @retval SE_RESPONSE_OK when the command was executed successfully or a
996 * signature was successfully verified,
997 * @retval SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
998 * @retval SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
999 * @retval SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
1000 * @retval SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command,
1001 * e.g. because of conflicting Secure/Non-Secure
1002 * memory accesses,
1003 * @retval SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
1004 * @retval SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
1005 ******************************************************************************/
SE_writeUserData(uint32_t offset,void * data,uint32_t numBytes)1006 SE_Response_t SE_writeUserData(uint32_t offset,
1007 void *data,
1008 uint32_t numBytes)
1009 {
1010 // SE command structures
1011 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_WRITE_USER_DATA);
1012 SE_DataTransfer_t userData = SE_DATATRANSFER_DEFAULT(data, numBytes);
1013
1014 SE_addDataInput(&command, &userData);
1015
1016 SE_addParameter(&command, offset);
1017 SE_addParameter(&command, numBytes);
1018
1019 SE_executeCommand(&command);
1020 SE_Response_t res = SE_readCommandResponse();
1021 return res;
1022 }
1023
1024 /***************************************************************************//**
1025 * @brief
1026 * @deprecated
1027 * This function has been moved to the SE manager, and will be removed in a
1028 * future version of emlib.
1029 *
1030 * Erases User Data section in MTP.
1031 *
1032 * @return
1033 * One of the SE_RESPONSE return codes.
1034 * @retval SE_RESPONSE_OK when the command was executed successfully or a
1035 * signature was successfully verified,
1036 * @retval SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
1037 * @retval SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
1038 * @retval SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
1039 * @retval SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command,
1040 * e.g. because of conflicting Secure/Non-Secure
1041 * memory accesses,
1042 * @retval SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
1043 * @retval SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
1044 ******************************************************************************/
SE_eraseUserData()1045 SE_Response_t SE_eraseUserData()
1046 {
1047 // SE command structures
1048 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_ERASE_USER_DATA);
1049
1050 SE_addParameter(&command, SE_COMMAND_OPTION_ERASE_UD);
1051 SE_executeCommand(&command);
1052 SE_Response_t res = SE_readCommandResponse();
1053 return res;
1054 }
1055
1056 /***************************************************************************//**
1057 * @brief
1058 * @deprecated
1059 * This function has been moved to the SE manager, and will be removed in a
1060 * future version of emlib.
1061 *
1062 * Returns the current boot status, versions and system configuration.
1063 *
1064 * @param[out] status
1065 * @ref SE_Status_t containing current SE status.
1066 *
1067 * @return
1068 * One of the SE_RESPONSE return codes.
1069 * @retval SE_RESPONSE_OK upon command completion. Errors are encoded in the
1070 * different parts of the returned status object.
1071 ******************************************************************************/
SE_getStatus(SE_Status_t * status)1072 SE_Response_t SE_getStatus(SE_Status_t *status)
1073 {
1074 volatile uint32_t output[9] = { 0 };
1075
1076 // SE command structures
1077 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_GET_STATUS);
1078 SE_DataTransfer_t outData = SE_DATATRANSFER_DEFAULT((void*)output, 4 * 9);
1079
1080 SE_addDataOutput(&command, &outData);
1081
1082 // Execute command and return response
1083 SE_executeCommand(&command);
1084 SE_Response_t res = SE_readCommandResponse();
1085
1086 // Update status object
1087 status->bootStatus = output[4];
1088 status->seFwVersion = output[5];
1089 status->hostFwVersion = output[6];
1090
1091 SE_DebugStatus_t debugStatus;
1092 debugStatus.debugLockEnabled = (output[7] & (1 << 0));
1093 debugStatus.deviceEraseEnabled = (output[7] & (1 << 1));
1094 debugStatus.secureDebugEnabled = (output[7] & (1 << 2));
1095 status->debugStatus = debugStatus;
1096
1097 status->secureBootEnabled = ((output[8] & 0x1) && ((output[8] & ~0x1) == 0));
1098
1099 return res;
1100 }
1101
1102 /***************************************************************************//**
1103 * @brief
1104 * @deprecated
1105 * This function has been moved to the SE manager, and will be removed in a
1106 * future version of emlib.
1107 *
1108 * Read the serial number of the SE module.
1109 *
1110 * @param[out] serial
1111 * Pointer to array of size 16 bytes.
1112 *
1113 * @return
1114 * One of the @ref SE_Response_t return codes.
1115 * @retval SE_RESPONSE_OK when serial number is returned successfully,
1116 * @retval SE_RESPONSE_INTERNAL_ERROR if not.
1117 ******************************************************************************/
SE_serialNumber(void * serial)1118 SE_Response_t SE_serialNumber(void *serial)
1119 {
1120 // SE command structures
1121 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_READ_SERIAL);
1122 SE_DataTransfer_t outData = SE_DATATRANSFER_DEFAULT(serial, 16);
1123
1124 SE_addDataOutput(&command, &outData);
1125
1126 // Execute command and return response
1127 SE_executeCommand(&command);
1128 SE_Response_t res = SE_readCommandResponse();
1129 return res;
1130 }
1131
1132 /***************************************************************************//**
1133 * @brief
1134 * @deprecated
1135 * This function has been moved to the SE manager, and will be removed in a
1136 * future version of emlib.
1137 *
1138 * Read pubkey or pubkey signature.
1139 *
1140 * @details
1141 * Read out a public key stored in the SE, or its signature. The command can
1142 * be used to read:
1143 * * SE_KEY_TYPE_BOOT
1144 * * SE_KEY_TYPE_AUTH
1145 *
1146 * @param[in] key_type
1147 * ID of key type to read.
1148 *
1149 * @param[out] pubkey
1150 * Pointer to a buffer to contain the returned public key.
1151 * Must be word aligned and have a length of 64 bytes.
1152 *
1153 * @param[in] numBytes
1154 * Length of pubkey buffer (64 bytes).
1155 *
1156 * @param[in] signature
1157 * If true, the function will return the signature programmed for the
1158 * specified public key instead of the public key itself.
1159 *
1160 * @return
1161 * One of the SE_RESPONSE return codes.
1162 * @retval SE_RESPONSE_OK when the command was executed successfully
1163 * @retval SE_RESPONSE_TEST_FAILED when the pubkey is not set
1164 * @retval SE_RESPONSE_INVALID_PARAMETER when an invalid type is passed
1165 ******************************************************************************/
SE_readPubkey(uint32_t key_type,void * pubkey,uint32_t numBytes,bool signature)1166 SE_Response_t SE_readPubkey(uint32_t key_type, void *pubkey, uint32_t numBytes, bool signature)
1167 {
1168 EFM_ASSERT((key_type == SE_KEY_TYPE_BOOT)
1169 || (key_type == SE_KEY_TYPE_AUTH));
1170
1171 EFM_ASSERT(numBytes == 64);
1172 EFM_ASSERT(!((size_t)pubkey & 3U));
1173
1174 // SE command structures
1175 uint32_t commandWord =
1176 (signature) ? SE_COMMAND_READ_PUBKEY_SIGNATURE : SE_COMMAND_READ_PUBKEY;
1177 SE_Command_t command = SE_COMMAND_DEFAULT(commandWord | key_type);
1178
1179 SE_DataTransfer_t pubkeyData = SE_DATATRANSFER_DEFAULT(pubkey, numBytes);
1180 SE_addDataOutput(&command, &pubkeyData);
1181
1182 SE_executeCommand(&command);
1183 SE_Response_t res = SE_readCommandResponse();
1184 return res;
1185 }
1186
1187 /***************************************************************************//**
1188 * @brief
1189 * @deprecated
1190 * This function has been moved to the SE manager, and will be removed in a
1191 * future version of emlib.
1192 *
1193 * Returns the current debug lock configuration.
1194 * @param[out] status
1195 * The command returns a @ref SE_DebugStatus_t with the current status of the
1196 * debug configuration.
1197 * @return
1198 * One of the SE_RESPONSE return codes.
1199 * @retval SE_RESPONSE_OK when the command was executed successfully.
1200 * @retval SE_RESPONSE_INTERNAL_ERROR if there are configuration errors.
1201 ******************************************************************************/
SE_debugLockStatus(SE_DebugStatus_t * status)1202 SE_Response_t SE_debugLockStatus(SE_DebugStatus_t *status)
1203 {
1204 SE_Response_t res;
1205
1206 // SE command structures
1207 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DBG_LOCK_STATUS);
1208
1209 volatile uint32_t status_word = 0;
1210 SE_DataTransfer_t statusData = SE_DATATRANSFER_DEFAULT((void*)&status_word, 4);
1211 SE_addDataOutput(&command, &statusData);
1212
1213 SE_executeCommand(&command);
1214 res = SE_readCommandResponse();
1215
1216 status->debugLockEnabled = (status_word & (1 << 0));
1217 status->deviceEraseEnabled = (status_word & (1 << 1));
1218 status->secureDebugEnabled = (status_word & (1 << 2));
1219
1220 return res;
1221 }
1222
1223 /***************************************************************************//**
1224 * @brief
1225 * @deprecated
1226 * This function has been moved to the SE manager, and will be removed in a
1227 * future version of emlib.
1228 *
1229 * Enables the debug lock for the part.
1230 * @details
1231 * The debug port will be closed and the only way to open it is through
1232 * device erase (if enabled) or temporarily through secure debug unlock (if
1233 * enabled).
1234 *
1235 * @return
1236 * One of the SE_RESPONSE return codes.
1237 * @retval SE_RESPONSE_OK when the command was executed successfully.
1238 * @retval SE_RESPONSE_INTERNAL_ERROR there was a problem locking the debug port.
1239 ******************************************************************************/
SE_debugLockApply(void)1240 SE_Response_t SE_debugLockApply(void)
1241 {
1242 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DBG_LOCK_APPLY);
1243 SE_executeCommand(&command);
1244
1245 return SE_readCommandResponse();
1246 }
1247
1248 /***************************************************************************//**
1249 * @brief
1250 * @deprecated
1251 * This function has been moved to the SE manager, and will be removed in a
1252 * future version of emlib.
1253 *
1254 * Enables the secure debug functionality.
1255 * @details
1256 * Enables the secure debug functionality. This functionality makes it
1257 * possible to open a locked debug port by signing a cryptographic challenge
1258 * and using the debug command interface (DCI).
1259 *
1260 * This command can only be executed before the debug port is locked, and
1261 * after a secure debug public key has been installed in the SE using
1262 * @ref SE_initPubkey() or the corresponding DCI command.
1263 *
1264 * @return
1265 * One of the SE_RESPONSE return codes.
1266 * @retval SE_RESPONSE_OK when the command was executed successfully.
1267 * @retval SE_RESPONSE_INVALID_COMMAND if debug port is locked.
1268 * @retval SE_RESPONSE_INVALID_PARAMETER if secure debug certificates are
1269 * missing.
1270 * @retval SE_RESPONSE_INTERNAL_ERROR if there was a problem during execution.
1271 ******************************************************************************/
SE_debugSecureEnable(void)1272 SE_Response_t SE_debugSecureEnable(void)
1273 {
1274 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DBG_LOCK_ENABLE_SECURE);
1275 SE_executeCommand(&command);
1276
1277 return SE_readCommandResponse();
1278 }
1279
1280 /***************************************************************************//**
1281 * @brief
1282 * @deprecated
1283 * This function has been moved to the SE manager, and will be removed in a
1284 * future version of emlib.
1285 *
1286 * Disables the secure debug functionality.
1287 * @details
1288 * Disables the secure debug functionality that can be used to open a
1289 * locked debug port.
1290 * @return
1291 * One of the SE_RESPONSE return codes.
1292 * @retval SE_RESPONSE_OK when the command was executed successfully.
1293 * @retval SE_RESPONSE_INTERNAL_ERROR if there was a problem during execution.
1294 ******************************************************************************/
SE_debugSecureDisable(void)1295 SE_Response_t SE_debugSecureDisable(void)
1296 {
1297 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DBG_LOCK_DISABLE_SECURE);
1298 SE_executeCommand(&command);
1299
1300 return SE_readCommandResponse();
1301 }
1302
1303 /***************************************************************************//**
1304 * @brief
1305 * @deprecated
1306 * This function has been moved to the SE manager, and will be removed in a
1307 * future version of emlib.
1308 *
1309 * Performs a device mass erase and debug unlock.
1310 *
1311 * @details
1312 * Performs a device mass erase and resets the debug configuration to its
1313 * initial unlocked state. Only available before @ref SE_deviceEraseDisable or
1314 * the corresponding DCI command has been executed.
1315 *
1316 * @note
1317 * This command clears and verifies the complete flash and ram of the
1318 * system, excluding the user data pages and one-time programmable
1319 * commissioning information in the secure element.
1320 *
1321 * @return
1322 * One of the SE_RESPONSE return codes.
1323 * @retval SE_RESPONSE_OK when the command was executed successfully.
1324 * @retval SE_RESPONSE_INVALID_COMMAND if device erase is disabled.
1325 * @retval SE_RESPONSE_INTERNAL_ERROR if there was a problem during execution.
1326 ******************************************************************************/
SE_deviceErase(void)1327 SE_Response_t SE_deviceErase(void)
1328 {
1329 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DEVICE_ERASE);
1330 SE_executeCommand(&command);
1331
1332 return SE_readCommandResponse();
1333 }
1334
1335 /***************************************************************************//**
1336 * @brief
1337 * @deprecated
1338 * This function has been moved to the SE manager, and will be removed in a
1339 * future version of emlib.
1340 *
1341 * Disabled device erase functionality.
1342 *
1343 * @details
1344 * This command disables the device erase command. It does not lock the
1345 * debug interface to the part, but it is a permanent action for the part.
1346 * If device erase is disabled and the device is debug locked, there is no
1347 * way to permanently unlock the part. If secure debug unlock is enabled,
1348 * secure debug unlock can still be used to temporarily open the debug port.
1349 *
1350 * @warning
1351 * This command permanently disables the device erase functionality!
1352 *
1353 * @return
1354 * One of the SE_RESPONSE return codes.
1355 * @retval SE_RESPONSE_OK when the command was executed successfully.
1356 * @retval SE_RESPONSE_INTERNAL_ERROR if there was a problem during execution.
1357 ******************************************************************************/
SE_deviceEraseDisable(void)1358 SE_Response_t SE_deviceEraseDisable(void)
1359 {
1360 SE_Command_t command = SE_COMMAND_DEFAULT(SE_COMMAND_DEVICE_ERASE_DISABLE);
1361 SE_executeCommand(&command);
1362
1363 return SE_readCommandResponse();
1364 }
1365
1366 #endif // #if defined(SEMAILBOX_PRESENT)
1367 #endif // #if !defined(SLI_EM_SE_HOST)
1368
1369 /** @} (end addtogroup deprecated_se) */
1370 /** @} (end addtogroup se) */
1371
1372 #endif /* defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT) */
1373