1 /*
2 * FreeRTOS V202212.00
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
24 *
25 */
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "FreeRTOSConfig.h"
31
32 /* FreeRTOS includes. */
33 #include "FreeRTOS.h"
34 #include "semphr.h"
35
36 /* mbed TLS includes. */
37 #if defined( MBEDTLS_CONFIG_FILE )
38 #include MBEDTLS_CONFIG_FILE
39 #else
40 #include "mbedtls/mbedtls_config.h"
41 #endif
42 #include "mbedtls/entropy.h"
43
44 #include "entropy_poll.h"
45
46 #include "mbedtls_freertos_port.h"
47
48 /*-----------------------------------------------------------*/
49
50 /**
51 * @brief Allocates memory for an array of members.
52 *
53 * @param[in] nmemb Number of members that need to be allocated.
54 * @param[in] size Size of each member.
55 *
56 * @return Pointer to the beginning of newly allocated memory.
57 */
mbedtls_platform_calloc(size_t nmemb,size_t size)58 void * mbedtls_platform_calloc( size_t nmemb,
59 size_t size )
60 {
61 size_t totalSize = nmemb * size;
62 void * pBuffer = NULL;
63
64 /* Check that neither nmemb nor size were 0. */
65 if( totalSize > 0 )
66 {
67 /* Overflow check. */
68 if( ( totalSize / size ) == nmemb )
69 {
70 pBuffer = pvPortMalloc( totalSize );
71
72 if( pBuffer != NULL )
73 {
74 ( void ) memset( pBuffer, 0U, totalSize );
75 }
76 }
77 }
78
79 return pBuffer;
80 }
81
82 /*-----------------------------------------------------------*/
83
84 /**
85 * @brief Frees the space previously allocated by calloc.
86 *
87 * @param[in] ptr Pointer to the memory to be freed.
88 */
mbedtls_platform_free(void * ptr)89 void mbedtls_platform_free( void * ptr )
90 {
91 if( ptr != NULL )
92 {
93 vPortFree( ptr );
94 }
95 }
96
97 /*-----------------------------------------------------------*/
98
99 #if defined( MBEDTLS_THREADING_C )
100
101 /**
102 * @brief Creates a mutex.
103 *
104 * @param[in, out] pMutex mbedtls mutex handle.
105 */
mbedtls_platform_mutex_init(mbedtls_threading_mutex_t * pMutex)106 static void mbedtls_platform_mutex_init( mbedtls_threading_mutex_t * pMutex )
107 {
108 configASSERT( pMutex != NULL );
109
110 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
111
112 /* Create a statically-allocated FreeRTOS mutex. This should never fail as
113 * storage is provided. */
114
115 pMutex->mutexHandle = xSemaphoreCreateMutexStatic( &( pMutex->mutexStorage ) );
116 #elif ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
117 pMutex->mutexHandle = xSemaphoreCreateMutex();
118 #endif
119
120 configASSERT( pMutex->mutexHandle != NULL );
121 }
122
123 /*-----------------------------------------------------------*/
124
125 /**
126 * @brief Frees a mutex.
127 *
128 * @param[in] pMutex mbedtls mutex handle.
129 *
130 * @note This function is an empty stub as nothing needs to be done to free
131 * a statically allocated FreeRTOS mutex.
132 */
mbedtls_platform_mutex_free(mbedtls_threading_mutex_t * pMutex)133 static void mbedtls_platform_mutex_free( mbedtls_threading_mutex_t * pMutex )
134 {
135 vSemaphoreDelete( pMutex->mutexHandle );
136 pMutex->mutexHandle = NULL;
137 }
138
139 /*-----------------------------------------------------------*/
140
141 /**
142 * @brief Function to lock a mutex.
143 *
144 * @param[in] pMutex mbedtls mutex handle.
145 *
146 * @return 0 (success) is always returned as any other failure is asserted.
147 */
mbedtls_platform_mutex_lock(mbedtls_threading_mutex_t * pMutex)148 static int mbedtls_platform_mutex_lock( mbedtls_threading_mutex_t * pMutex )
149 {
150 BaseType_t mutexStatus = 0;
151
152 configASSERT( pMutex != NULL );
153 configASSERT( pMutex->mutexHandle != NULL );
154
155 /* mutexStatus is not used if asserts are disabled. */
156 ( void ) mutexStatus;
157
158 /* This function should never fail if the mutex is initialized. */
159 mutexStatus = xSemaphoreTake( pMutex->mutexHandle, portMAX_DELAY );
160
161 configASSERT( mutexStatus == pdTRUE );
162
163 return 0;
164 }
165
166 /*-----------------------------------------------------------*/
167
168 /**
169 * @brief Function to unlock a mutex.
170 *
171 * @param[in] pMutex mbedtls mutex handle.
172 *
173 * @return 0 is always returned as any other failure is asserted.
174 */
mbedtls_platform_mutex_unlock(mbedtls_threading_mutex_t * pMutex)175 static int mbedtls_platform_mutex_unlock( mbedtls_threading_mutex_t * pMutex )
176 {
177 BaseType_t mutexStatus = 0;
178
179 configASSERT( pMutex != NULL );
180 configASSERT( pMutex->mutexHandle != NULL );
181 /* mutexStatus is not used if asserts are disabled. */
182 ( void ) mutexStatus;
183
184 /* This function should never fail if the mutex is initialized. */
185 mutexStatus = xSemaphoreGive( pMutex->mutexHandle );
186 configASSERT( mutexStatus == pdTRUE );
187
188 return 0;
189 }
190
191 /*-----------------------------------------------------------*/
192
193 #if defined( MBEDTLS_THREADING_ALT )
mbedtls_platform_threading_init(void)194 int mbedtls_platform_threading_init( void )
195 {
196 mbedtls_threading_set_alt( mbedtls_platform_mutex_init,
197 mbedtls_platform_mutex_free,
198 mbedtls_platform_mutex_lock,
199 mbedtls_platform_mutex_unlock );
200 return 0;
201 }
202
203 #else /* !MBEDTLS_THREADING_ALT */
204
205 void (* mbedtls_mutex_init)( mbedtls_threading_mutex_t * mutex ) = mbedtls_platform_mutex_init;
206 void (* mbedtls_mutex_free)( mbedtls_threading_mutex_t * mutex ) = mbedtls_platform_mutex_free;
207 int (* mbedtls_mutex_lock)( mbedtls_threading_mutex_t * mutex ) = mbedtls_platform_mutex_lock;
208 int (* mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * mutex ) = mbedtls_platform_mutex_unlock;
209
210 #endif /* !MBEDTLS_THREADING_ALT */
211
212 #endif /* MBEDTLS_THREADING_C */
213 /*-----------------------------------------------------------*/
214
215 #if defined( MBEDTLS_ENTROPY_HARDWARE_ALT )
216 /* Determine which API is available */
217 #if defined( _WIN32 )
218 #define RNG_SOURCE_WINDOWS_CRYPT
219 #elif defined( __linux__ )
220 #include <unistd.h>
221 #include <sys/syscall.h>
222 #if defined( SYS_getrandom )
223 #define RNG_SOURCE_GETRANDOM
224 #endif /* SYS_getrandom */
225 #elif defined( ARM_RDI_MONITOR ) || defined( SEMIHOSTING )
226 #define RNG_SOURCE_SEMIHOST
227 #else
228 #define RNG_SOURCE_DEV_RANDOM
229 #endif /* if defined( _WIN32 ) */
230
231 #if defined( RNG_SOURCE_WINDOWS_CRYPT )
232 #include <windows.h>
233 #include <wincrypt.h>
mbedtls_hardware_poll(void * data,unsigned char * output,size_t len,size_t * olen)234 int mbedtls_hardware_poll( void * data,
235 unsigned char * output,
236 size_t len,
237 size_t * olen )
238 {
239 int lStatus = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
240 HCRYPTPROV hProv = 0;
241
242 /* Unreferenced parameter. */
243 ( void ) data;
244
245 /*
246 * This is port-specific for the Windows simulator, so just use Crypto API.
247 */
248
249 if( TRUE == CryptAcquireContextA(
250 &hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) )
251 {
252 if( TRUE == CryptGenRandom( hProv, len, output ) )
253 {
254 lStatus = 0;
255 *olen = len;
256 }
257
258 CryptReleaseContext( hProv, 0 );
259 }
260
261 return lStatus;
262 }
263 #elif defined( RNG_SOURCE_GETRANDOM )
mbedtls_hardware_poll(void * data,unsigned char * output,size_t len,size_t * olen)264 int mbedtls_hardware_poll( void * data,
265 unsigned char * output,
266 size_t len,
267 size_t * olen )
268 {
269 ( void ) data;
270 int rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
271
272 configASSERT( olen != NULL );
273
274 rslt = getrandom( output, len, 0 );
275
276 if( rslt >= 0 )
277 {
278 *olen = ( size_t ) rslt;
279 rslt = 0;
280 }
281 else
282 {
283 rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
284 }
285
286 return rslt;
287 }
288 #elif defined( RNG_SOURCE_SEMIHOST )
mbedtls_hardware_poll(void * data,unsigned char * output,size_t len,size_t * olen)289 int mbedtls_hardware_poll( void * data,
290 unsigned char * output,
291 size_t len,
292 size_t * olen )
293 {
294 int rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
295 int file;
296
297 ( void ) data;
298
299 configASSERT( olen != NULL );
300 configASSERT( output != NULL );
301
302 file = _open( "/dev/urandom", O_RDONLY );
303
304 if( file >= 0 )
305 {
306 rslt = _read( file, ( char * ) output, len );
307 }
308
309 if( rslt >= 0 )
310 {
311 *olen = len;
312 }
313
314 if( rslt >= 0 )
315 {
316 *olen = len;
317 rslt = 0;
318 }
319 else
320 {
321 rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
322 }
323
324 ( void ) _close( file );
325 return rslt;
326 }
327 #else /* if defined( RNG_SOURCE_WINDOWS_CRYPT ) */
328 #include <stdio.h>
mbedtls_hardware_poll(void * data,unsigned char * output,size_t len,size_t * olen)329 int mbedtls_hardware_poll( void * data,
330 unsigned char * output,
331 size_t len,
332 size_t * olen )
333 {
334 int rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
335 FILE * file;
336 size_t read_length = 0U;
337
338 configASSERT( olen != NULL );
339 configASSERT( output != NULL );
340
341 file = fopen( "/dev/urandom", "rb" );
342
343 if( file != NULL )
344 {
345 rslt = fread( output, 1, len, file );
346 fclose( file );
347 }
348
349 if( rslt >= 0 )
350 {
351 *olen = len;
352 rslt = 0;
353 }
354 else
355 {
356 rslt = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
357 }
358
359 return rslt;
360 }
361 #endif /* if defined( RNG_SOURCE_WINDOWS_CRYPT ) */
362 #endif /* if defined( MBEDTLS_ENTROPY_HARDWARE_ALT ) */
363 /*-----------------------------------------------------------*/
364