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