From d6a607a5cfd10a321bf8fe57b738f47359599240 Mon Sep 17 00:00:00 2001 From: Anton Livaja Date: Sat, 3 Aug 2024 17:23:14 -0400 Subject: [PATCH] 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.