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(&parameters, 8);
852   SE_addDataInput(&command, &parametersData);
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(&parameters, 8);
865   SE_addDataInput(&command, &parametersData);
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