Skip to content

Commit

Permalink
pico mbedtls
Browse files Browse the repository at this point in the history
  • Loading branch information
bettio committed Nov 29, 2023
1 parent b288b76 commit 77ff4b8
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 2 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Crypto functions on generic_unix platform now rely on MbedTLS instead of OpenSSL
- Platform function providing time used by timers was changed from `sys_monotonic_millis` to `sys_monotonic_time_u64`, `sys_monotonic_time_u64_to_ms` and `sys_monotonic_time_ms_to_u64`.
- Implement `atomvm:random/0` and `atomvm:rand_bytes/1` on top of `crypto:strong_rand_bytes/1` on
generic_unix platform and ESP32
generic_unix, ESP32 and RP2040 platforms.

### Added

Expand All @@ -41,7 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for `crypto:one_time/4,5` on Unix and Pico as well as for `crypto:hash/2` on Pico
- Added ability to configure STM32 Nucleo boards onboard UART->USB-COM using the `-DBOARD=nucleo` cmake option
- Added STM32 cmake option `-DAVM_CFG_CONSOLE=` to select a different uart peripheral for the system console
- Added `crypto:strong_rand_bytes/1` using Mbed-TLS (only on generic_unix and ESP32 platforms)
- Added `crypto:strong_rand_bytes/1` using Mbed-TLS (only on generic_unix, ESP32 and RP2040
platforms)

### Removed

Expand Down
15 changes: 15 additions & 0 deletions src/platforms/rp2040/src/lib/rp2040_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include <pico/cond.h>
#include <pico/util/queue.h>

#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>

#pragma GCC diagnostic pop

#include "sys.h"
Expand Down Expand Up @@ -112,6 +115,18 @@ struct RP2040PlatformData
cond_t event_poll_cond;
#endif
queue_t event_queue;

#ifndef AVM_NO_SMP
Mutex *entropy_mutex;
#endif
mbedtls_entropy_context entropy_ctx;
bool entropy_is_initialized;

#ifndef AVM_NO_SMP
Mutex *random_mutex;
#endif
mbedtls_ctr_drbg_context random_ctx;
bool random_is_initialized;
};

typedef void (*port_driver_init_t)(GlobalContext *global);
Expand Down
93 changes: 93 additions & 0 deletions src/platforms/rp2040/src/lib/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
#include <otp_socket.h>
#endif

#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000)
#include <mbedtls/build_info.h>
#else
#include <mbedtls/config.h>
#endif

// libAtomVM
#include <avmpack.h>
#include <defaultatoms.h>
Expand All @@ -57,6 +63,14 @@
// Platform uses listeners
#include "listeners.h"

#ifndef AVM_NO_SMP
#define SMP_MUTEX_LOCK(mtx) smp_mutex_lock(mtx)
#define SMP_MUTEX_UNLOCK(mtx) smp_mutex_unlock(mtx)
#else
#define SMP_MUTEX_LOCK(mtx)
#define SMP_MUTEX_UNLOCK(mtx)
#endif

struct PortDriverDefListItem *port_driver_list;
struct NifCollectionDefListItem *nif_collection_list;

Expand All @@ -75,6 +89,9 @@ void sys_init_platform(GlobalContext *glb)
cyw43_arch_init();
otp_socket_init(glb);
#endif

platform->entropy_is_initialized = false;
platform->random_is_initialized = false;
}

void sys_free_platform(GlobalContext *glb)
Expand All @@ -85,6 +102,15 @@ void sys_free_platform(GlobalContext *glb)

struct RP2040PlatformData *platform = glb->platform_data;
queue_free(&platform->event_queue);

if (platform->random_is_initialized) {
mbedtls_ctr_drbg_free(&platform->random_ctx);
}

if (platform->entropy_is_initialized) {
mbedtls_entropy_free(&platform->entropy_ctx);
}

free(platform);

#ifndef AVM_NO_SMP
Expand Down Expand Up @@ -387,3 +413,70 @@ void sys_unregister_listener_from_event(GlobalContext *global, listener_event_t
}
synclist_unlock(&global->listeners);
}

int sys_mbedtls_entropy_func(void *entropy, unsigned char *buf, size_t size)
{
#ifndef MBEDTLS_THREADING_C
struct RP2040PlatformData *platform
= CONTAINER_OF(entropy, struct RP2040PlatformData, entropy_ctx);
SMP_MUTEX_LOCK(platform->entropy_mutex);
int result = mbedtls_entropy_func(entropy, buf, size);
SMP_MUTEX_UNLOCK(platform->entropy_mutex);

return result;
#else
return mbedtls_entropy_func(entropy, buf, size);
#endif
}

mbedtls_entropy_context *sys_mbedtls_get_entropy_context_lock(GlobalContext *global)
{
struct RP2040PlatformData *platform = global->platform_data;

SMP_MUTEX_LOCK(platform->entropy_mutex);

if (!platform->entropy_is_initialized) {
mbedtls_entropy_init(&platform->entropy_ctx);
platform->entropy_is_initialized = true;
}

return &platform->entropy_ctx;
}

void sys_mbedtls_entropy_context_unlock(GlobalContext *global)
{
struct RP2040PlatformData *platform = global->platform_data;
SMP_MUTEX_UNLOCK(platform->entropy_mutex);
}

mbedtls_ctr_drbg_context *sys_mbedtls_get_ctr_drbg_context_lock(GlobalContext *global)
{
struct RP2040PlatformData *platform = global->platform_data;

SMP_MUTEX_LOCK(platform->random_mutex);

if (!platform->random_is_initialized) {
mbedtls_ctr_drbg_init(&platform->random_ctx);

mbedtls_entropy_context *entropy_ctx = sys_mbedtls_get_entropy_context_lock(global);
// Safe to unlock it now, sys_mbedtls_entropy_func will lock it again later
sys_mbedtls_entropy_context_unlock(global);

const char *seed = "AtomVM RP2040 Mbed-TLS initial seed.";
int seed_len = strlen(seed);
int seed_err = mbedtls_ctr_drbg_seed(&platform->random_ctx, sys_mbedtls_entropy_func,
entropy_ctx, (const unsigned char *) seed, seed_len);
if (UNLIKELY(seed_err != 0)) {
abort();
}
platform->random_is_initialized = true;
}

return &platform->random_ctx;
}

void sys_mbedtls_ctr_drbg_context_unlock(GlobalContext *global)
{
struct RP2040PlatformData *platform = global->platform_data;
SMP_MUTEX_UNLOCK(platform->random_mutex);
}

0 comments on commit 77ff4b8

Please sign in to comment.