Skip to content

Commit

Permalink
seed RNG from entropy source (#11)
Browse files Browse the repository at this point in the history
seed RNG from entropy source + code/doc improvements
  • Loading branch information
virgesmith authored Sep 15, 2024
1 parent dc4f35f commit e361af2
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 27 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if(${PICO_BOARD} STREQUAL pico_w)
target_link_libraries(${PICO_IMAGE}
pico_stdlib
pico_unique_id
pico_rand
hardware_flash
hardware_sync
tinyusb_device
Expand All @@ -50,6 +51,7 @@ elseif(${PICO_BOARD} STREQUAL pico2)
target_link_libraries(${PICO_IMAGE}
pico_stdlib
pico_unique_id
pico_rand
pico_sha256
hardware_flash
hardware_sync
Expand All @@ -61,6 +63,7 @@ else()
target_link_libraries(${PICO_IMAGE}
pico_stdlib
pico_unique_id
pico_rand
hardware_flash
hardware_sync
tinyusb_device
Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ I'm not a security expert and the device/software is almost certainly not harden

Pico, Pico W, Tiny2040 and Pico2 boards are known to work. Other RP2040/RP2350 boards have not been tested but are likely to (mostly) work. E.g. the Pico W requires the wifi driver purely for the LED (which is connected to the wifi chip) to function (though neither wifi nor bluetooth are enabled.)

## Update v1.4.1

- Use standard library implementation of `minstd_rand` and seed it with the TRNG from `pico_rand` (used by ECDSA).
- Minor code improvements

## Update v1.4.0

- Updates pico SDK to v2.0
Expand Down Expand Up @@ -102,7 +107,7 @@ You will then need to:
sudo apt install gcc-arm-none-eabi cmake
```

NB 13.2.0 is recommended. A prebuilt RISC-V toolchain can be found [here](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable).
NB 13.2.0 is recommended, but 10.3.1 and 14 seem to work too. A prebuilt RISC-V toolchain can be found [here](https://github.com/raspberrypi/pico-sdk-tools/releases/tag/v2.0.0-1).

- download [pico-sdk](https://github.com/raspberrypi/pico-sdk) >= 2, see [here](https://www.raspberrypi.org/documentation/pico/getting-started/). NB This project uses a tagged release of pico-sdk, so download and extract e.g. [2.0.0](hhttps://github.com/raspberrypi/pico-sdk/archive/refs/tags/2.0.0.tar.gz)

Expand All @@ -118,16 +123,14 @@ You will then need to:

- [**pico2 only**] tinyUSB 0.16.0 doesn't work. I used a cloned SDK with submodules (rather than a release) for pico2 builds

- download [mbedtls](https://tls.mbed.org/api/): see also their [repo](https://github.com/ARMmbed/mbedtls). Currently using the 3.6.0 release/tag.
- download [mbedtls](https://tls.mbed.org/api/): see also their [repo](https://github.com/ARMmbed/mbedtls). Currently using the 3.6.0 release/tag. This must be kept separate from the implementation in the SDK (which still on v2) and requires a custom configuration.

create a symlinks in the project root to the pico SDK and mbedtls, e.g.:
create a symlink in the project root to the pico SDK and mbedtls, e.g.:

```sh
ln -s ../mbedtls-3.6.0 mbedtls
```

Not sure why, but I couldn't get it to work with the symlink inside pico-sdk like tinyusb.

You should now have a structure something like this:

```txt
Expand Down
17 changes: 6 additions & 11 deletions pico_crypto_key/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ def _get_config(board: str) -> dict[str, str]:
return cfg["default"] | cfg[board]


@app.command()
def configure():
"""Configure the project."""
raise NotImplementedError("TODO...")


def _check_symlink(path: str) -> bool:
path = Path(path)
print(f"Checking {path} ", end="")
Expand All @@ -42,13 +36,14 @@ def _check_symlink(path: str) -> bool:
print(f"-> {link}")
return True
elif path.is_dir():
print("")
return True
else:
print("NOT FOUND")
return False


@app.command()
@app.command(no_args_is_help=True)
def check(board: str = typer.Option(help="the target board")):
"""Check the project configuration."""

Expand Down Expand Up @@ -84,7 +79,7 @@ def check(board: str = typer.Option(help="the target board")):
print("check ok" if ok else "configuration errors found")


@app.command()
@app.command(no_args_is_help=True)
def clean(board: str = typer.Option(help="the target board")) -> None:
"""Clean intermediate build files."""
_get_config(board) # load config just to check board name is valid
Expand All @@ -93,7 +88,7 @@ def clean(board: str = typer.Option(help="the target board")) -> None:
shutil.rmtree(_build_dir(board))


@app.command()
@app.command(no_args_is_help=True)
def build(board: str = typer.Option(help="the target board")) -> None:
"""Build the pico-crypto-key image."""

Expand Down Expand Up @@ -124,7 +119,7 @@ def build(board: str = typer.Option(help="the target board")) -> None:
assert result.returncode == 0


@app.command()
@app.command(no_args_is_help=True)
def install(
device_path: str = typer.Argument(..., help="the path to the device storage, e.g. /media/${USER}/RPI-RP2"),
board: str = typer.Option(help="the target board"),
Expand All @@ -145,7 +140,7 @@ def install(
assert result.returncode == 0


@app.command()
@app.command(no_args_is_help=True)
def reset_pin(
device_path: str = typer.Argument(..., help="the path to the device storage, e.g. /media/${USER}/RPI-RP2"),
board: str = typer.Option(help="the target board"),
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pico-crypto-key"
version = "1.4.0"
version = "1.4.1"
authors = [
{ name="Andrew Smith", email="[email protected]" },
]
Expand Down
15 changes: 11 additions & 4 deletions src/ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "mbedtls/asn1write.h" // for local ecdsa_signature_to_asn1
#include "mbedtls/error.h" // for local ecdsa_signature_to_asn1

#include "pico/rand.h"

#include <random>

#include <cstdint>
#include <cstring>

Expand Down Expand Up @@ -38,12 +42,15 @@ int ecdsa_signature_to_asn1(const mbedtls_mpi* r, const mbedtls_mpi* s, unsigned
return 0;
}

// int (*f_rng_blind)(void *, unsigned char *, size_t)
#if !defined(PICO_RAND_SEED_ENTROPY_SRC_ROSC) | !defined(PICO_RAND_ENTROPY_SRC_TIME)
#error Entropy sources not enabled
#endif

// ECDSA requires this signature
extern "C" int minstd_rand(void*, byte* p, size_t n) {
static uint32_t r = 1;
static std::minstd_rand rng(get_rand_32());
for (size_t i = 0; i < n; ++i) {
r = r * 48271 % 2147483647;
p[i] = static_cast<byte>(r); // % 256;
p[i] = static_cast<byte>(rng());
}
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/sha256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
#include "error.h"
#include "usb_cdc.h"

#include "mbedtls/sha256.h"
#ifdef PICO_RP2350
#include "pico/sha256.h"
#else
#include "mbedtls/sha256.h"
#endif

namespace {
Expand Down Expand Up @@ -50,7 +51,6 @@ bytes sha256::hash_in() {

pico_sha256_finish(&state, &result);
bytes hash(result.bytes, result.bytes + SHA256_RESULT_BYTES);

#else
wrap<mbedtls_sha256_context> ctx(mbedtls_sha256_init, mbedtls_sha256_free);
mbedtls_sha256_starts(&ctx, 0);
Expand Down
8 changes: 4 additions & 4 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ typedef std::vector<byte> bytes;

namespace std
{
// force byte to print as character
// force byte to print as character
inline std::string to_string(uint8_t c)
{
return std::string(1, c);
Expand All @@ -34,8 +34,8 @@ using namespace std::string_literals;
template <typename T> class wrap final {
public:
typedef T value_type;
typedef void (*f_init_t)(T*);
typedef void (*f_free_t)(T*);
typedef void (*f_init_t)(value_type*);
typedef void (*f_free_t)(value_type*);

wrap(f_init_t init, f_free_t free) : m_struct(), m_deleter(free) { init(&m_struct); }

Expand All @@ -58,6 +58,6 @@ template <typename T> class wrap final {
const value_type& operator*() const { return m_struct; }

private:
T m_struct;
value_type m_struct;
f_free_t m_deleter;
};

0 comments on commit e361af2

Please sign in to comment.