From c0690e1c4cc83a8a7a212779424ea0aae4610293 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Wed, 14 May 2025 07:51:20 +0000 Subject: [PATCH 01/14] Import and cleanup notes for distribution --- SECENV.md | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 SECENV.md diff --git a/SECENV.md b/SECENV.md new file mode 100644 index 0000000..67996ef --- /dev/null +++ b/SECENV.md @@ -0,0 +1,75 @@ +# Creating a Secure Environment for GPG in Alpine Linux + +by Matt Borja + +**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on even *older versions* of architecturally diverse platforms such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of the Alpine Package Keeper (APK) to provide for ease of installation and use in air-gapped environments. + +**Tags.** Tails OS, Alpine Linux, GnuPG, Raspberry Pi. + +**Disclaimer.** The procedures outlined in this document are provided as best effort measures for creating a safer working environment for managing GPG keys; and are not intended to eliminate every possible threat scenario including, but not limited to those arising from the presence of: advanced persistent threats, viruses, infected firmware, or other similarly compromised peripherals or protocols used by these procedures. Caution must still be exercised when considering the use, proximity, and direct connection of any “active” or unshielded electronic device. + +## Stage 1: Establishing a Secure Imaging Host + +Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable image (e.g. Raspbian, Alpine Linux). While potentially sufficient for sensitive tasks as-is, this scenario could also be easily presumed contaminated by unknown threats in original imaging host environment, especially if the host is used regularly for day-to-day tasks, etc. + +Therefore, to mitigate the potential of host contamination, an *intermediary imaging environment* should first be established, isolated, hardened and *booted* as the current working environment (abstraction) prior to creating and the actual final, secure working environment. This process of creating and booting into an abstracted working environment may optionally be repeated (and also varied) as often as deemed necessary to evade any threats, potential or realized, in the preceding environment. + +**Note.** It will be necessary for this first working environment to either be: a) Internet-connected, or b) connected to a USB storage medium containing images for the final environment; for the purpose building and deploying the final secure image. + +### Obtaining Alpine Linux +**Smartphone Device Example.** The user connects a USB storage medium to their fully updated iPhone (cannot be jail broken) using an Apple-certified USB camera adapter. The iPhone in this scenario can serve as an initial intermediary environment reserved solely for the purpose of downloading an [official Alpine Linux ISO image](https://alpinelinux.org/downloads/) for the Raspberry Pi along with its corresponding signatures and public keys to the connected USB storage medium via the Files app. + +Note: This same acquisition method can be applied to any desired OS supported by the target device. + +**Post-Environment Example.** The user creates an intermediary environment using the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) and boots the 32-bit Alpine Linux image on their Raspberry Pi 1 Model B with networking enabled. + +Note: While this is the same OS that will ultimately be used for GPG, we are merely borrowing it as a "post-environment" at this stage in the process, solely for the purpose of prefetching an offline copy of the selfsame OS-specific APK packages that will be required for GPG (and smart card use) later on. + +### Downloading APK packages for offline use +While still booted in the "post-environment," you can run the following commands to update APK and download the relevant packages: +```shell +$ apk update && apk upgrade && apk fetch --recursive gpg gnupg-scdaemon pcsc-lite +``` + +**Tip.** The `--recursive` option is key to ensuring all dependencies are also downloaded. + +After running the above command, the downloaded packages will be found downloaded locally in the current working directory and should then be transferred to a USB storage medium. + +**CI/CD Considerations.** It is possible to bypass this entire user story if a CI/CD pipeline were to be carefully designed to demonstrate software provenance in the curation and signing of a custom Alpine Linux image with these requirements. + +### Building the Secure Environment +Once an intermediary environment has been finalized and selected to become the new imaging host environment, the user may begin to build out their final working environment, including but not limited to the base OS, and any post-installation scripts, packages, tools, etc. needed for work. + +**Example.** The user elects to use Tails OS as the last intermediate environment (the new imaging host environment) following a series of abstracted pre-environments. During its creation (prior to booting), an encrypted persistent storage is configured (e.g., LUKS) and used to store an offline, verified copy of Alpine Linux (32-bit) for their Raspberry Pi, along with all prefetched APK packages required for use in the final working environment. With permanent storage detached and networking completely disabled, the user proceeds to boot into Tails OS with Persistent Storage unlocked. Once booted, they use the disk utility program (Disks) to to "Restore Disk Image" to an SD card using the Alpine Linux image residing in Persistent Storage. Once imaged, the use proceeds to mount its writable 80 MB boot partition to copy relevant prefetched APK packages into a subfolder for post-installation. The SD card should now have everything needed to boot a securely created environment without the need to be connected to the Internet or other extraneous storage medium or peripherals. + +## Stage 2. Secure Environment + +At this point, the newly provisioned secure environment should be booted, free of any extraneous peripheral attachments, with networking completely disabled. + +Post-installation packages should be readily available (e.g., written to its boot partition for the preceding in intermediate environment) and cryptographically re-verified cryptographically before continuing with offline installation. + +Additional setup requirements within the secure environment may include: + +- Manually setting the system date +- Setting the keyboard language and layout +- Configuring the local GPG system +- Adding entropy sources +- Importing keys + +**Example.** After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues they following command within the package subdirectory to install them: + +```shell +$ apk --allow-untrusted --force-non-repository add *.apk +``` + +The user can now begin working with GPG and smart cards in their new environment: + +```shell +$ gpg --import yubikey.pub +$ gpg --card-status +$ gpg --list-secret-keys +``` + +### Stage 3. Takedown + +When finished performing tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file From ae6cac57f1be420f120cc8e2744f9e14445edb28 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Wed, 14 May 2025 08:04:29 +0000 Subject: [PATCH 02/14] Update headings: - Fix heading level for Stage 3 - Assign sub-headings Link "working with GPG" to existing guide --- SECENV.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/SECENV.md b/SECENV.md index 67996ef..7b96bac 100644 --- a/SECENV.md +++ b/SECENV.md @@ -16,7 +16,7 @@ Therefore, to mitigate the potential of host contamination, an *intermediary ima **Note.** It will be necessary for this first working environment to either be: a) Internet-connected, or b) connected to a USB storage medium containing images for the final environment; for the purpose building and deploying the final secure image. -### Obtaining Alpine Linux +### 1.1 Obtaining Alpine Linux **Smartphone Device Example.** The user connects a USB storage medium to their fully updated iPhone (cannot be jail broken) using an Apple-certified USB camera adapter. The iPhone in this scenario can serve as an initial intermediary environment reserved solely for the purpose of downloading an [official Alpine Linux ISO image](https://alpinelinux.org/downloads/) for the Raspberry Pi along with its corresponding signatures and public keys to the connected USB storage medium via the Files app. Note: This same acquisition method can be applied to any desired OS supported by the target device. @@ -25,7 +25,7 @@ Note: This same acquisition method can be applied to any desired OS supported by Note: While this is the same OS that will ultimately be used for GPG, we are merely borrowing it as a "post-environment" at this stage in the process, solely for the purpose of prefetching an offline copy of the selfsame OS-specific APK packages that will be required for GPG (and smart card use) later on. -### Downloading APK packages for offline use +### 1.2 Downloading APK packages for offline use While still booted in the "post-environment," you can run the following commands to update APK and download the relevant packages: ```shell $ apk update && apk upgrade && apk fetch --recursive gpg gnupg-scdaemon pcsc-lite @@ -37,7 +37,7 @@ After running the above command, the downloaded packages will be found downloade **CI/CD Considerations.** It is possible to bypass this entire user story if a CI/CD pipeline were to be carefully designed to demonstrate software provenance in the curation and signing of a custom Alpine Linux image with these requirements. -### Building the Secure Environment +### 1.3 Building the Secure Environment Once an intermediary environment has been finalized and selected to become the new imaging host environment, the user may begin to build out their final working environment, including but not limited to the base OS, and any post-installation scripts, packages, tools, etc. needed for work. **Example.** The user elects to use Tails OS as the last intermediate environment (the new imaging host environment) following a series of abstracted pre-environments. During its creation (prior to booting), an encrypted persistent storage is configured (e.g., LUKS) and used to store an offline, verified copy of Alpine Linux (32-bit) for their Raspberry Pi, along with all prefetched APK packages required for use in the final working environment. With permanent storage detached and networking completely disabled, the user proceeds to boot into Tails OS with Persistent Storage unlocked. Once booted, they use the disk utility program (Disks) to to "Restore Disk Image" to an SD card using the Alpine Linux image residing in Persistent Storage. Once imaged, the use proceeds to mount its writable 80 MB boot partition to copy relevant prefetched APK packages into a subfolder for post-installation. The SD card should now have everything needed to boot a securely created environment without the need to be connected to the Internet or other extraneous storage medium or peripherals. @@ -56,13 +56,15 @@ Additional setup requirements within the secure environment may include: - Adding entropy sources - Importing keys -**Example.** After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues they following command within the package subdirectory to install them: +### 2.1 Installing Offline Packages +After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues they following command within the package subdirectory to install them: ```shell $ apk --allow-untrusted --force-non-repository add *.apk ``` -The user can now begin working with GPG and smart cards in their new environment: +### 2.2 GPG Environment +The user can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in their new environment: ```shell $ gpg --import yubikey.pub @@ -70,6 +72,6 @@ $ gpg --card-status $ gpg --list-secret-keys ``` -### Stage 3. Takedown +## Stage 3. Takedown When finished performing tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file From 3cc423037b4c76c5ea72fb26c09e817e939d73fd Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Wed, 14 May 2025 08:11:40 +0000 Subject: [PATCH 03/14] Fix minor spelling/grammar issues --- SECENV.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECENV.md b/SECENV.md index 7b96bac..5fee425 100644 --- a/SECENV.md +++ b/SECENV.md @@ -40,7 +40,7 @@ After running the above command, the downloaded packages will be found downloade ### 1.3 Building the Secure Environment Once an intermediary environment has been finalized and selected to become the new imaging host environment, the user may begin to build out their final working environment, including but not limited to the base OS, and any post-installation scripts, packages, tools, etc. needed for work. -**Example.** The user elects to use Tails OS as the last intermediate environment (the new imaging host environment) following a series of abstracted pre-environments. During its creation (prior to booting), an encrypted persistent storage is configured (e.g., LUKS) and used to store an offline, verified copy of Alpine Linux (32-bit) for their Raspberry Pi, along with all prefetched APK packages required for use in the final working environment. With permanent storage detached and networking completely disabled, the user proceeds to boot into Tails OS with Persistent Storage unlocked. Once booted, they use the disk utility program (Disks) to to "Restore Disk Image" to an SD card using the Alpine Linux image residing in Persistent Storage. Once imaged, the use proceeds to mount its writable 80 MB boot partition to copy relevant prefetched APK packages into a subfolder for post-installation. The SD card should now have everything needed to boot a securely created environment without the need to be connected to the Internet or other extraneous storage medium or peripherals. +**Example.** The user elects to use Tails OS as the last intermediate environment (the new imaging host environment) following a series of abstracted pre-environments. During its creation (prior to booting), an encrypted persistent storage is configured (e.g., LUKS) and used to store an offline, verified copy of Alpine Linux (32-bit) for their Raspberry Pi, along with all prefetched APK packages required for use in the final working environment. With permanent storage detached and networking completely disabled, the user proceeds to boot into Tails OS with Persistent Storage unlocked. Once booted, they use the disk utility program (Disks) to "Restore Disk Image" to an SD card using the Alpine Linux image residing in Persistent Storage. Once imaged, the use proceeds to mount its writable 80 MB boot partition to copy relevant prefetched APK packages into a subfolder for post-installation. The SD card should now have everything needed to boot a securely created environment without the need to be connected to the Internet or other extraneous storage medium or peripherals. ## Stage 2. Secure Environment @@ -57,7 +57,7 @@ Additional setup requirements within the secure environment may include: - Importing keys ### 2.1 Installing Offline Packages -After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues they following command within the package subdirectory to install them: +After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues the following command within the package subdirectory to install them: ```shell $ apk --allow-untrusted --force-non-repository add *.apk From acdbd14f8d32cd651a799deb982441b08918a523 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 01:58:01 +0000 Subject: [PATCH 04/14] Rework section introductory paragraphs for readability Begin reworking user stories as more procedural for brevity and procedural specificity (clarity) - Establishing a Secure Image Host - Use Tails OS as an Intermediary - Use the target OS to download packages - Acquire the target image - Boot the target image and download OS packages The "clean plate" analogy is becoming more prominent (recurring), potentially indicating an accessible codename suitable for this document. --- SECENV.md | 57 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/SECENV.md b/SECENV.md index 5fee425..fd1ad22 100644 --- a/SECENV.md +++ b/SECENV.md @@ -2,7 +2,7 @@ by Matt Borja -**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on even *older versions* of architecturally diverse platforms such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of the Alpine Package Keeper (APK) to provide for ease of installation and use in air-gapped environments. +**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of Alpine Package Keeper (APK) to provide for ease of package installation and use in air-gapped environments. **Tags.** Tails OS, Alpine Linux, GnuPG, Raspberry Pi. @@ -10,30 +10,57 @@ by Matt Borja ## Stage 1: Establishing a Secure Imaging Host -Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable image (e.g. Raspbian, Alpine Linux). While potentially sufficient for sensitive tasks as-is, this scenario could also be easily presumed contaminated by unknown threats in original imaging host environment, especially if the host is used regularly for day-to-day tasks, etc. +Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable disk. While this might be satisfactory to many, it is worth considering the risk of contamination through daily use. Think of it as grabbing a clean plate before putting food on it! -Therefore, to mitigate the potential of host contamination, an *intermediary imaging environment* should first be established, isolated, hardened and *booted* as the current working environment (abstraction) prior to creating and the actual final, secure working environment. This process of creating and booting into an abstracted working environment may optionally be repeated (and also varied) as often as deemed necessary to evade any threats, potential or realized, in the preceding environment. +Therefore, to mitigate the potential of host contamination, we will establish an *intermediary environment* (abstraction) prior to creating the actual secure working environment. We will also consider a tightly coupled process for verifying the target image before writing it to disk. + +### 1.1. Use Tails OS as an Intermediary (Recommended) +[Tails OS](https://tails.net/install/expert/index.en.html) provides for a convenient, isolated ephemeral environment, placing special emphasis on proper verification of its USB images before use. Consider booting into a system like this before starting in on these procedures. -**Note.** It will be necessary for this first working environment to either be: a) Internet-connected, or b) connected to a USB storage medium containing images for the final environment; for the purpose building and deploying the final secure image. +### 1.2. Use the target OS to download packages -### 1.1 Obtaining Alpine Linux -**Smartphone Device Example.** The user connects a USB storage medium to their fully updated iPhone (cannot be jail broken) using an Apple-certified USB camera adapter. The iPhone in this scenario can serve as an initial intermediary environment reserved solely for the purpose of downloading an [official Alpine Linux ISO image](https://alpinelinux.org/downloads/) for the Raspberry Pi along with its corresponding signatures and public keys to the connected USB storage medium via the Files app. +#### 1.2.1. Acquire the target image +Let's assume you've gone through the steps of downloading, verifying, and booting into **Tails**. You'll now need to import a copy of the target OS image ([Alpine Linux](https://alpinelinux.org/downloads/)) by either: +- Connecting Tails to the Internet and using its Tor Browser to download the image +- Leaving Tails disconnected from the Internet and instead using another device (e.g., smartphone) to bring over the downloaded image using a removable storage device -Note: This same acquisition method can be applied to any desired OS supported by the target device. +**Important.** You must verify this image using its GPG signature and corresponding signing key just as you should have done to verify Tails prior to using as an intermediary. These steps may seem repetitive, but are critical to building a clean path into a highly secure environment. -**Post-Environment Example.** The user creates an intermediary environment using the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) and boots the 32-bit Alpine Linux image on their Raspberry Pi 1 Model B with networking enabled. +#### 1.2.2. Boot the target image and download OS packages +In the same way you installed Tails onto a USB stick using the `dd` command, you will want to do this *within Tails* for the Alpine Linux image you've just acquired. Clearly, this will require its own separate USB stick, but what you've now accomplished will be an Alpine Linux image written to a USB stick from the intermediary environment as a preferred alternative to a contaminated host environment. -Note: While this is the same OS that will ultimately be used for GPG, we are merely borrowing it as a "post-environment" at this stage in the process, solely for the purpose of prefetching an offline copy of the selfsame OS-specific APK packages that will be required for GPG (and smart card use) later on. +Next, you will want to boot into the Alpine Linux system you've just created, login as `root`, and connect to the Internet to download the required packages for this specific platform: -### 1.2 Downloading APK packages for offline use -While still booted in the "post-environment," you can run the following commands to update APK and download the relevant packages: ```shell -$ apk update && apk upgrade && apk fetch --recursive gpg gnupg-scdaemon pcsc-lite +# 1. Set date +root@host:~$ date -s 'YYYY-MM-DD hh:mm:ss' + +# 2. Connect to Internet +# See https://wiki.alpinelinux.org/wiki/Configure_Networking + +# 3. Download packages for offline installation +root@host:~$ apk update +root@host:~$ apk upgrade +root@host:~$ apk fetch --recursive gpg gnupg-scdaemon pcsc-lite + +# NOTE: Internet is no longer required beyond this point + +# 4. Review downloaded packages +root@host:~$ ls -lha *.apk + +# 5. Bundle packages for offline use +root@host:~$ tar -czvf gpg-bundle.tar.gz *.apk + +# 6. Optional. Take SHA256 checksum +root@host:~$ sha256sum gpg-bundle.tar.gz > gpg-bundle.tar.gz.sha256 + +# 6. Mount removable storage and copy over (replace /dev/sda1 with your actual device file handle) +root@host:~$ mount -t exfat /dev/sda1 /mnt +root@host:~$ cp gpg-bundle.* /mnt/ +root@host:~$ umount /mnt ``` -**Tip.** The `--recursive` option is key to ensuring all dependencies are also downloaded. - -After running the above command, the downloaded packages will be found downloaded locally in the current working directory and should then be transferred to a USB storage medium. +**Important.** With offline packages in hand, you may consider repeating the prior section (*1.2.1. Acquiring the target image*) to provide yourself with another "clean plate" (one that's never been connected to the Internet) before continuing. **CI/CD Considerations.** It is possible to bypass this entire user story if a CI/CD pipeline were to be carefully designed to demonstrate software provenance in the curation and signing of a custom Alpine Linux image with these requirements. From 1a7bc2ccf6770667ae9277d299ab6a1f3ec614ea Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 02:08:14 +0000 Subject: [PATCH 05/14] Rework section introductory paragraphs for readability Begin reworking user stories as more procedural for brevity and procedural specificity (clarity) - Establishing a Secure Image Host - Use Tails OS as an Intermediary - Use the target OS to download packages - Acquire the target image - Boot the target image and download OS packages The "clean plate" analogy is becoming more prominent (recurring), potentially indicating an accessible codename suitable for this document. --- SECENV.md | 57 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/SECENV.md b/SECENV.md index 5fee425..fd1ad22 100644 --- a/SECENV.md +++ b/SECENV.md @@ -2,7 +2,7 @@ by Matt Borja -**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on even *older versions* of architecturally diverse platforms such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of the Alpine Package Keeper (APK) to provide for ease of installation and use in air-gapped environments. +**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of Alpine Package Keeper (APK) to provide for ease of package installation and use in air-gapped environments. **Tags.** Tails OS, Alpine Linux, GnuPG, Raspberry Pi. @@ -10,30 +10,57 @@ by Matt Borja ## Stage 1: Establishing a Secure Imaging Host -Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable image (e.g. Raspbian, Alpine Linux). While potentially sufficient for sensitive tasks as-is, this scenario could also be easily presumed contaminated by unknown threats in original imaging host environment, especially if the host is used regularly for day-to-day tasks, etc. +Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable disk. While this might be satisfactory to many, it is worth considering the risk of contamination through daily use. Think of it as grabbing a clean plate before putting food on it! -Therefore, to mitigate the potential of host contamination, an *intermediary imaging environment* should first be established, isolated, hardened and *booted* as the current working environment (abstraction) prior to creating and the actual final, secure working environment. This process of creating and booting into an abstracted working environment may optionally be repeated (and also varied) as often as deemed necessary to evade any threats, potential or realized, in the preceding environment. +Therefore, to mitigate the potential of host contamination, we will establish an *intermediary environment* (abstraction) prior to creating the actual secure working environment. We will also consider a tightly coupled process for verifying the target image before writing it to disk. + +### 1.1. Use Tails OS as an Intermediary (Recommended) +[Tails OS](https://tails.net/install/expert/index.en.html) provides for a convenient, isolated ephemeral environment, placing special emphasis on proper verification of its USB images before use. Consider booting into a system like this before starting in on these procedures. -**Note.** It will be necessary for this first working environment to either be: a) Internet-connected, or b) connected to a USB storage medium containing images for the final environment; for the purpose building and deploying the final secure image. +### 1.2. Use the target OS to download packages -### 1.1 Obtaining Alpine Linux -**Smartphone Device Example.** The user connects a USB storage medium to their fully updated iPhone (cannot be jail broken) using an Apple-certified USB camera adapter. The iPhone in this scenario can serve as an initial intermediary environment reserved solely for the purpose of downloading an [official Alpine Linux ISO image](https://alpinelinux.org/downloads/) for the Raspberry Pi along with its corresponding signatures and public keys to the connected USB storage medium via the Files app. +#### 1.2.1. Acquire the target image +Let's assume you've gone through the steps of downloading, verifying, and booting into **Tails**. You'll now need to import a copy of the target OS image ([Alpine Linux](https://alpinelinux.org/downloads/)) by either: +- Connecting Tails to the Internet and using its Tor Browser to download the image +- Leaving Tails disconnected from the Internet and instead using another device (e.g., smartphone) to bring over the downloaded image using a removable storage device -Note: This same acquisition method can be applied to any desired OS supported by the target device. +**Important.** You must verify this image using its GPG signature and corresponding signing key just as you should have done to verify Tails prior to using as an intermediary. These steps may seem repetitive, but are critical to building a clean path into a highly secure environment. -**Post-Environment Example.** The user creates an intermediary environment using the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) and boots the 32-bit Alpine Linux image on their Raspberry Pi 1 Model B with networking enabled. +#### 1.2.2. Boot the target image and download OS packages +In the same way you installed Tails onto a USB stick using the `dd` command, you will want to do this *within Tails* for the Alpine Linux image you've just acquired. Clearly, this will require its own separate USB stick, but what you've now accomplished will be an Alpine Linux image written to a USB stick from the intermediary environment as a preferred alternative to a contaminated host environment. -Note: While this is the same OS that will ultimately be used for GPG, we are merely borrowing it as a "post-environment" at this stage in the process, solely for the purpose of prefetching an offline copy of the selfsame OS-specific APK packages that will be required for GPG (and smart card use) later on. +Next, you will want to boot into the Alpine Linux system you've just created, login as `root`, and connect to the Internet to download the required packages for this specific platform: -### 1.2 Downloading APK packages for offline use -While still booted in the "post-environment," you can run the following commands to update APK and download the relevant packages: ```shell -$ apk update && apk upgrade && apk fetch --recursive gpg gnupg-scdaemon pcsc-lite +# 1. Set date +root@host:~$ date -s 'YYYY-MM-DD hh:mm:ss' + +# 2. Connect to Internet +# See https://wiki.alpinelinux.org/wiki/Configure_Networking + +# 3. Download packages for offline installation +root@host:~$ apk update +root@host:~$ apk upgrade +root@host:~$ apk fetch --recursive gpg gnupg-scdaemon pcsc-lite + +# NOTE: Internet is no longer required beyond this point + +# 4. Review downloaded packages +root@host:~$ ls -lha *.apk + +# 5. Bundle packages for offline use +root@host:~$ tar -czvf gpg-bundle.tar.gz *.apk + +# 6. Optional. Take SHA256 checksum +root@host:~$ sha256sum gpg-bundle.tar.gz > gpg-bundle.tar.gz.sha256 + +# 6. Mount removable storage and copy over (replace /dev/sda1 with your actual device file handle) +root@host:~$ mount -t exfat /dev/sda1 /mnt +root@host:~$ cp gpg-bundle.* /mnt/ +root@host:~$ umount /mnt ``` -**Tip.** The `--recursive` option is key to ensuring all dependencies are also downloaded. - -After running the above command, the downloaded packages will be found downloaded locally in the current working directory and should then be transferred to a USB storage medium. +**Important.** With offline packages in hand, you may consider repeating the prior section (*1.2.1. Acquiring the target image*) to provide yourself with another "clean plate" (one that's never been connected to the Internet) before continuing. **CI/CD Considerations.** It is possible to bypass this entire user story if a CI/CD pipeline were to be carefully designed to demonstrate software provenance in the curation and signing of a custom Alpine Linux image with these requirements. From bd96779276404707c8f280093f4fc052df1531c2 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 02:18:47 +0000 Subject: [PATCH 06/14] Cleanup remaining extraneous sections - 1.3 Building the Secure Environment Cleanup CI/CD Considerations paragraph --- SECENV.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/SECENV.md b/SECENV.md index fd1ad22..e506065 100644 --- a/SECENV.md +++ b/SECENV.md @@ -62,12 +62,7 @@ root@host:~$ umount /mnt **Important.** With offline packages in hand, you may consider repeating the prior section (*1.2.1. Acquiring the target image*) to provide yourself with another "clean plate" (one that's never been connected to the Internet) before continuing. -**CI/CD Considerations.** It is possible to bypass this entire user story if a CI/CD pipeline were to be carefully designed to demonstrate software provenance in the curation and signing of a custom Alpine Linux image with these requirements. - -### 1.3 Building the Secure Environment -Once an intermediary environment has been finalized and selected to become the new imaging host environment, the user may begin to build out their final working environment, including but not limited to the base OS, and any post-installation scripts, packages, tools, etc. needed for work. - -**Example.** The user elects to use Tails OS as the last intermediate environment (the new imaging host environment) following a series of abstracted pre-environments. During its creation (prior to booting), an encrypted persistent storage is configured (e.g., LUKS) and used to store an offline, verified copy of Alpine Linux (32-bit) for their Raspberry Pi, along with all prefetched APK packages required for use in the final working environment. With permanent storage detached and networking completely disabled, the user proceeds to boot into Tails OS with Persistent Storage unlocked. Once booted, they use the disk utility program (Disks) to "Restore Disk Image" to an SD card using the Alpine Linux image residing in Persistent Storage. Once imaged, the use proceeds to mount its writable 80 MB boot partition to copy relevant prefetched APK packages into a subfolder for post-installation. The SD card should now have everything needed to boot a securely created environment without the need to be connected to the Internet or other extraneous storage medium or peripherals. +**CI/CD Considerations.** It is curate a clean, custom bootable image of Alpine Linux with these same offline packages using a CI/CD pipeline if carefully designed to also demonstrate software provenance and image signing before release. ## Stage 2. Secure Environment From 0d709dd9ba4d0d1ef5aa06198cb44a0e82b8d25b Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 02:24:13 +0000 Subject: [PATCH 07/14] Update instructions for installing offline packages from removable storage after booting into the secure environment --- SECENV.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/SECENV.md b/SECENV.md index e506065..0797805 100644 --- a/SECENV.md +++ b/SECENV.md @@ -79,14 +79,23 @@ Additional setup requirements within the secure environment may include: - Importing keys ### 2.1 Installing Offline Packages -After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages stored in the boot partition. Once verified, the user issues the following command within the package subdirectory to install them: +After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages download to removable storage: ```shell -$ apk --allow-untrusted --force-non-repository add *.apk +root@host:~$ date -s 'YYYY-MM-DD hh:mm:ss' +root@host:~$ mount -t exfat /dev/sda1 /mnt +root@host:~$ cp /mnt/gpg-bundle.* . +root@host:~$ umount /mnt +root@host:~$ sha256sum -c gpg-bundle.tar.gz.sha256 && tar -xzvf gpg-bundle-tar-gz +``` + +Once verified and extracted from the tarball, the user issues the following command within the package subdirectory to install them: +```shell +root@host:~$ apk --allow-untrusted --force-non-repository add *.apk ``` ### 2.2 GPG Environment -The user can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in their new environment: +At this point, the user can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in their new environment: ```shell $ gpg --import yubikey.pub From dc2221e7de7a650c5fbcb1220c8ad098dcecd33e Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 02:29:37 +0000 Subject: [PATCH 08/14] Add notes for restarting gpg-agent if connection to HSM is lost between $GNUPGHOME directories Cleanup heading with procedure verbiage: - Install Offline Packages for GnuPG - Verify the Environment --- SECENV.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/SECENV.md b/SECENV.md index 0797805..31f6d1d 100644 --- a/SECENV.md +++ b/SECENV.md @@ -64,7 +64,7 @@ root@host:~$ umount /mnt **CI/CD Considerations.** It is curate a clean, custom bootable image of Alpine Linux with these same offline packages using a CI/CD pipeline if carefully designed to also demonstrate software provenance and image signing before release. -## Stage 2. Secure Environment +## Stage 2. Using the Secure Environment At this point, the newly provisioned secure environment should be booted, free of any extraneous peripheral attachments, with networking completely disabled. @@ -78,7 +78,7 @@ Additional setup requirements within the secure environment may include: - Adding entropy sources - Importing keys -### 2.1 Installing Offline Packages +### 2.1 Install Offline Packages for GnuPG After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages download to removable storage: ```shell @@ -94,15 +94,21 @@ Once verified and extracted from the tarball, the user issues the following comm root@host:~$ apk --allow-untrusted --force-non-repository add *.apk ``` -### 2.2 GPG Environment +### 2.2 Verify the Environment At this point, the user can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in their new environment: ```shell -$ gpg --import yubikey.pub -$ gpg --card-status -$ gpg --list-secret-keys +root@host:~$ gpg --import yubikey.pub +root@host:~$ gpg --card-status +root@host:~$ gpg --list-secret-keys +``` + +**Important.** If you run into issues detecting your YubiKey switching between `$GNUPGHOME` directories (common during heavy key management operations such as ring transfers, etc.), try restarting the `gpg-agent` as follows: + +```shell +root@host:~$ pkill gpg-agent +root@host:~$ gpg --card-status ``` ## Stage 3. Takedown - When finished performing tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file From 8536df9cfc5aa1848ca881937393ea16a5bca0c2 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 07:37:10 +0000 Subject: [PATCH 09/14] Rework Purpose section as Abstract and cleanup Align heading for procedure verbiage: Establish a Secure Imaging Host --- SECENV.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECENV.md b/SECENV.md index 31f6d1d..6f469b5 100644 --- a/SECENV.md +++ b/SECENV.md @@ -2,13 +2,13 @@ by Matt Borja -**Purpose.** This document describes a process for creating a secure environment using Alpine Linux: a lightweight and secure distribution of Linux capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable characteristics of Alpine Package Keeper (APK) to provide for ease of package installation and use in air-gapped environments. +**Abstract.** This document describes a process for creating a secure environment for GPG key management using Alpine Linux: a lightweight and secure Linux distribution capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable nature of Alpine Package Keeper (APK) for ease of dependency installation in air-gapped environments. **Tags.** Tails OS, Alpine Linux, GnuPG, Raspberry Pi. **Disclaimer.** The procedures outlined in this document are provided as best effort measures for creating a safer working environment for managing GPG keys; and are not intended to eliminate every possible threat scenario including, but not limited to those arising from the presence of: advanced persistent threats, viruses, infected firmware, or other similarly compromised peripherals or protocols used by these procedures. Caution must still be exercised when considering the use, proximity, and direct connection of any “active” or unshielded electronic device. -## Stage 1: Establishing a Secure Imaging Host +## Stage 1: Establish a Secure Imaging Host Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable disk. While this might be satisfactory to many, it is worth considering the risk of contamination through daily use. Think of it as grabbing a clean plate before putting food on it! From 67e63f5e40f19145f86b31c86b4b37880d870f15 Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 07:46:47 +0000 Subject: [PATCH 10/14] Cleanup Stage 1 introductory paragraph and rearrange "clean plate" analogy for logical flow --- SECENV.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECENV.md b/SECENV.md index 6f469b5..9218e53 100644 --- a/SECENV.md +++ b/SECENV.md @@ -10,9 +10,9 @@ by Matt Borja ## Stage 1: Establish a Secure Imaging Host -Preparing a secure environment for GPG normally involves the initial use of a host system (e.g., Windows, Mac OS) to create a bootable disk. While this might be satisfactory to many, it is worth considering the risk of contamination through daily use. Think of it as grabbing a clean plate before putting food on it! +Preparing a secure environment for GPG normally involves the initial use of an external host system (e.g., Windows, Mac OS) to create its bootable disk. While this might be satisfactory to many, it is worth considering the risk of host contamination through daily use. Therefore, we will establish an *intermediary environment* from which we will then create the bootable disk. One might think of this seemingly superfluous step as merely grabbing a clean plate before putting food on it to eat! -Therefore, to mitigate the potential of host contamination, we will establish an *intermediary environment* (abstraction) prior to creating the actual secure working environment. We will also consider a tightly coupled process for verifying the target image before writing it to disk. +We will also consider a tightly coupled process for verifying the target image before writing it to disk. ### 1.1. Use Tails OS as an Intermediary (Recommended) [Tails OS](https://tails.net/install/expert/index.en.html) provides for a convenient, isolated ephemeral environment, placing special emphasis on proper verification of its USB images before use. Consider booting into a system like this before starting in on these procedures. From fbc9d4f5170ffd9d37ad32f51ccd33e16067556c Mon Sep 17 00:00:00 2001 From: Matt Borja Date: Mon, 19 May 2025 17:43:14 +0000 Subject: [PATCH 11/14] - Use dedicated section headings for Abstract and Disclaimer - Include MIT disclaimer and add copyright - Clarify use of tightly coupled process intended for offline package installation (bootable images already presumed to be verified through via external documentation) - Specify appropriate use of secure imaging host (imaging purposes only) - Provide link to Tails installation guide - Cleanup verbiage throughout using more direct procedural language - Rearrange paragraphs as needed to address disparities in logical flow of procedures, as in C/CD Considerations - Clarify hardware requirements for devices elected for air-gap use (e.g. SD card) - Reiterate verification requirements for Alpine Linux, citing both official sources and additional evidence sources - Add callout (3b) to fetch additional packages required for offlnie work in the air-gapped environment and thus rename gpg-bundle-* to airgap-bundle-* - Add explicit step to visually inspect and note SHA256 checksum of air-gap bundle before continuing (required for later verification) - Parameterize device paths when referencing use of removable storage medium - Note alternate use of repeating section 1.2.1 over current SD card (used for offline package retrieval) - Cleanup additional post-installation setup tasks introduced elsewhere in, else considered outside the scope of this document - Demonstrate use of `&&` for requiring SHA256 to be valid before allowing air-gap bundle to be extracted and installed - Include sample command for listing key certifications during GPG environment verification (--list-sigs) --- SECENV.md | 115 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 47 deletions(-) diff --git a/SECENV.md b/SECENV.md index 9218e53..2a8ed9d 100644 --- a/SECENV.md +++ b/SECENV.md @@ -1,114 +1,135 @@ # Creating a Secure Environment for GPG in Alpine Linux -by Matt Borja +Copyright (c) 2025 Matt Borja -**Abstract.** This document describes a process for creating a secure environment for GPG key management using Alpine Linux: a lightweight and secure Linux distribution capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also demonstrates the highly portable nature of Alpine Package Keeper (APK) for ease of dependency installation in air-gapped environments. +## Abstract +This document describes a process for creating a secure environment for GPG key management using Alpine Linux: a lightweight and secure Linux distribution capable of supporting newer versions of GPG with smart card support on very modest hardware such as the ARM-based Raspberry Pi 1 Model B (32-bit). This document also considers the highly portable nature of Alpine Package Keeper (APK) for ease of dependency installation in air-gapped environments and a tightly coupled process to further assert package integrity as an installation prerequisite within the air-gapped environment. **Tags.** Tails OS, Alpine Linux, GnuPG, Raspberry Pi. -**Disclaimer.** The procedures outlined in this document are provided as best effort measures for creating a safer working environment for managing GPG keys; and are not intended to eliminate every possible threat scenario including, but not limited to those arising from the presence of: advanced persistent threats, viruses, infected firmware, or other similarly compromised peripherals or protocols used by these procedures. Caution must still be exercised when considering the use, proximity, and direct connection of any “active” or unshielded electronic device. +## Disclaimer +The procedures outlined in this document are provided as best effort measures for creating a safer working environment for managing GPG keys; and are not intended to eliminate every possible threat scenario including, but not limited to those arising from the presence of: advanced persistent threats, viruses, infected firmware, or other similarly compromised peripherals or protocols used by these procedures. Caution must still be exercised when considering the use, proximity, and direct connection of any “active” or unshielded electronic device. -## Stage 1: Establish a Secure Imaging Host +Furthermore: -Preparing a secure environment for GPG normally involves the initial use of an external host system (e.g., Windows, Mac OS) to create its bootable disk. While this might be satisfactory to many, it is worth considering the risk of host contamination through daily use. Therefore, we will establish an *intermediary environment* from which we will then create the bootable disk. One might think of this seemingly superfluous step as merely grabbing a clean plate before putting food on it to eat! +THIS DOCUMENTATION IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS DOCUMENTATION OR THE USE OR OTHER DEALINGS IN THIS DOCUMENTATION. -We will also consider a tightly coupled process for verifying the target image before writing it to disk. +## 1. Prepare a Secure Imaging Host + +Preparing a secure environment for GPG normally involves the initial use of an external host system (e.g., Windows, Mac OS, etc.) to create its bootable disk. While this might be satisfactory to many, it is worth considering the risk of host contamination through daily use. Therefore we will consider an *intermediary environment* from which we will then create the bootable disk. One might think of this seemingly superfluous step as merely grabbing a clean plate before putting food on it to eat! ### 1.1. Use Tails OS as an Intermediary (Recommended) [Tails OS](https://tails.net/install/expert/index.en.html) provides for a convenient, isolated ephemeral environment, placing special emphasis on proper verification of its USB images before use. Consider booting into a system like this before starting in on these procedures. +As mentioned before, this environment alone may arguably be considered satisfactory for GPG purposes, but it is out of an abundance of caution we are limiting our use of it for verification and imaging purposes only. + ### 1.2. Use the target OS to download packages +If you haven't already, follow the [Tails installation guide](https://tails.net/install/expert/index.en.html) *carefully* to ensure you have [verified](https://tails.net/install/expert/index.en.html#verify-key) and booted into a valid Tails environment before continuing. + #### 1.2.1. Acquire the target image -Let's assume you've gone through the steps of downloading, verifying, and booting into **Tails**. You'll now need to import a copy of the target OS image ([Alpine Linux](https://alpinelinux.org/downloads/)) by either: -- Connecting Tails to the Internet and using its Tor Browser to download the image +Next, import a copy of [Alpine Linux](https://alpinelinux.org/downloads/) by either: +- Connecting Tails to the Internet and using the Tor Browser to download the image - Leaving Tails disconnected from the Internet and instead using another device (e.g., smartphone) to bring over the downloaded image using a removable storage device -**Important.** You must verify this image using its GPG signature and corresponding signing key just as you should have done to verify Tails prior to using as an intermediary. These steps may seem repetitive, but are critical to building a clean path into a highly secure environment. +**Note.** If you have designated an older Raspberry Pi as your preferred air-gapped device, you will need to provide a SD card for imaging and likely use the ARMhf (hard float) images from their [downloads page](https://www.alpinelinux.org/downloads/). -#### 1.2.2. Boot the target image and download OS packages -In the same way you installed Tails onto a USB stick using the `dd` command, you will want to do this *within Tails* for the Alpine Linux image you've just acquired. Clearly, this will require its own separate USB stick, but what you've now accomplished will be an Alpine Linux image written to a USB stick from the intermediary environment as a preferred alternative to a contaminated host environment. +**Important.** In the same way you should have done for Tails, you must verify the Alpine Linux image using its corresponding GPG signature against its signing key before continuing. Always check [official sources](https://docs.alpinelinux.org/user-handbook/0.1a/Installing/medium.html#_optional_verifying_the_downloaded_files_pgp) and consider additional evidence sources ([example](https://sig3.dev)) for validity completness. These steps may seem repetitive and strenuous, but are critical to building a verifiable path into a highly secure environment. -Next, you will want to boot into the Alpine Linux system you've just created, login as `root`, and connect to the Internet to download the required packages for this specific platform: +Once you've verified the image download, you can use the **Restore Disk Image...** in the *Disks* utility from within Tails to write the image to a target disk (e.g., SD card for a Raspberry Pi). + +#### 1.2.2. Boot the target image to download OS-specific packages for GnuPG + +Boot into the Alpine Linux system, login as `root`, and connect to the Internet to download the required packages for this specific platform: ```shell # 1. Set date root@host:~$ date -s 'YYYY-MM-DD hh:mm:ss' -# 2. Connect to Internet -# See https://wiki.alpinelinux.org/wiki/Configure_Networking +# 2. Connect to Internet (https://wiki.alpinelinux.org/wiki/Configure_Networking) -# 3. Download packages for offline installation +# 3a. Download packages for offline installation root@host:~$ apk update root@host:~$ apk upgrade root@host:~$ apk fetch --recursive gpg gnupg-scdaemon pcsc-lite -# NOTE: Internet is no longer required beyond this point +# 3b. Use the same apk fetch --recursive command to download any additional packages you require for additional work in the air-gapped enviroment. + +# Note. Internet is no longer required beyond this point. # 4. Review downloaded packages root@host:~$ ls -lha *.apk -# 5. Bundle packages for offline use -root@host:~$ tar -czvf gpg-bundle.tar.gz *.apk +# 5. Bundle for offline use and take SHA256 checksum +root@host:~$ tar -czvf airgap-bundle.tar.gz *.apk +root@host:~$ sha256sum airgap-bundle.tar.gz > airgap-bundle.tar.gz.sha256 -# 6. Optional. Take SHA256 checksum -root@host:~$ sha256sum gpg-bundle.tar.gz > gpg-bundle.tar.gz.sha256 +# 6. Visually inspect and note SHA256 checksum for verification +root@root:~$ cat airgap-bundle.tar.gz.sha256 -# 6. Mount removable storage and copy over (replace /dev/sda1 with your actual device file handle) -root@host:~$ mount -t exfat /dev/sda1 /mnt -root@host:~$ cp gpg-bundle.* /mnt/ +# 6. Mount removable storage and transfer (replace $SD_PARTITION_DEV with your actual device file handle, as in /dev/sda1, etc.) +root@host:~$ mount -t exfat "${SD_PARTITION_DEV}" /mnt +root@host:~$ cp airgap-bundle.* /mnt/ root@host:~$ umount /mnt ``` -**Important.** With offline packages in hand, you may consider repeating the prior section (*1.2.1. Acquiring the target image*) to provide yourself with another "clean plate" (one that's never been connected to the Internet) before continuing. +**Note.** With offline packages now in hand, you might consider repeating the prior section (*1.2.1. Acquiring the target image*) to provide yourself with another "clean plate" (one that's never been connected to the Internet) before continuing. Pragmatically speaking, you can also just "wash the plate" by re-imaging Alpine Linux over the selfsame SD card used in this step to download packages. -**CI/CD Considerations.** It is curate a clean, custom bootable image of Alpine Linux with these same offline packages using a CI/CD pipeline if carefully designed to also demonstrate software provenance and image signing before release. +## 2. Boot the Secure Environment -## Stage 2. Using the Secure Environment +The newly provisioned Alpine Linux environment should now be booted, free of any extraneous peripheral attachments, with networking completely disabled. -At this point, the newly provisioned secure environment should be booted, free of any extraneous peripheral attachments, with networking completely disabled. +Additional setup tasks may include: -Post-installation packages should be readily available (e.g., written to its boot partition for the preceding in intermediate environment) and cryptographically re-verified cryptographically before continuing with offline installation. - -Additional setup requirements within the secure environment may include: - -- Manually setting the system date +- Manually setting the system date (`date -s "$CURRENT_UTC_TIMESTAMP"`) - Setting the keyboard language and layout -- Configuring the local GPG system -- Adding entropy sources -- Importing keys ### 2.1 Install Offline Packages for GnuPG After booting into the secure environment, the user proceeds to verify the SHA256 checksums of the previously GPG-verified APK packages download to removable storage: ```shell -root@host:~$ date -s 'YYYY-MM-DD hh:mm:ss' -root@host:~$ mount -t exfat /dev/sda1 /mnt -root@host:~$ cp /mnt/gpg-bundle.* . -root@host:~$ umount /mnt -root@host:~$ sha256sum -c gpg-bundle.tar.gz.sha256 && tar -xzvf gpg-bundle-tar-gz +root@host:~$ mkdir work && cd work +root@host:~/work$ mount -t exfat "${SD_PARTITION_DEV}" /mnt +root@host:~/work$ cp /mnt/airgap-bundle.* . +root@host:~/work$ umount /mnt ``` -Once verified and extracted from the tarball, the user issues the following command within the package subdirectory to install them: +The following command provides strict coupling (`&&`) between the cryptographic verification of the bundle created earlier, and its subsequent extraction. If the checksum is invalid, the tarball will not be extracted and the `apk` command that follows is expected to fail. ```shell -root@host:~$ apk --allow-untrusted --force-non-repository add *.apk +# Require sha256sum to pass before extracting and installing with `apk` +root@host:~/work$ sha256sum -c airgap-bundle.tar.gz.sha256 \ + && tar -xzvf airgap-bundle-tar-gz \ + && apk --allow-untrusted --force-non-repository add *.apk ``` +**CI/CD Considerations.** For DevOps teams, this concludes the essential requirements for provisioning an Alpine Linux image with an offline copy of packages for GPG key management. In the interest of transparency, be sure to include any relevant steps and artifacts in your software provenance and image signing before releasing. + ### 2.2 Verify the Environment -At this point, the user can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in their new environment: +Assuming package installation is successfully, begin verifying the environment for GPG use: + +**Note.** If you have a YubiKey, go ahead and insert it now. ```shell -root@host:~$ gpg --import yubikey.pub +# Verify GPG installation +root@host:~$ gpg --version + +# Verify smartcard connection root@host:~$ gpg --card-status -root@host:~$ gpg --list-secret-keys + +# Import corresponding public key to view all details +root@host:~$ gpg --import yubikey.pub +root@host:~$ gpg --list-sigs "$YUBIKEY_FINGERPRINT" +root@host:~$ gpg --list-secret-keys "$YUBIKEY_FINGERPRINT" ``` -**Important.** If you run into issues detecting your YubiKey switching between `$GNUPGHOME` directories (common during heavy key management operations such as ring transfers, etc.), try restarting the `gpg-agent` as follows: +**Note.** If you run into issues detecting your YubiKey switching between `$GNUPGHOME` directories (common during heavy key management operations such as ring transfers, etc.), try restarting the `gpg-agent` as follows: ```shell root@host:~$ pkill gpg-agent root@host:~$ gpg --card-status ``` +**All done!** You can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in your new air-gapped environment! + ## Stage 3. Takedown -When finished performing tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file +When finished performing key management tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file From 454cf8e0bf857fd9545bc6fd395aacceac25937f Mon Sep 17 00:00:00 2001 From: Matt Borja <3855027+mattborja@users.noreply.github.com> Date: Fri, 23 May 2025 02:47:09 +0000 Subject: [PATCH 12/14] Include recommendation for sourcing offline copy of gpg.conf to avert needing an Internet connection in post --- SECENV.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/SECENV.md b/SECENV.md index 2a8ed9d..1777367 100644 --- a/SECENV.md +++ b/SECENV.md @@ -23,11 +23,12 @@ Preparing a secure environment for GPG normally involves the initial use of an e As mentioned before, this environment alone may arguably be considered satisfactory for GPG purposes, but it is out of an abundance of caution we are limiting our use of it for verification and imaging purposes only. -### 1.2. Use the target OS to download packages - -If you haven't already, follow the [Tails installation guide](https://tails.net/install/expert/index.en.html) *carefully* to ensure you have [verified](https://tails.net/install/expert/index.en.html#verify-key) and booted into a valid Tails environment before continuing. +### 1.2. Use the target OS to download packages and gpg.conf +The goal of this section is to have all the necessary assets in hand to avert the need for an Internet connection post-installation towards the end of this guide. #### 1.2.1. Acquire the target image +If you haven't already, follow the [Tails installation guide](https://tails.net/install/expert/index.en.html) *carefully* to ensure you have [verified](https://tails.net/install/expert/index.en.html#verify-key) and booted into a valid Tails environment before continuing. + Next, import a copy of [Alpine Linux](https://alpinelinux.org/downloads/) by either: - Connecting Tails to the Internet and using the Tor Browser to download the image - Leaving Tails disconnected from the Internet and instead using another device (e.g., smartphone) to bring over the downloaded image using a removable storage device @@ -38,7 +39,11 @@ Next, import a copy of [Alpine Linux](https://alpinelinux.org/downloads/) by eit Once you've verified the image download, you can use the **Restore Disk Image...** in the *Disks* utility from within Tails to write the image to a target disk (e.g., SD card for a Raspberry Pi). -#### 1.2.2. Boot the target image to download OS-specific packages for GnuPG +#### 1.2.2. Download a copy of gpg.conf (hardened) + +While still connected to the Internet, consider downloading a copy of a hardened version of gpg.conf ([example](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf) to add to your `$GNUPGHOME` on initial boot into the secure environment. + +#### 1.2.3. Boot the target image to download OS-specific packages for GnuPG Boot into the Alpine Linux system, login as `root`, and connect to the Internet to download the required packages for this specific platform: @@ -102,6 +107,8 @@ root@host:~/work$ sha256sum -c airgap-bundle.tar.gz.sha256 \ && apk --allow-untrusted --force-non-repository add *.apk ``` +**Don't forget!** If you obtained a copy of [gpg.conf](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf), be sure to import it into your `$GNUPGHOME` before continuing. + **CI/CD Considerations.** For DevOps teams, this concludes the essential requirements for provisioning an Alpine Linux image with an offline copy of packages for GPG key management. In the interest of transparency, be sure to include any relevant steps and artifacts in your software provenance and image signing before releasing. ### 2.2 Verify the Environment @@ -129,7 +136,7 @@ root@host:~$ pkill gpg-agent root@host:~$ gpg --card-status ``` -**All done!** You can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#prepare-gnupg) and smart cards in your new air-gapped environment! +**All done!** You can now begin [working with GPG](https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#identity) and smart cards in your new air-gapped environment! ## Stage 3. Takedown When finished performing key management tasks, the secure environment should either be a) promptly destroyed or b) properly secured away; to close the window on unknown threats to a dormant system (e.g., physical, technological, theoretical, unknown). \ No newline at end of file From 7e3f6f76470276e8c4523cf36f44eef24c185e6d Mon Sep 17 00:00:00 2001 From: Matt Borja <3855027+mattborja@users.noreply.github.com> Date: Fri, 23 May 2025 02:47:52 +0000 Subject: [PATCH 13/14] Add missing closing parenthesis --- SECENV.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECENV.md b/SECENV.md index 1777367..fe67076 100644 --- a/SECENV.md +++ b/SECENV.md @@ -41,7 +41,7 @@ Once you've verified the image download, you can use the **Restore Disk Image... #### 1.2.2. Download a copy of gpg.conf (hardened) -While still connected to the Internet, consider downloading a copy of a hardened version of gpg.conf ([example](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf) to add to your `$GNUPGHOME` on initial boot into the secure environment. +While still connected to the Internet, consider downloading a copy of a hardened version of gpg.conf ([example](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf)) to add to your `$GNUPGHOME` on initial boot into the secure environment. #### 1.2.3. Boot the target image to download OS-specific packages for GnuPG From bc9a7a8954fce61faf3e00995c707c0c28894fe1 Mon Sep 17 00:00:00 2001 From: Matt Borja <3855027+mattborja@users.noreply.github.com> Date: Fri, 23 May 2025 02:49:49 +0000 Subject: [PATCH 14/14] =?UTF-8?q?Update=20verbiage=20for=20read=20flow=20(?= =?UTF-8?q?=E2=80=9Cobtained=20in=20advance=E2=80=9D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SECENV.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECENV.md b/SECENV.md index fe67076..8843512 100644 --- a/SECENV.md +++ b/SECENV.md @@ -107,7 +107,7 @@ root@host:~/work$ sha256sum -c airgap-bundle.tar.gz.sha256 \ && apk --allow-untrusted --force-non-repository add *.apk ``` -**Don't forget!** If you obtained a copy of [gpg.conf](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf), be sure to import it into your `$GNUPGHOME` before continuing. +**Don't forget!** If you obtained a copy of [gpg.conf](https://github.com/drduh/YubiKey-Guide/blob/master/config/gpg.conf) in advance, be sure to import it into your `$GNUPGHOME` before continuing. **CI/CD Considerations.** For DevOps teams, this concludes the essential requirements for provisioning an Alpine Linux image with an offline copy of packages for GPG key management. In the interest of transparency, be sure to include any relevant steps and artifacts in your software provenance and image signing before releasing.