mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2025-01-03 03:31:04 -05:00
672 lines
26 KiB
ReStructuredText
672 lines
26 KiB
ReStructuredText
|
=========
|
|||
|
Split GPG
|
|||
|
=========
|
|||
|
|
|||
|
|
|||
|
Split GPG implements a concept similar to having a smart card with your
|
|||
|
private GPG keys, except that the role of the “smart card” is played by
|
|||
|
another Qubes app qube. This way one not-so-trusted domain, e.g. the one
|
|||
|
where Thunderbird is running, can delegate all crypto operations – such
|
|||
|
as encryption/decryption and signing – to another, more trusted,
|
|||
|
network-isolated domain. This way the compromise of your domain where
|
|||
|
Thunderbird or another client app is running – arguably a
|
|||
|
not-so-unthinkable scenario – does not allow the attacker to
|
|||
|
automatically also steal all your keys. (We should make a rather obvious
|
|||
|
comment here that the so-often-used passphrases on private keys are
|
|||
|
pretty meaningless because the attacker can easily set up a simple
|
|||
|
backdoor which would wait until the user enters the passphrase and steal
|
|||
|
the key then.)
|
|||
|
|
|||
|
|split-gpg-diagram.png|
|
|||
|
|
|||
|
This diagram presents an overview of the Split GPG architecture.
|
|||
|
|
|||
|
Advantages of Split GPG vs. traditional GPG with a smart card
|
|||
|
-------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
It is often thought that the use of smart cards for private key storage
|
|||
|
guarantees ultimate safety. While this might be true (unless the
|
|||
|
attacker can find a
|
|||
|
usually-very-expensive-and-requiring-physical-presence way to extract
|
|||
|
the key from the smart card) but only with regards to the safety of the
|
|||
|
private key itself. However, there is usually nothing that could stop
|
|||
|
the attacker from requesting the smart card to perform decryption of all
|
|||
|
the user documents the attacker has found or need to decrypt. In other
|
|||
|
words, while protecting the user’s private key is an important task, we
|
|||
|
should not forget that ultimately it is the user data that are to be
|
|||
|
protected and that the smart card chip has no way of knowing the
|
|||
|
requests to decrypt documents are now coming from the attacker’s script
|
|||
|
and not from the user sitting in front of the monitor. (Similarly the
|
|||
|
smart card doesn’t make the process of digitally signing a document or a
|
|||
|
transaction in any way more secure – the user cannot know what the chip
|
|||
|
is really signing. Unfortunately this problem of signing reliability is
|
|||
|
not solvable by Split GPG)
|
|||
|
|
|||
|
With Qubes Split GPG this problem is drastically minimized, because each
|
|||
|
time the key is to be used the user is asked for consent (with a
|
|||
|
definable time out, 5 minutes by default), plus is always notified each
|
|||
|
time the key is used via a tray notification from the domain where GPG
|
|||
|
backend is running. This way it would be easy to spot unexpected
|
|||
|
requests to decrypt documents.
|
|||
|
|
|||
|
|r2-split-gpg-1.png| |r2-split-gpg-3.png|
|
|||
|
|
|||
|
Configuring Split GPG
|
|||
|
---------------------
|
|||
|
|
|||
|
|
|||
|
In dom0, make sure the ``qubes-gpg-split-dom0`` package is installed.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@dom0 ~]$ sudo qubes-dom0-update qubes-gpg-split-dom0
|
|||
|
|
|||
|
|
|||
|
Make sure you have the ``qubes-gpg-split`` package installed in the
|
|||
|
template you will use for the GPG domain.
|
|||
|
|
|||
|
For Debian or Whonix:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@debian-10 ~]$ sudo apt install qubes-gpg-split
|
|||
|
|
|||
|
|
|||
|
|
|||
|
For Fedora:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@fedora-32 ~]$ sudo dnf install qubes-gpg-split
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Setting up the GPG backend domain
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
First, create a dedicated app qube for storing your keys (we will be
|
|||
|
calling it the GPG backend domain). It is recommended that this domain
|
|||
|
be network disconnected (set its netvm to ``none``) and only used for
|
|||
|
this one purpose. In later examples this app qube is named ``work-gpg``,
|
|||
|
but of course it might have any other name.
|
|||
|
|
|||
|
Make sure that gpg is installed there. At this stage you can add the
|
|||
|
private keys you want to store there, or you can now set up Split GPG
|
|||
|
and add the keys later. To check which private keys are in your GPG
|
|||
|
keyring, use:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-gpg ~]$ gpg -K
|
|||
|
/home/user/.gnupg/secring.gpg
|
|||
|
-----------------------------
|
|||
|
sec 4096R/3F48CB21 2012-11-15
|
|||
|
uid Qubes OS Security Team <security@qubes-os.org>
|
|||
|
ssb 4096R/30498E2A 2012-11-15
|
|||
|
(...)
|
|||
|
|
|||
|
|
|||
|
This is pretty much all that is required. However, you might want to
|
|||
|
modify the default timeout: this tells the backend for how long the
|
|||
|
user’s approval for key access should be valid. (The default is 5
|
|||
|
minutes.) You can change this via the ``QUBES_GPG_AUTOACCEPT``
|
|||
|
environment variable. You can override it e.g. in ``~/.profile``:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-gpg ~]$ echo "export QUBES_GPG_AUTOACCEPT=86400" >> ~/.profile
|
|||
|
|
|||
|
|
|||
|
Please note that previously, this parameter was set in ~/.bash_profile.
|
|||
|
This will no longer work. If you have the parameter set in
|
|||
|
~/.bash_profile you *must* update your configuration.
|
|||
|
|
|||
|
Please be aware of the caveat regarding passphrase-protected keys in the
|
|||
|
`Current limitations <#current-limitations>`__ section.
|
|||
|
|
|||
|
Configuring the client apps to use Split GPG backend
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
Normally it should be enough to set the ``QUBES_GPG_DOMAIN`` to the GPG
|
|||
|
backend domain name and use ``qubes-gpg-client`` in place of ``gpg``,
|
|||
|
e.g.:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ export QUBES_GPG_DOMAIN=work-gpg
|
|||
|
[user@work-email ~]$ gpg -K
|
|||
|
[user@work-email ~]$ qubes-gpg-client -K
|
|||
|
/home/user/.gnupg/secring.gpg
|
|||
|
-----------------------------
|
|||
|
sec 4096R/3F48CB21 2012-11-15
|
|||
|
uid Qubes OS Security Team <security@qubes-os.org>
|
|||
|
ssb 4096R/30498E2A 2012-11-15
|
|||
|
(...)
|
|||
|
|
|||
|
[user@work-email ~]$ qubes-gpg-client secret_message.txt.asc
|
|||
|
(...)
|
|||
|
|
|||
|
|
|||
|
Note that running normal ``gpg -K`` in the demo above shows no private
|
|||
|
keys stored in this app qube.
|
|||
|
|
|||
|
A note on ``gpg`` and ``gpg2``:
|
|||
|
|
|||
|
Throughout this guide, we refer to ``gpg``, but note that Split GPG uses
|
|||
|
``gpg2`` under the hood for compatibility with programs like Enigmail
|
|||
|
(which now supports only ``gpg2``). If you encounter trouble while
|
|||
|
trying to set up Split GPG, make sure you’re using ``gpg2`` for your
|
|||
|
configuration and testing, since keyring data may differ between the two
|
|||
|
installations.
|
|||
|
|
|||
|
Advanced Configuration
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
The ``qubes-gpg-client-wrapper`` script sets the ``QUBES_GPG_DOMAIN``
|
|||
|
variable automatically based on the content of the file
|
|||
|
``/rw/config/gpg-split-domain``, which should be set to the name of the
|
|||
|
GPG backend VM. This file survives the app qube reboot, of course.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ sudo bash
|
|||
|
[root@work-email ~]$ echo "work-gpg" > /rw/config/gpg-split-domain
|
|||
|
|
|||
|
|
|||
|
Split GPG’s default qrexec policy requires the user to enter the name of
|
|||
|
the app qube containing GPG keys on each invocation. To improve
|
|||
|
usability for applications like Thunderbird with Enigmail, in ``dom0``
|
|||
|
place the following line at the top of the file
|
|||
|
``/etc/qubes-rpc/policy/qubes.Gpg``:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
work-email work-gpg allow
|
|||
|
|
|||
|
|
|||
|
|
|||
|
where ``work-email`` is the Thunderbird + Enigmail app qube and
|
|||
|
``work-gpg`` contains your GPG keys.
|
|||
|
|
|||
|
You may also edit the qrexec policy file for Split GPG in order to tell
|
|||
|
Qubes your default gpg vm (qrexec prompts will appear with the gpg vm
|
|||
|
preselected as the target, instead of the user needing to type a name in
|
|||
|
manually). To do this, append ``default_target=<vmname>`` to ``ask`` in
|
|||
|
``/etc/qubes-rpc/policy/qubes.Gpg``. For the examples given on this
|
|||
|
page:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
@anyvm @anyvm ask default_target=work-gpg
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Note that, because this makes it easier to accept Split GPG’s qrexec
|
|||
|
authorization prompts, it may decrease security if the user is not
|
|||
|
careful in reviewing presented prompts. This may also be inadvisable if
|
|||
|
there are multiple app qubes with Split GPG set up.
|
|||
|
|
|||
|
Using Thunderbird
|
|||
|
-----------------
|
|||
|
|
|||
|
|
|||
|
Thunderbird 78 and higher
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
Starting with version 78, Thunderbird has a built-in PGP feature and no
|
|||
|
longer requires the Enigmail extension. For users coming from the
|
|||
|
Enigmail extension, the built-in functionality is more limited
|
|||
|
currently, including that **public keys must live in your ``work-email`` qube with Thunderbird rather than your offline ``work-gpg`` qube**.
|
|||
|
|
|||
|
In ``work-email``, use the Thunderbird config editor (found at the
|
|||
|
bottom of preferences/options), and search for
|
|||
|
``mail.openpgp.allow_external_gnupg``. Switch the value to true. Still
|
|||
|
in config editor, search for ``mail.openpgp.alternative_gpg_path``. Set
|
|||
|
its value to ``/usr/bin/qubes-gpg-client-wrapper``. Restart Thunderbird
|
|||
|
after this change.
|
|||
|
|
|||
|
|tb78-1.png| |tb78-2.png| |tb78-3.png|
|
|||
|
|
|||
|
You need to obtain your key ID which should be **exactly 16 characters**. Enter the command
|
|||
|
``qubes-gpg-client-wrapper -K --keyid-format long``:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ qubes-gpg-client-wrapper -K --keyid-format long
|
|||
|
/home/user/.gnupg/pubring.kbx
|
|||
|
-----------------------------
|
|||
|
sec rsa2048/777402E6D301615C 2020-09-05 [SC] [expires: 2022-09-05]
|
|||
|
F7D2D4E922DFB7B2589AF3E9777402E6D301615C
|
|||
|
uid [ultimate] Qubes test <user@localhost>
|
|||
|
ssb rsa2048/370CE932085BA13B 2020-09-05 [E] [expires: 2022-09-05]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ qubes-gpg-client-wrapper --armor --export 777402E6D301615C > 777402E6D301615C.asc
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Open the Account Settings and open the *End-to-End Encryption* tab of
|
|||
|
the respective email account. Click the *Add Key* button. You’ll be
|
|||
|
offered the choice *Use your external key through GnuPG*. Select it and
|
|||
|
click Continue.
|
|||
|
|
|||
|
|tb78-4.png| |tb78-5.png|
|
|||
|
|
|||
|
The key ID reference you would need here is ``777402E6D301615C``. Now
|
|||
|
paste or type the ID of the secret key that you would like to use. Be
|
|||
|
careful to enter it correctly, because your input isn’t verified.
|
|||
|
Confirm to save this key ID. Now you can select the key ID to use.
|
|||
|
|
|||
|
|tb78-6.png| |tb78-7.png|
|
|||
|
|
|||
|
This key ID will be used to digitally sign or send an encrypted message
|
|||
|
with your account. For this to work, Thunderbird needs a copy of your
|
|||
|
public key. At this time, Thunderbird doesn’t fetch the public key from
|
|||
|
``/usr/bin/qubes-gpg-client-wrapper``, you must manually import it.
|
|||
|
Export the key as follow (assuming the key ID would be
|
|||
|
``777402E6D301615C``):
|
|||
|
|
|||
|
|tb78-8.png| |tb78-9.png|
|
|||
|
|
|||
|
Use Thunderbird’s Tools menu to open *OpenPGP Key Management*. In that
|
|||
|
window, use the File menu to access the *Import Public Key(s) From File*
|
|||
|
command. Open the file with your public key. After the import was
|
|||
|
successful, right click on the imported key in the list and select *Key Properties*. You must mark your own key as *Yes, I’ve verified in person this key has the correct fingerprint*.
|
|||
|
|
|||
|
Once this is done, you should be able to send an encrypted and signed
|
|||
|
email by selecting *Require Encryption* or *Digitally Sign This Message*
|
|||
|
in the compose menu *Options* or *Security* toolbar button. You can try
|
|||
|
it by sending an email to yourself.
|
|||
|
|
|||
|
|tb78-10.png|
|
|||
|
|
|||
|
For more details about using smart cards/Split GPG with Thunderbird PGP
|
|||
|
feature, please see
|
|||
|
`Thunderbird:OpenPGP:Smartcards <https://wiki.mozilla.org/Thunderbird:OpenPGP:Smartcards>`__
|
|||
|
from which the above documentation is inspired.
|
|||
|
|
|||
|
Older Thunderbird versions
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
For Thunderbird versions below 78, the traditional Enigmail + Split GPG
|
|||
|
setup is required. It is recommended to set up and use
|
|||
|
``/usr/bin/qubes-gpg-client-wrapper``, as discussed above, in
|
|||
|
Thunderbird through the Enigmail addon.
|
|||
|
|
|||
|
**Warning:** Before adding any account, configuring Enigmail with
|
|||
|
``/usr/bin/qubes-gpg-client-wrapper`` is **required**. By default,
|
|||
|
Enigmail will generate a default GPG key in ``work-email`` associated
|
|||
|
with the newly created Thunderbird account. Generally, it corresponds to
|
|||
|
the email used in ``work-gpg`` associated to your private key. In
|
|||
|
consequence, a new, separate private key will be stored in
|
|||
|
``work-email`` but it *does not* correspond to your private key in
|
|||
|
``work-gpg``. Comparing the ``fingerprint`` or ``expiration date`` will
|
|||
|
show that they are not the same private key. In order to prevent
|
|||
|
Enigmail using this default generated local key in ``work-email``, you
|
|||
|
can safely remove it.
|
|||
|
|
|||
|
On a fresh Enigmail install, your need to change the default
|
|||
|
``Enigmail Junior Mode``. Go to Thunderbird preferences and then privacy
|
|||
|
tab. Select ``Force using S/MIME and Enigmail``. Then, in the
|
|||
|
preferences of Enigmail, make it point to
|
|||
|
``/usr/bin/qubes-gpg-client-wrapper`` instead of the standard GnuPG
|
|||
|
binary:
|
|||
|
|
|||
|
|tb-enigmail-split-gpg-settings-2.png|
|
|||
|
|
|||
|
Using Keybase with Split GPG
|
|||
|
----------------------------
|
|||
|
|
|||
|
|
|||
|
Keybase, a security focused messaging and file-sharing app with GPG
|
|||
|
integration, can be configured to use Split GPG.
|
|||
|
|
|||
|
The Keybase service does not preserve/pass the ``QUBES_GPG_DOMAIN``
|
|||
|
environment variable through to underlying GPG processes, so it **must**
|
|||
|
be configured to use ``/usr/bin/qubes-gpg-client-wrapper`` (as discussed
|
|||
|
above) rather than ``/usr/bin/qubes-gpg-client``.
|
|||
|
|
|||
|
The following command will configure Keybase to use
|
|||
|
``/usr/bin/qubes-gpg-client-wrapper`` instead of its built-in GPG
|
|||
|
client:
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
$ keybase config set gpg.command /usr/bin/qubes-gpg-client-wrapper
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Now that Keybase is configured to use ``qubes-gpg-client-wrapper``, you
|
|||
|
will be able to use ``keybase pgp select`` to choose a GPG key from your
|
|||
|
backend GPG app qube and link that key to your Keybase identity.
|
|||
|
|
|||
|
Using Git with Split GPG
|
|||
|
------------------------
|
|||
|
|
|||
|
|
|||
|
Git can be configured to utilize Split GPG, something useful if you
|
|||
|
would like to contribute to the Qubes OS Project as every commit is
|
|||
|
required to be signed. The most basic ``~/.gitconfig`` file enabling
|
|||
|
Split GPG looks something like this.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user]
|
|||
|
name = <YOUR_NAME>
|
|||
|
email = <YOUR_EMAIL_ADDRESS>
|
|||
|
signingKey = <YOUR_KEY_ID>
|
|||
|
|
|||
|
[gpg]
|
|||
|
program = qubes-gpg-client-wrapper
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Your key id is the public id of your signing key, which can be found by
|
|||
|
running ``qubes-gpg-client --list-keys``. In this instance, the key id
|
|||
|
is E142F75A6B1B610E0E8F874FB45589245791CACB.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ qubes-gpg-client --list-keys
|
|||
|
/home/user/.gnupg/pubring.kbx
|
|||
|
-----------------------------
|
|||
|
pub ed25519 2022-08-16 [C]
|
|||
|
E142F75A6B1B610E0E8F874FB45589245791CACB
|
|||
|
uid [ultimate] Qubes User <user@example.com>
|
|||
|
sub ed25519 2022-08-16 [S]
|
|||
|
sub cv25519 2022-08-16 [E]
|
|||
|
sub ed25519 2022-08-16 [A]
|
|||
|
|
|||
|
|
|||
|
To sign commits, you now add the “-S” flag to your commit command, which
|
|||
|
should prompt for Split GPG usage. If you would like to automatically
|
|||
|
sign all commits, you can add the following snippet to ``~/.gitconfig``.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[commit]
|
|||
|
gpgSign = true
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Lastly, if you would like to add aliases to sign and verify tags using
|
|||
|
the conventions the Qubes OS Project recommends, refer to the :ref:`code signing documentation <developer/code/code-signing:using pgp with git>`.
|
|||
|
|
|||
|
Importing public keys
|
|||
|
---------------------
|
|||
|
|
|||
|
|
|||
|
Use ``qubes-gpg-import-key`` in the client app qube to import the key
|
|||
|
into the GPG backend VM.
|
|||
|
|
|||
|
.. code:: bash
|
|||
|
|
|||
|
[user@work-email ~]$ export QUBES_GPG_DOMAIN=work-gpg
|
|||
|
[user@work-email ~]$ qubes-gpg-import-key ~/Downloads/marmarek.asc
|
|||
|
|
|||
|
|
|||
|
A safe, unspoofable user consent dialog box is displayed.
|
|||
|
|
|||
|
|r2-split-gpg-5.png|
|
|||
|
|
|||
|
Selecting “Yes to All” will add a line in the corresponding :doc:`RPC Policy </user/advanced-topics/rpc-policy>` file.
|
|||
|
|
|||
|
Advanced: Using Split GPG with Subkeys
|
|||
|
--------------------------------------
|
|||
|
|
|||
|
|
|||
|
Users with particularly high security requirements may wish to use Split
|
|||
|
GPG with `subkeys <https://wiki.debian.org/Subkeys>`__. However, this
|
|||
|
setup comes at a significant cost: It will be impossible to sign other
|
|||
|
people’s keys with the master secret key without breaking this security
|
|||
|
model. Nonetheless, if signing others’ keys is not required, then Split
|
|||
|
GPG with subkeys offers unparalleled security for one’s master secret
|
|||
|
key.
|
|||
|
|
|||
|
Setup Description
|
|||
|
^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
In this example, the following keys are stored in the following
|
|||
|
locations (see below for definitions of these terms):
|
|||
|
|
|||
|
.. list-table::
|
|||
|
:widths: 10 10
|
|||
|
:align: center
|
|||
|
:header-rows: 1
|
|||
|
|
|||
|
* - PGP Key(s)
|
|||
|
- VM Name
|
|||
|
* - sec
|
|||
|
- vault
|
|||
|
* - ssb
|
|||
|
- work-gpg
|
|||
|
* - pub
|
|||
|
- work-email
|
|||
|
|
|||
|
|
|||
|
|
|||
|
- ``sec`` (master secret key)
|
|||
|
Depending on your needs, you may wish to create this as a
|
|||
|
**certify-only (C)** key, i.e., a key which is capable only of
|
|||
|
signing (a.k.a., “certifying”) other keys. This key may be created
|
|||
|
*without* an expiration date. This is for two reasons. First, the
|
|||
|
master secret key is never to leave the ``vault`` VM, so it is
|
|||
|
extremely unlikely ever to be obtained by an adversary (see below).
|
|||
|
Second, an adversary who *does* manage to obtain the master secret
|
|||
|
key either possesses the passphrase to unlock the key (if one is
|
|||
|
used) or does not. An adversary who *does* possess the passphrase can
|
|||
|
simply use it to legally extend the expiration date of the key (or
|
|||
|
remove it entirely). An adversary who does *not* possess the
|
|||
|
passphrase cannot use the key at all. In either case, an expiration
|
|||
|
date provides no additional benefit.
|
|||
|
By the same token, however, having a passphrase on the key is of
|
|||
|
little value. An adversary who is capable of stealing the key from
|
|||
|
your ``vault`` would almost certainly also be capable of stealing the
|
|||
|
passphrase as you enter it. An adversary who obtains the passphrase
|
|||
|
can then use it in order to change or remove the passphrase from the
|
|||
|
key. Therefore, using a passphrase at all should be considered
|
|||
|
optional. It is, however, recommended that a **revocation certificate** be created and safely stored in multiple locations so
|
|||
|
that the master keypair can be revoked in the (exceedingly unlikely)
|
|||
|
event that it is ever compromised.
|
|||
|
|
|||
|
- ``ssb`` (secret subkey)
|
|||
|
Depending on your needs, you may wish to create two different
|
|||
|
subkeys: one for **signing (S)** and one for **encryption (E)**. You
|
|||
|
may also wish to give these subkeys reasonable expiration dates
|
|||
|
(e.g., one year). Once these keys expire, it is up to you whether to
|
|||
|
*renew* these keys by extending the expiration dates or to create
|
|||
|
*new* subkeys when the existing set expires.
|
|||
|
On the one hand, an adversary who obtains any existing encryption
|
|||
|
subkey (for example) will be able to use it in order to decrypt all
|
|||
|
emails (for example) which were encrypted to that subkey. If the same
|
|||
|
subkey were to continue to be used–and its expiration date
|
|||
|
continually extended–only that one key would need to be stolen (e.g.,
|
|||
|
as a result of the ``work-gpg`` VM being compromised; see below) in
|
|||
|
order to decrypt *all* of the user’s emails. If, on the other hand,
|
|||
|
each encryption subkey is used for at most approximately one year,
|
|||
|
then an adversary who obtains the secret subkey will be capable of
|
|||
|
decrypting at most approximately one year’s worth of emails.
|
|||
|
On the other hand, creating a new signing subkey each year without
|
|||
|
renewing (i.e., extending the expiration dates of) existing signing
|
|||
|
subkeys would mean that all of your old signatures would eventually
|
|||
|
read as “EXPIRED” whenever someone attempts to verify them. This can
|
|||
|
be problematic, since there is no consensus on how expired signatures
|
|||
|
should be handled. Generally, digital signatures are intended to last
|
|||
|
forever, so this is a strong reason against regularly retiring one’s
|
|||
|
signing subkeys.
|
|||
|
|
|||
|
- ``pub`` (public key)
|
|||
|
This is the complement of the master secret key. It can be uploaded
|
|||
|
to keyservers (or otherwise publicly distributed) and may be signed
|
|||
|
by others.
|
|||
|
|
|||
|
- ``vault``
|
|||
|
This is a network-isolated VM. The initial master keypair and subkeys
|
|||
|
are generated in this VM. The master secret key *never* leaves this
|
|||
|
VM under *any* circumstances. No files or text is *ever*
|
|||
|
:ref:`copied <user/how-to-guides/how-to-copy-and-move-files:security>` or
|
|||
|
:ref:`pasted <user/how-to-guides/how-to-copy-and-paste-text:security>` into this VM
|
|||
|
under *any* circumstances.
|
|||
|
|
|||
|
- ``work-gpg``
|
|||
|
This is a network-isolated VM. This VM is used *only* as the GPG
|
|||
|
backend for ``work-email``. The secret subkeys (but *not* the master
|
|||
|
secret key) are
|
|||
|
:ref:`copied <user/how-to-guides/how-to-copy-and-move-files:security>` from the
|
|||
|
``vault`` VM to this VM. Files from less trusted VMs are *never*
|
|||
|
:ref:`copied <user/how-to-guides/how-to-copy-and-move-files:security>` into this VM
|
|||
|
under *any* circumstances.
|
|||
|
|
|||
|
- ``work-email``
|
|||
|
This VM has access to the mail server. It accesses the ``work-gpg``
|
|||
|
VM via the Split GPG protocol. The public key may be stored in this
|
|||
|
VM so that it can be attached to emails and for other such purposes.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Security Benefits
|
|||
|
^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
In the standard Split GPG setup, there are at least two ways in which
|
|||
|
the ``work-gpg`` VM might be compromised. First, an attacker who is
|
|||
|
capable of exploiting a hypothetical bug in ``work-email``’s
|
|||
|
`MUA <https://en.wikipedia.org/wiki/Mail_user_agent>`__ could gain
|
|||
|
control of the ``work-email`` VM and send a malformed request which
|
|||
|
exploits a hypothetical bug in the GPG backend (running in the
|
|||
|
``work-gpg`` VM), giving the attacker control of the ``work-gpg`` VM.
|
|||
|
Second, a malicious public key file which is imported into the
|
|||
|
``work-gpg`` VM might exploit a hypothetical bug in the GPG backend
|
|||
|
which is running there, again giving the attacker control of the
|
|||
|
``work-gpg`` VM. In either case, such an attacker might then be able to
|
|||
|
leak both the master secret key and its passphrase (if any is used, it
|
|||
|
would regularly be input in the work-gpg VM and therefore easily
|
|||
|
obtained by an attacker who controls this VM) back to the ``work-email``
|
|||
|
VM or to another VM (e.g., the ``netvm``, which is always untrusted by
|
|||
|
default) via the Split GPG protocol or other :doc:`covert channels </user/security-in-qubes/data-leaks>`. Once the master secret key is in the
|
|||
|
``work-email`` VM, the attacker could simply email it to himself (or to
|
|||
|
the world).
|
|||
|
|
|||
|
In the alternative setup described in this section (i.e., the subkey
|
|||
|
setup), even an attacker who manages to gain access to the ``work-gpg``
|
|||
|
VM will not be able to obtain the user’s master secret key since it is
|
|||
|
simply not there. Rather, the master secret key remains in the ``vault``
|
|||
|
VM, which is extremely unlikely to be compromised, since nothing is ever
|
|||
|
copied or transferred into it. [1]_ The attacker might nonetheless be
|
|||
|
able to leak the secret subkeys from the ``work-gpg`` VM in the manner
|
|||
|
described above, but even if this is successful, the secure master
|
|||
|
secret key can simply be used to revoke the compromised subkeys and to
|
|||
|
issue new subkeys in their place. (This is significantly less
|
|||
|
devastating than having to create a new *master* keypair.)
|
|||
|
|
|||
|
Subkey Tutorials and Discussions
|
|||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|||
|
|
|||
|
|
|||
|
(Note: Although the tutorials below were not written with Qubes Split
|
|||
|
GPG in mind, they can be adapted with a few commonsense adjustments. As
|
|||
|
always, exercise caution and use your good judgment.)
|
|||
|
|
|||
|
- `“OpenPGP in Qubes OS” on the qubes-users mailing list <https://groups.google.com/d/topic/qubes-users/Kwfuern-R2U/discussion>`__
|
|||
|
|
|||
|
- `“Creating the Perfect GPG Keypair” by Alex Cabal <https://alexcabal.com/creating-the-perfect-gpg-keypair/>`__
|
|||
|
|
|||
|
- `“GPG Offline Master Key w/ smartcard” maintained by Abel Luck <https://gist.github.com/abeluck/3383449>`__
|
|||
|
|
|||
|
- `“Using GnuPG with QubesOS” by Alex <https://apapadop.wordpress.com/2013/08/21/using-gnupg-with-qubesos/>`__
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Current limitations
|
|||
|
-------------------
|
|||
|
|
|||
|
|
|||
|
- Current implementation requires importing of public keys to the vault
|
|||
|
domain. This opens up an avenue to attack the gpg running in the
|
|||
|
backend domain via a hypothetical bug in public key importing code.
|
|||
|
See ticket
|
|||
|
`#474 <https://github.com/QubesOS/qubes-issues/issues/474>`__ for
|
|||
|
more details and plans how to get around this problem, as well as the
|
|||
|
section on `using Split GPG with subkeys <#advanced-using-split-gpg-with-subkeys>`__.
|
|||
|
|
|||
|
- It doesn’t solve the problem of allowing the user to know what is to
|
|||
|
be signed before the operation gets approved. Perhaps the GPG backend
|
|||
|
domain could start a disposable and have the to-be-signed document
|
|||
|
displayed there? To Be Determined.
|
|||
|
|
|||
|
- The Split GPG client will fail to sign or encrypt if the private key
|
|||
|
in the GnuPG backend is protected by a passphrase. It will give an
|
|||
|
``Inappropriate ioctl for device`` error. Do not set passphrases for
|
|||
|
the private keys in the GPG backend domain. Doing so won’t provide
|
|||
|
any extra security anyway, as explained in the introduction and in
|
|||
|
`using Split GPG with subkeys <#advanced-using-split-gpg-with-subkeys>`__. If you are
|
|||
|
generating a new key pair, or if you have a private key that already
|
|||
|
has a passphrase, you can use ``gpg2 --edit-key <key_id>`` then
|
|||
|
``passwd`` to set an empty passphrase. Note that ``pinentry`` might
|
|||
|
show an error when you try to set an empty passphrase, but it will
|
|||
|
still make the change. (See `this StackExchange answer <https://unix.stackexchange.com/a/379373>`__ for more
|
|||
|
information.) Note: The error shows only if you **do not** have
|
|||
|
graphical pinentry installed.
|
|||
|
|
|||
|
|
|||
|
.. [1]
|
|||
|
In order to gain access to the ``vault`` VM, the attacker would
|
|||
|
require the use of, e.g., a general Xen VM escape exploit or a
|
|||
|
:ref:`signed, compromised package which is already installed in the template <user/templates/templates:trusting your templates>` upon which the
|
|||
|
``vault`` VM is based.
|
|||
|
|
|||
|
.. |split-gpg-diagram.png| image:: /attachment/doc/split-gpg-diagram.png
|
|||
|
|
|||
|
|
|||
|
.. |r2-split-gpg-1.png| image:: /attachment/doc/r2-split-gpg-1.png
|
|||
|
|
|||
|
|
|||
|
.. |r2-split-gpg-3.png| image:: /attachment/doc/r2-split-gpg-3.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-1.png| image:: /attachment/doc/tb78-1.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-2.png| image:: /attachment/doc/tb78-2.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-3.png| image:: /attachment/doc/tb78-3.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-4.png| image:: /attachment/doc/tb78-4.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-5.png| image:: /attachment/doc/tb78-5.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-6.png| image:: /attachment/doc/tb78-6.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-7.png| image:: /attachment/doc/tb78-7.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-8.png| image:: /attachment/doc/tb78-8.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-9.png| image:: /attachment/doc/tb78-9.png
|
|||
|
|
|||
|
|
|||
|
.. |tb78-10.png| image:: /attachment/doc/tb78-10.png
|
|||
|
|
|||
|
|
|||
|
.. |tb-enigmail-split-gpg-settings-2.png| image:: /attachment/doc/tb-enigmail-split-gpg-settings-2.png
|
|||
|
|
|||
|
|
|||
|
.. |r2-split-gpg-5.png| image:: /attachment/doc/r2-split-gpg-5.png
|
|||
|
|