Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9cea545
Support added for RPi4
DesobedienteTecnologico Dec 1, 2022
b6b53dc
Merge pull request #23 from newtonick/restructure
DesobedienteTecnologico Dec 10, 2022
8757f2a
first pass at improving readme
newtonick Dec 11, 2022
0254a6c
minor cleanup
newtonick Dec 11, 2022
7c2b1a2
fix indentation
newtonick Dec 11, 2022
fc2c567
add development cycle description and examples
newtonick Dec 13, 2022
4444d35
dev configs
newtonick Dec 13, 2022
1f5eaec
remove gzip of img file and remove the move command of the config folder
newtonick Dec 13, 2022
e528469
Add skip-build option to use with keep-alive
newtonick Dec 13, 2022
109d851
cleanup
newtonick Dec 13, 2022
784f26e
Merge pull request #26 from newtonick/remove-gzip
DesobedienteTecnologico Dec 13, 2022
e6ccafd
Merge pull request #27 from newtonick/add-skip-build-option
DesobedienteTecnologico Dec 13, 2022
6ebcc0a
libncurses-dev added in Dockerfile
DesobedienteTecnologico Dec 18, 2022
78af4c5
Pi4 added to build script
DesobedienteTecnologico Jan 22, 2023
e3d3b8c
Update build.sh to default to 0.5.2 release
newtonick Jan 24, 2023
443d31b
updated to add additional note from DT (https://desobedientetecnologi…
newtonick Jan 24, 2023
eeb7ad5
Merge pull request #24 from newtonick/update-readme-202212
DesobedienteTecnologico Jan 24, 2023
b928a79
Merge pull request #33 from newtonick/patch-7
DesobedienteTecnologico Jan 24, 2023
c062079
update embit to version 0.7.0 adding the required bip-85 support need…
newtonick Jan 25, 2023
65471eb
Merge pull request #30 from DesobedienteTecnologico/libncurses-lib_do…
SeedSigner Jan 25, 2023
0fe331b
Merge pull request #35 from newtonick/update-embit-0.7.0
DesobedienteTecnologico Jan 26, 2023
17f8e2a
Fix - umount MicroSD
DesobedienteTecnologico Feb 4, 2023
7fbcb8f
Merge branch 'main' into rpi4_support
DesobedienteTecnologico Feb 4, 2023
f3618c6
File mode fixed
DesobedienteTecnologico Feb 5, 2023
06c7fdf
Camera Kernel modules added and bootcode.bin removed
DesobedienteTecnologico Feb 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ lsb-release \
git \
wget \
make \
binutils \gcc \
binutils \
gcc \
g++ \
patch \
gzip \
Expand All @@ -22,7 +23,8 @@ file \
bc \
libssl-dev \
vim \
build-essential
build-essential \
libncurses-dev

# Locale
RUN locale-gen en_US.UTF-8
Expand All @@ -36,4 +38,4 @@ RUN echo "LANG=en_US.UTF-8" > /etc/locale.conf
RUN locale-gen en_US.UTF-8

WORKDIR /opt
ENTRYPOINT ["./build.sh"]
ENTRYPOINT ["./build.sh"]
184 changes: 138 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,68 +12,141 @@
<a href="" title="Twitter">
<img src="https://img.shields.io/twitter/follow/seedsigner?style=social">
</a>

</p>


## ✅ Purpose
# ✅ About

A custom linux based operating system built to manage software running on airgapped Bitcoin signing device. SeedSigner is both the project name and [application](http://github.com/SeedSigner/seedsigner/) running on airgapped hardware. This custom operating system, like all operating systems, manages the hardware resources and provides them to the application code. It's currently designed to run on common Raspberry Pi hardware with [accessories](https://github.com/SeedSigner/seedsigner/#shopping-list). The goal of SeedSigner OS is to provide an easy, fast, and secure way to build microSD card image to securely run [SeedSigner](https://seedsigner.com) code.


## ⚙️ Under the Hood

SeedSigner OS is built using [Buildroot](https://www.buildroot.org). Buildroot is a simple, efficient and easy-to-use tool to generate embedded Linux systems through cross-compilation. SeedSigner OS does not fork Buildroot, but uses Buildroot with custom configurations to build microSD card images tailor made for running SeedSigner.

The goal of this project is to make the easiest, fastest, safer and most painless way to build a custom OS that runs <a href="https://seedsigner.com">SeedSigner</a>. For that reason we have pick <a href="https://www.buildroot.org">Buildroot</a>.

## 🛂 Security
1. **SeedSigner OS boots from RAM**. So, once you see the SeedSigner splash screen, you can release the MicroSD and keep using the device!
2. **No** /rootfs partition on MicroSD
3. Many Kernel modules disabled by default:
- Networking and Bluetooth
- SWAP
- I2C
- Serial
- USB
- Pulse-Width Modulation (PWM)
- ...
4. **NO** HDMI
5. **NO** Serial connection TTL
6. **NO** Software that can try to use or access to the wireless, audio, RF...
7. We will have only **/boot** partition in our MicroSD. In which is located a zImage file **(read-only)** that contains the Linux Kernel and RootFS
8. Images are not reproducible. Unique hash in every compilation
9. ...

## 🛠 Building

#### 🔧 Steps to build an image using docker:

SeedSigner OS is built to reduce the attack surface area and enable additional application functionality. The OS is an order of magnatude smaller in size than Raspberry Pi OS (which is what typically is used to run software on a Pi device). Here are a list of some security and functional advantages of using SeedSigner OS.

- Boots 100% from RAM. This means, once you see the SeedSigner splash screen, you can remove the microSD card because no disk I/O is needed after boot!
- One FAT32 partition on the microSD card
- Removes these standard Raspberry Pi OS Kernel modules:
- Networking and Bluetooth
- SWAP
- I2C
- Serial
- USB
- Pulse-Width Modulation (PWM)
- NO HDMI support
- NO Serial connection TTL support
- NO Software supporting any wireless or networking chips
- A single read only zImage file on the boot partition containing the entire Linux kernel and filesystem


# 🛠 Building

## 🐳 Using Docker

Easiest way to build SeedSigner OS is using docker. This keeps the build process repeatable and the build system clean.

### Build Dependencies

* [Docker Compose](https://docs.docker.com/compose/install/)
* [Docker](https://docs.docker.com/get-docker/)

### Steps to build using docker-compose

1. Clone the repository in your machine:
```bash
git clone --recursive https://github.com/SeedSigner/seedsigner-os.git
```
```bash
git clone --recursive https://github.com/SeedSigner/seedsigner-os.git
```
2. Go into the repo directory:
```bash
cd seedsigner-os
```
3. Build images using docker-compose (expect this to take more than 1 hour). You can change the `--pi0` option to the board type you wish to build or use `--all` to build all images types.
```bash
SS_ARGS="--pi0" docker-compose up -d
```

This command will build a docker image from the Dockerfile and in the background (as a daemon) run a container used to compile SeedSigner OS. You can monitor the seedsigner-os-build-images container in Docker Dashboard (if using Docker Desktop) or by running the docker contain list command waiting for the container to complete with an Exit (0) status. The container will create the image(s) in the images directory.

```bash
docker container list --all
```

Run ```SS_ARGS="--help" docker-compose up``` to see the possible build options you can pass in via the SS_ARGS env variable.

### Image Location and Naming

By default, the docker-compose.yml is configured to create a container volume to the images directory in the repo. This is where all the image files are written out after the container completes building the OS from source. The images are named following this convension:

`seedsigner_os.<app_repo_branch>.<board_config>.img`

Example name for a pi0 built off the 0.5.2 branch would be named:

`seedsigner_os.0.5.2.pi0.img`

Here is a table Raspberry Pi boards to image filenames/configs

| Board | Image Name | Build Script Option |
| --------------------- | --------------------------------- | ------------------- |
|Raspberry Pi Zero |`seedsigner_os.<tag>.pi0.img` | --pi0 |
|Raspberry Pi Zero W |`seedsigner_os.<tag>.pi0.img` | --pi0 |
|Raspberry Pi 2 Model B |`seedsigner_os.<tag>.pi2.img` | --pi2 |
|Raspberry Pi Zero 2 W |`seedsigner_os.<tag>.pi02w.img` | --pi02w |
|Raspberry Pi 3 Model B |`seedsigner_os.<tag>.pi02w.img` | --pi02w |
|Raspberry Pi 4 Model B |`seedsigner_os.<tag>.pi4.img` | --pi4 |

### Development cycle using docker

Each time the `docker-compose up` command runs a full build from scratch is performed. To have faster development cycles you'll likely want to avoid building the OS from scratch each time. You can avoid recreating the docker image/container a few different ways. One way is to pass the options `--skip-build` and `--keep-alive` to the `SS_ARGS` env variable when running `docker-compse up -d`. This will cause the container to skip build steps but keep the container running in the background until you explicitly stop it. You can then launch a shell session into the container and work interactively running any specific build commands you desire.

Using docker-compose will build the image and launch the container
```bash
cd seedsigner-os
```
3. Build images using docker-compose (this will take a long time 1-8 hours, depending on PC):
```bash
docker-compose up
SS_ARGS="--skip-build --keep-alive" docker-compose up -d
```

#### Additional helpful build commands
Start a shell session inside the container by running
```bash
SS_ARGS="--pi0 --dev --keep-alive" docker-compose up --build
docker exec -it seedsigner-os-build-images-1 /bin/bash
```

Once you are in the container you can use the build script directly
```bash
docker rm -f seedsigner-os-build-images-1
./build.sh --pi0 --app-repo=https://github.com/seedsigner/seedsigner.git --app-branch=dev --no-clean
```

Or you can use any of the Buildroot customization commands like `make menuconfig` or `linux-menuconfig`

## Developement Configs

Each board also has a developer configuration (dev config). Inside the `/opt` folder are all the build configs for each board matching the name of the build script option. The dev configs are built to work on each board but enable many of the kernel and OS features needed for development. This also makes this the image built less secure, so please do not use with real funds. Dev configs are only used when the `--dev` option is passed in to the build.sh script.

## 📑 Using Debian/Ubuntu (without docker)

If you are not using the docker image, then these build tools will be required for cross-compiling with Buildroot. This is only tested and expected to work on a debian based OS using apt package manager (not MacOS). This single command will install required dependencies for a debian based linux os.

```bash
docker build . -t ss
sudo apt update && sudo apt install make binutils build-essential gcc g++ patch gzip bzip2 perl tar cpio unzip rsync file bc libssl-dev
```

Then to build to image(s), run the build script passing in the desired options

```bash
docker run -v $(pwd)/opt:/opt -v $(pwd)/images:/images --name ss ss:latest --pi0-dev
cd opt
./build --pi0
```

The final image **seedsigner_os.img** is going to be located under **images/** with a name matching the architecture and branch name
You can see the different build options with `./build.sh --help`

## Customizing buildroot configurations

### ℹ️ ./build.sh help
You can see the different build options with `./build.sh -h`
See the Buildroot [quick start guide](https://www.buildroot.org/downloads/manual/manual.html#_buildroot_quick_start) first

### Common Buildroot customization commands:

## 📝 <a href="https://www.buildroot.org/downloads/manual/manual.html#_buildroot_quick_start">See and modify configurations</a>
Buildroot:
```bash
make menuconfig
Expand All @@ -89,10 +162,29 @@ Busybox:
busybox-menuconfig
```

## 📑 <a href="https://www.buildroot.org/downloads/manual/manual.html#requirement">Requirements</a>
If you are not using the docker image, then these build tools will be required for cross-compiling with Buildroot.
This single command will install required dependencies for a debian based linux os.
## SeedSignerOS Layers

```bash
sudo apt update && sudo apt install make binutils build-essential gcc g++ patch gzip bzip2 perl tar cpio unzip rsync file bc libssl-dev
```
Kernel and User space all built from scratch.

![Image Showing SeedSignerOS Layers](docs/img/ssos_layers.png?raw=true "SeedSignerOS Layers")

1. First layer is the hardware. Normally this is the raspberry pi board, camera, LCD Waveshare HAT, and microSD card.
2. Second layer is the linux kernel. Using buildroot specific and minimum required modules have been hand selected to use in the kernel. This layer is required to make use of hardware functionality.
3. Third layer is user space. This is were all the libraries and applications preside. The SeedSigner applications lives in this space. This is also where libraries typically live to do networking, display drivers, external port communications, etc. However on SeedSignerOS none of these drivers or libraries are loaded (that are typically found in a linux OS).

## How is the .iso structure?

![SeedSignerOS microSD File Structure](docs/img/ssos_sd_files.png?raw=true "SeedSignerOS microSD File Structure")

The zImage a compressed version of the Linux kernel that is self-extracting. In that compressed image, we added RootFS. The entire system in a single file!

## Boot Sequence

1. When Raspberry Pi is powered on, the bootloader starts on GPU and read the MicroSD (SDRAM disabled at this point)
2. GPU reads bootcode.bin and starts the bootloader to enable SDRAM
3. Then start_x.elf reads config.txt, cmdline.txt and kernel
4. CPU starts working and then boot the kernel

![Boot Sequence](docs/img/ssos_boot_seq.png?raw=true "Boot Sequence")

Source: https://raspberrypi.stackexchange.com/questions/10442/what-is-the-boot-sequence
Binary file added docs/img/ssos_boot_seq.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/ssos_layers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/ssos_sd_files.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 32 additions & 7 deletions opt/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cur_dir_name=${PWD##*/}
cur_dir=$(pwd)
seedsigner_app_repo="https://github.com/SeedSigner/seedsigner.git"
seedsigner_app_repo_branch="0.5.1-ram"
seedsigner_app_repo_branch="0.5.2"

help()
{
Expand All @@ -18,16 +18,22 @@ help()
--pi4 Build for pi4 and pi4cmio (Not Implemented Yet)

Options:
-h, --help Display a help screen and quit
-h, --help Display a help screen and quit
--dev Builds developer version of images
--no-clean Leave previous build, target, and output files
--skip-repo Skip pulling repo, assume rootfs-overlay/opt is populated with app code
--app-repo Build image with not official seedsigner github repo
--app-branch Build image with repo branch other than default
--keep-alive Keeps container/script running after completeing"
--keep-alive Keeps container/script running after completeing
--skip-build Used generally with keep-alive to run an interactive container"
exit 2
}

tail_endless() {
echo "Running 'tail -f /dev/null' to keep script alive"
tail -f /dev/null
}

download_app_repo() {
# remove previous opt seedsigner app repo code if it already exists
rm -fr ${rootfs_overlay}/opt/
Expand Down Expand Up @@ -90,8 +96,6 @@ build_image() {

if [ -f "${build_dir}/images/seedsigner_os.img" ] && [ -d "${image_dir}" ]; then
mv -f "${build_dir}/images/seedsigner_os.img" "${image_dir}/seedsigner_os.${seedsigner_app_repo_branch}.${config_name}.img"
gzip -f "${image_dir}/seedsigner_os.${seedsigner_app_repo_branch}.${config_name}.img"
mv -f "${build_dir}/images" "${image_dir}/seedsigner_os.${seedsigner_app_repo_branch}.${config_name}"
fi

cd - # return to previous working directory
Expand Down Expand Up @@ -126,6 +130,9 @@ while (( "$#" )); do
--pi02w)
PI02W_FLAG=0; ((ARCH_CNT=ARCH_CNT+1)); shift
;;
--pi4)
PI4_FLAG=0; ((ARCH_CNT=ARCH_CNT+1)); shift
;;
--no-clean)
NOCLEAN=0; shift
;;
Expand All @@ -135,6 +142,9 @@ while (( "$#" )); do
--keep-alive)
KEEPALIVE=0; shift
;;
--skip-build)
SKIPBUILD=0; shift
;;
--dev)
DEVBUILD=0; shift
;;
Expand Down Expand Up @@ -168,6 +178,14 @@ if [ $ARCH_CNT -gt 1 ]; then
exit 3
fi

