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