Skip to content

Commit 5b803bd

Browse files
feat: Add image signing instrctuons, docs and scripts
Co-authored-by: MarkoSagadin <marko.sagadin42@gmail.com>
1 parent bde1b95 commit 5b803bd

File tree

9 files changed

+113
-0
lines changed

9 files changed

+113
-0
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ on:
1515

1616
env:
1717
GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}
18+
IMAGE_SIGN_KEY: ${{ secrets.IMAGE_SIGN_KEY}}
1819

1920
jobs:
2021
build:

.github/workflows/codechecker.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ env:
2020
CODECHECKER_CREDENTIALS: ${{ secrets.CODECHECKER_CREDENTIALS }}
2121
EAST_CODECHECKER_SERVER_URL: ${{ secrets.CODECHECKER_SERVER_URL }}
2222
GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}
23+
IMAGE_SIGN_KEY: ${{ secrets.IMAGE_SIGN_KEY}}
2324

2425
jobs:
2526
codechecker:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,6 @@ codechecker-diffs/*
6060

6161
# version files
6262
VERSION
63+
64+
# private keys
65+
*.pem

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ The project's documentation can be found in the [doc/](./doc/README.md) folder.
2929
- [ ] Provide repository setup instructions, use the template in the
3030
[Setup document](./doc/development/setup.md). Replace `<repo-name>` and `<board_name>` as
3131
appropriate for your project.
32+
- [ ] Create signing keys for MCUboot and set them up for the project. See the
33+
[Signing Keys document](./doc/development/signing_keys.md) for more information.
3234

3335
### GitHub Actions
3436

app/sysbuild.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
11
# Enable MCUBOOT
22
SB_CONFIG_BOOTLOADER_MCUBOOT=y
3+
4+
# Below path can look a bit confusing.
5+
# At this point the APPLICATION_CONFIG_DIR is still unmodified, so it points to
6+
# the directory where this sysbuild.conf file is located.
7+
# But during the app build it gets modified (in the CMakeLists.txt) to point to
8+
# the conf/ directory.
9+
SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APPLICATION_CONFIG_DIR}/signing_key.pem"
10+
SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y

doc/development/setup.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,19 @@ make pre-build
2121
Turn on `pre-commit` tool by running `pre-commit install`. If you do not have it installed or the
2222
**command did not succeed** follow
2323
[these instructions](https://github.com/IRNAS/irnas-guidelines-docs/tree/main/tools/pre-commit).
24+
25+
## Setup signing keys
26+
27+
This project uses the MCUboot bootloader which uses private-public key cryptography to validate the
28+
image signatures at boot time. When building images the build system needs to have access to the
29+
signing keys, so it can sign the built image.
30+
31+
1. Find the keys in 1Password, search by the repository GitHub name.
32+
2. Copy the contents of the signing key files to a local file at the expected paths. The expected
33+
paths can be found by checking the `pre-build` make target in the `Makefile`.
34+
35+
<!-- prettier-ignore -->
36+
> [!WARNING]
37+
> Signing keys are private keys! Therefore, they must never be leaked to the public. That is why
38+
> they are not included in the repository and ignored in the `.gitignore` file.
39+
> They must always be added to each developer's local environment manually, as described above.

doc/development/signing_keys.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Signing keys
2+
3+
Each project using MCUBoot requires signing keys to sign the firmware images. These keys are used to
4+
verify the integrity and authenticity of the firmware during the boot process.
5+
6+
In most cases, the project will require only a single signing key, due to using a single application
7+
firmware. If more than one application firmware is needed, multiple signing keys are probably needed
8+
as well.
9+
10+
## Creating the first signing key
11+
12+
1. Create a signing key file using the following command from the root of the project:
13+
14+
```shell
15+
east bypass -- python3 ../bootloader/mcuboot/scripts/imgtool.py keygen -t ecdsa-p256 -k app/signing_key.pem
16+
```
17+
18+
2. Create an entry in 1Password and paste contents of the created signing key file, so that it can
19+
be used by other developers. Use GitHub repository name and keys purpose as the entry title, for
20+
example `client-project-firmware - Main application signing key`.
21+
22+
3. Add a new GitHub secret with the signing key file contents:
23+
24+
- Go to your GitHub repository.
25+
- Navigate to `Settings -> Secrets and variables -> Actions`.
26+
- Press the `New secret` button.
27+
- Set the name of the secret to `IMAGE_SIGN_KEY`, and paste the contents of the signing key file.
28+
29+
The `app/signing_key.pem` file is not tracked by Git, so it will not be included in the repository.
30+
If you ever delete the file, you will need to recreate it from the 1Password entry.
31+
32+
## Creating additional signing keys
33+
34+
For each additional signing key you need to create, follow these steps:
35+
36+
1. Follow the steps from the "Creating the first signing key" section to create an additional
37+
signing key. Use a different name for the signing key file, 1Password entry and GitHub secret.
38+
Use a consistent naming scheme.
39+
2. Update the `env` section in each workflow file (found in `.github/workflow`) that calls the
40+
`make pre-build` target. The `env` section should convert the secret into an environment
41+
variable, e.g. `EXTRA_IMAGE_SIGN_KEY: ${{ secrets.EXTRA_IMAGE_SIGN_KEY}}`.
42+
3. Update the `pre-build` make target in the `Makefile` by adding an additional call to the
43+
`create_signing_keys.sh` script with chosen signing key filename.

makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ project-setup:
3333

3434
pre-build:
3535
east util version
36+
# Create signing keys from env variables
37+
./scripts/create_signing_keys.sh app/signing_key.pem IMAGE_SIGN_KEY
3638

3739
# Runs on every push to the main branch
3840
quick-build:

scripts/create_signing_keys.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#! /usr/bin/env bash
2+
# Usage: ./create_signing_keys.sh key_file secret_key_var
3+
#
4+
# Description:
5+
#
6+
# Create private key files from env vars.
7+
#
8+
# Arguments:
9+
#
10+
# key_file The full path of the key file to create, e.g. app/signing_key_rsa2048.pem
11+
# secret_key_var The name of the ENV variable or Github secret that contains the private keys,
12+
# e.g. IMAGE_SIGN_KEY.
13+
14+
NUM_ARGS=2
15+
# Print help text and exit if -h, or --help or insufficient number of arguments
16+
# was given.
17+
if [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ $# -lt ${NUM_ARGS} ]; then
18+
sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' <"$0"
19+
exit 1
20+
fi
21+
22+
FILE_PATH="$1"
23+
KEY_VAR="$2"
24+
25+
# Check that the key content is not empty
26+
# If it is, we are probably running in a local environment.
27+
# In CI, the key should be set as a GitHub secret and the variable should not be empty.
28+
# If it is empty, the file will not be created, and the build will fail.
29+
if [ -z "${!KEY_VAR}" ]; then
30+
echo "${KEY_VAR} is not set, doing nothing."
31+
exit 0
32+
fi
33+
34+
# Create the key file
35+
echo "${!KEY_VAR}" >"${FILE_PATH}"
36+
37+
echo "Created key file ${FILE_PATH} from environment variable ${KEY_VAR}"

0 commit comments

Comments
 (0)