1 /***************************************************************************//**
2  * @file
3  * @brief Silicon Labs Secure Engine Manager API.
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2020 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)
33 
34 #include "sl_se_manager.h"
35 #include "sli_se_manager_internal.h"
36 #include "em_se.h"
37 #include "em_system.h"
38 #include <string.h>
39 
40 /// @addtogroup sl_se_manager
41 /// @{
42 
43 // -----------------------------------------------------------------------------
44 // Global Functions
45 
46 /***************************************************************************//**
47  * Get random data from hardware TRNG.
48  ******************************************************************************/
sl_se_get_random(sl_se_command_context_t * cmd_ctx,void * data,uint32_t num_bytes)49 sl_status_t sl_se_get_random(sl_se_command_context_t *cmd_ctx,
50                              void * data,
51                              uint32_t num_bytes)
52 {
53   SE_Command_t *se_cmd;
54   sl_status_t ret;
55   uint32_t surplus_bytes, i;
56   uint32_t surplus_word = 0;
57 
58   if (cmd_ctx == NULL || (num_bytes != 0 && data == NULL)) {
59     return SL_STATUS_INVALID_PARAMETER;
60   }
61 
62   se_cmd = &cmd_ctx->command;
63   surplus_bytes = num_bytes & 0x3U;
64   num_bytes &= ~0x3U;
65 
66   if (num_bytes > 0U) {
67     sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_TRNG_GET_RANDOM);
68     SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(data, num_bytes);
69 
70     SE_addDataOutput(se_cmd, &data_out);
71     SE_addParameter(se_cmd, num_bytes);
72 
73     // Execute and wait
74     if ((ret = sli_se_execute_and_wait(cmd_ctx)) != SL_STATUS_OK) {
75       memset(data, 0, num_bytes);
76       return ret;
77     }
78   }
79 
80   if (surplus_bytes > 0) {
81     sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_TRNG_GET_RANDOM);
82     SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(&surplus_word, 4);
83 
84     SE_addDataOutput(se_cmd, &data_out);
85     SE_addParameter(se_cmd, 4);
86 
87     // Execute and wait
88     if ((ret = sli_se_execute_and_wait(cmd_ctx)) != SL_STATUS_OK) {
89       memset(data, 0, num_bytes + surplus_bytes);
90       return ret;
91     }
92 
93     uint8_t *output = (uint8_t*)data + num_bytes;
94     for (i = 0; i < surplus_bytes; i++) {
95       output[i] = (surplus_word >> (i * 8U)) & 0xFFU;
96     }
97   }
98 
99   return SL_STATUS_OK;
100 }
101 
102 /** @} (end addtogroup sl_se) */
103 
104 #endif // defined(SEMAILBOX_PRESENT)
105