# if skip build and check for endless
if ! [ -z $SKIPBUILD ]; then
if ! [ -z $KEEPALIVE ]; then
tail_endless
fi
exit 0
fi

# Check for --no-clean argument to pass clean/no-clean to build_image function
if [ -z $NOCLEAN ]; then
CLEAN_ARG="clean"
Expand Down Expand Up @@ -208,7 +226,8 @@ fi
if ! [ -z ${ALL_FLAG} ]; then
build_image "pi0${DEVARG}" "clean" "${SKIPREPO_ARG}"
build_image "pi02w${DEVARG}" "clean" "${SKIPREPO_ARG}"
build_image "pi2${DEVARG}" "${CLEAN_ARG}" "${SKIPREPO_ARG}"
build_image "pi2${DEVARG}" "clean" "${SKIPREPO_ARG}"
build_image "pi4${DEVARG}" "clean" "${SKIPREPO_ARG}"
fi

# Build only for pi0, pi0w, and pi1
Expand All @@ -227,9 +246,15 @@ if ! [ -z ${PI02W_FLAG} ]; then
build_image "pi02w${DEVARG}" "${CLEAN_ARG}" "${SKIPREPO_ARG}"
fi

# build for pi4
if ! [ -z ${PI4_FLAG} ]; then
build_image "pi4${DEVARG}" "${CLEAN_ARG}" "${SKIPREPO_ARG}"
fi


