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