many updates

This commit is contained in:
Anton Livaja 2025-01-23 04:28:32 -05:00
parent b1787f7b51
commit 4157641f09
Signed by: anton
GPG Key ID: 44A86CFF1FDF0E85
11 changed files with 253 additions and 43 deletions

View File

@ -21,6 +21,7 @@
* [Provision Computer](generated-documents/level-2/fixed-location/provisioner/provision-computer.md) * [Provision Computer](generated-documents/level-2/fixed-location/provisioner/provision-computer.md)
* [Provision SD Card](generated-documents/level-2/fixed-location/provisioner/provision-sd-card.md) * [Provision SD Card](generated-documents/level-2/fixed-location/provisioner/provision-sd-card.md)
* [Provision AirgapOS](generated-documents/level-2/fixed-location/provisioner/provision-airgapos.md) * [Provision AirgapOS](generated-documents/level-2/fixed-location/provisioner/provision-airgapos.md)
* [Provision Root Entropy Ceremony SD Card](generated-documents/level-2/fixed-location/provisioner/provision-root-entropy-ceremony-sd-card.md)
* [Copy Shardfile SD Card](generated-documents/level-2/fixed-location/provisioner/copy-shardfile-sd-card.md) * [Copy Shardfile SD Card](generated-documents/level-2/fixed-location/provisioner/copy-shardfile-sd-card.md)
* [Provision Air-Gapped Bundle](generated-documents/level-2/fixed-location/provisioner/air-gapped-bundle.md) * [Provision Air-Gapped Bundle](generated-documents/level-2/fixed-location/provisioner/air-gapped-bundle.md)
* [Proposer](system-roles.md) * [Proposer](system-roles.md)

View File

@ -39,9 +39,9 @@ ceremonies/
policies/ policies/
spending-policy.json spending-policy.json
keychain/ keychain/
<key_id>/ <key_fingerprint>/
sig_1.asc <last_16_digits_of_key_fingerprint>.asc
sig_2.asc <last_16_digits_of_key_fingerprint>.<last_16_digits_of_sigining_key>.asc.sig
``` ```
## Procedure: Setting up Repository ## Procedure: Setting up Repository

View File