# if build.sh makes it this far without errors, and --keep-alive flag is set, then keep container/script running
if ! [ -z $KEEPALIVE ]; then
tail -f /dev/null
tail_endless
fi

exit 0
4 changes: 2 additions & 2 deletions opt/external-packages/python-embit/python-embit.hash
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# md5, sha256 from https://pypi.org/project/embit/#copy-hash-modal-0adf5c0d-26d5-4b77-b9d4-2ebd488fb1c9
md5 f44cfb6927dcb729ce17a71a6f6dbcc5 embit-0.6.1.tar.gz
sha256 16a84c6668dc9ffc907594457a46f7142cee379646bc009a5a9b77b0d2cb4e12 embit-0.6.1.tar.gz
md5 c43ce954576a2d08896aeeade89fc75d embit-0.7.0.tar.gz
sha256 3dbd42582b5c3e40623e7b2af02956ba6019f6e1ca1c3363f27aa9f9bca03366 embit-0.7.0.tar.gz
4 changes: 2 additions & 2 deletions opt/external-packages/python-embit/python-embit.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#
################################################################################

PYTHON_EMBIT_VERSION = 0.6.1
PYTHON_EMBIT_VERSION = 0.7.0
PYTHON_EMBIT_SOURCE = embit-$(PYTHON_EMBIT_VERSION).tar.gz
PYTHON_EMBIT_SITE = https://files.pythonhosted.org/packages/9a/74/e5e213b5c6471eb56d773eb936ba14c3a4e04ab6c6069a56c0d9a0278a39
PYTHON_EMBIT_SITE = https://files.pythonhosted.org/packages/39/51/9f606c964a45e74cc9df259c5df5e69586c491178bf2972a59b40a889be0
PYTHON_EMBIT_LICENSE = MIT
PYTHON_EMBIT_SETUP_TYPE = setuptools

Expand Down
6 changes: 6 additions & 0 deletions opt/pi4-dev/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "../external-packages/python-urtypes/Config.in"
source "../external-packages/python-pyzbar/Config.in"
source "../external-packages/python-mock/Config.in"
source "../external-packages/python-embit/Config.in"
source "../external-packages/python-picamera/Config.in"
source "../external-packages/python-qrcode/Config.in"
Loading