From d6a607a5cfd10a321bf8fe57b738f47359599240 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 17:23:14 -0400 Subject: [PATCH 01/19] initial commit of QKMS docs --- quorum-kms/.gitignore | 1 + quorum-kms/README.md | 15 ++ quorum-kms/book.toml | 6 + quorum-kms/src/SUMMARY.md | 42 +++++ quorum-kms/src/autorun-sh-setup.md | 43 +++++ quorum-kms/src/ceremony-log-template.md | 62 +++++++ quorum-kms/src/core-key-ceremonies.md | 14 ++ quorum-kms/src/destroying-hardware.md | 1 + .../src/enable-pure-boot-restricted-boot.md | 8 + quorum-kms/src/flash-pureboot-firmware.md | 36 +++++ quorum-kms/src/flashing-iso.md | 21 +++ quorum-kms/src/glossary.md | 108 +++++++++++++ quorum-kms/src/hardware-destruction.md | 19 +++ quorum-kms/src/hardware-procurement.md | 86 ++++++++++ quorum-kms/src/hybrid-key-provisioning.md | 72 +++++++++ quorum-kms/src/img/download-airgap-os.png | Bin 0 -> 86930 bytes .../src/initialize-pureboot-smart-card.md | 151 ++++++++++++++++++ quorum-kms/src/intro.md | 69 ++++++++ quorum-kms/src/local-key-provisioning.md | 53 ++++++ quorum-kms/src/location-key-provisioning.md | 73 +++++++++ quorum-kms/src/locations.md | 72 +++++++++ quorum-kms/src/one-time-repository-setup.md | 56 +++++++ quorum-kms/src/one-time-use-airgapos.md | 38 +++++ .../src/one-time-use-hardware-procurement.md | 33 ++++ quorum-kms/src/one-time-use-locations.md | 18 +++ quorum-kms/src/operator-key-provisioning.md | 44 +++++ quorum-kms/src/physical-artifact-storage.md | 38 +++++ .../src/provisioning-hardware-and-firmware.md | 87 ++++++++++ .../src/public-ceremony-artifact-storage.md | 34 ++++ quorum-kms/src/quorum-team.md | 40 +++++ quorum-kms/src/remote-key-provisioning.md | 3 + quorum-kms/src/repeat-use-airgapos.md | 61 +++++++ quorum-kms/src/secure-boot-sequence.md | 40 +++++ .../src/secure-physical-storage-guidelines.md | 1 + quorum-kms/src/selecting-quorum.md | 38 +++++ quorum-kms/src/setting-smart-card-pins.md | 38 +++++ quorum-kms/src/software.md | 38 +++++ quorum-kms/src/storage-device-management.md | 1 + quorum-kms/src/threat-model.md | 81 ++++++++++ 39 files changed, 1641 insertions(+) create mode 100644 quorum-kms/.gitignore create mode 100644 quorum-kms/README.md create mode 100644 quorum-kms/book.toml create mode 100644 quorum-kms/src/SUMMARY.md create mode 100644 quorum-kms/src/autorun-sh-setup.md create mode 100644 quorum-kms/src/ceremony-log-template.md create mode 100644 quorum-kms/src/core-key-ceremonies.md create mode 100644 quorum-kms/src/destroying-hardware.md create mode 100644 quorum-kms/src/enable-pure-boot-restricted-boot.md create mode 100644 quorum-kms/src/flash-pureboot-firmware.md create mode 100644 quorum-kms/src/flashing-iso.md create mode 100644 quorum-kms/src/glossary.md create mode 100644 quorum-kms/src/hardware-destruction.md create mode 100644 quorum-kms/src/hardware-procurement.md create mode 100644 quorum-kms/src/hybrid-key-provisioning.md create mode 100644 quorum-kms/src/img/download-airgap-os.png create mode 100644 quorum-kms/src/initialize-pureboot-smart-card.md create mode 100644 quorum-kms/src/intro.md create mode 100644 quorum-kms/src/local-key-provisioning.md create mode 100644 quorum-kms/src/location-key-provisioning.md create mode 100644 quorum-kms/src/locations.md create mode 100644 quorum-kms/src/one-time-repository-setup.md create mode 100644 quorum-kms/src/one-time-use-airgapos.md create mode 100644 quorum-kms/src/one-time-use-hardware-procurement.md create mode 100644 quorum-kms/src/one-time-use-locations.md create mode 100644 quorum-kms/src/operator-key-provisioning.md create mode 100644 quorum-kms/src/physical-artifact-storage.md create mode 100644 quorum-kms/src/provisioning-hardware-and-firmware.md create mode 100644 quorum-kms/src/public-ceremony-artifact-storage.md create mode 100644 quorum-kms/src/quorum-team.md create mode 100644 quorum-kms/src/remote-key-provisioning.md create mode 100644 quorum-kms/src/repeat-use-airgapos.md create mode 100644 quorum-kms/src/secure-boot-sequence.md create mode 100644 quorum-kms/src/secure-physical-storage-guidelines.md create mode 100644 quorum-kms/src/selecting-quorum.md create mode 100644 quorum-kms/src/setting-smart-card-pins.md create mode 100644 quorum-kms/src/software.md create mode 100644 quorum-kms/src/storage-device-management.md create mode 100644 quorum-kms/src/threat-model.md diff --git a/quorum-kms/.gitignore b/quorum-kms/.gitignore new file mode 100644 index 0000000..3006b27 --- /dev/null +++ b/quorum-kms/.gitignore @@ -0,0 +1 @@ +book/ diff --git a/quorum-kms/README.md b/quorum-kms/README.md new file mode 100644 index 0000000..b8ae827 --- /dev/null +++ b/quorum-kms/README.md @@ -0,0 +1,15 @@ +# Quroum-KMS (QKMS) + +Quorum-KMS (QKMS) is an open source system of playbooks and tooling which +facilitates the creation and maintenance of highly resilient Quorum-based Key +Management Systems based on a strict threat model which can be used for a +variety of different cryptographic algorithms. + +## Usage + +In order to read the `mdbook` run the following commands: + +``` +cargo install mdbook +mdbook serve +``` diff --git a/quorum-kms/book.toml b/quorum-kms/book.toml new file mode 100644 index 0000000..ef754bc --- /dev/null +++ b/quorum-kms/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Anton Livaja", "Lance R. Vick", "Ryan Heywood"] +language = "en" +multilingual = false +src = "src" +title = "Quorum-KMS" diff --git a/quorum-kms/src/SUMMARY.md b/quorum-kms/src/SUMMARY.md new file mode 100644 index 0000000..a71fc8c --- /dev/null +++ b/quorum-kms/src/SUMMARY.md @@ -0,0 +1,42 @@ +# Summary +* [Introduction](intro.md) + * [Threat Model](threat-model.md) + * [Selecting a Quorum](selecting-quorum.md) + * [Software](software.md) + * [Hardware](provisioning-hardware-and-firmware.md) + * [Glossary](glossary.md) + +* [Preparations]() + * [Repeat Use]() + * [Flash PureBoot to Librem](flash-pureboot-firmware.md) + * [Initialize PureBoot Smart Card](initialize-pureboot-smart-card.md) + * [Change Smart Card PINs](setting-smart-card-pins.md) + * [PureBoot Restricted Boot](enable-pure-boot-restricted-boot.md) + * [AirgapOS Setup](repeat-use-airgapos.md) + * [`autorun.sh` Setup](autorun-sh-setup.md) + * [Secure Boot Sequence](secure-boot-sequence.md) + * [Selecting Locations](locations.md) + + * [One Time Use]() + * [Procure Hardware](one-time-use-hardware-procurement.md) + * [AirgapOS Setup](one-time-use-airgapos.md) + * [Repository Setup](one-time-repository-setup.md) + * [Selecting Locations](one-time-use-locations.md) + +* [Key Ceremonies]() + * [Ceremony Log Template](ceremony-log-template.md) + * [Root Entropy Ceremonies](core-key-ceremonies.md) + * [Local Key Provisioning](local-key-provisioning.md) + * [Hybrid Key Provisioning](hybrid-key-provisioning.md) + * [Remote Key Provisioning](remote-key-provisioning.md) + + * [Additional Key Ceremonies]() + * [Operator Key Provisioning](operator-key-provisioning.md) + * [Location Key Provisioning](location-key-provisioning.md) + + * [Post Ceremony]() + * [Online Artifact Storage](public-ceremony-artifact-storage.md) + * [Physical Artifact Storage](physical-artifact-storage.md) + +* [Lifecycle Management]() + * [Destroying Hardware](hardware-destruction.md) \ No newline at end of file diff --git a/quorum-kms/src/autorun-sh-setup.md b/quorum-kms/src/autorun-sh-setup.md new file mode 100644 index 0000000..80e6716 --- /dev/null +++ b/quorum-kms/src/autorun-sh-setup.md @@ -0,0 +1,43 @@ +# `autorun.sh` Setup + +This document describes how `autorun.sh`, a file that AirgapOS automatically +boots and runs should be set up. + +This setup can be done on any machine. + +1. Create a file called `autorun.sh` that has the following contents: + + You may accomplish this by doing the following: + + * In your Terminal use this command: + `vi autorun.sh` + * Once you are in the editor press "i" to enter "insert mode" + * Type in the contents, replacing and with your chosen threshold numbers according to your [Quorum](selecting-quorum.md): + ```sh + #!/bin/sh + keyfork wizard generate-shard-secret --threshold --max --output shards.pgp + ``` + * Press "esc" + * Press ":" + * Press "x" + * Press Enter + +2. Hash the file + The file should be hashed by using the following command: + + ```sh + sha256sum autorun.sh + ``` + Make note of the hash on a piece of paper + +3. Copy the file to the Storage Device which contains AirgapOS. + + a. If you don't have a Storage Device set up with AirgapOS use [this guide](repeat-use-airgapos.md) +to do so. + + b. Mount the AirgapOS Storage Device using [this guide](storage-device-management.md#mounting-a-storage-device) + + c. Copy the `autorun.sh` file to the Storage Device + +4. Make note of this hash on a piece of paper or print it as you will need it +to verify the file during Ceremonies. \ No newline at end of file diff --git a/quorum-kms/src/ceremony-log-template.md b/quorum-kms/src/ceremony-log-template.md new file mode 100644 index 0000000..475e962 --- /dev/null +++ b/quorum-kms/src/ceremony-log-template.md @@ -0,0 +1,62 @@ +# Ceremony Log Template + +This template is to be used during the ceremony in order to keep track of events +that take place during the Key Derivation Ceremony. + +Capture as much information as possible - more data is always better than less, +this means being specific about the exact location, full names of participants, +exact models of equipment used etc. + +## Date + +``` +2024-08-03 +``` + +## Individuals Present +Individuals may be Operators or Witnesses. Include the individual's full legal +name + +``` +Max Rockatansky - Witness +Paul Atreides - Operator +``` + +## Location +Specify exact location, including details such as the floor, room etc. + +``` +12 Grimmauld Place, Islington, London +2nd floor, first room on the left when coming up the stairs +``` + +## Equipment + +### Type of Laptop Used + +``` +Purism Librem 14 +``` + +### Type of SD Card Used + +``` +SD Card: Kingston SDCIT2/8GBSP +``` + +## Software +Specify the exact version / commit + +``` +AirgapOS: https://git.distrust.co/public/airgap/commit/df223e6deb2833a8160c836f435ee01f7b776e87 +``` + +## Chronological Timeline +Ensure to capture as much details as possible, even if it seems trivial. + +* 2024-01-01:0900: The team assembles at the airport and selects the location +from a pre-made list of potential locations +* 2024-01-01:1030: The team arrives at location and inspects the premises for +cameras and ensures that the location criteria are adhered to +* 2024-01-01:1440: The hardware is set up and the software and firmware are +verified \ No newline at end of file diff --git a/quorum-kms/src/core-key-ceremonies.md b/quorum-kms/src/core-key-ceremonies.md new file mode 100644 index 0000000..81f5efb --- /dev/null +++ b/quorum-kms/src/core-key-ceremonies.md @@ -0,0 +1,14 @@ +# Root Entropy Ceremonies + +There are 3 primary types of key derivation ceremonies: + + +* "Local": where all cryptographic material, including the Operator Keys, +Location Keys, and the Root Entropy are all generated during a single in-person +ceremony + +* "Hybrid": where the Operator Keys and Location Keys are generated separately +prior to the in-person ceremony where the Root Entropy is generated + +* "Remote": where all cryptographic material is generated in a decentralized +manner, remotely. \ No newline at end of file diff --git a/quorum-kms/src/destroying-hardware.md b/quorum-kms/src/destroying-hardware.md new file mode 100644 index 0000000..65201f4 --- /dev/null +++ b/quorum-kms/src/destroying-hardware.md @@ -0,0 +1 @@ +# Destorying Hardware diff --git a/quorum-kms/src/enable-pure-boot-restricted-boot.md b/quorum-kms/src/enable-pure-boot-restricted-boot.md new file mode 100644 index 0000000..cd1ff85 --- /dev/null +++ b/quorum-kms/src/enable-pure-boot-restricted-boot.md @@ -0,0 +1,8 @@ +# Enable PureBoot Restricted Boot + +With PureBoot Restricted Boot, you can lock down your boot firmware to only boot +trusted, signed executables both on a local disk and USB, so you control the +keys. + +In order to enable Restricted Boot, the user may follow the Purism guide found +[here](https://docs.puri.sm/PureBoot/Restricted.html). \ No newline at end of file diff --git a/quorum-kms/src/flash-pureboot-firmware.md b/quorum-kms/src/flash-pureboot-firmware.md new file mode 100644 index 0000000..9aeee20 --- /dev/null +++ b/quorum-kms/src/flash-pureboot-firmware.md @@ -0,0 +1,36 @@ +# Flash Pureboot Firmware + +The version required for being able to complete all steps for setting up the +Ceremony Machine using a Librem 14: +* https://source.puri.sm/firmware/releases/-/blob/PureBoot-Release-24-L14JackDetect-1/librem_14/pureboot-librem_14-Release-24-L14JackDetect-1.rom.gz?ref_type=heads + +If another type of hardware is used you may have to try different versions of +the PureBoot firmware as some have issues with the `/etc/gui_functions` and `/etc/functions` which are used during the [Secure Boot Sequence](secure-boot-sequence.md) + +## Steps + +1. Download the [.rom](https://source.puri.sm/firmware/releases/-/blob/PureBoot-Release-24-L14JackDetect-1/librem_14/pureboot-librem_14-Release-24-L14JackDetect-1.rom.gz?ref_type=heads) file + +2. Put the `.rom` file on a Storage Device + +3. Plug the Storage Device with the `.rom` file into the Librem 14 + +4. During boot, press *any* key when prompted + +5. Select "Options -->", press Enter + +6. Select "Flash/Update the BIOS -->", press Enter + +7. Select "Flash the firmware with a new ROM, retain settings" + +8. "You will need to insert a USB drive containing your BIOS image (*.rom...) + After you select this file, this program will reflash your BIOS. + Do you want to proceed?" + + * Select "Yes", Press Enter + +9. Select the `.rom` file and press Enter + +10. Do you wish to proceed? + + * Select "Yes", Press Enter diff --git a/quorum-kms/src/flashing-iso.md b/quorum-kms/src/flashing-iso.md new file mode 100644 index 0000000..efdd7b1 --- /dev/null +++ b/quorum-kms/src/flashing-iso.md @@ -0,0 +1,21 @@ +4. Flash ISO Image to a Storage Device + + a. Select a new Storage Device which can be overwritten entirely + + b. Find the name of the Storage Device using [this guide](storage-device-management.md#finding-a-storage-device-name) + + d. Use the `dd` utility in the Terminal to flash AirgapOS to it. You will need + to replace `` with the name of your device. + + ```bash + sudo dd bs=4M if=~/airgap/dist/airgap.iso of=/dev/ status=progress + ``` + + In the example, the name of the device is `sda` so the complete command would look like this: + + ```bash + sudo dd bs=4M if=~/airgap/dist/airgap.iso of=/dev/sda status=progress + ``` + + Once this step is complete, you have successfully set up a Storage Device + with AirgapOS. \ No newline at end of file diff --git a/quorum-kms/src/glossary.md b/quorum-kms/src/glossary.md new file mode 100644 index 0000000..f0910cb --- /dev/null +++ b/quorum-kms/src/glossary.md @@ -0,0 +1,108 @@ +# Glossary + +## Ciphertext +In cryptography, ciphertext is the result of encryption performed on plaintext +using an algorithm, called a cipher. + +## Quorum-KMS (QKMS) +A set of highly specified processes and tooling used for setting up a highly +resilient quorum-based key management system. + +## Operator +An individual who manages an [Operator Key](#operator-key) which is used for +protecting the passphrase of a Location key and participates in different +aspects of the lifecycle management of the QKMS system. + +## Operator Key +An asymmetric key used for protecting the passphrase of a Location key + +## Quorum +The chosen M of N threshold used to achieve "quorum", which is a type of +agreement or consensus between a group of individuals. In the context of +Shamir's Secret Sharing, it refers to the minimum number of shards required to +reassemble the [Root Entropy](#root-entripy-re). + +#### Wrench Factor +How many people are required to be put under duress (via smacking them with a +wrench repeatedly or otherwise to get access to their Shard) before the Disaster +Recover Key is compromised. + +#### Bus Factor +How many members of the Quorum can meet an untimely demise without irretrievably +locking access to the Distrust Quroum system. + +## Root Entropy (RE) +The root cryptographic material which is used for hierarchical deterministic +key derivation of a variety of cryptographic algorithms. + +## Shard +Crytpographic shard created using Shamir's Secret Sharing algorithm. + +## Shamir's Secret Sharing (SSS) +An algorithm used to split cryptographic material into shards which can be +used to reassemble a secret. The shards can be combined according to a threshold +which is set at the time of initial sharding, expressed as M of N, or in other +words M shards of the total N shards in existence are required to reveal the +secret. + +## Workstation +Highly secure computer which is used for sensitive operations, typically in the +context of [Production Engineering](TODO). + +#### Minimum +In order to set up a Workstation, as part of a [Production Engineering](TODO) setup, +a separate computer only used for carrying out sensitive operations should be used. + +#### Recommended +Setting up a computer with QubesOS is recommended as it makes it easy to create +purpose built environments with minimal surface area for attacks, on the OS, and +networking level. + +## Air-Gapped +Hardware which has no access to radio frequency or cable based networking +capabilities in order to reduce area for surface attacks. Typically Air-Gapped +computers are laptops which are never connected to the internet or any other +networks, and have had their radio frequency hardware permanently disabled or +ideally removed. + +## Key Derivation Ceremony +Highly specified process which is used to secure derivation of cryptographic +material, with a focus on ensuring no single party has access to the Disaster +Recovery Key. The ceremony includes witnesses who can help attest to the fact +that the ceremony was executed properly, as well as instructions on hardware, +software and location that should be used. Each step of the ceremony is +carefully planned, and executed accordingly. + +## Location Key +Is a asymmetric key pair which is used for encrypting shards which are used to +re-assemble the Root Entropy. Location Keys are stored in [Locations](location.md) +which adhere to a strict set of criteria to maximize their security. The location +smart card passphrase is encrypted to a Operator Key in order to secure access +to it. + +## M of N +M is the minimum number of shards required to reassemble the secret, and N is the +total number of shards that exist. The minimum recommended threshold is 2-of-3. + +## Organization +An organization which owns the QKMS and is responsible for funding the setup and +maintenance. The organization is also responsible for ensuring that the +[Warehouse](#warehouse) is properly maintained in order to ensure that the +ciphertext blobs associated with the system are redundantly stored and +protected. + +## Witness +An individual who attests the ceremony was performed according to specification +in order to have additional assurances the cryptographic material, most +importantly the Root Entropy was never exposed. + +## Warehouse +* Online storage for encrypted data replicated across multiple providers +* All data in DR Warehouse can only be decrypted by the DR Key +* Tolerate loss of any single provider by duplicating data to all of them +* Storage backends can be any combination of the following: + * S3 Compatible object stores: + * AWS, Google Cloud, DigitalOcean, Azure, etc. +* [Version Control Systems](software.md#version-control-system-vcs): +* We tolerate a loss of all but one DR storage backend +* A minimum of three storage backends should be maintained diff --git a/quorum-kms/src/hardware-destruction.md b/quorum-kms/src/hardware-destruction.md new file mode 100644 index 0000000..8b66025 --- /dev/null +++ b/quorum-kms/src/hardware-destruction.md @@ -0,0 +1,19 @@ +# Destroying Hardware + +Destroying hardware should be done by using a combination of: + +* Degaussing + +* Burning + +* Shredding + +All three methods should be used because of the efficacy of using electron +microscopy to read data from storage drives which have not been completely +destroyed. + +Drilling through the storage drive, a common hardware destruction method, is not +considered to be secure. + +In the best case scenario, the hardware should be melted in a foundry, as this +makes it impossible to retrieve any data by any means. \ No newline at end of file diff --git a/quorum-kms/src/hardware-procurement.md b/quorum-kms/src/hardware-procurement.md new file mode 100644 index 0000000..6d3fd44 --- /dev/null +++ b/quorum-kms/src/hardware-procurement.md @@ -0,0 +1,86 @@ +# Equipment + +This page describes different equipment which is required, and makes opinionated +recommendations as well as alternatives. One may improve the overall security +of their system by using a variety of hardware in order to benefit from their +diversity, by reducing the likelihood that all hardware has suffered the same +kind of hardware supply chain compromise, has the same vulnerability present, or +has the same type of hardware failure issue. + +Based on the decided upon [Quorum](selecting-quorum.md), the amount of equipment +required to set up a [QKMS](glossary.md#quorum-kms-qkms) will +vary. In order to figure out what equipment is required, decide on a Quorum, +which is expressed as "N of M". Once you know your M, the required equipment list +is the following: + +* M x 4 Smart Cards + + * It is recommended to use two Smart Cards for storing each key pair + + * Ideally two different types of hardware are used in order to reduce the + risk of simultaneous failure + + * At least 1 Smart Card is required for each Operator Key and 1 Smart Card + for each Location Key + + * The number of Operator Keys is M, and the number of Location Keys is also + M, hence the minimum of 2 x M Smart Cards, with the recommendation of using + two smart cards for each, resulting in 4 x M Smart Cards + +* 2 + X Storage Devices + + * 1 Storage Device for [AirgapOS](repeat-use-airgapos.md) + + * 1 Storage Device for storing [Public Ceremony Artifacts](public-ceremony-artifact-storage) + + * X, or *any* number of additional Storage Devices to duplicate the data, a + good measure would be to have at least 3 Storage Devices for the ceremony + +* Librem 14 Laptop + + * Get as many laptops as desired to satisfy your operational needs + + * For each Librem 14, get a Librem Smart Card used for [PureBoot](initialize-pureboot-smart-card.md) + +## Smart Cards +Smart Cards are primarily used for storing OpenPGP cryptographic keys which are +used as a building block for security controls. These smart cards hold OpenPGP +keys which are derived in secure environments. FIPS 140-2 is required but the +end user may choose their manufacturer. + +* NitroKey 3 - because of its open source approach which helps improve the +overall security of the products +* YubiKey 5 - because of the widespread use and battle-tested reliability +* Librem Key - because of the manufacturer's approach to hardware supply chain +security and verifiable software + +## Air-Gapped Computer +[Air-Gapped](glossary.md#Air-Gapped) computers are used for the lifecycle management +of cryptographic material that is part of the QKMS. + +The primary hardware recommendation for a Air-Gapped Cmputer is the [Librem 14](https://puri.sm/products/librem-14/), manufactured by [Purism](puri.sm). Purism specializes in reducing hardware and +firmware security risks, especially via their [Anti-Interdiction Service](https://puri.sm/posts/anti-interdiction-services/) and [PureBoot](https://docs.puri.sm/PureBoot.html) +and as such is an excellent choice for hardware which high integrity assurance is +required for. + +#### Alternative + +An alternative approach is to use an off-the-shelf computer that is randomly +selected right before the ceremony, removing the radio cards from it, using it +to conduct a Ceremony, and then destroying the laptop using sufficiently +adequate method to ensure that no data forensics can be used to recover the data +from the drive, or memory. This can be achieved by using a combination of +incineration, degaussing, shredding and drilling. Special care should be taken +to completely destroy all components of the computer that are able to store data, +even if it's only in ephemeral form as some forensic methods all extraction of +data from components with "temporary memory". + +Three letter agencies are known to collect and exploit physical destroyed drives, +as data can still be extracted from them using methods such as electron +microscopy, therefore a combination of degaussing, shredding and burning should +be used, and the remaining debris should be spread out across multiple disposal +locations. + +## Storage Device +Can be an SD Card or USB Drive but should be procured from a vendor with +a good reputation, and ideally hardware of industrial grade should be prioritized. diff --git a/quorum-kms/src/hybrid-key-provisioning.md b/quorum-kms/src/hybrid-key-provisioning.md new file mode 100644 index 0000000..4a3a2d3 --- /dev/null +++ b/quorum-kms/src/hybrid-key-provisioning.md @@ -0,0 +1,72 @@ +# Hybrid Key Provisioning + +This document contains instructions on how Operators collaborate to set up +QKMS where the Operator Keys and Location Keys were generated before this +ceremony and only the PGP Public Certificates of the Location keys are brought +to the ceremony which are used to shard the Root Entropy. This is useful +when conducting the ceremony in a lower trust environment, and where not all +aspects of the ceremony can be controlled to the desired degree. + +## Steps + +1. Prior to the ceremony, set up a git repository with relevant artifacts in it, +and create Ceremony Notes according to [this](one-time-repository-setup.md) +guide. + +2. Ensure there are additional witnesses for the ceremony, outside of the +operators to assist in monitoring and verifying the integrity of the process. + + * Designate at least 1 individual to keep notes on the ceremony based + on the [Ceremony Log Template](ceremony-log-template.md) + +3. Ensure that no participants have brought digital devices other than ones +necessary for the ceremony. A faraday bag may be used to hold any such devices +for the duration of the ceremony. + +4. Procure a laptop and SD cards (3) from a randomly selected store and +ensure at least 2 people are in line of sight of all the hardware until the +ceremony is executed. It may be worthwhile to try booting from the SD card at +the store. Dell laptops tend to support booting from SD cards while Lenovo +don't. More notes on selecting hardware can be found [here](one-time-use-hardware-procurement.md) + +5. Secure a [Location](one-time-use-locations.md) + +6. Each member needs to bring their: + + * Ceremony Notes + + * Ceremony SD Card + + * Airgap SD Card (only 1 member needs to bring this - set up according to + [One Time Use / AirgapOS Setup](one-time-use-airgapos.md)). + +7. Verify the SD card by either: + + * Booting a separate AirgapOS to the machine used for the ceremony in order + to verify the SD card is not writeable and the hash matches using the steps + from the [One Time Use/ AirgapOS Setup](one-time-use-airgapos.md) guide. + + OR + + * Mounting the SD card to a separate machine and verifying it's not + writeable and verify the hash matches using steps from the [One Time Use/AirgapOS Setup](one-time-use-airgapos.md) guide. + + * NOTE: It is essential that the SD card remain in line of sight from the + moment it is verified to the moment is is used. + +8. Plug in and boot from Airgap SD card: + + * Boot from internal SD card reader or USB device reader + + * Verify the `sha256sum ceremony.sh` hash matches each of the Operator's + "Ceremony Notes" + +9. Button mash to ensure adequate entropy on the OS + +10. Run `ceremony.sh` + +11. Back up the `shardfile`, and `pub.asc` to 3 separate SD cards, +one for each operator + +12. Destroy the computer according to [Hardware Destruction](hardware-destruction.md) +guide. \ No newline at end of file diff --git a/quorum-kms/src/img/download-airgap-os.png b/quorum-kms/src/img/download-airgap-os.png new file mode 100644 index 0000000000000000000000000000000000000000..a88a0086ae486dfb00838c966f60d19c95edecf7 GIT binary patch literal 86930 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 z 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 a;fUl}?PM0I&k2hY;2#F1iY$`58}NVUlKFxF literal 0 HcmV?d00001 diff --git a/quorum-kms/src/initialize-pureboot-smart-card.md b/quorum-kms/src/initialize-pureboot-smart-card.md new file mode 100644 index 0000000..f703307 --- /dev/null +++ b/quorum-kms/src/initialize-pureboot-smart-card.md @@ -0,0 +1,151 @@ +# PureBoot Setup + +This guide walks the user through setting up a machine which relies on +[PureBoot](https://source.puri.sm/firmware/pureboot) to verify the authenticity +of the .iso image which is being booted, as well to ensure that firmware of the +machine has not been tampered with between uses. + +This guide assumes the use of a Purism machine, with a Librem Key. + +## Requirements + +* 1 Storage Device + +* 1 Librem Smart Card + +* 1 Librem 14 Computer with [PureBoot firmware installed](flash-pureboot-firmware.md). + +## Notes + +After you complete this setup, the Librem Smart Card will be provisioned with a +new GPG key pair, which will be used for signing the BIOS, as well as any `.iso` +images which will be booted using the [Restricted Boot](https://docs.puri.sm/PureBoot/Restricted.html) +mode. + +At the end of this guide you will have: + +* 1 Librem Smart Card + + * With a newly generated GPG key pair + + * With a newly generated HOTP secret + +* 1 storage device with the public key of the newly generated GPG key + + * This GPG key will be used to sign `.iso` files booted on the machine + +## Steps + +1. Plug in the Librem Smart Card into the machine + +2. Turn on the machine + +3. Wait for the prompt that says "Automatic boot in 5 seconds unless interrupted +by keypress..." + + * Press *any* key + +4. Select "Options -->" + + * Press Enter + +5. Select "GPG Options" --> + + * Press Enter + +6. Select "Generate GPG keys manually on a Librem Key" + + * Press Enter + +7. Please Confirm that your GPG card is inserted [Y/n/] + + * Input "Y", press Enter + +8. $ gpg/card> + + * Input `admin`, press Enter + +9. $ gpg/card> + + * Inpuut `generate`, press Enter + +10. Make off-card backup of encryption key (Y/n): + + * Input "n", Press Enter + +11. Replace existing keys? (y/n): + + * Input "y", press Enter + +12. PIN: (default is 123456) + + * Input `user_pin`, press Enter + +13. Key is valid for? (0): + + * Press Enter + +14. Key does not expire at all. Is this correct? (y/N): + + * Input "y", press Enter + +15. Real name: + + * Note: You must supply at least one of the "Real name", "Email address" + or "Comment" + * Input one of the values, and press Enter + +16. Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? + + * Input "O", press Enter + +17. Admin PIN: (default is 12345678) + + * Input `admin_pin`, press Enter + +18. After step q, the generation of the key will take some time then you will +see a prompt: + ``` + gpg: key market as ultimately trusted + gpg: directory '//.gnupg/openpgp-revocs.d' created + gpg: recovation certificate stored as '//.gnupg/openpgp-revocs.d/.rev' + public and secret key created and signed + ``` + +19. $ gpg/card> + + * Input "quit", press Enter + +20. "Would you like to copy the GPG public key you generated to a USB disk? + You may need it, if you want to use it outside of Heads later. + The file will show up as .asc" + + * Ensure a USB drive is connected + + * Select "Yes", press Enter + +21. "Would you like to add the GPG public key you generated to the BIOS? + This makes it a trusted key used to sign files in /boot" + + * Select "Yes", press Enter + +22. "Would you like to update the checksum and sign all of the files in /boot? + You will need your GPG key to continue and this will modify your disk + Otherwise the system will reboot immediately." + + * Select "Yes", press Enter + +23. Please confirm that your GPG card is inserted [Y/n]: + + * Input "Y", press Enter + +24. After the computer reboots you will be faced with an error: + "ERROR: PureBoot couldn't generate the TOTP code." + + * Select "Generate new HOTP/TOTP secret", press Enter + +25. "This will erase your old secret and replace it with a new one! Do you want +to proceed?" + + * Select "Yes", press Enter + diff --git a/quorum-kms/src/intro.md b/quorum-kms/src/intro.md new file mode 100644 index 0000000..23fa137 --- /dev/null +++ b/quorum-kms/src/intro.md @@ -0,0 +1,69 @@ +# Introduction + +Quorum-KMS (QKMS) is an open source system of playbooks and tooling which +facilitates the creation and maintenance of highly resilient Quorum-based +Key Management Systems based on a strict [threat model](threat-model.md) +which can be used for a variety of different cryptographic algorithms. The +system was designed and developed by [Distrust](https://distrust.co), with the +generous support of the following sponsors: TODO. + +The basic premise of QKMS is that primary cryptographic material akin to a root +certificate, called Root Entropy, is derived during a secure key derivation +ceremony, and then used to derive chosen cryptographic material via different +algorithms such as PGP keys, digital asset wallets, web certificates and more. +The system was designed with extensibility in mind. + +The Root Entropy is sharded using [Shamir's Secret Sharing](glossary.md#shamirs-secret-sharing-sss) to a [Quorum](glossary.md#quorum) in order to +protect it from single points of failure, requiring cooperation of multiple +individuals - a quorum, and use of cryptographic material stored in separate +physical locations with significant access controls in order to reconstruct the +secret material, namely the Root Entropy. + +## Use Cases + +QKMS can be used for a wide range of use-cases which span but are not limited +to: + +* Deriving a PGP key pair whose public key can be used as a "one-way deposit +box" - for example a company can back up keys for their digital asset wallets by +encrypting them to the public key and storing the encrypted ciphertext blobs on +multiple cloud storage platforms, or on offline hard drives for redundancy. + +* Deriving PGP keys for multiple individual users in a deterministic manner. + +* Deriving wallets for digital assets using BIP-0032 style derivation as part of +a cold signing setup. + +* Decrypting data in a secure, quorum protected, air-gapped environment. + +* Generating digital certificates + +## Playbooks + +QKMS can be set up by using a set of highly opinionated playbooks which outline +the process. The documentation should be read in its entirety by all +participants in the ceremony in order to ensure that the system is well +understood by all in order to ensure that the integrity of the process is +preserved and enforced by all participants. + +## Directives + +The documentation provides directives in order to specify the importance of +adhering to parts of the specification as follows to achieve high levels of +security: + +* **MUST** - not adhering to this will result in significant deterioration of +security properties of the system + +* **SHOULD** - is recommended and may impact the security of the system +depending on the context + +* **MAY** - is typically a design decision with no significant impact to the +overall security of the system + +## Method + +The reader is encouraged to read through the entire body of documents which +should not take more than 30 minutes. If any parts are unclear, they may contact +Distrust for clarification, which is welcomed as it will aid improving the +documentation. \ No newline at end of file diff --git a/quorum-kms/src/local-key-provisioning.md b/quorum-kms/src/local-key-provisioning.md new file mode 100644 index 0000000..d45ee59 --- /dev/null +++ b/quorum-kms/src/local-key-provisioning.md @@ -0,0 +1,53 @@ +# Local Key Provisioning + +This document contains instructions on how Operators collaborate to set up +QKMS which requires an N-of-M quorum to be reconstituted. The encrypted shards +which result from this ceremony are stored in separate physical +[Locations](location.md) which contain [Location Keys](glossary.md#location-key) +to which shards are encrypted, and whose passphrases are protected using +[Operator Keys](glossary#operator-key). + + +### Requirements + +* [Smart Card](hardware-procurement.md#smart-cards): whatever number of smart +cards you would like to have seeded for each Operator, usually 2 per Operator is +recommended - one NitroKey 3 and 1 YubiKey Series 5. + +* [Storage Devices](hardware-procurement.md#storage-device): as many storage +devices as you would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) + +* Storage Device loaded with + * [airgap.iso](repeat-use-airgapos.md) + * [airgap.iso.asc](airgap-setup.md) + * [autorun.sh](autorun-sh-setup.md) + +* All participants need Ceremony Notes which contain a record of which they +verified and wrote down themselves: + * The SHA256 hash of airgap.iso + * The SHA256 hash of autorun.sh + +### Steps + +1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the +established [Location](location.md) + +2. Ensure that no participants have brought digital devices other than ones +necessary for the ceremony. A faraday bag may be used to hold any such devices +for the duration of the ceremony. + +3. Plug in a new Storage Device + +4. Boot your Ceremony Machine using [Secure Boot Sequence](secure-boot-sequence.md) + +5. As prompted plug in new Smart Cards + +6. Once the ceremony is complete, make as many copies of the Storage Device +from Step 3 as desired. + +7. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide + for storage of the Operator Smart Cards and Location Smart Cards + +8. Follow the [Public Ceremony Artifacts Storage](public-ceremony-artifact-storage.md) +guide for all public artifacts produced during the ceremony + diff --git a/quorum-kms/src/location-key-provisioning.md b/quorum-kms/src/location-key-provisioning.md new file mode 100644 index 0000000..0b44cfd --- /dev/null +++ b/quorum-kms/src/location-key-provisioning.md @@ -0,0 +1,73 @@ +# Location Key Provisioning + +## Description +This ceremony is for generating Location Keys. Location Keys are typically +stored in vaults as prescribed in the [Secure Storage Guidelines](secure-storage-guidelines.md). +Location Keys are keypairs to which the Root Entropy of a QKMS is sharded. The +keypairs are stored exclusively on Smart Cards, and the PINs which protect the +Smart Cards are encrypted to Operator Keys. + +## Requirements +* Smart Card(s): whatever number of smart cards you would like to have seeded +for each Operator, usually 2 per Operator is recommended - one NitroKey 3 and +1 YubiKey Series 5. + +* [Storage Devices](equipment.md#storage-device): as many storage devices as you +would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) + +## Steps + +1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the +established [Location](location.md) + +2. Boot your Ceremony Machine using [Secure Boot Sequence](secure-boot-sequence.md) +or the [One Time Use Airgap-OS](one-time-use-airgapos.md) + +3. Provision new key in the selected secure environment + + * Load your personal PGP certificate which will be used as the Operator + Key in to the local keyring + + * `gpg --import ` + + * Generate the mnemonic: + + * `keyfork mnemonic generate --size 256 > mnemonic.txt` + + * Encrypt the mnemonic to the Operator Key + + * `gpg -er mnemonic.txt` + + * Save the encrypted mnemonic, `mnemonic.txt.gpg` to two SD cards + + * Print the contents of the mnemonic in a new terminal window as the seed + phrase words need to be typed in during the following steps: + + * `cat mnemonic.txt` + + * In a new terminal window start `keyfork` daemon with the mnemonic: + + * `keyfork recover mnemonic` + + * Derive PGP keypair: + + * `keyfork derive openpgp "FirstName LastName (alias) " > priv.asc` + + * Import PGP key into keyring + + * `gpg --import priv.asc` + + * Export PGP Public Certificate + + * `gpg --armor --export > pub.asc` + + * Save `pub.asc` to two SD cards + + * Delete all the generated assets before shutting down computer, namely + `pub.asc`, `priv.asc`, `mnemonic.txt` and `mnemonic.txt.gpg` + +4. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide + for storage of the Operator Smart Cards and Location Smart Cards + +5. Follow the [Public Ceremony Artifacts Storage](public-ceremony-artifact-storage.md) +guide for all public artifacts produced during the ceremony diff --git a/quorum-kms/src/locations.md b/quorum-kms/src/locations.md new file mode 100644 index 0000000..ba584a9 --- /dev/null +++ b/quorum-kms/src/locations.md @@ -0,0 +1,72 @@ +# Location + +Locations refer to physical points in space which are used for storing +cryptographic material or performing actions related to the DRK lifecycle and +adhere to a set of criteria which focus on achieving a high level of security - +specifically with respect to: + +* Protecting access to devices which store cryptographic material + +* Mitigating the risk stemming from natural disaster and other black swan events +such as civil unrest or war. + +* Reducing the risk of exposing cryptographic material, for example via +side-channel attacks + +There are three sub-types of Locations, one which is used for performing +any actions related to the management of the cryptographic material life-cycle +and is referred to as the Management Location, one for long term secure +storage of cryptographic material such as Smart Cards which are used to decrypt +[Shards](glossary.md#shard), referred to as a Storage Location, and a location +for Ceremonies, known as the Ceremony Location. + +The Storage Location has a shorter list of requirements while the Management +and Ceremony locations have a number of additional requirements. The Management +and Ceremony Location may be one and the same. + +## All Locations + +* MUST have physical access restrictions which require identification + +* MUST have the ability to require more than 1 person to gain access + + * This control can be both physical, for example in vaults which require 2 + keys for access AND/OR process level, where the personnel of the facility + may verify the identity of one or more individuals + +* SHOULD have anti-fire systems + +* SHOULD have anti-flood systems + + +## Management & Ceremony Locations + +* MUST not have cameras installed + +* MUST not have windows with direct line of sight to monitors + +* MUST have all walls protected with EM shielding which adheres to the TEMPEST +standard NATO SDIP-27 Level A + +* SHOULD be organizations which are ideally immune to being legally subpoenaed + +* SHOULD not be susceptible to being subpoenaed + +## Storage Location + +* MUST have anti-fire systems + +* MUST have anti-flood systems + +* MUST have 24/7 security monitoring + +* MUST be in different geographic locations + + * This ensures that natural disasters are not likely to impact multiple + locations simultaneously + +* SHOULD be facilities owned by different organizations to reduce the risk of +collusion unless the organization who owns the DRK has their own facility such +as a SCIF (Secure Compartmentalized Information Facility) + +* SHOULD have seismic detectors diff --git a/quorum-kms/src/one-time-repository-setup.md b/quorum-kms/src/one-time-repository-setup.md new file mode 100644 index 0000000..e078d18 --- /dev/null +++ b/quorum-kms/src/one-time-repository-setup.md @@ -0,0 +1,56 @@ +# Repository Setup + +Before the one time ceremony, a git repository should be set up which contains +several items which will be relevant to the ceremony. Namely the following: + +* PGP public certificates of the Location Keys which will be used for the +ceremony. The key ids of these certificates will be verified during the +ceremony. + +* `ceremony.sh` a script which imports the PGP public certificates of the +location keys, and displays their ids so that Operators can verify that they are +the correct ones. This script will also execute the appropriate `keyfork` +command with a desired threshold: + ``` + #!/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 2 --output-cert /dev/null --output-shardfile /dev/null --user-id "Distrust Key Ceremony" public-certificates/ + ``` + +* The `airgap.iso` which is to be used during the ceremony + +* Each operator should produce Ceremony Notes which contain: + + * `sha256sum` of `airgap.iso` + + * The AirgapOS commit and date for the version that was used + + * `sha256sum` of `ceremony.sh` + + * Key ID of each PGP Public Certificate located in `public-certificates` + in the ceremony repository \ No newline at end of file diff --git a/quorum-kms/src/one-time-use-airgapos.md b/quorum-kms/src/one-time-use-airgapos.md new file mode 100644 index 0000000..3fc34c9 --- /dev/null +++ b/quorum-kms/src/one-time-use-airgapos.md @@ -0,0 +1,38 @@ +# Set up AirgapOS + +Because without a Librem 14 there is no easy way to have a secure boot sequence, +instead the AirgapOS `.iso` image is flashed to an SD card, locked using +`sdtool` and then verified using any machine. + +## Setup Steps + +* Clone the latest AirgapOS version: + + * `git clone git@distrust.co:public/airgap.git` + +* Build the image: + + * `cd airgap && make` + +* Flash `airgap.iso` to an SD Card: + + * `dd if=out/airgap.iso of=/dev/ bs=4M status=progress oflag=direct` + +* Use the `sdtool` to lock the SD Card: + + * `git clone git@github.com:BertoldVdb/sdtool.git` + + * `cd sdtool` + + * `make` + + * `./sdtool /dev/mmcblk permlock` + + * Test that the card can't be written to: + + * `dd if=out/airgap.iso of=/dev/sdb bs=1M conv=sync status=progress` + +* Verify that the hash of `airgap.iso` matches what's flashed on the SD card: + + * `head -c $(stat -c '%s' out/airgap.iso) /dev/sdb | sha256sum` + * `sha256sum out/airgap.iso` diff --git a/quorum-kms/src/one-time-use-hardware-procurement.md b/quorum-kms/src/one-time-use-hardware-procurement.md new file mode 100644 index 0000000..45dd7b9 --- /dev/null +++ b/quorum-kms/src/one-time-use-hardware-procurement.md @@ -0,0 +1,33 @@ +# Procure Hardware + +* Procure a laptop, and SD cards from a randomly selected store. A randomly +selected store is used in order to reduce the possibility of a malicious actor +having time to plant compromised hardware at the store, and/or make arrangements +by coercing store staff to sell compromised hardware to the quroum team. Of +course, there still may be hardware that's compromised being sold, but not +specifically targeting the specific quorum group. + +* Ensure at least 2 people are in line of sight of access to all of the +equipment, for example a bag carried in hand, until the ceremony is executed. +This is done in order to eliminate the possibility of the equipment being +swapped for compromised hardware. + +* The laptop should ideally support booting from an SD card and have a built in +micro or standard SD card reader built in; if this is not possible, you will +also need to purchase a USB SD card reader. + +* Dell laptops tend to have support for booting from SD cards so they are a +good option. + +* The store and laptop model should be selected on the spot via consensu of at +least 2 members of the Quorum. This is done for several reasons: + + * To ensure that no time is given to a malicious actor to deploy + compromised hardware to the store + + * To reduce likelihood that arrangements can be made by a malicious actor + for the store to sell compromised hardware to the Quroum team + +* Note that a secondary computer, or secondary SD card with bootable OS will be +required in order to be able to verify the flashed AirgapOS SD card right before +the ceremony. \ No newline at end of file diff --git a/quorum-kms/src/one-time-use-locations.md b/quorum-kms/src/one-time-use-locations.md new file mode 100644 index 0000000..e8b1427 --- /dev/null +++ b/quorum-kms/src/one-time-use-locations.md @@ -0,0 +1,18 @@ +# Selecting Locations + +Secure a location that is randomly selected that has a private space with EM +shielding, or no electronics in at least a 10 m radius. A moving vehicle (eg. +car, bus, train, ferris wheel) is also a viable alternative. Additionally, the +ceremony may be conducted in an open outdoor space, such as a forest, or a +desert, at a location that is not near any human made buildings. The point of +narrowing the location selection to these spaces is that it makes it hard for a +malicious actor to prepare for the ceremony and deploy equipment for +side-channel attacks - with the intent of stealing the cryptographic material +which is produced or managed during key ceremonies. + +The location should be selected immediately before the ceremony in order to +eliminate the possibility of a malicious actor having time to infiltrate and +compromise the space ahead of the ceremony. The location may be compromised +anyways, as a malicious actor may have done so with another target in mind, or a +more broad campaign, for example in the case for three letter agencies may plant +cameras and microphones in hotels for intel gathering. \ No newline at end of file diff --git a/quorum-kms/src/operator-key-provisioning.md b/quorum-kms/src/operator-key-provisioning.md new file mode 100644 index 0000000..f6e8ed9 --- /dev/null +++ b/quorum-kms/src/operator-key-provisioning.md @@ -0,0 +1,44 @@ +# Operator Key Provisioning + +## Description +This guide can be used for provisioning Operator key pairs, and the output of +the ceremony is a set of the following for each Operator: +* Smart Card(s) seeded with PGP keys +* Storage Device with a backup of: + * PGP key pair public key + +## Requirements +* Smart Card(s): whatever number of smart cards you would like to have seeded +for each Operator, usually 2 per Operator is recommended - one NitroKey 3 and +1 YubiKey Series 5. + +* [Storage Devices](equipment.md#storage-device): as many storage devices as you +would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) + +## Playbook + +### Steps +This playbook allows the setup of any number of Operator Keys. For each Operator, +the steps that follow need to be repeated. + +1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the +established [Location](location.md) + +2. Boot your Ceremony Machine using [Secure Boot Sequence](secure-boot-sequence.md) + +3. Plug in a new Storage Device + +4. Run `keyfork wizard operator` TODO: this command is not part of `keyfork` yet + +5. As prompted plug in new Smart Cards + +6. Once the ceremony is complete, make as many copies of the Storage Device +from Step 3 as desired. + +7. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide + for storage of the Operator Smart Cards and Location Smart Cards + +8. Follow the [Public Ceremony Artifacts Storage](public-ceremony-artifact-storage.md) +guide for all public artifacts produced during the ceremony + + diff --git a/quorum-kms/src/physical-artifact-storage.md b/quorum-kms/src/physical-artifact-storage.md new file mode 100644 index 0000000..db74742 --- /dev/null +++ b/quorum-kms/src/physical-artifact-storage.md @@ -0,0 +1,38 @@ +# Physical Artifact Storage + +QKMS requires that some of the hardware containing cryptographic material be +securely stored in physical locations. The two primary cases where physical +storage is necessary are the storage of Location Key Smart Cards, and Operator +Key Smart Cards. These Smart Cards are necessary to successfully execute a +ceremony. + +There are two primary physical artifacts which need to be stored properly: + +* Operator Smart Cards + +* Location Smart Cards + +## Operator Smart Cards + +These cards should be stored by Operators in personal vaults using a high +quality hidden safe, or in a vaulting facility such as a bank vault, or a +private vaulting provider. + +## Location Smart Cards + +These cards should only be stored in secure vaults which meet the criteria +outliened for Storage Locations in the [Location](location.md) document. + + +## Additional Criteria + +* MUST place smart cards in a tamper proof bag, whose picture is taken upon +sealing, and stored along with other [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) + +* SHOULD provision all GPG keys to at least two smart cards, ideally made +by different manufacturers in order to decrease the likelihood that they both +simultaneously experience a hardware failure. + +* SHOULD place the smart cards in anti-static bags + +* SHOULD place the smart cards in a faraday bag diff --git a/quorum-kms/src/provisioning-hardware-and-firmware.md b/quorum-kms/src/provisioning-hardware-and-firmware.md new file mode 100644 index 0000000..10b8702 --- /dev/null +++ b/quorum-kms/src/provisioning-hardware-and-firmware.md @@ -0,0 +1,87 @@ +# Provisioning Hardware and Firmware + +This page describes different equipment which is required, and makes opinionated +recommendations as well as alternatives. One may improve the overall security +of their system by using a variety of hardware in order to benefit from their +diversity, by reducing the likelihood that all hardware has suffered the same +kind of hardware supply chain compromise, has the same vulnerability present, or +has the same type of hardware failure issue. + +Based on the decided upon [Quorum](selecting-quorum.md), the amount of equipment +required to set up a [QKMS](glossary.md#quroum-kms-qkms) will +vary. In order to figure out what equipment is required, decide on a Quorum, +which is expressed as "N of M". Once you know your M, the required equipment list +is the following: + +* M x 4 Smart Cards + + * It is recommended to use two Smart Cards for storing each key pair + + * Ideally two different types of hardware are used in order to reduce the + risk of simultaneous failure + + * At least 1 Smart Card is required for each Operator Key and 1 Smart Card + for each Location Key + + * The number of Operator Keys is M, and the number of Location Keys is also + M, hence the minimum of 2 x M Smart Cards, with the recommendation of using + two smart cards for each, resulting in 4 x M Smart Cards + +* 2 + X Storage Devices + + * 1 Storage Device for [AirgapOS](repeat-use-airgapos.md) + + * 1 Storage Device for storing [Public Ceremony Artifacts](public-ceremony-artifact-storage) + + * X, or *any* number of additional Storage Devices to duplicate the data, a + good measure would be to have at least 3 Storage Devices for the ceremony + +* Librem 14 Laptop + + * Get as many laptops as desired to satisfy your operational needs + + * For each Librem 14, get a Librem Smart Card used for [PureBoot](initialize-pureboot-smart-card.md) + +## Smart Cards + +Smart Cards are primarily used for storing OpenPGP cryptographic keys which are +used as a building block for security controls. These smart cards hold OpenPGP +keys which are derived in secure environments. FIPS 140-2 is required but the +end user may choose their manufacturer. + +* NitroKey 3 - because of its open source approach which helps improve the +overall security of the products +* YubiKey 5 - because of the widespread use and battle-tested reliability +* Librem Key - because of the manufacturer's approach to hardware supply chain +security and verifiable software + +## Air-Gapped Computer +[Air-Gapped](glossary.md#Air-Gapped) computers are used for the lifecycle management +of cryptographic material that is part of QKMS. + +The primary hardware recommendation for a Air-Gapped Computer is the [Librem 14](https://puri.sm/products/librem-14/), manufactured by [Purism](puri.sm). Purism specializes in reducing hardware and +firmware security risks, especially via their [Anti-Interdiction Service](https://puri.sm/posts/anti-interdiction-services/) and [PureBoot](https://docs.puri.sm/PureBoot.html) +and as such is an excellent choice for hardware which high integrity assurance is +required for. + +#### Alternative + +An alternative approach is to use an off-the-shelf computer that is randomly +selected right before the ceremony, removing the radio cards from it, using it +to conduct a Ceremony, and then destroying the laptop using sufficiently +adequate method to ensure that no data forensics can be used to recover the data +from the drive, or memory. This can be achieved by using a combination of +incineration, degaussing, shredding and drilling. Special care should be taken +to completely destroy all components of the computer that are able to store data, +even if it's only in ephemeral form as some forensic methods all extraction of +data from components with "temporary memory". + +Three letter agencies are known to collect and exploit physical destroyed drives, +as data can still be extracted from them using methods such as electron +microscopy, therefore a combination of degaussing, shredding and burning should +be used, and the remaining debris should be spread out across multiple disposal +locations. + +## Storage Device +Can be an SD Card or USB Drive but should be procured from a vendor with +a good reputation, and ideally hardware of industrial grade should be prioritized. \ No newline at end of file diff --git a/quorum-kms/src/public-ceremony-artifact-storage.md b/quorum-kms/src/public-ceremony-artifact-storage.md new file mode 100644 index 0000000..78c19ae --- /dev/null +++ b/quorum-kms/src/public-ceremony-artifact-storage.md @@ -0,0 +1,34 @@ +# Redundant Storage of Ceremony Artifacts + +Ceremony Artifacts consist of data which is not sensitive in nature, but +essential to ongoing operation of a QKMS. + +The primary artifacts which are produced during the ceremony are: + +* PGP Key Certificates + +* Shard Files + +* Pin Files + +* Pictures of tamper proof measures such as tamper proof bags, glitter applied +to bags, or hardware, such as screws on the bottoms of laptops etc. + +## Key Principles + +* MUST verify that all Public Artifacts generated during the Ceremonies are +present in the Ceremony Artifacts bundle. + +* MUST store all Ceremony Artifacts in at least 2 different cloud storage +systems. Some options are: + + * AWS S3 + + * Google Cloud Platform Storage + + * Azure Storage + + * GitHub + +* The data SHOULD have proper access controls, and only be accessible to +authorized personnel who are part of the organization. diff --git a/quorum-kms/src/quorum-team.md b/quorum-kms/src/quorum-team.md new file mode 100644 index 0000000..cd24e2f --- /dev/null +++ b/quorum-kms/src/quorum-team.md @@ -0,0 +1,40 @@ +# Quorum Team + +The Quorum Team is a team of individuals who are selected to perform different +roles related to a QKMS. Some of the Quorum Team members have ongoing roles, +while others may participate in a partial manner. + +Depending on the type of actions performed, some or all of the members of the +Quorum may be required to participate. For example, it is recommended that there +is at least 1 witness for all sensitive actions, but having 3 witnesses during +the primary Key Derivation Ceremony can give better assurances that the most +crucial part of the ceremony was properly conducted. + +The roles which are required for the Quorum Team are the following: + +## Operator +Operators are individuals who protect [Smart Cards](equipment.md) which +store a [GPG Key Certificate](glossary.md#gpg-certificate), which is used +for encrypting information, such as the [Location Key](glossary.md#location-key) +PINs as well as other [Ceremony Artifacts](reduntant-storage-of-ceremony-artifacts.md). +They are also individuals who participate in Ceremonies in order to Reconstitute +the key and perform actions with it. + +## Controller +Controllers are an additional optional role which can be used to protect access +to the physical locations which hold the Location Keys. Some vaulting solutions +allow for requiring more than 1 individual in order to access a vault. Multiple +Controllers may be used to protect access to physical locations - according to +risk appetite. + +## Witness +Witnesses are individuals who are familiar with the QKMS specification, and can +ensure that the different aspects of the system are set up correctly, and +processes carried out as they should be. The main objective of the witnesses is +to monitor and attest that processes such as the ceremonies are done according +to the strictly prescribed rules. + +## Courier +This role can be fulfilled by members of the Quorum Team and their main role is +getting materials to their designated locations - the main task being getting +the Location Keys securely to their physical location. \ No newline at end of file diff --git a/quorum-kms/src/remote-key-provisioning.md b/quorum-kms/src/remote-key-provisioning.md new file mode 100644 index 0000000..737ec50 --- /dev/null +++ b/quorum-kms/src/remote-key-provisioning.md @@ -0,0 +1,3 @@ +# Remote Key Provisioning + +TODO \ No newline at end of file diff --git a/quorum-kms/src/repeat-use-airgapos.md b/quorum-kms/src/repeat-use-airgapos.md new file mode 100644 index 0000000..223fd29 --- /dev/null +++ b/quorum-kms/src/repeat-use-airgapos.md @@ -0,0 +1,61 @@ +# AirgapOS Setup +This section can be completed on any machine. + +AirgapOS has `keyfork` built into it for cryptographic operations such as key +derivation. + +1. Clone the `AirgapOS` repository locally or download it as a zip + + To clone use the following command in the terminal: + ``` + cd ~ + git clone git@distrust.co:public/airgap.git + ``` + + To download as a ZIP from https://git.distrust.co/public/airgap: + ![Downloading AirgapOS as ZIP](img/download-airgap-os.png) + +2. Navigate into the `airgap` repository locally, and build the iso image. + ``` + cd ~/airgap + make reproduce + ``` +The resulting iso will be located in `airgap/out/` + +3. Place signed .iso on a storage device + + a. Import the public key for the PureBoot Smart Card from [Initialize PureBoot Smart Card](initialize-pureboot-smart-card.md) guide. + ``` + gpg --import .asc + ``` + + b. Get the GPG key ID using the command: + ``` + gpg --list-keys + ``` + It should look something like `6B61ECD76088748C70590D55E90A401336C8AAA9` + + c. Sign the `airgap.iso` image using the "PureBoot Smart Card", which is + set up in [Initalize PureBoot Smart Card](initialize-pureboot-smart-card.md) + guide. + ``` + gpg --detach-sign --armor --default-key airgap.iso + ``` + +4. Copy `airgap.iso` and detached signature to a storage device + a. Select a new Storage Device which has no other files on it and plug it + into the machine that has the `airgap.iso` file and the detached GPG signature. + + b. Find the name of the Storage Device using [this guide](storage-device-management.md#finding-a-storage-device-name) + + d. Use the `mount` command to mount the drive + + e. Copy both the `airgap.iso` and detached signature to the drive. + +5. Make sure to note the `sha256sum` hash of the `airgap.iso` and write it +down on a piece of paper. + +6. Multiple members of your team should build the `airgap.iso` image +independently and use `sha256sum airgap.iso` in order to hash it, then record +the value for later use. This value will be checked during Ceremonies before +booting the ISO image to ensure it can be trusted. \ No newline at end of file diff --git a/quorum-kms/src/secure-boot-sequence.md b/quorum-kms/src/secure-boot-sequence.md new file mode 100644 index 0000000..a9e909a --- /dev/null +++ b/quorum-kms/src/secure-boot-sequence.md @@ -0,0 +1,40 @@ +# Secure Boot Sequence + +1. Plug in the [PureBoot Smart Card](initialize-pureboot-smart-card.md) + +2. Plug in [AirgapOS Storage Device](repeat-use-airgapos.md) + +3. Turn on the machine + +4. Press space when the message "Automatic boot in 5 seconds unless interrupted by keypress..." + +5. Once in the PureBoot Boot Menu, navigate to "Options -->" and press Enter + +6. Navigate to "Exit to recovery shell" and press enter + +7. Use the command `source /etc/gui_functions` to load gui functions + +8. Use the command `mount_usb` to mount the Storage Device which contains `airgap.iso` and the detached GPG signature. + +9. Type `sha256sum /media/airgap.iso.asc` + +10. Verify the hash that appears using whatever number of witnesses the Quroum +agreed are necessary for witnessing key parts of the Ceremony. Each witness +should bring their own piece of paper with the hash written out based on the +binary they built on their own system according to the [AirgapOS Setup Playbook](repeat-use-airgapos.md). + +12. Once everyone is satisfied that the hash matches, the computer should be +be restarted. + +13. Press space when the message "Automatic boot in 5 seconds unless interrupted by keypress..." + +14. Once in the PureBoot Boot Menu, navigate to "Options -->" and press Enter + +15. Navigate to "Boot Options -->" and press enter + +16. Navigate to "USB boot" and press enter + +17. Ensure that `/media/airgap.iso` is selected and press Enter + +18. Once booted, verify the version of the software matches the AirgapOS Hash +which was noted during the [AirgapOS Setup](repeat-use-airgapos.md). \ No newline at end of file diff --git a/quorum-kms/src/secure-physical-storage-guidelines.md b/quorum-kms/src/secure-physical-storage-guidelines.md new file mode 100644 index 0000000..a82beb9 --- /dev/null +++ b/quorum-kms/src/secure-physical-storage-guidelines.md @@ -0,0 +1 @@ +# Physical Artifact Storage Guidelines diff --git a/quorum-kms/src/selecting-quorum.md b/quorum-kms/src/selecting-quorum.md new file mode 100644 index 0000000..75be693 --- /dev/null +++ b/quorum-kms/src/selecting-quorum.md @@ -0,0 +1,38 @@ +# Selecting a Quorum + +The backbone of the Distrust Quroum system is a Quorum which is used to +reconstitute or re-assemble cryptographic material, and approve actions. +Quorum is a general term referring to a system which requires the collaboration +of multiple individuals in order to achieve something, and it is based on a +Threshold which determines how many Members of a Quorum there are in total, and +the Quorum, which is how Members are required to reach consensus. + +The following is a simple Quorum example. Let's assume there are 3 trusted +individuals who will be part of Quorum and at least 2 of the Members of the +Quorum should be required to reach consensus. In that case the chosen Quorum +would be "2 of 3" - in other words, 2 of the total of 3 are required to achieve +consensus. These numbers may be adjusted in order to optimize risk tolerance +along two axis: + +* Tolerating loss of X members aka "Bus Factor" + +* Tolerating duress of Y members aka "Wrench Factor" + +In a "2 of 3" Quorum, the **Bus Factor** is 1 as we can only afford to lose 1 +member of the Quorum before the ability to reach consensus is lost permanently. +For that same Quorum, the **Wrench Factor** is 2, as an adversary has to use +their wrench on two different Quorum Members to force them to give them access +to their shards before the system is compromised (this is an over-simplification +as there are additional security controls in place such as the physical +locations which hold Location Keys, and as such the Wrench Factor is hardened). + +It is recommended to use a "2 of 3" Threshold at a minimum, but many organizations +may choose to go with more resilient Threshold such as "3 of 5", "2 of 6", or +"5 of 7", depending on considerations pertaining to: + +* Availability requirements + +* Bus Factor requirements + +* Wrench Factor requirements + diff --git a/quorum-kms/src/setting-smart-card-pins.md b/quorum-kms/src/setting-smart-card-pins.md new file mode 100644 index 0000000..dcd025f --- /dev/null +++ b/quorum-kms/src/setting-smart-card-pins.md @@ -0,0 +1,38 @@ +# Setting Smart Card Pins + +In order to protect unauthorized use of smart cards, we can leverage PINs. + +There are two pins with different levels of authorization for making changes +to the smart card: + +* User PIN + +* Admin PIN + +Both PINs support alphanumeric characters and typically need to be at least 6 +characters long. + +For Operator Keys it is recommended to use the default PINs, while for Location +Keys, PINs are generated by the `keyfork` utility and have high entropy. + +## Guide + +To set the smart card pins you may use the `gpg` utility. + +1. Plug the smart card into a computer which has the `gpg` utility intalled +2. Use the command `gpg --edit-card` to enter edit mode +3. gpg/card> + * Input `admin`, press Enter +4. Your selection? + * Input 1, press Enter +5. Please enter the PIN: + * Enter old PIN (default is 123456), press Enter +6. New PIN: + * Enter the new PIN, press Enter +7. Repeat this PIN: + * Enter the new PIN, press Enter + +8. For the Admin PIN, the steps are the same, except in step 4, input "3", then +press Enter. + +9. Once done, shut down the computer diff --git a/quorum-kms/src/software.md b/quorum-kms/src/software.md new file mode 100644 index 0000000..a994af7 --- /dev/null +++ b/quorum-kms/src/software.md @@ -0,0 +1,38 @@ +# Software +This page outlines the software used for setting up a QKMS. All software used in +the setup is open source and audited by security firms in order to ensure their +security. Furthermore, all software is built in a deterministic manner and +reproduced by multiple individuals on diverse hardware to minimize the risks +associated with supply chain attacks. + +To achieve this, [StageX](https://codeberg.org/stagex/stagex) +is used - a toolchain for building software using a fully bootstrapped compiler, +which itself is built deterministically, and multi-reproduced. +## [AirgapOS](https://git.distrust.co/public/airgap) + +AirgapOS is an operating system built for those that want to be -really- sure +that sensitive cryptographic material is managed in a clean environment with an +"air gap" between the machine and the internet with high integrity on the supply +chain of the firmware and OS used. This OS is hardened and specifically designed +as an appliance for working with cryptographic material. + +The software was developed by [Distrust](https://distrust.co) and has undergone +an [audit](https://git.distrust.co/public/airgap/src/branch/main/audits) by +Cure53 with no significant vulnerabilities found and has since then undergone +additional hardening. + +The [AirgapOS Setup](repeat-use-airgapos.md) guides the user through verifying and +setting up AirgapOS on a bootable disk to use as part of the [Key Derivation +Ceremony](glossary.md#key-derivation-ceremony) + +## [Keyfork](https://git.distrust.co/public/keyfork) + +Keyfork is an opinionated and modular toolchain for generating and managing a +wide range of cryptographic keys offline and on Smart Cards from a shared +BIP-0039 mnemonic phrase. BIP-0039 phrases are used to calculate a BIP-0032 +seed, which is used for hierarchical deterministic key derivation. + +This software is the backbone for all cryptographic actions performed as part +of QKMS. It was developed by [Distrust](https://distrust.co) and is included +with AirgapOS and has been audited by two firms, NCC and Cure53 with no +significant vulnerabilities found. diff --git a/quorum-kms/src/storage-device-management.md b/quorum-kms/src/storage-device-management.md new file mode 100644 index 0000000..73c5bae --- /dev/null +++ b/quorum-kms/src/storage-device-management.md @@ -0,0 +1 @@ +# Storage Device Operation diff --git a/quorum-kms/src/threat-model.md b/quorum-kms/src/threat-model.md new file mode 100644 index 0000000..0ce386e --- /dev/null +++ b/quorum-kms/src/threat-model.md @@ -0,0 +1,81 @@ +# Threat Model + +QKMS is designed according to a high-assurance threat model which ers on the +side of making exaggerated, rather than conservative assumptions in order to +build a resilient system. + +The assumption is made that attackers who target QKMS are extremely +sophisticated, well funded and patient attackers, and as such, the full arsenal +of attacks is on the table. This means that the attacker can purchase and +weaponize multiple 0day vulnerabilities, execute physical attacks or deploy +moles, target different supply chains of hardware, firmware and software used, +and generally attack the system using an array of known and unknown attacks. + +One of the guiding principles in the design is the elimination of Single Points +of Failure (SPOFs), and relies on a number of different control mechanisms which +help reduce risk of any one individual being able to compromise the system, +whether it's maintainers of software used in the system, the firmware that's +used, or the individuals or locations that hold secret material which is the +backbone of the system. + +To achieve this, the QKMS focuses on reducing the risk by: + +* Only using fully open source software and firmware to allow full verification +of their security + +* Creating custom purpose specific tooling which eliminates dependencies in +order to reduce supply chain attacks, and adds desirable security properties + +* Using a fully bootstrapped and deterministically built compiler for building +all software that's used + +* Building all of the software and firmware deterministically + +* Using computers which either have a hard switch for disabling networking or +which had radio networking cards (bluetooth, wifi etc.) removed + +* Leveraging smart cards (personal HSMs) to protect cryptographic material + +* Leveraging sharding in order to physically separate cryptographic material + +* Leveraging tamper evident controls to protect hardware + +## General Threat Model Assumptions + +Some additional assumptions are made to help contextualize the threat model: + +* All screens are visible to an adversary + +* All keyboards are logging to an adversary + +* Any firmware/boot-loaders not verified on every boot are compromised + +* Any host OS with network access is compromised + +* Any guest OS used for any purpose other than prod access is compromised + +* At least one member of the PRODUCTION team is always compromised + +* At least one maintainer of third party used in the system is compromised + +* Physical attacks are viable and likely + + +## Additional Threat Model Notes + +### Smart Cards + +The Operator Smart Card uses the default PIN because it is meant to be something +a user "has", rather than "knows". On the other hand, the Location Smart Card +is protected by a complex PIN, which can only be decrypted using the PGP keys +stored on the Operator Smart Card. This is done in order to protect the access +to the Location key by anyone except the Operator, but also to allow for adding +controls which require more than one individual to access a Location Smart Card. +In this way, there is an additional "quorum" which needs to be achieved to +access the Location key - more on this in the [Location](locations.md) section. + +The Smart Cards are used as they are an HSM (Hardware Security Module) which +provides excellent protection for the cryptographic material stored on it, and +they are portable, which makes them suitable for creating systems where the +cards are in separate physical locations, and need to be brought together in +order to re-assemble secret material. From 6002939ff9069963e61f4668258ec9c21edb9f27 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 17:50:07 -0400 Subject: [PATCH 02/19] fix: remove unused docs and add back storage device management guide --- quorum-kms/src/SUMMARY.md | 3 +- quorum-kms/src/destroying-hardware.md | 1 - .../src/secure-physical-storage-guidelines.md | 1 - quorum-kms/src/storage-device-management.md | 54 ++++++++++++++++++- 4 files changed, 55 insertions(+), 4 deletions(-) delete mode 100644 quorum-kms/src/destroying-hardware.md delete mode 100644 quorum-kms/src/secure-physical-storage-guidelines.md diff --git a/quorum-kms/src/SUMMARY.md b/quorum-kms/src/SUMMARY.md index a71fc8c..f6a9d0c 100644 --- a/quorum-kms/src/SUMMARY.md +++ b/quorum-kms/src/SUMMARY.md @@ -39,4 +39,5 @@ * [Physical Artifact Storage](physical-artifact-storage.md) * [Lifecycle Management]() - * [Destroying Hardware](hardware-destruction.md) \ No newline at end of file + * [Destroying Hardware](hardware-destruction.md) + * [Storage Device Management](storage-device-management.md) \ No newline at end of file diff --git a/quorum-kms/src/destroying-hardware.md b/quorum-kms/src/destroying-hardware.md deleted file mode 100644 index 65201f4..0000000 --- a/quorum-kms/src/destroying-hardware.md +++ /dev/null @@ -1 +0,0 @@ -# Destorying Hardware diff --git a/quorum-kms/src/secure-physical-storage-guidelines.md b/quorum-kms/src/secure-physical-storage-guidelines.md deleted file mode 100644 index a82beb9..0000000 --- a/quorum-kms/src/secure-physical-storage-guidelines.md +++ /dev/null @@ -1 +0,0 @@ -# Physical Artifact Storage Guidelines diff --git a/quorum-kms/src/storage-device-management.md b/quorum-kms/src/storage-device-management.md index 73c5bae..201f917 100644 --- a/quorum-kms/src/storage-device-management.md +++ b/quorum-kms/src/storage-device-management.md @@ -1 +1,53 @@ -# Storage Device Operation +# Storage Device Management + +In order to interact with a USB device on a Linux system it first has to be +`mounted`. In order to mount a USB device, one must first identify the device +name, and then use the `mount` command. + +## Finding a Storage Device Name +USB devices are assigned names when they are connected to a Linux operating +system. The first storage device is assigned the name `sda` (storage device a), +the second `sdb`, the third `sdc` and so on. + +One may use the `lsblk` to list the detected storage devices for a system, which +will output something like this: +``` +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +xvda 202:0 1 50G 0 disk +├─xvda1 202:1 1 200M 0 part +├─xvda2 202:2 1 2M 0 part +└─xvda3 202:3 1 49.8G 0 part / +xvdb 202:16 1 1.9T 0 disk /rw +xvdc 202:32 1 10G 0 disk +├─xvdc1 202:33 1 1G 0 part [SWAP] +└─xvdc3 202:35 1 9G 0 part +xvdd 202:48 1 526.8M 1 disk +``` + +Then after plugging in the Storage Device run `lsblk` and look for what's +different. In this example, the newly detected storage device is `sdb`: +``` +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +sdb 8:16 1 14.5G 0 disk +xvda 202:0 1 50G 0 disk +├─xvda1 202:1 1 200M 0 part +├─xvda2 202:2 1 2M 0 part +└─xvda3 202:3 1 49.8G 0 part / +xvdb 202:16 1 1.9T 0 disk /rw +xvdc 202:32 1 10G 0 disk +├─xvdc1 202:33 1 1G 0 part [SWAP] +└─xvdc3 202:35 1 9G 0 part +xvdd 202:48 1 526.8M 1 disk +``` + +## Mounting a Storage Device +In order to mount a device, first ensure that the directory you will mount to +exists by running: + +```sh +mkdir -p /media/usb +``` + +Then run the following command to mount the storage device: +```sh +sudo mount /dev/ /media/usb \ No newline at end of file From b1d46820015e02f88dc420a9a9786fa8804fc2c8 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 17:53:52 -0400 Subject: [PATCH 03/19] fix: rename from Quroum-KMS to Quorum Key Management System (QKMS) --- .../.gitignore | 0 .../README.md | 4 ++-- .../book.toml | 2 +- .../src/SUMMARY.md | 0 .../src/autorun-sh-setup.md | 0 .../src/ceremony-log-template.md | 0 .../src/core-key-ceremonies.md | 0 .../src/enable-pure-boot-restricted-boot.md | 0 .../src/flash-pureboot-firmware.md | 0 .../src/flashing-iso.md | 0 .../src/glossary.md | 2 +- .../src/hardware-destruction.md | 0 .../src/hardware-procurement.md | 2 +- .../src/hybrid-key-provisioning.md | 0 .../src/img/download-airgap-os.png | Bin .../src/initialize-pureboot-smart-card.md | 0 .../src/intro.md | 6 +++--- .../src/local-key-provisioning.md | 0 .../src/location-key-provisioning.md | 0 .../src/locations.md | 0 .../src/one-time-repository-setup.md | 0 .../src/one-time-use-airgapos.md | 0 .../src/one-time-use-hardware-procurement.md | 0 .../src/one-time-use-locations.md | 0 .../src/operator-key-provisioning.md | 0 .../src/physical-artifact-storage.md | 0 .../src/provisioning-hardware-and-firmware.md | 0 .../src/public-ceremony-artifact-storage.md | 0 .../src/quorum-team.md | 0 .../src/remote-key-provisioning.md | 0 .../src/repeat-use-airgapos.md | 0 .../src/secure-boot-sequence.md | 0 .../src/selecting-quorum.md | 0 .../src/setting-smart-card-pins.md | 0 .../src/software.md | 0 .../src/storage-device-management.md | 0 .../src/threat-model.md | 0 37 files changed, 8 insertions(+), 8 deletions(-) rename {quorum-kms => quorum-key-management-system}/.gitignore (100%) rename {quorum-kms => quorum-key-management-system}/README.md (70%) rename {quorum-kms => quorum-key-management-system}/book.toml (71%) rename {quorum-kms => quorum-key-management-system}/src/SUMMARY.md (100%) rename {quorum-kms => quorum-key-management-system}/src/autorun-sh-setup.md (100%) rename {quorum-kms => quorum-key-management-system}/src/ceremony-log-template.md (100%) rename {quorum-kms => quorum-key-management-system}/src/core-key-ceremonies.md (100%) rename {quorum-kms => quorum-key-management-system}/src/enable-pure-boot-restricted-boot.md (100%) rename {quorum-kms => quorum-key-management-system}/src/flash-pureboot-firmware.md (100%) rename {quorum-kms => quorum-key-management-system}/src/flashing-iso.md (100%) rename {quorum-kms => quorum-key-management-system}/src/glossary.md (99%) rename {quorum-kms => quorum-key-management-system}/src/hardware-destruction.md (100%) rename {quorum-kms => quorum-key-management-system}/src/hardware-procurement.md (98%) rename {quorum-kms => quorum-key-management-system}/src/hybrid-key-provisioning.md (100%) rename {quorum-kms => quorum-key-management-system}/src/img/download-airgap-os.png (100%) rename {quorum-kms => quorum-key-management-system}/src/initialize-pureboot-smart-card.md (100%) rename {quorum-kms => quorum-key-management-system}/src/intro.md (91%) rename {quorum-kms => quorum-key-management-system}/src/local-key-provisioning.md (100%) rename {quorum-kms => quorum-key-management-system}/src/location-key-provisioning.md (100%) rename {quorum-kms => quorum-key-management-system}/src/locations.md (100%) rename {quorum-kms => quorum-key-management-system}/src/one-time-repository-setup.md (100%) rename {quorum-kms => quorum-key-management-system}/src/one-time-use-airgapos.md (100%) rename {quorum-kms => quorum-key-management-system}/src/one-time-use-hardware-procurement.md (100%) rename {quorum-kms => quorum-key-management-system}/src/one-time-use-locations.md (100%) rename {quorum-kms => quorum-key-management-system}/src/operator-key-provisioning.md (100%) rename {quorum-kms => quorum-key-management-system}/src/physical-artifact-storage.md (100%) rename {quorum-kms => quorum-key-management-system}/src/provisioning-hardware-and-firmware.md (100%) rename {quorum-kms => quorum-key-management-system}/src/public-ceremony-artifact-storage.md (100%) rename {quorum-kms => quorum-key-management-system}/src/quorum-team.md (100%) rename {quorum-kms => quorum-key-management-system}/src/remote-key-provisioning.md (100%) rename {quorum-kms => quorum-key-management-system}/src/repeat-use-airgapos.md (100%) rename {quorum-kms => quorum-key-management-system}/src/secure-boot-sequence.md (100%) rename {quorum-kms => quorum-key-management-system}/src/selecting-quorum.md (100%) rename {quorum-kms => quorum-key-management-system}/src/setting-smart-card-pins.md (100%) rename {quorum-kms => quorum-key-management-system}/src/software.md (100%) rename {quorum-kms => quorum-key-management-system}/src/storage-device-management.md (100%) rename {quorum-kms => quorum-key-management-system}/src/threat-model.md (100%) diff --git a/quorum-kms/.gitignore b/quorum-key-management-system/.gitignore similarity index 100% rename from quorum-kms/.gitignore rename to quorum-key-management-system/.gitignore diff --git a/quorum-kms/README.md b/quorum-key-management-system/README.md similarity index 70% rename from quorum-kms/README.md rename to quorum-key-management-system/README.md index b8ae827..abb2b05 100644 --- a/quorum-kms/README.md +++ b/quorum-key-management-system/README.md @@ -1,6 +1,6 @@ -# Quroum-KMS (QKMS) +# Quorum Key Management System (QKMS) -Quorum-KMS (QKMS) is an open source system of playbooks and tooling which +Quorum Key Management System (QKMS) is an open source system of playbooks and tooling which facilitates the creation and maintenance of highly resilient Quorum-based Key Management Systems based on a strict threat model which can be used for a variety of different cryptographic algorithms. diff --git a/quorum-kms/book.toml b/quorum-key-management-system/book.toml similarity index 71% rename from quorum-kms/book.toml rename to quorum-key-management-system/book.toml index ef754bc..35d8a9e 100644 --- a/quorum-kms/book.toml +++ b/quorum-key-management-system/book.toml @@ -3,4 +3,4 @@ authors = ["Anton Livaja", "Lance R. Vick", "Ryan Heywood"] language = "en" multilingual = false src = "src" -title = "Quorum-KMS" +title = "Quorum Key Management System (QKMS)" diff --git a/quorum-kms/src/SUMMARY.md b/quorum-key-management-system/src/SUMMARY.md similarity index 100% rename from quorum-kms/src/SUMMARY.md rename to quorum-key-management-system/src/SUMMARY.md diff --git a/quorum-kms/src/autorun-sh-setup.md b/quorum-key-management-system/src/autorun-sh-setup.md similarity index 100% rename from quorum-kms/src/autorun-sh-setup.md rename to quorum-key-management-system/src/autorun-sh-setup.md diff --git a/quorum-kms/src/ceremony-log-template.md b/quorum-key-management-system/src/ceremony-log-template.md similarity index 100% rename from quorum-kms/src/ceremony-log-template.md rename to quorum-key-management-system/src/ceremony-log-template.md diff --git a/quorum-kms/src/core-key-ceremonies.md b/quorum-key-management-system/src/core-key-ceremonies.md similarity index 100% rename from quorum-kms/src/core-key-ceremonies.md rename to quorum-key-management-system/src/core-key-ceremonies.md diff --git a/quorum-kms/src/enable-pure-boot-restricted-boot.md b/quorum-key-management-system/src/enable-pure-boot-restricted-boot.md similarity index 100% rename from quorum-kms/src/enable-pure-boot-restricted-boot.md rename to quorum-key-management-system/src/enable-pure-boot-restricted-boot.md diff --git a/quorum-kms/src/flash-pureboot-firmware.md b/quorum-key-management-system/src/flash-pureboot-firmware.md similarity index 100% rename from quorum-kms/src/flash-pureboot-firmware.md rename to quorum-key-management-system/src/flash-pureboot-firmware.md diff --git a/quorum-kms/src/flashing-iso.md b/quorum-key-management-system/src/flashing-iso.md similarity index 100% rename from quorum-kms/src/flashing-iso.md rename to quorum-key-management-system/src/flashing-iso.md diff --git a/quorum-kms/src/glossary.md b/quorum-key-management-system/src/glossary.md similarity index 99% rename from quorum-kms/src/glossary.md rename to quorum-key-management-system/src/glossary.md index f0910cb..bdf452f 100644 --- a/quorum-kms/src/glossary.md +++ b/quorum-key-management-system/src/glossary.md @@ -4,7 +4,7 @@ In cryptography, ciphertext is the result of encryption performed on plaintext using an algorithm, called a cipher. -## Quorum-KMS (QKMS) +## Quorum Key Management System (QKMS) A set of highly specified processes and tooling used for setting up a highly resilient quorum-based key management system. diff --git a/quorum-kms/src/hardware-destruction.md b/quorum-key-management-system/src/hardware-destruction.md similarity index 100% rename from quorum-kms/src/hardware-destruction.md rename to quorum-key-management-system/src/hardware-destruction.md diff --git a/quorum-kms/src/hardware-procurement.md b/quorum-key-management-system/src/hardware-procurement.md similarity index 98% rename from quorum-kms/src/hardware-procurement.md rename to quorum-key-management-system/src/hardware-procurement.md index 6d3fd44..7b42520 100644 --- a/quorum-kms/src/hardware-procurement.md +++ b/quorum-key-management-system/src/hardware-procurement.md @@ -8,7 +8,7 @@ kind of hardware supply chain compromise, has the same vulnerability present, or has the same type of hardware failure issue. Based on the decided upon [Quorum](selecting-quorum.md), the amount of equipment -required to set up a [QKMS](glossary.md#quorum-kms-qkms) will +required to set up a [QKMS](glossary.md#quorum-key-management-system-qkms) will vary. In order to figure out what equipment is required, decide on a Quorum, which is expressed as "N of M". Once you know your M, the required equipment list is the following: diff --git a/quorum-kms/src/hybrid-key-provisioning.md b/quorum-key-management-system/src/hybrid-key-provisioning.md similarity index 100% rename from quorum-kms/src/hybrid-key-provisioning.md rename to quorum-key-management-system/src/hybrid-key-provisioning.md diff --git a/quorum-kms/src/img/download-airgap-os.png b/quorum-key-management-system/src/img/download-airgap-os.png similarity index 100% rename from quorum-kms/src/img/download-airgap-os.png rename to quorum-key-management-system/src/img/download-airgap-os.png diff --git a/quorum-kms/src/initialize-pureboot-smart-card.md b/quorum-key-management-system/src/initialize-pureboot-smart-card.md similarity index 100% rename from quorum-kms/src/initialize-pureboot-smart-card.md rename to quorum-key-management-system/src/initialize-pureboot-smart-card.md diff --git a/quorum-kms/src/intro.md b/quorum-key-management-system/src/intro.md similarity index 91% rename from quorum-kms/src/intro.md rename to quorum-key-management-system/src/intro.md index 23fa137..8ac5d78 100644 --- a/quorum-kms/src/intro.md +++ b/quorum-key-management-system/src/intro.md @@ -1,8 +1,8 @@ # Introduction -Quorum-KMS (QKMS) is an open source system of playbooks and tooling which -facilitates the creation and maintenance of highly resilient Quorum-based -Key Management Systems based on a strict [threat model](threat-model.md) +Quorum Key Management System (QKMS) is an open source system of playbooks and +tooling which facilitates the creation and maintenance of highly resilient +Quorum-based Key Management Systems based on a strict [threat model](threat-model.md) which can be used for a variety of different cryptographic algorithms. The system was designed and developed by [Distrust](https://distrust.co), with the generous support of the following sponsors: TODO. diff --git a/quorum-kms/src/local-key-provisioning.md b/quorum-key-management-system/src/local-key-provisioning.md similarity index 100% rename from quorum-kms/src/local-key-provisioning.md rename to quorum-key-management-system/src/local-key-provisioning.md diff --git a/quorum-kms/src/location-key-provisioning.md b/quorum-key-management-system/src/location-key-provisioning.md similarity index 100% rename from quorum-kms/src/location-key-provisioning.md rename to quorum-key-management-system/src/location-key-provisioning.md diff --git a/quorum-kms/src/locations.md b/quorum-key-management-system/src/locations.md similarity index 100% rename from quorum-kms/src/locations.md rename to quorum-key-management-system/src/locations.md diff --git a/quorum-kms/src/one-time-repository-setup.md b/quorum-key-management-system/src/one-time-repository-setup.md similarity index 100% rename from quorum-kms/src/one-time-repository-setup.md rename to quorum-key-management-system/src/one-time-repository-setup.md diff --git a/quorum-kms/src/one-time-use-airgapos.md b/quorum-key-management-system/src/one-time-use-airgapos.md similarity index 100% rename from quorum-kms/src/one-time-use-airgapos.md rename to quorum-key-management-system/src/one-time-use-airgapos.md diff --git a/quorum-kms/src/one-time-use-hardware-procurement.md b/quorum-key-management-system/src/one-time-use-hardware-procurement.md similarity index 100% rename from quorum-kms/src/one-time-use-hardware-procurement.md rename to quorum-key-management-system/src/one-time-use-hardware-procurement.md diff --git a/quorum-kms/src/one-time-use-locations.md b/quorum-key-management-system/src/one-time-use-locations.md similarity index 100% rename from quorum-kms/src/one-time-use-locations.md rename to quorum-key-management-system/src/one-time-use-locations.md diff --git a/quorum-kms/src/operator-key-provisioning.md b/quorum-key-management-system/src/operator-key-provisioning.md similarity index 100% rename from quorum-kms/src/operator-key-provisioning.md rename to quorum-key-management-system/src/operator-key-provisioning.md diff --git a/quorum-kms/src/physical-artifact-storage.md b/quorum-key-management-system/src/physical-artifact-storage.md similarity index 100% rename from quorum-kms/src/physical-artifact-storage.md rename to quorum-key-management-system/src/physical-artifact-storage.md diff --git a/quorum-kms/src/provisioning-hardware-and-firmware.md b/quorum-key-management-system/src/provisioning-hardware-and-firmware.md similarity index 100% rename from quorum-kms/src/provisioning-hardware-and-firmware.md rename to quorum-key-management-system/src/provisioning-hardware-and-firmware.md diff --git a/quorum-kms/src/public-ceremony-artifact-storage.md b/quorum-key-management-system/src/public-ceremony-artifact-storage.md similarity index 100% rename from quorum-kms/src/public-ceremony-artifact-storage.md rename to quorum-key-management-system/src/public-ceremony-artifact-storage.md diff --git a/quorum-kms/src/quorum-team.md b/quorum-key-management-system/src/quorum-team.md similarity index 100% rename from quorum-kms/src/quorum-team.md rename to quorum-key-management-system/src/quorum-team.md diff --git a/quorum-kms/src/remote-key-provisioning.md b/quorum-key-management-system/src/remote-key-provisioning.md similarity index 100% rename from quorum-kms/src/remote-key-provisioning.md rename to quorum-key-management-system/src/remote-key-provisioning.md diff --git a/quorum-kms/src/repeat-use-airgapos.md b/quorum-key-management-system/src/repeat-use-airgapos.md similarity index 100% rename from quorum-kms/src/repeat-use-airgapos.md rename to quorum-key-management-system/src/repeat-use-airgapos.md diff --git a/quorum-kms/src/secure-boot-sequence.md b/quorum-key-management-system/src/secure-boot-sequence.md similarity index 100% rename from quorum-kms/src/secure-boot-sequence.md rename to quorum-key-management-system/src/secure-boot-sequence.md diff --git a/quorum-kms/src/selecting-quorum.md b/quorum-key-management-system/src/selecting-quorum.md similarity index 100% rename from quorum-kms/src/selecting-quorum.md rename to quorum-key-management-system/src/selecting-quorum.md diff --git a/quorum-kms/src/setting-smart-card-pins.md b/quorum-key-management-system/src/setting-smart-card-pins.md similarity index 100% rename from quorum-kms/src/setting-smart-card-pins.md rename to quorum-key-management-system/src/setting-smart-card-pins.md diff --git a/quorum-kms/src/software.md b/quorum-key-management-system/src/software.md similarity index 100% rename from quorum-kms/src/software.md rename to quorum-key-management-system/src/software.md diff --git a/quorum-kms/src/storage-device-management.md b/quorum-key-management-system/src/storage-device-management.md similarity index 100% rename from quorum-kms/src/storage-device-management.md rename to quorum-key-management-system/src/storage-device-management.md diff --git a/quorum-kms/src/threat-model.md b/quorum-key-management-system/src/threat-model.md similarity index 100% rename from quorum-kms/src/threat-model.md rename to quorum-key-management-system/src/threat-model.md From 8ce53c2b7b6a954d4ea983ba66cc0a2a6678d680 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 18:59:25 -0400 Subject: [PATCH 04/19] fix links --- quorum-key-management-system/src/SUMMARY.md | 2 +- quorum-key-management-system/src/glossary.md | 2 +- .../src/hardware-procurement.md | 86 ------------------- ...g-hardware-and-firmware.md => hardware.md} | 4 +- .../src/local-key-provisioning.md | 10 +-- .../src/location-key-provisioning.md | 2 +- .../src/operator-key-provisioning.md | 8 +- .../src/physical-artifact-storage.md | 2 +- 8 files changed, 15 insertions(+), 101 deletions(-) delete mode 100644 quorum-key-management-system/src/hardware-procurement.md rename quorum-key-management-system/src/{provisioning-hardware-and-firmware.md => hardware.md} (97%) diff --git a/quorum-key-management-system/src/SUMMARY.md b/quorum-key-management-system/src/SUMMARY.md index f6a9d0c..077a3cb 100644 --- a/quorum-key-management-system/src/SUMMARY.md +++ b/quorum-key-management-system/src/SUMMARY.md @@ -3,7 +3,7 @@ * [Threat Model](threat-model.md) * [Selecting a Quorum](selecting-quorum.md) * [Software](software.md) - * [Hardware](provisioning-hardware-and-firmware.md) + * [Hardware](hardware.md) * [Glossary](glossary.md) * [Preparations]() diff --git a/quorum-key-management-system/src/glossary.md b/quorum-key-management-system/src/glossary.md index bdf452f..5e1f70d 100644 --- a/quorum-key-management-system/src/glossary.md +++ b/quorum-key-management-system/src/glossary.md @@ -75,7 +75,7 @@ carefully planned, and executed accordingly. ## Location Key Is a asymmetric key pair which is used for encrypting shards which are used to -re-assemble the Root Entropy. Location Keys are stored in [Locations](location.md) +re-assemble the Root Entropy. Location Keys are stored in [Locations](locations.md) which adhere to a strict set of criteria to maximize their security. The location smart card passphrase is encrypted to a Operator Key in order to secure access to it. diff --git a/quorum-key-management-system/src/hardware-procurement.md b/quorum-key-management-system/src/hardware-procurement.md deleted file mode 100644 index 7b42520..0000000 --- a/quorum-key-management-system/src/hardware-procurement.md +++ /dev/null @@ -1,86 +0,0 @@ -# Equipment - -This page describes different equipment which is required, and makes opinionated -recommendations as well as alternatives. One may improve the overall security -of their system by using a variety of hardware in order to benefit from their -diversity, by reducing the likelihood that all hardware has suffered the same -kind of hardware supply chain compromise, has the same vulnerability present, or -has the same type of hardware failure issue. - -Based on the decided upon [Quorum](selecting-quorum.md), the amount of equipment -required to set up a [QKMS](glossary.md#quorum-key-management-system-qkms) will -vary. In order to figure out what equipment is required, decide on a Quorum, -which is expressed as "N of M". Once you know your M, the required equipment list -is the following: - -* M x 4 Smart Cards - - * It is recommended to use two Smart Cards for storing each key pair - - * Ideally two different types of hardware are used in order to reduce the - risk of simultaneous failure - - * At least 1 Smart Card is required for each Operator Key and 1 Smart Card - for each Location Key - - * The number of Operator Keys is M, and the number of Location Keys is also - M, hence the minimum of 2 x M Smart Cards, with the recommendation of using - two smart cards for each, resulting in 4 x M Smart Cards - -* 2 + X Storage Devices - - * 1 Storage Device for [AirgapOS](repeat-use-airgapos.md) - - * 1 Storage Device for storing [Public Ceremony Artifacts](public-ceremony-artifact-storage) - - * X, or *any* number of additional Storage Devices to duplicate the data, a - good measure would be to have at least 3 Storage Devices for the ceremony - -* Librem 14 Laptop - - * Get as many laptops as desired to satisfy your operational needs - - * For each Librem 14, get a Librem Smart Card used for [PureBoot](initialize-pureboot-smart-card.md) - -## Smart Cards -Smart Cards are primarily used for storing OpenPGP cryptographic keys which are -used as a building block for security controls. These smart cards hold OpenPGP -keys which are derived in secure environments. FIPS 140-2 is required but the -end user may choose their manufacturer. - -* NitroKey 3 - because of its open source approach which helps improve the -overall security of the products -* YubiKey 5 - because of the widespread use and battle-tested reliability -* Librem Key - because of the manufacturer's approach to hardware supply chain -security and verifiable software - -## Air-Gapped Computer -[Air-Gapped](glossary.md#Air-Gapped) computers are used for the lifecycle management -of cryptographic material that is part of the QKMS. - -The primary hardware recommendation for a Air-Gapped Cmputer is the [Librem 14](https://puri.sm/products/librem-14/), manufactured by [Purism](puri.sm). Purism specializes in reducing hardware and -firmware security risks, especially via their [Anti-Interdiction Service](https://puri.sm/posts/anti-interdiction-services/) and [PureBoot](https://docs.puri.sm/PureBoot.html) -and as such is an excellent choice for hardware which high integrity assurance is -required for. - -#### Alternative - -An alternative approach is to use an off-the-shelf computer that is randomly -selected right before the ceremony, removing the radio cards from it, using it -to conduct a Ceremony, and then destroying the laptop using sufficiently -adequate method to ensure that no data forensics can be used to recover the data -from the drive, or memory. This can be achieved by using a combination of -incineration, degaussing, shredding and drilling. Special care should be taken -to completely destroy all components of the computer that are able to store data, -even if it's only in ephemeral form as some forensic methods all extraction of -data from components with "temporary memory". - -Three letter agencies are known to collect and exploit physical destroyed drives, -as data can still be extracted from them using methods such as electron -microscopy, therefore a combination of degaussing, shredding and burning should -be used, and the remaining debris should be spread out across multiple disposal -locations. - -## Storage Device -Can be an SD Card or USB Drive but should be procured from a vendor with -a good reputation, and ideally hardware of industrial grade should be prioritized. diff --git a/quorum-key-management-system/src/provisioning-hardware-and-firmware.md b/quorum-key-management-system/src/hardware.md similarity index 97% rename from quorum-key-management-system/src/provisioning-hardware-and-firmware.md rename to quorum-key-management-system/src/hardware.md index 10b8702..8fbaa7d 100644 --- a/quorum-key-management-system/src/provisioning-hardware-and-firmware.md +++ b/quorum-key-management-system/src/hardware.md @@ -1,4 +1,4 @@ -# Provisioning Hardware and Firmware +# Hardware This page describes different equipment which is required, and makes opinionated recommendations as well as alternatives. One may improve the overall security @@ -31,7 +31,7 @@ is the following: * 1 Storage Device for [AirgapOS](repeat-use-airgapos.md) - * 1 Storage Device for storing [Public Ceremony Artifacts](public-ceremony-artifact-storage) + * 1 Storage Device for storing [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) * X, or *any* number of additional Storage Devices to duplicate the data, a good measure would be to have at least 3 Storage Devices for the ceremony diff --git a/quorum-key-management-system/src/local-key-provisioning.md b/quorum-key-management-system/src/local-key-provisioning.md index d45ee59..911f6ae 100644 --- a/quorum-key-management-system/src/local-key-provisioning.md +++ b/quorum-key-management-system/src/local-key-provisioning.md @@ -3,23 +3,23 @@ This document contains instructions on how Operators collaborate to set up QKMS which requires an N-of-M quorum to be reconstituted. The encrypted shards which result from this ceremony are stored in separate physical -[Locations](location.md) which contain [Location Keys](glossary.md#location-key) +[Locations](locations.md) which contain [Location Keys](glossary.md#location-key) to which shards are encrypted, and whose passphrases are protected using [Operator Keys](glossary#operator-key). ### Requirements -* [Smart Card](hardware-procurement.md#smart-cards): whatever number of smart +* [Smart Card](hardware.md#smart-cards): whatever number of smart cards you would like to have seeded for each Operator, usually 2 per Operator is recommended - one NitroKey 3 and 1 YubiKey Series 5. -* [Storage Devices](hardware-procurement.md#storage-device): as many storage +* [Storage Devices](hardware.md#storage-device): as many storage devices as you would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) * Storage Device loaded with * [airgap.iso](repeat-use-airgapos.md) - * [airgap.iso.asc](airgap-setup.md) + * [airgap.iso.asc](repeat-use-airgapos.md) * [autorun.sh](autorun-sh-setup.md) * All participants need Ceremony Notes which contain a record of which they @@ -30,7 +30,7 @@ verified and wrote down themselves: ### Steps 1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the -established [Location](location.md) +established [Location](locations.md) 2. Ensure that no participants have brought digital devices other than ones necessary for the ceremony. A faraday bag may be used to hold any such devices diff --git a/quorum-key-management-system/src/location-key-provisioning.md b/quorum-key-management-system/src/location-key-provisioning.md index 0b44cfd..0731fe8 100644 --- a/quorum-key-management-system/src/location-key-provisioning.md +++ b/quorum-key-management-system/src/location-key-provisioning.md @@ -18,7 +18,7 @@ would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-s ## Steps 1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the -established [Location](location.md) +established [Location](locations.md) 2. Boot your Ceremony Machine using [Secure Boot Sequence](secure-boot-sequence.md) or the [One Time Use Airgap-OS](one-time-use-airgapos.md) diff --git a/quorum-key-management-system/src/operator-key-provisioning.md b/quorum-key-management-system/src/operator-key-provisioning.md index f6e8ed9..bacc63c 100644 --- a/quorum-key-management-system/src/operator-key-provisioning.md +++ b/quorum-key-management-system/src/operator-key-provisioning.md @@ -12,7 +12,7 @@ the ceremony is a set of the following for each Operator: for each Operator, usually 2 per Operator is recommended - one NitroKey 3 and 1 YubiKey Series 5. -* [Storage Devices](equipment.md#storage-device): as many storage devices as you +* [Storage Devices](hardware.md#storage-device): as many storage devices as you would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) ## Playbook @@ -21,8 +21,8 @@ would like for backing up [Public Ceremony Artifacts](public-ceremony-artifact-s This playbook allows the setup of any number of Operator Keys. For each Operator, the steps that follow need to be repeated. -1. Bring the Ceremony Machine and [Quorum Team](quorum-team.md) into the -established [Location](location.md) +1. Bring the Ceremony Machine and [Quorum](selecting-quorum.md) team into the +established [Location](locations.md) 2. Boot your Ceremony Machine using [Secure Boot Sequence](secure-boot-sequence.md) @@ -38,7 +38,7 @@ from Step 3 as desired. 7. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide for storage of the Operator Smart Cards and Location Smart Cards -8. Follow the [Public Ceremony Artifacts Storage](public-ceremony-artifact-storage.md) +8. Follow the [Online Artifacts Storage](public-ceremony-artifact-storage.md) guide for all public artifacts produced during the ceremony diff --git a/quorum-key-management-system/src/physical-artifact-storage.md b/quorum-key-management-system/src/physical-artifact-storage.md index db74742..5168886 100644 --- a/quorum-key-management-system/src/physical-artifact-storage.md +++ b/quorum-key-management-system/src/physical-artifact-storage.md @@ -21,7 +21,7 @@ private vaulting provider. ## Location Smart Cards These cards should only be stored in secure vaults which meet the criteria -outliened for Storage Locations in the [Location](location.md) document. +outliened for Storage Locations in the [Location](locations.md) document. ## Additional Criteria From a81363443270988b5304052a5c4d6f7560c2e91e Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 19:02:38 -0400 Subject: [PATCH 05/19] fix: rename to Quorum Key Management (QKM) --- .../.gitignore | 0 .../README.md | 4 ++-- .../book.toml | 2 +- .../src/SUMMARY.md | 0 .../src/autorun-sh-setup.md | 0 .../src/ceremony-log-template.md | 0 .../src/core-key-ceremonies.md | 0 .../src/enable-pure-boot-restricted-boot.md | 0 .../src/flash-pureboot-firmware.md | 0 .../src/flashing-iso.md | 0 .../src/glossary.md | 6 +++--- .../src/hardware-destruction.md | 0 .../src/hardware.md | 4 ++-- .../src/hybrid-key-provisioning.md | 2 +- .../src/img/download-airgap-os.png | Bin .../src/initialize-pureboot-smart-card.md | 0 .../src/intro.md | 8 ++++---- .../src/local-key-provisioning.md | 2 +- .../src/location-key-provisioning.md | 2 +- .../src/locations.md | 0 .../src/one-time-repository-setup.md | 0 .../src/one-time-use-airgapos.md | 0 .../src/one-time-use-hardware-procurement.md | 0 .../src/one-time-use-locations.md | 0 .../src/operator-key-provisioning.md | 0 .../src/physical-artifact-storage.md | 2 +- .../src/public-ceremony-artifact-storage.md | 2 +- .../src/quorum-team.md | 4 ++-- .../src/remote-key-provisioning.md | 0 .../src/repeat-use-airgapos.md | 0 .../src/secure-boot-sequence.md | 0 .../src/selecting-quorum.md | 0 .../src/setting-smart-card-pins.md | 0 .../src/software.md | 4 ++-- .../src/storage-device-management.md | 0 .../src/threat-model.md | 6 +++--- 36 files changed, 24 insertions(+), 24 deletions(-) rename {quorum-key-management-system => quorum-key-management}/.gitignore (100%) rename {quorum-key-management-system => quorum-key-management}/README.md (70%) rename {quorum-key-management-system => quorum-key-management}/book.toml (71%) rename {quorum-key-management-system => quorum-key-management}/src/SUMMARY.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/autorun-sh-setup.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/ceremony-log-template.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/core-key-ceremonies.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/enable-pure-boot-restricted-boot.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/flash-pureboot-firmware.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/flashing-iso.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/glossary.md (96%) rename {quorum-key-management-system => quorum-key-management}/src/hardware-destruction.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/hardware.md (96%) rename {quorum-key-management-system => quorum-key-management}/src/hybrid-key-provisioning.md (97%) rename {quorum-key-management-system => quorum-key-management}/src/img/download-airgap-os.png (100%) rename {quorum-key-management-system => quorum-key-management}/src/initialize-pureboot-smart-card.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/intro.md (89%) rename {quorum-key-management-system => quorum-key-management}/src/local-key-provisioning.md (96%) rename {quorum-key-management-system => quorum-key-management}/src/location-key-provisioning.md (96%) rename {quorum-key-management-system => quorum-key-management}/src/locations.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/one-time-repository-setup.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/one-time-use-airgapos.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/one-time-use-hardware-procurement.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/one-time-use-locations.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/operator-key-provisioning.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/physical-artifact-storage.md (94%) rename {quorum-key-management-system => quorum-key-management}/src/public-ceremony-artifact-storage.md (95%) rename {quorum-key-management-system => quorum-key-management}/src/quorum-team.md (89%) rename {quorum-key-management-system => quorum-key-management}/src/remote-key-provisioning.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/repeat-use-airgapos.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/secure-boot-sequence.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/selecting-quorum.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/setting-smart-card-pins.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/software.md (92%) rename {quorum-key-management-system => quorum-key-management}/src/storage-device-management.md (100%) rename {quorum-key-management-system => quorum-key-management}/src/threat-model.md (94%) diff --git a/quorum-key-management-system/.gitignore b/quorum-key-management/.gitignore similarity index 100% rename from quorum-key-management-system/.gitignore rename to quorum-key-management/.gitignore diff --git a/quorum-key-management-system/README.md b/quorum-key-management/README.md similarity index 70% rename from quorum-key-management-system/README.md rename to quorum-key-management/README.md index abb2b05..700b397 100644 --- a/quorum-key-management-system/README.md +++ b/quorum-key-management/README.md @@ -1,6 +1,6 @@ -# Quorum Key Management System (QKMS) +# Quorum Key Management (QKM) -Quorum Key Management System (QKMS) is an open source system of playbooks and tooling which +Quorum Key Management (QKM) is an open source system of playbooks and tooling which facilitates the creation and maintenance of highly resilient Quorum-based Key Management Systems based on a strict threat model which can be used for a variety of different cryptographic algorithms. diff --git a/quorum-key-management-system/book.toml b/quorum-key-management/book.toml similarity index 71% rename from quorum-key-management-system/book.toml rename to quorum-key-management/book.toml index 35d8a9e..118e4ea 100644 --- a/quorum-key-management-system/book.toml +++ b/quorum-key-management/book.toml @@ -3,4 +3,4 @@ authors = ["Anton Livaja", "Lance R. Vick", "Ryan Heywood"] language = "en" multilingual = false src = "src" -title = "Quorum Key Management System (QKMS)" +title = "Quorum Key Management (QKM)" diff --git a/quorum-key-management-system/src/SUMMARY.md b/quorum-key-management/src/SUMMARY.md similarity index 100% rename from quorum-key-management-system/src/SUMMARY.md rename to quorum-key-management/src/SUMMARY.md diff --git a/quorum-key-management-system/src/autorun-sh-setup.md b/quorum-key-management/src/autorun-sh-setup.md similarity index 100% rename from quorum-key-management-system/src/autorun-sh-setup.md rename to quorum-key-management/src/autorun-sh-setup.md diff --git a/quorum-key-management-system/src/ceremony-log-template.md b/quorum-key-management/src/ceremony-log-template.md similarity index 100% rename from quorum-key-management-system/src/ceremony-log-template.md rename to quorum-key-management/src/ceremony-log-template.md diff --git a/quorum-key-management-system/src/core-key-ceremonies.md b/quorum-key-management/src/core-key-ceremonies.md similarity index 100% rename from quorum-key-management-system/src/core-key-ceremonies.md rename to quorum-key-management/src/core-key-ceremonies.md diff --git a/quorum-key-management-system/src/enable-pure-boot-restricted-boot.md b/quorum-key-management/src/enable-pure-boot-restricted-boot.md similarity index 100% rename from quorum-key-management-system/src/enable-pure-boot-restricted-boot.md rename to quorum-key-management/src/enable-pure-boot-restricted-boot.md diff --git a/quorum-key-management-system/src/flash-pureboot-firmware.md b/quorum-key-management/src/flash-pureboot-firmware.md similarity index 100% rename from quorum-key-management-system/src/flash-pureboot-firmware.md rename to quorum-key-management/src/flash-pureboot-firmware.md diff --git a/quorum-key-management-system/src/flashing-iso.md b/quorum-key-management/src/flashing-iso.md similarity index 100% rename from quorum-key-management-system/src/flashing-iso.md rename to quorum-key-management/src/flashing-iso.md diff --git a/quorum-key-management-system/src/glossary.md b/quorum-key-management/src/glossary.md similarity index 96% rename from quorum-key-management-system/src/glossary.md rename to quorum-key-management/src/glossary.md index 5e1f70d..5696524 100644 --- a/quorum-key-management-system/src/glossary.md +++ b/quorum-key-management/src/glossary.md @@ -4,14 +4,14 @@ In cryptography, ciphertext is the result of encryption performed on plaintext using an algorithm, called a cipher. -## Quorum Key Management System (QKMS) +## Quorum Key Management (QKM) A set of highly specified processes and tooling used for setting up a highly resilient quorum-based key management system. ## Operator An individual who manages an [Operator Key](#operator-key) which is used for protecting the passphrase of a Location key and participates in different -aspects of the lifecycle management of the QKMS system. +aspects of the lifecycle management of the QKM system. ## Operator Key An asymmetric key used for protecting the passphrase of a Location key @@ -85,7 +85,7 @@ M is the minimum number of shards required to reassemble the secret, and N is th total number of shards that exist. The minimum recommended threshold is 2-of-3. ## Organization -An organization which owns the QKMS and is responsible for funding the setup and +An organization which owns the QKM and is responsible for funding the setup and maintenance. The organization is also responsible for ensuring that the [Warehouse](#warehouse) is properly maintained in order to ensure that the ciphertext blobs associated with the system are redundantly stored and diff --git a/quorum-key-management-system/src/hardware-destruction.md b/quorum-key-management/src/hardware-destruction.md similarity index 100% rename from quorum-key-management-system/src/hardware-destruction.md rename to quorum-key-management/src/hardware-destruction.md diff --git a/quorum-key-management-system/src/hardware.md b/quorum-key-management/src/hardware.md similarity index 96% rename from quorum-key-management-system/src/hardware.md rename to quorum-key-management/src/hardware.md index 8fbaa7d..990bf92 100644 --- a/quorum-key-management-system/src/hardware.md +++ b/quorum-key-management/src/hardware.md @@ -8,7 +8,7 @@ kind of hardware supply chain compromise, has the same vulnerability present, or has the same type of hardware failure issue. Based on the decided upon [Quorum](selecting-quorum.md), the amount of equipment -required to set up a [QKMS](glossary.md#quroum-kms-qkms) will +required to set up a [QKM](glossary.md#quroum-kms-QKM) will vary. In order to figure out what equipment is required, decide on a Quorum, which is expressed as "N of M". Once you know your M, the required equipment list is the following: @@ -57,7 +57,7 @@ security and verifiable software ## Air-Gapped Computer [Air-Gapped](glossary.md#Air-Gapped) computers are used for the lifecycle management -of cryptographic material that is part of QKMS. +of cryptographic material that is part of QKM. The primary hardware recommendation for a Air-Gapped Computer is the [Librem 14](https://puri.sm/products/librem-14/), manufactured by [Purism](puri.sm). Purism specializes in reducing hardware and firmware security risks, especially via their [Anti-Interdiction Service](https://puri.sm/posts/anti-interdiction-services/) and [PureBoot](https://docs.puri.sm/PureBoot.html) diff --git a/quorum-key-management-system/src/hybrid-key-provisioning.md b/quorum-key-management/src/hybrid-key-provisioning.md similarity index 97% rename from quorum-key-management-system/src/hybrid-key-provisioning.md rename to quorum-key-management/src/hybrid-key-provisioning.md index 4a3a2d3..b6df96c 100644 --- a/quorum-key-management-system/src/hybrid-key-provisioning.md +++ b/quorum-key-management/src/hybrid-key-provisioning.md @@ -1,7 +1,7 @@ # Hybrid Key Provisioning This document contains instructions on how Operators collaborate to set up -QKMS where the Operator Keys and Location Keys were generated before this +QKM where the Operator Keys and Location Keys were generated before this ceremony and only the PGP Public Certificates of the Location keys are brought to the ceremony which are used to shard the Root Entropy. This is useful when conducting the ceremony in a lower trust environment, and where not all diff --git a/quorum-key-management-system/src/img/download-airgap-os.png b/quorum-key-management/src/img/download-airgap-os.png similarity index 100% rename from quorum-key-management-system/src/img/download-airgap-os.png rename to quorum-key-management/src/img/download-airgap-os.png diff --git a/quorum-key-management-system/src/initialize-pureboot-smart-card.md b/quorum-key-management/src/initialize-pureboot-smart-card.md similarity index 100% rename from quorum-key-management-system/src/initialize-pureboot-smart-card.md rename to quorum-key-management/src/initialize-pureboot-smart-card.md diff --git a/quorum-key-management-system/src/intro.md b/quorum-key-management/src/intro.md similarity index 89% rename from quorum-key-management-system/src/intro.md rename to quorum-key-management/src/intro.md index 8ac5d78..c9d318e 100644 --- a/quorum-key-management-system/src/intro.md +++ b/quorum-key-management/src/intro.md @@ -1,13 +1,13 @@ # Introduction -Quorum Key Management System (QKMS) is an open source system of playbooks and +Quorum Key Management (QKM) is an open source system of playbooks and tooling which facilitates the creation and maintenance of highly resilient Quorum-based Key Management Systems based on a strict [threat model](threat-model.md) which can be used for a variety of different cryptographic algorithms. The system was designed and developed by [Distrust](https://distrust.co), with the generous support of the following sponsors: TODO. -The basic premise of QKMS is that primary cryptographic material akin to a root +The basic premise of QKM is that primary cryptographic material akin to a root certificate, called Root Entropy, is derived during a secure key derivation ceremony, and then used to derive chosen cryptographic material via different algorithms such as PGP keys, digital asset wallets, web certificates and more. @@ -21,7 +21,7 @@ secret material, namely the Root Entropy. ## Use Cases -QKMS can be used for a wide range of use-cases which span but are not limited +QKM can be used for a wide range of use-cases which span but are not limited to: * Deriving a PGP key pair whose public key can be used as a "one-way deposit @@ -40,7 +40,7 @@ a cold signing setup. ## Playbooks -QKMS can be set up by using a set of highly opinionated playbooks which outline +QKM can be set up by using a set of highly opinionated playbooks which outline the process. The documentation should be read in its entirety by all participants in the ceremony in order to ensure that the system is well understood by all in order to ensure that the integrity of the process is diff --git a/quorum-key-management-system/src/local-key-provisioning.md b/quorum-key-management/src/local-key-provisioning.md similarity index 96% rename from quorum-key-management-system/src/local-key-provisioning.md rename to quorum-key-management/src/local-key-provisioning.md index 911f6ae..9c531f2 100644 --- a/quorum-key-management-system/src/local-key-provisioning.md +++ b/quorum-key-management/src/local-key-provisioning.md @@ -1,7 +1,7 @@ # Local Key Provisioning This document contains instructions on how Operators collaborate to set up -QKMS which requires an N-of-M quorum to be reconstituted. The encrypted shards +QKM which requires an N-of-M quorum to be reconstituted. The encrypted shards which result from this ceremony are stored in separate physical [Locations](locations.md) which contain [Location Keys](glossary.md#location-key) to which shards are encrypted, and whose passphrases are protected using diff --git a/quorum-key-management-system/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md similarity index 96% rename from quorum-key-management-system/src/location-key-provisioning.md rename to quorum-key-management/src/location-key-provisioning.md index 0731fe8..73bc126 100644 --- a/quorum-key-management-system/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -3,7 +3,7 @@ ## Description This ceremony is for generating Location Keys. Location Keys are typically stored in vaults as prescribed in the [Secure Storage Guidelines](secure-storage-guidelines.md). -Location Keys are keypairs to which the Root Entropy of a QKMS is sharded. The +Location Keys are keypairs to which the Root Entropy of a QKM is sharded. The keypairs are stored exclusively on Smart Cards, and the PINs which protect the Smart Cards are encrypted to Operator Keys. diff --git a/quorum-key-management-system/src/locations.md b/quorum-key-management/src/locations.md similarity index 100% rename from quorum-key-management-system/src/locations.md rename to quorum-key-management/src/locations.md diff --git a/quorum-key-management-system/src/one-time-repository-setup.md b/quorum-key-management/src/one-time-repository-setup.md similarity index 100% rename from quorum-key-management-system/src/one-time-repository-setup.md rename to quorum-key-management/src/one-time-repository-setup.md diff --git a/quorum-key-management-system/src/one-time-use-airgapos.md b/quorum-key-management/src/one-time-use-airgapos.md similarity index 100% rename from quorum-key-management-system/src/one-time-use-airgapos.md rename to quorum-key-management/src/one-time-use-airgapos.md diff --git a/quorum-key-management-system/src/one-time-use-hardware-procurement.md b/quorum-key-management/src/one-time-use-hardware-procurement.md similarity index 100% rename from quorum-key-management-system/src/one-time-use-hardware-procurement.md rename to quorum-key-management/src/one-time-use-hardware-procurement.md diff --git a/quorum-key-management-system/src/one-time-use-locations.md b/quorum-key-management/src/one-time-use-locations.md similarity index 100% rename from quorum-key-management-system/src/one-time-use-locations.md rename to quorum-key-management/src/one-time-use-locations.md diff --git a/quorum-key-management-system/src/operator-key-provisioning.md b/quorum-key-management/src/operator-key-provisioning.md similarity index 100% rename from quorum-key-management-system/src/operator-key-provisioning.md rename to quorum-key-management/src/operator-key-provisioning.md diff --git a/quorum-key-management-system/src/physical-artifact-storage.md b/quorum-key-management/src/physical-artifact-storage.md similarity index 94% rename from quorum-key-management-system/src/physical-artifact-storage.md rename to quorum-key-management/src/physical-artifact-storage.md index 5168886..78ee34a 100644 --- a/quorum-key-management-system/src/physical-artifact-storage.md +++ b/quorum-key-management/src/physical-artifact-storage.md @@ -1,6 +1,6 @@ # Physical Artifact Storage -QKMS requires that some of the hardware containing cryptographic material be +QKM requires that some of the hardware containing cryptographic material be securely stored in physical locations. The two primary cases where physical storage is necessary are the storage of Location Key Smart Cards, and Operator Key Smart Cards. These Smart Cards are necessary to successfully execute a diff --git a/quorum-key-management-system/src/public-ceremony-artifact-storage.md b/quorum-key-management/src/public-ceremony-artifact-storage.md similarity index 95% rename from quorum-key-management-system/src/public-ceremony-artifact-storage.md rename to quorum-key-management/src/public-ceremony-artifact-storage.md index 78c19ae..8333d19 100644 --- a/quorum-key-management-system/src/public-ceremony-artifact-storage.md +++ b/quorum-key-management/src/public-ceremony-artifact-storage.md @@ -1,7 +1,7 @@ # Redundant Storage of Ceremony Artifacts Ceremony Artifacts consist of data which is not sensitive in nature, but -essential to ongoing operation of a QKMS. +essential to ongoing operation of a QKM. The primary artifacts which are produced during the ceremony are: diff --git a/quorum-key-management-system/src/quorum-team.md b/quorum-key-management/src/quorum-team.md similarity index 89% rename from quorum-key-management-system/src/quorum-team.md rename to quorum-key-management/src/quorum-team.md index cd24e2f..e903fa1 100644 --- a/quorum-key-management-system/src/quorum-team.md +++ b/quorum-key-management/src/quorum-team.md @@ -1,7 +1,7 @@ # Quorum Team The Quorum Team is a team of individuals who are selected to perform different -roles related to a QKMS. Some of the Quorum Team members have ongoing roles, +roles related to a QKM. Some of the Quorum Team members have ongoing roles, while others may participate in a partial manner. Depending on the type of actions performed, some or all of the members of the @@ -28,7 +28,7 @@ Controllers may be used to protect access to physical locations - according to risk appetite. ## Witness -Witnesses are individuals who are familiar with the QKMS specification, and can +Witnesses are individuals who are familiar with the QKM specification, and can ensure that the different aspects of the system are set up correctly, and processes carried out as they should be. The main objective of the witnesses is to monitor and attest that processes such as the ceremonies are done according diff --git a/quorum-key-management-system/src/remote-key-provisioning.md b/quorum-key-management/src/remote-key-provisioning.md similarity index 100% rename from quorum-key-management-system/src/remote-key-provisioning.md rename to quorum-key-management/src/remote-key-provisioning.md diff --git a/quorum-key-management-system/src/repeat-use-airgapos.md b/quorum-key-management/src/repeat-use-airgapos.md similarity index 100% rename from quorum-key-management-system/src/repeat-use-airgapos.md rename to quorum-key-management/src/repeat-use-airgapos.md diff --git a/quorum-key-management-system/src/secure-boot-sequence.md b/quorum-key-management/src/secure-boot-sequence.md similarity index 100% rename from quorum-key-management-system/src/secure-boot-sequence.md rename to quorum-key-management/src/secure-boot-sequence.md diff --git a/quorum-key-management-system/src/selecting-quorum.md b/quorum-key-management/src/selecting-quorum.md similarity index 100% rename from quorum-key-management-system/src/selecting-quorum.md rename to quorum-key-management/src/selecting-quorum.md diff --git a/quorum-key-management-system/src/setting-smart-card-pins.md b/quorum-key-management/src/setting-smart-card-pins.md similarity index 100% rename from quorum-key-management-system/src/setting-smart-card-pins.md rename to quorum-key-management/src/setting-smart-card-pins.md diff --git a/quorum-key-management-system/src/software.md b/quorum-key-management/src/software.md similarity index 92% rename from quorum-key-management-system/src/software.md rename to quorum-key-management/src/software.md index a994af7..4d005e8 100644 --- a/quorum-key-management-system/src/software.md +++ b/quorum-key-management/src/software.md @@ -1,5 +1,5 @@ # Software -This page outlines the software used for setting up a QKMS. All software used in +This page outlines the software used for setting up a QKM. All software used in the setup is open source and audited by security firms in order to ensure their security. Furthermore, all software is built in a deterministic manner and reproduced by multiple individuals on diverse hardware to minimize the risks @@ -33,6 +33,6 @@ BIP-0039 mnemonic phrase. BIP-0039 phrases are used to calculate a BIP-0032 seed, which is used for hierarchical deterministic key derivation. This software is the backbone for all cryptographic actions performed as part -of QKMS. It was developed by [Distrust](https://distrust.co) and is included +of QKM. It was developed by [Distrust](https://distrust.co) and is included with AirgapOS and has been audited by two firms, NCC and Cure53 with no significant vulnerabilities found. diff --git a/quorum-key-management-system/src/storage-device-management.md b/quorum-key-management/src/storage-device-management.md similarity index 100% rename from quorum-key-management-system/src/storage-device-management.md rename to quorum-key-management/src/storage-device-management.md diff --git a/quorum-key-management-system/src/threat-model.md b/quorum-key-management/src/threat-model.md similarity index 94% rename from quorum-key-management-system/src/threat-model.md rename to quorum-key-management/src/threat-model.md index 0ce386e..f24cce5 100644 --- a/quorum-key-management-system/src/threat-model.md +++ b/quorum-key-management/src/threat-model.md @@ -1,10 +1,10 @@ # Threat Model -QKMS is designed according to a high-assurance threat model which ers on the +QKM is designed according to a high-assurance threat model which ers on the side of making exaggerated, rather than conservative assumptions in order to build a resilient system. -The assumption is made that attackers who target QKMS are extremely +The assumption is made that attackers who target QKM are extremely sophisticated, well funded and patient attackers, and as such, the full arsenal of attacks is on the table. This means that the attacker can purchase and weaponize multiple 0day vulnerabilities, execute physical attacks or deploy @@ -18,7 +18,7 @@ whether it's maintainers of software used in the system, the firmware that's used, or the individuals or locations that hold secret material which is the backbone of the system. -To achieve this, the QKMS focuses on reducing the risk by: +To achieve this, the QKM focuses on reducing the risk by: * Only using fully open source software and firmware to allow full verification of their security From 18cbd8ff696b1adaf3b9019aa5c0eb5c7546cc2d Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 19:07:55 -0400 Subject: [PATCH 06/19] fix: minor cleanup of root-entropy-ceremonies file --- quorum-key-management/src/SUMMARY.md | 2 +- quorum-key-management/src/autorun-sh-setup.md | 7 ++++--- quorum-key-management/src/glossary.md | 4 ++-- .../{core-key-ceremonies.md => root-entropy-ceremonies.md} | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) rename quorum-key-management/src/{core-key-ceremonies.md => root-entropy-ceremonies.md} (78%) diff --git a/quorum-key-management/src/SUMMARY.md b/quorum-key-management/src/SUMMARY.md index 077a3cb..6442cbd 100644 --- a/quorum-key-management/src/SUMMARY.md +++ b/quorum-key-management/src/SUMMARY.md @@ -25,7 +25,7 @@ * [Key Ceremonies]() * [Ceremony Log Template](ceremony-log-template.md) - * [Root Entropy Ceremonies](core-key-ceremonies.md) + * [Root Entropy Ceremonies](root-entropy-ceremonies.md) * [Local Key Provisioning](local-key-provisioning.md) * [Hybrid Key Provisioning](hybrid-key-provisioning.md) * [Remote Key Provisioning](remote-key-provisioning.md) diff --git a/quorum-key-management/src/autorun-sh-setup.md b/quorum-key-management/src/autorun-sh-setup.md index 80e6716..0b15356 100644 --- a/quorum-key-management/src/autorun-sh-setup.md +++ b/quorum-key-management/src/autorun-sh-setup.md @@ -12,7 +12,8 @@ This setup can be done on any machine. * In your Terminal use this command: `vi autorun.sh` * Once you are in the editor press "i" to enter "insert mode" - * Type in the contents, replacing and with your chosen threshold numbers according to your [Quorum](selecting-quorum.md): + * Type in the contents, replacing and with your chosen threshold + numbers according to your [Quorum](selecting-quorum.md): ```sh #!/bin/sh keyfork wizard generate-shard-secret --threshold --max --output shards.pgp @@ -39,5 +40,5 @@ to do so. c. Copy the `autorun.sh` file to the Storage Device -4. Make note of this hash on a piece of paper or print it as you will need it -to verify the file during Ceremonies. \ No newline at end of file +4. Make note of this hash on a piece of paper or print it as you will need it to +verify the file during Ceremonies. \ No newline at end of file diff --git a/quorum-key-management/src/glossary.md b/quorum-key-management/src/glossary.md index 5696524..7dfff83 100644 --- a/quorum-key-management/src/glossary.md +++ b/quorum-key-management/src/glossary.md @@ -32,8 +32,8 @@ How many members of the Quorum can meet an untimely demise without irretrievably locking access to the Distrust Quroum system. ## Root Entropy (RE) -The root cryptographic material which is used for hierarchical deterministic -key derivation of a variety of cryptographic algorithms. +The main entropy/randomness which is used for hierarchical deterministic key +derivation of a variety of cryptographic algorithms. ## Shard Crytpographic shard created using Shamir's Secret Sharing algorithm. diff --git a/quorum-key-management/src/core-key-ceremonies.md b/quorum-key-management/src/root-entropy-ceremonies.md similarity index 78% rename from quorum-key-management/src/core-key-ceremonies.md rename to quorum-key-management/src/root-entropy-ceremonies.md index 81f5efb..cae7c7c 100644 --- a/quorum-key-management/src/core-key-ceremonies.md +++ b/quorum-key-management/src/root-entropy-ceremonies.md @@ -1,7 +1,7 @@ # Root Entropy Ceremonies -There are 3 primary types of key derivation ceremonies: - +There are 3 primary types of [Root Entropy](glossary.md#root-entropy-re) +derivation ceremonies: * "Local": where all cryptographic material, including the Operator Keys, Location Keys, and the Root Entropy are all generated during a single in-person @@ -11,4 +11,4 @@ ceremony prior to the in-person ceremony where the Root Entropy is generated * "Remote": where all cryptographic material is generated in a decentralized -manner, remotely. \ No newline at end of file +manner, remotely. From 25516fcd7fe1ca9e81094388e72a6749164b2f24 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sun, 4 Aug 2024 14:31:08 -0400 Subject: [PATCH 07/19] fix: specify smart cards must have openpgp ed25519 support --- quorum-key-management/src/hardware.md | 15 +++++++++++++-- quorum-key-management/src/locations.md | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/quorum-key-management/src/hardware.md b/quorum-key-management/src/hardware.md index 990bf92..4c8dc5c 100644 --- a/quorum-key-management/src/hardware.md +++ b/quorum-key-management/src/hardware.md @@ -46,12 +46,23 @@ is the following: Smart Cards are primarily used for storing OpenPGP cryptographic keys which are used as a building block for security controls. These smart cards hold OpenPGP -keys which are derived in secure environments. FIPS 140-2 is required but the -end user may choose their manufacturer. +keys which are derived in secure environments. + +There are two primary requirements for smart cards: + +* FIPS 140-2 + +* Support for Ed25519 OpenPGP + +* Touch for enacting operations + +Some options include: * NitroKey 3 - because of its open source approach which helps improve the overall security of the products + * YubiKey 5 - because of the widespread use and battle-tested reliability + * Librem Key - because of the manufacturer's approach to hardware supply chain security and verifiable software diff --git a/quorum-key-management/src/locations.md b/quorum-key-management/src/locations.md index ba584a9..77dc795 100644 --- a/quorum-key-management/src/locations.md +++ b/quorum-key-management/src/locations.md @@ -50,7 +50,7 @@ standard NATO SDIP-27 Level A * SHOULD be organizations which are ideally immune to being legally subpoenaed -* SHOULD not be susceptible to being subpoenaed +* SHOULD NOT be susceptible to being subpoenaed ## Storage Location From 9f8297bd0ec3a01ae0fd62f4fa74143b253b8b12 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sun, 4 Aug 2024 19:28:16 -0400 Subject: [PATCH 08/19] fix: ceremony.sh script keyfork command and pub certs path --- quorum-key-management/src/one-time-repository-setup.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/quorum-key-management/src/one-time-repository-setup.md b/quorum-key-management/src/one-time-repository-setup.md index e078d18..f160aee 100644 --- a/quorum-key-management/src/one-time-repository-setup.md +++ b/quorum-key-management/src/one-time-repository-setup.md @@ -16,13 +16,11 @@ command with a desired threshold: 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" + read -p "Provide the absoute path to PGP certificates which will be used for the ceremony: " directory_path if [ ! -d "$directory_path" ]; then - echo "Directory does not exist. Please enter a valid directory path." - exit 1 + echo "Directory does not exist. Please enter a valid directory path." + exit 1 fi for file in "$directory_path"/*; do @@ -39,7 +37,7 @@ command with a desired threshold: exit 1 fi - keyfork bottoms-up --threshold 2 --output-cert /dev/null --output-shardfile /dev/null --user-id "Distrust Key Ceremony" public-certificates/ + keyfork wizard bottoms-up --threshold 2 --output-cert /dev/null --output-shardfile /dev/null --user-id "Distrust Key Ceremony" public-certificates/ ``` * The `airgap.iso` which is to be used during the ceremony From 65d0e0269d5cb4a4d6edab1110636ecbbb50ac05 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sun, 4 Aug 2024 20:14:23 -0400 Subject: [PATCH 09/19] fix: update paths in ceremony.sh script for hybrid ceremony --- quorum-key-management/src/one-time-repository-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quorum-key-management/src/one-time-repository-setup.md b/quorum-key-management/src/one-time-repository-setup.md index f160aee..2291cce 100644 --- a/quorum-key-management/src/one-time-repository-setup.md +++ b/quorum-key-management/src/one-time-repository-setup.md @@ -37,7 +37,7 @@ command with a desired threshold: exit 1 fi - keyfork wizard bottoms-up --threshold 2 --output-cert /dev/null --output-shardfile /dev/null --user-id "Distrust Key Ceremony" public-certificates/ + keyfork wizard bottoms-up --threshold 2 --output-cert /media/cert --output-shardfile /media/shardfile --user-id "Distrust Key Ceremony" public-certificates/ ``` * The `airgap.iso` which is to be used during the ceremony From 230851330975ffbbb07e2306cab2c71695abb465 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sun, 4 Aug 2024 20:14:42 -0400 Subject: [PATCH 10/19] fix: add note about setting system time --- quorum-key-management/src/hybrid-key-provisioning.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quorum-key-management/src/hybrid-key-provisioning.md b/quorum-key-management/src/hybrid-key-provisioning.md index b6df96c..1101a1c 100644 --- a/quorum-key-management/src/hybrid-key-provisioning.md +++ b/quorum-key-management/src/hybrid-key-provisioning.md @@ -63,6 +63,11 @@ don't. More notes on selecting hardware can be found [here](one-time-use-hardwar 9. Button mash to ensure adequate entropy on the OS +10. Set the system time as it has to be after the PGP +public certificates were created, and before they expire: + + * `date -s "YYYY-MM-DD HH:MM:SS"` + 10. Run `ceremony.sh` 11. Back up the `shardfile`, and `pub.asc` to 3 separate SD cards, From e8e649983c556d331bee2c3817d401d01c0ece43 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sun, 4 Aug 2024 22:27:20 -0400 Subject: [PATCH 11/19] feat: add instructions for impregnating a smart card with seed --- quorum-key-management/src/location-key-provisioning.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 73bc126..5da03ac 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -53,6 +53,12 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * `keyfork derive openpgp "FirstName LastName (alias) " > priv.asc` + * Provision a YubiKey: + + * `oct list` + + * `oct admin --card import priv.asc` + * Import PGP key into keyring * `gpg --import priv.asc` From 46358df51e624c33cffcb8eb100c900f85b6a7a3 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 13:47:08 -0400 Subject: [PATCH 12/19] fix: minor location key ceremony update --- .../src/location-key-provisioning.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 5da03ac..74d057b 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -40,18 +40,25 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * Save the encrypted mnemonic, `mnemonic.txt.gpg` to two SD cards - * Print the contents of the mnemonic in a new terminal window as the seed - phrase words need to be typed in during the following steps: - - * `cat mnemonic.txt` + * 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) * In a new terminal window start `keyfork` daemon with the mnemonic: * `keyfork recover mnemonic` + * `export KEYFORKD_SOCKET_PATH=/tmp/keyforkd.socket` + + * `keyfork recover mnemonic` + + * ctrl + z + + * `bg` + * Derive PGP keypair: - * `keyfork derive openpgp "FirstName LastName (alias) " > priv.asc` + * `keyfork derive openpgp "FirstName LastName (Location Key: Distrust Disaster Recovery) " > priv.asc` * Provision a YubiKey: From d8eacdaa5b790a6f30d4aa8529e064b82be55118 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 13:47:28 -0400 Subject: [PATCH 13/19] feat: add details about tamper proofing hardware --- quorum-key-management/src/physical-artifact-storage.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/quorum-key-management/src/physical-artifact-storage.md b/quorum-key-management/src/physical-artifact-storage.md index 78ee34a..2436086 100644 --- a/quorum-key-management/src/physical-artifact-storage.md +++ b/quorum-key-management/src/physical-artifact-storage.md @@ -21,11 +21,16 @@ private vaulting provider. ## Location Smart Cards These cards should only be stored in secure vaults which meet the criteria -outliened for Storage Locations in the [Location](locations.md) document. - +outlined for Storage Locations in the [Location](locations.md) document. ## Additional Criteria +* MUST apply glitter nail polish to screws/seams of hardware casing, and take +photographs. + +* MAY put the hardware in a vacuum sealed bag with confetti, and take +photographs. + * MUST place smart cards in a tamper proof bag, whose picture is taken upon sealing, and stored along with other [Public Ceremony Artifacts](public-ceremony-artifact-storage.md) From 52ebb41eb8af532edafd2e0295e0286eaf461d90 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 14:13:28 -0400 Subject: [PATCH 14/19] fix: rename location key --- quorum-key-management/src/location-key-provisioning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 74d057b..7624739 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -58,7 +58,7 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * Derive PGP keypair: - * `keyfork derive openpgp "FirstName LastName (Location Key: Distrust Disaster Recovery) " > priv.asc` + * `keyfork derive openpgp "Location Key: Distrust Disaster Recovery" > priv.asc` * Provision a YubiKey: From 265add34f58f188f86fc597866fa5329b25c4f1e Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 15:55:11 -0400 Subject: [PATCH 15/19] fix: update location key ceremony --- .../src/location-key-provisioning.md | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 7624739..701f0de 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -28,18 +28,12 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * Load your personal PGP certificate which will be used as the Operator Key in to the local keyring - * `gpg --import ` + * `gpg --import /media/` * Generate the mnemonic: * `keyfork mnemonic generate --size 256 > mnemonic.txt` - * Encrypt the mnemonic to the Operator Key - - * `gpg -er mnemonic.txt` - - * Save the encrypted mnemonic, `mnemonic.txt.gpg` to two SD cards - * 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) @@ -58,26 +52,66 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * Derive PGP keypair: - * `keyfork derive openpgp "Location Key: Distrust Disaster Recovery" > priv.asc` + * `keyfork derive openpgp "Location Key: Distrust Disaster Recovery" > location.priv.asc` - * Provision a YubiKey: + * Provision two YubiKey: - * `oct list` + * To get the `smart_card_id`: `oct list` - * `oct admin --card import priv.asc` + * `oct admin --card import location.priv.asc` + + * `keyfork mnemonic generate --size 256 | awk '{ print $1, $2, $3, $4, $5 }' > smart-card-pin.txt` + + * `cat smart-card-pin.txt` + + * `oct pin --card set-user` + + * Enter the + + * `oct pin --card set-admin` + + * Enter the * Import PGP key into keyring - * `gpg --import priv.asc` + * `gpg --import location.priv.asc` - * Export PGP Public Certificate + * Encrypt and back up the `mnemonic.txt` - * `gpg --armor --export > pub.asc` + * `gpg -er mnemonic.txt` - * Save `pub.asc` to two SD cards + * `cp mnemonic.txt.gpg /media` - * Delete all the generated assets before shutting down computer, namely - `pub.asc`, `priv.asc`, `mnemonic.txt` and `mnemonic.txt.gpg` + * Encrypt and back up the `smart-card-pin` + + * `gpg -er smart-card-pin.txt` + + * `cp smart-card-pin.txt.gpg /media` + + * Export and back up `location.pub.asc` + + * `gpg --armor --export > location.pub.asc` + + * `cp location.pub.asc /media` + + * Duplicate all backup files to a second SD card: + + * `mnemonic.txt.gpg`, `smart-card-pin.gpg`, `location.pub.asc` + + * For posterity, delete all the generated assets before shutting down + computer, namely: + + * `mnemonic.txt` + + * `mnemonic.txt.gpg` + + * `smart-card-pin.txt` + + * `smart-card-pin.txt.gpg` + + * `location.pub.asc` + + * `location.priv.asc` 4. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide for storage of the Operator Smart Cards and Location Smart Cards From 7044041772b2a7f11d813f92d4aeafd3684a1af6 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 16:35:09 -0400 Subject: [PATCH 16/19] fix: add system time setting and copying pub key to operator pub key SD card --- .../src/location-key-provisioning.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 701f0de..f8af03d 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -25,6 +25,11 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) 3. Provision new key in the selected secure environment + * Set system time to date greater than operator key creation but less than + operator key expiry + + * `date -s "YYYY-MM-DD HH:MM:SS"` + * Load your personal PGP certificate which will be used as the Operator Key in to the local keyring @@ -98,6 +103,12 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * `mnemonic.txt.gpg`, `smart-card-pin.gpg`, `location.pub.asc` + * Copy the `location.pub.asc` to the SD card that was used to bring over + the operator key. This will be used to bring the public key to the Hybrid + Ceremony Later on: + + * `cp location.pub.asc /media` + * For posterity, delete all the generated assets before shutting down computer, namely: From 51fcd742a331d6d7f3596b0f9478a7a0df7ffc1b Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 16:45:13 -0400 Subject: [PATCH 17/19] fix: simplify deletion instruction at the end of the ceremony --- .../src/location-key-provisioning.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index f8af03d..0193476 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -110,19 +110,9 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * `cp location.pub.asc /media` * For posterity, delete all the generated assets before shutting down - computer, namely: + computer: - * `mnemonic.txt` - - * `mnemonic.txt.gpg` - - * `smart-card-pin.txt` - - * `smart-card-pin.txt.gpg` - - * `location.pub.asc` - - * `location.priv.asc` + * `rm -rf *` 4. Follow the [Physical Artifact Storage](physical-artifact-storage.md) guide for storage of the Operator Smart Cards and Location Smart Cards From ebe07875b732744d742a3a248159dca077905823 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 19:34:25 -0400 Subject: [PATCH 18/19] fix: improve tampering docs --- quorum-key-management/src/physical-artifact-storage.md | 3 ++- quorum-key-management/src/public-ceremony-artifact-storage.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/quorum-key-management/src/physical-artifact-storage.md b/quorum-key-management/src/physical-artifact-storage.md index 2436086..4936f03 100644 --- a/quorum-key-management/src/physical-artifact-storage.md +++ b/quorum-key-management/src/physical-artifact-storage.md @@ -26,7 +26,8 @@ outlined for Storage Locations in the [Location](locations.md) document. ## Additional Criteria * MUST apply glitter nail polish to screws/seams of hardware casing, and take -photographs. +photographs. It's best to use nail polish where the glitter is of different +sizes and colors. * MAY put the hardware in a vacuum sealed bag with confetti, and take photographs. diff --git a/quorum-key-management/src/public-ceremony-artifact-storage.md b/quorum-key-management/src/public-ceremony-artifact-storage.md index 8333d19..1f1542e 100644 --- a/quorum-key-management/src/public-ceremony-artifact-storage.md +++ b/quorum-key-management/src/public-ceremony-artifact-storage.md @@ -12,7 +12,8 @@ The primary artifacts which are produced during the ceremony are: * Pin Files * Pictures of tamper proof measures such as tamper proof bags, glitter applied -to bags, or hardware, such as screws on the bottoms of laptops etc. +to bags, or hardware, such as screws on the bottoms of laptops etc. Pictures +should be cryptographically signed to prevent tampering. ## Key Principles From 0df2c9ce08ba2381e2cc448b080721373de13539 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Mon, 5 Aug 2024 21:39:48 -0400 Subject: [PATCH 19/19] fix: remove duplicate command --- quorum-key-management/src/location-key-provisioning.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/quorum-key-management/src/location-key-provisioning.md b/quorum-key-management/src/location-key-provisioning.md index 0193476..688872b 100644 --- a/quorum-key-management/src/location-key-provisioning.md +++ b/quorum-key-management/src/location-key-provisioning.md @@ -45,8 +45,6 @@ or the [One Time Use Airgap-OS](one-time-use-airgapos.md) * In a new terminal window start `keyfork` daemon with the mnemonic: - * `keyfork recover mnemonic` - * `export KEYFORKD_SOCKET_PATH=/tmp/keyforkd.socket` * `keyfork recover mnemonic`