@ -9,22 +9,18 @@ Setting up a PGP key pair is necessary for a number of different aspects of QVS.
* `keyfork mnemonic generate --size 256 > mnemonic.txt` * `keyfork mnemonic generate --size 256 > mnemonic.txt`
1. Write the mnemonic on a small piece of paper as you will need to enter the words in the next step. After entering the words, set the piece of paper on fire (that's why it should be small enough - to make burning it easy) 1. Setting socket may not be necessary anymore (TODO test on Airgap):
1. In a new terminal window start `keyfork` daemon with the mnemonic:
* `export KEYFORKD_SOCKET_PATH=/tmp/keyforkd.socket` * `export KEYFORKD_SOCKET_PATH=/tmp/keyforkd.socket`
* `keyfork recover mnemonic` 1. Recover mnemonic to `keyforkd` and send process to background
* Enter the mnemonic as prompted * `keyfork recover mnemonic < mnemonic.txt`
* ctrl + z * ctrl + z
* `bg` * `bg`
* Burn the piece of paper which has the mnemonic written on it (HACK goes away when we fix keyfork)
1. Set expiration using the `KEYFORK_OPENPGP_EXPIRE` environment variable: 1. Set expiration using the `KEYFORK_OPENPGP_EXPIRE` environment variable:
* `export KEYFORK_OPENPGP_EXPIRE=2y` * `export KEYFORK_OPENPGP_EXPIRE=2y`
@ -80,7 +76,7 @@ Setting up a PGP key pair is necessary for a number of different aspects of QVS.
1. Rename the private key file to contain the `key_id`: 1. Rename the private key file to contain the `key_id`:
* `mv priv.asc key_id.priv` * `mv priv.asc <key_id>.priv`
1. Export the public key: 1. Export the public key:

View File

@ -207,6 +207,16 @@ To construct an appropriate Tamper Proofing Station, the simplest setup consists
Pick a location for the station, and attach the LED light and the camera to the overhead camera mounting rig. Set up the camera so that when it's turned on, a 14" laptop is perfectly framed without having to zoom in or out if possible. Pick a location for the station, and attach the LED light and the camera to the overhead camera mounting rig. Set up the camera so that when it's turned on, a 14" laptop is perfectly framed without having to zoom in or out if possible.
## High Visibility Storage
The purpose of high visibility storage is to provide a way to keep items which are used during a ceremony from risk of being swapped by one of the participants in the ceremony. As such, a high visibility storage should be a plastic container which is sealed, and which is only opened under the close supervision of a quorum of individuals.
Some examples include:
* Large glass jar
* Plastic bag
## Safe ## Safe
Placing objects into a safe helps improve the security of objects, and introduces an additional layer of tamper evidence. Placing objects into a safe helps improve the security of objects, and introduces an additional layer of tamper evidence.

View File

@ -22,7 +22,7 @@ The approver is responsible for verifying a transaction proposed by a [proposer]
1. To sign the transaction payload and produce a detached signature use: 1. To sign the transaction payload and produce a detached signature use:
* `gpg --armor --output <approver.sig> --detach-sig <filename>` * `gpg --detach-sig <filename>`
1. Commit the detached signature alongside the tx 1. Commit the detached signature alongside the tx

View File

@ -4,6 +4,8 @@
* Online machine * Online machine
* [High Visibility Storage](TODO): plastic container or bag that's used to keep items while not in use in a visible location like the middle of a desk.
* [Operator PGP key pairs](../../key-types.md#operator-pgp-keypair) * [Operator PGP key pairs](../../key-types.md#operator-pgp-keypair)
{{ #include ../../../../operator-requirements.md:requirements }} {{ #include ../../../../operator-requirements.md:requirements }}
@ -24,13 +26,15 @@
{{ #include ../../../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}} {{ #include ../../../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}}
1. Place all contents except for the laptop into High Visibility Storage
### Ceremony ### Ceremony
1. Turn on online machine 1. Turn on online machine
1. Once booted, run `icepick workflow sol broadcast --nonce-address=<nonce_address>` command 1. Once booted, run `icepick workflow sol broadcast --nonce-address=<nonce_address>` command
- [ ] TODO find a place for the nonce_address in the ceremony repo - [ ] TODO find a place for the nonce_address in the ceremony repo or airgapOS
* Plug in "Transaction" SD card * Plug in "Transaction" SD card
@ -42,34 +46,133 @@
1. Boot the computer 1. Boot the computer
1. Unplug the "AirgapOS" SD card 1. Unplug the "AirgapOS" SD card and place it in High Visibility Storage
1. Plug in SD card labelled "Keychain" 1. Plug in SD card labelled "Keychain"
* Load well known PGP keys of proposer and approver 1. Use detached signatures of the keys on the SD cards to verify the pub certs. Each operator should verify that the each key in the Keychain has been signed by that operator's key.
* `gpg --import <keyfile_name>`
1. Use detached signatures of the keys on the SD cards to verify the pub certs 1. Plug in a smart card with Operator PGP Key
- [ ] write bash script that for each pub cert, looks for 2 detached sigs made by two other certs 1. Use the following script to check that a signature by the plugged in key exists for all the public certificates found on the Keychain
- [ ] TODO move this to ceremony SD card or airgapOS
```
#!/bin/bash
1. Unplug the "Keychain" SD card set -eu -o pipefail
DIRECTORY="$1"
if ! compgen -G "$DIRECTORY/*.asc" > /dev/null; then
echo "No .asc files found in the directory."
exit 1
fi
if ! gpg --card-status > /dev/null 2>&1; then
echo "No smart card detected. Please insert a smart card."
exit 1
fi
smart_card_id=$(gpg --card-status | grep sec | cut -d'/' -f2 | cut -d' ' -f1)
for asc_file in "$DIRECTORY"/*.asc; do
gpg --import "$asc_file"
done
for asc_file in "$DIRECTORY"/*.asc; do
sig_exists="false"
for sig_file in "$DIRECTORY"/*.asc.sig; do
sigfile_basename=$(basename "$sig_file" .asc.sig)
ascfile_basename=$(basename "$asc_file" .asc)
if [[ "$sigfile_basename" != "$ascfile_basename" ]]; then
continue
fi
sig_key_id=$(gpg --verify "$sig_file" 2>&1 | grep 'Primary key fingerprint' | cut -d' ' -f4- | tr -d ' ')
trimmed_key_id="${sig_key_id: -16}"
if [[ "$trimmed_key_id" == "$smart_card_id" ]]; then
sig_exists="true"
break
fi
done
if [[ "$sig_exists" == "false" ]]; then
printf "\nWARNING: Signature for %s by operator key %s does not exist\n" "$asc_file" "$smart_card_id"
fi
done
```
1. Ensure that the script doesn't output any "WARNING" messages to the console. If it does, abort the ceremony and initiate incident response.
1. Unplug the "Keychain" SD card and place it in High Visibility Storage
1. Insert SD card labelled "Shardfile" 1. Insert SD card labelled "Shardfile"
1. [ ] in root entropy ceremony add step to write an autorun.sh script to shardfile sd card that runs `keyfork recover shard --daemon` 1. If no prompt appears, run the command:
* Follow on screen prompts * `keyfork recover shard --daemon`
1. Unplug SD card labelled "Shardfile" 1. Follow on screen prompts
1. Plug in the "Transaction" SD card 1. Unplug SD card labelled "Shardfile" and place it in High Visibility Storage
1. Retrieve the "Transaction" SD card from High Visibility Storage and plug in the "Transaction" SD card
1. For each transaction, verify that the signature is made by trusted keys that are loaded in the gpg keyring: 1. For each transaction, verify that the signature is made by trusted keys that are loaded in the gpg keyring:
- [ ] TODO: move this to ceremony SD card
```
#!/bin/bash
* `gpg --verify <detached_signature>` DIRECTORY=$1
declare -a key_ids
while IFS= read -r line; do
key_id=$(echo "$line" | awk -F: '/^pub/{print $5}')
if [[ -n "$key_id" ]]; then
key_ids+=("$key_id")
fi
done < <(gpg --list-keys --with-colons)
check_key_id() {
local search_key_id="$1"
for id in "${key_ids[@]}"; do
if [[ "$id" == "$search_key_id" ]]; then
return 0
fi
done
return 1
}
for tx in "$DIRECTORY"/*.json; do
basename=$(basename "$tx" .json)
number_of_sigs=0
tx_sig="$DIRECTORY/$basename.json.sig"
if [[ ! -f "$tx_sig" ]]; then
echo "WARNING: No signature file found for transaction $tx."
continue
fi
sig_key_id=$(gpg --verify "$tx_sig" 2>&1 | grep 'Primary key fingerprint' | cut -d' ' -f4- | tr -d ' ')
trimmed_key_id="${sig_key_id: -16}"
if check_key_id "$trimmed_key_id"; then
((number_of_sigs++))
else
echo "Key ID $trimmed_key_id not found in key_ids array."
fi
if (( number_of_sigs < 2 )); then
echo "WARNING: Insufficient signatures ($number_of_sigs) for transaction $tx."
fi
done
```
- [ ] todo write a script for this
1. Run the `icepick` command with the transaction payload 1. Run the `icepick` command with the transaction payload
@ -77,7 +180,7 @@
* Follow on screen prompts * Follow on screen prompts
1. Unplug the "Transaction" SD card 1. Unplug the "Transaction" SD card and place it in High Visibility Storage
### Broadcast Transaction ### Broadcast Transaction

View File

@ -8,12 +8,11 @@ This is a ceremony for generating root entropy.
{{ #include ../../operator-requirements.md:requirements }} {{ #include ../../operator-requirements.md:requirements }}
* Each member needs to bring their: * Minimum of 2 fresh SD cards
* Ceremony Notes * [Ceremony SD Card](../provisioner/provision-root-entropy-ceremony-sd-card.md)
* Ceremony SD Card * [High Visibility Storage](TODO): plastic container or bag that's used to keep items while not in use in a visible location like the middle of a desk.
- [ ] TODO explain what this is
## Procedure ## Procedure
@ -21,24 +20,46 @@ This is a ceremony for generating root entropy.
1. Lock access to the location - there should be no inflow or outflow of people during the ceremony 1. Lock access to the location - there should be no inflow or outflow of people during the ceremony
1. Retrieve sealed laptop and polaroid from locked storage 1. Retrieve Air-Gapped Bundle from locked storage
### Unsealing Tamper Proofing ### Unsealing Tamper Proofing
{{ #include ../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}} {{ #include ../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}}
1. Place all materials except for the laptop into High Visibility Storage
### Generating Entropy ### Generating Entropy
1. Boot AirgapOS on the airgapped machine 1. Retrieve AirgapOS SD card from High Visibility Storage and plug it into air-gapped laptop
1. Verify the hash of the AirgapOS version once it's booted 1. Turn on the machine
1. Run `ceremony.sh` 1. Once booted, remove the AirgapOS SD card and place it into High Visibility Storage
1. Plug in the Ceremony SD card
1. Run `ceremony.sh` from the SD card
1. Button mash to ensure adequate entropy on the OS 1. Button mash to ensure adequate entropy on the OS
1. Back up the `shardfile`, and `pub.asc` to at least 2 separate SD cards 1. Back up the `shardfile` to any desired number of SD cards, and label each "Shardfile <date>"
1. Optionally write an `autorun.sh` file to the Shardfile SD card containing the following command:
* `keyfork recover shard --daemon`
1. If an OpenPGP certificate was derived, store the public key on a SD card, separate from the shardfiles
### Finalizing Ceremony ### Finalizing Ceremony
1. Seal the airgapped bundle (TODO) 1. Gather all the original items that were in the air-gapped bundle:
* Air-gapped computer
* AirgapOS SD card
* Shardfile SD card
* Keychain SD card
{{ #include ../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-sealing}}

View File

@ -26,7 +26,7 @@ The proposer must combine these values into a single message, which can be a sim
## Procedure ## Procedure
1. Define a new file "<date:time>-<currency>.tx.json", for example "16:40-PYTH-SPL.tx.json" 1. Define a new file `workflow_inputs_<num>.json`, for example `workflow_inputs_1.json`
1. Create a new directory in the `ceremonies` repository for the date on which the ceremony for the transaction will take place if it doesn't already exist, for example `2024-01-01/` 1. Create a new directory in the `ceremonies` repository for the date on which the ceremony for the transaction will take place if it doesn't already exist, for example `2024-01-01/`
@ -54,7 +54,7 @@ The proposer must combine these values into a single message, which can be a sim
1. Sign the data in the CLI using `gpg` or another OpenPGP implementation: 1. Sign the data in the CLI using `gpg` or another OpenPGP implementation:
* `gpg --clearsign <file>` * `gpg --detach-sig <file>`
1. Notify relevant individuals that there are new transactions queued up, and that a ceremony should be scheduled. This can be automated in the future so that when a commit is made or PR opened, others are notified, for example using a incident management tool. 1. Notify relevant individuals that there are new transactions queued up, and that a ceremony should be scheduled. This can be automated in the future so that when a commit is made or PR opened, others are notified, for example using a incident management tool.

View File

@ -2,4 +2,23 @@
There should be multiple SD cards containing the shardfile data. Shardfile data is produced during a [Root Entropy](../operator/hybrid-key-provisioning.md) derivation ceremony. There should be multiple SD cards containing the shardfile data. Shardfile data is produced during a [Root Entropy](../operator/hybrid-key-provisioning.md) derivation ceremony.
Label the SD card: "Shardfile <date>" ## Requirements
* Existing Shardfile SD card
* Fresh SD card(s)
## Procedure
1. Get the shardfile content from an existing Shardfile SD card or ceremony repository
1. Plug in a fresh SD card
1. Copy the shardfile to the new SD card
1. Label the SD card: "Shardfile <date>"
1. Optionally write an `autorun.sh` file to the Shardfile SD card containing the following command:
* `keyfork recover shard --daemon`

View File

@ -0,0 +1,50 @@
# Provision Root Entropy Ceremony SD Card
1. Plug in a fresh formatted SD card into the computer
1. Create a directory called `public_certificates` on the SD card
1. Copy the desired OpenPGP public certificates you wish to shard to during the ceremony into the `public_certificates` directory on the SD card. The number of public certificates in this directory corresponds to the `N` value in a `M of N` quorum.
1. Write the following script to a file called `ceremony.sh`
* `<threshold_value>` should be replaced with the desired `M` value in a `M of N` quorum
* If you would like to generate an OpenPGP public certificate, add `--output-cert /media/cert` and `--user-id <name>` to the command
```sh
#!/bin/sh
script_dir="$(dirname "$(realpath "$0")")"
read -p "Provide the path to PGP certificates which will be used for the ceremony: " relative_path
directory_path="$script_dir/$relative_path"
if [ ! -d "$directory_path" ]; then
echo "Directory does not exist. Please enter a valid directory path."
exit 1
fi
for file in "$directory_path"/*; do
if [ -f "$file" ]; then
echo "Processing file: $file"
gpg --import --import-options import-show $file
fi
done
read -p "Do the PGP key IDs match what you expect? (y/n): " matches_expectation
if [ $matches_expectation != "y" ]; then
echo "Ceasing ceremony as PGP key IDs don't match"
exit 1
fi
keyfork bottoms-up --threshold <threshold_value> --output-shardfile /media/shardfile /media/public-certificates/
```
1. Write the `ceremony.sh` script to the SD card
1. Burn the SD card contents to the SD card using `sdtool`
{{ #include ../../../../sdtool-instructions.md:steps }}

View File

@ -19,11 +19,21 @@ This tool is also available via [stagex](https://registry.hub.docker.com/r/stage
* To get container hash: `docker inspect --format='{{json .RepoDigests}}' stagex/sdtool` * To get container hash: `docker inspect --format='{{json .RepoDigests}}' stagex/sdtool`
* Check the [signatures dir](https://codeberg.org/stagex/stagex/src/branch/main/signatures/stagex) in stagex project for latest signed hashes * Check the [signatures dir](https://codeberg.org/stagex/stagex/src/branch/main/signatures/stagex) in stagex project for latest signed hashes
1. `./sdtool /dev/mmcblk permlock` 1. Use `lsblk` to figure out the SD card device name
* Note: the device will not mount as a proper block device on QubesOS so a different OS has to be used where the device appears as /dev/mmcblk<num>
1. `./sdtool /dev/<device_name> permlock`
1. Test that the card can't be written to: 1. Test that the card can't be written to:
* `dd if=out/airgap.iso of=/dev/sdb bs=1M conv=sync status=progress` * Create a test file:
* `echo "test" > test.txt`
* Try writing the file to the SD card
* `dd if=./test.txt of=/dev/<device_name> bs=1M conv=sync status=progress`
// ANCHOR_END: steps // ANCHOR_END: steps
/* ANCHOR_END: all */ /* ANCHOR_END: all */