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 "sl_se_manager_attestation.h"
37 #include "em_se.h"
38
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42
43 /// @addtogroup sl_se_manager
44 /// @{
45
46 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
47 // -----------------------------------------------------------------------------
48 // Static Functions
49
50 /***************************************************************************//**
51 * @brief
52 * Validate the command word, challenge size and update command word with
53 * option flags
54 *
55 * @param[in, out] command_word
56 * The command word to send to the SE. Will be modified to reflect challenge
57 * size.
58 *
59 * @param challenge_size
60 * Size of the challenge to be used.
61 *
62 * @return
63 * Status code, @ref sl_status.h.
64 ******************************************************************************/
validate_and_update_command_word(uint32_t * command_word,size_t challenge_size)65 static sl_status_t validate_and_update_command_word(uint32_t *command_word,
66 size_t challenge_size)
67 {
68 // Check supported challenge sizes
69 uint32_t command_id = *command_word & 0xFFFF0000UL;
70 if (command_id == SLI_SE_COMMAND_ATTEST_PSA_IAT) {
71 switch (challenge_size) {
72 case SL_SE_ATTESTATION_CHALLENGE_SIZE_32:
73 *command_word |= 0x01 << 8;
74 break;
75 case SL_SE_ATTESTATION_CHALLENGE_SIZE_48:
76 *command_word |= 0x02 << 8;
77 break;
78 case SL_SE_ATTESTATION_CHALLENGE_SIZE_64:
79 *command_word |= 0x03 << 8;
80 break;
81 default:
82 return SL_STATUS_INVALID_PARAMETER;
83 }
84 } else if (command_id == SLI_SE_COMMAND_ATTEST_CONFIG) {
85 if (challenge_size != SL_SE_ATTESTATION_CHALLENGE_SIZE_32) {
86 return SL_STATUS_INVALID_PARAMETER;
87 }
88 // No need to do anything with the command word
89 } else {
90 // Unknown command ID
91 return SL_STATUS_INVALID_PARAMETER;
92 }
93 // All the checks passed
94 return SL_STATUS_OK;
95 }
96
97 /***************************************************************************//**
98 * @brief
99 * Get the PSA initial attest token from the SE
100 *
101 * @param[in] cmd_ctx
102 * SE command context struct.
103 *
104 * @param[in] challenge_size
105 * Size of the challenge object in bytes. Must be either 32, 48 or 64.
106 *
107 * @param[out] token_size
108 * Number of bytes actually used in token_buf.
109 *
110 * @param[in] command_word
111 * The command word to send to the SE, to differentiat between token types
112 *
113 * @return
114 * Status code, @ref sl_status.h.
115 ******************************************************************************/
get_attestation_token_size(sl_se_command_context_t * cmd_ctx,size_t challenge_size,size_t * token_size,uint32_t command_word)116 static sl_status_t get_attestation_token_size(sl_se_command_context_t *cmd_ctx,
117 size_t challenge_size,
118 size_t *token_size,
119 uint32_t command_word)
120 {
121 // Parameter check
122 if (cmd_ctx == NULL || token_size == NULL) {
123 return SL_STATUS_INVALID_PARAMETER;
124 }
125
126 // Check command word and challenge size
127 sl_status_t status = validate_and_update_command_word(&command_word,
128 challenge_size);
129 if (status != SL_STATUS_OK) {
130 return status;
131 }
132
133 // Use a dummy nonce since the SE requires nonce input even if we just
134 // want to find the token length
135 uint8_t dummy_nonce[SL_SE_ATTESTATION_CHALLENGE_SIZE_64] = { 0 };
136
137 // Build and execute the command
138 SE_Command_t *se_cmd = &cmd_ctx->command;
139 // Or comman word with 0x01 to enable length output only
140 sli_se_command_init(cmd_ctx, command_word | 0x01UL);
141 SE_DataTransfer_t noncedata =
142 SE_DATATRANSFER_DEFAULT(dummy_nonce, challenge_size);
143 SE_addDataInput(se_cmd, &noncedata);
144 SE_DataTransfer_t sizedata =
145 SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
146 SE_addDataOutput(se_cmd, &sizedata);
147
148 return sli_se_execute_and_wait(cmd_ctx);
149 }
150
151 /***************************************************************************//**
152 * @brief
153 * Get an attestation token from the SE
154 *
155 * @param[in] cmd_ctx
156 * SE command context struct.
157 *
158 * @param[in] auth_challenge
159 * Buffer with a challenge object selected by the caller.
160 *
161 * @param[in] challenge_size
162 * Size of the challenge object in bytes. Must be either 32, 48 or 64.
163 *
164 * @param[out] token_buf
165 * Buffer where the output token will be stored.
166 *
167 * @param[in] token_buf_size
168 * Size of token_buf in bytes.
169 *
170 * @param[out] token_size
171 * Number of bytes actually used in token_buf.
172 *
173 * @param[in] command_word
174 * The command word to send to the SE, to differentiat between token types
175 *
176 * @return
177 * Status code, @ref sl_status.h.
178 ******************************************************************************/
get_attestation_token(sl_se_command_context_t * cmd_ctx,const uint8_t * auth_challenge,size_t challenge_size,uint8_t * token_buf,size_t token_buf_size,size_t * token_size,uint32_t command_word)179 static sl_status_t get_attestation_token(sl_se_command_context_t *cmd_ctx,
180 const uint8_t *auth_challenge,
181 size_t challenge_size,
182 uint8_t *token_buf,
183 size_t token_buf_size,
184 size_t *token_size,
185 uint32_t command_word)
186 {
187 // Parameter check
188 if (cmd_ctx == NULL
189 || auth_challenge == NULL
190 || token_buf == NULL
191 || token_size == NULL) {
192 return SL_STATUS_INVALID_PARAMETER;
193 }
194
195 // Check supported challenge sizes
196 sl_status_t status = validate_and_update_command_word(&command_word,
197 challenge_size);
198 if (status != SL_STATUS_OK) {
199 return status;
200 }
201
202 // Check that buffer is sufficiently large
203 status = get_attestation_token_size(cmd_ctx,
204 challenge_size,
205 token_size,
206 command_word);
207 if (status != SL_STATUS_OK) {
208 return status;
209 }
210 if (((*token_size + 0x3) & ~0x3) > token_buf_size) {
211 return SL_STATUS_WOULD_OVERFLOW;
212 }
213
214 // Build and execute the command
215 SE_Command_t *se_cmd = &cmd_ctx->command;
216 sli_se_command_init(cmd_ctx, command_word);
217 SE_DataTransfer_t noncedata =
218 SE_DATATRANSFER_DEFAULT(auth_challenge, challenge_size);
219 SE_addDataInput(se_cmd, &noncedata);
220 SE_DataTransfer_t sizedata =
221 SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
222 SE_addDataOutput(se_cmd, &sizedata);
223 SE_DataTransfer_t tokendata =
224 SE_DATATRANSFER_DEFAULT(token_buf, ((*token_size + 0x3) & ~0x3));
225 SE_addDataOutput(se_cmd, &tokendata);
226
227 return sli_se_execute_and_wait(cmd_ctx);
228 }
229
230 // -----------------------------------------------------------------------------
231 // Global Functions
232
233 /***************************************************************************//**
234 * Get the PSA initial attest token from the SE
235 ******************************************************************************/
sl_se_attestation_get_psa_iat_token(sl_se_command_context_t * cmd_ctx,const uint8_t * auth_challenge,size_t challenge_size,uint8_t * token_buf,size_t token_buf_size,size_t * token_size)236 sl_status_t sl_se_attestation_get_psa_iat_token(sl_se_command_context_t *cmd_ctx,
237 const uint8_t *auth_challenge,
238 size_t challenge_size,
239 uint8_t *token_buf,
240 size_t token_buf_size,
241 size_t *token_size)
242 {
243 return get_attestation_token(cmd_ctx,
244 auth_challenge,
245 challenge_size,
246 token_buf,
247 token_buf_size,
248 token_size,
249 SLI_SE_COMMAND_ATTEST_PSA_IAT);
250 }
251
252 /***************************************************************************//**
253 * Get the size of a PSA initial attest token with the given nonce
254 ******************************************************************************/
sl_se_attestation_get_psa_iat_token_size(sl_se_command_context_t * cmd_ctx,size_t challenge_size,size_t * token_size)255 sl_status_t sl_se_attestation_get_psa_iat_token_size(sl_se_command_context_t *cmd_ctx,
256 size_t challenge_size,
257 size_t *token_size)
258 {
259 return get_attestation_token_size(cmd_ctx,
260 challenge_size,
261 token_size,
262 SLI_SE_COMMAND_ATTEST_PSA_IAT);
263 }
264
265 /***************************************************************************//**
266 * Get an attested (signed) security configuration token from the SE
267 ******************************************************************************/
sl_se_attestation_get_config_token(sl_se_command_context_t * cmd_ctx,const uint8_t * auth_challenge,size_t challenge_size,uint8_t * token_buf,size_t token_buf_size,size_t * token_size)268 sl_status_t sl_se_attestation_get_config_token(sl_se_command_context_t *cmd_ctx,
269 const uint8_t *auth_challenge,
270 size_t challenge_size,
271 uint8_t *token_buf,
272 size_t token_buf_size,
273 size_t *token_size)
274 {
275 return get_attestation_token(cmd_ctx,
276 auth_challenge,
277 challenge_size,
278 token_buf,
279 token_buf_size,
280 token_size,
281 SLI_SE_COMMAND_ATTEST_CONFIG);
282 }
283
284 /***************************************************************************//**
285 * Get the size of a security configuration token
286 ******************************************************************************/
sl_se_attestation_get_config_token_size(sl_se_command_context_t * cmd_ctx,size_t challenge_size,size_t * token_size)287 sl_status_t sl_se_attestation_get_config_token_size(sl_se_command_context_t *cmd_ctx,
288 size_t challenge_size,
289 size_t *token_size)
290 {
291 return get_attestation_token_size(cmd_ctx,
292 challenge_size,
293 token_size,
294 SLI_SE_COMMAND_ATTEST_CONFIG);
295 }
296
297 #endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
298
299 #ifdef __cplusplus
300 }
301 #endif
302
303 /** @} (end addtogroup sl_se_manager) */
304
305 #endif // defined(SEMAILBOX_PRESENT)
306