freedomofpress / securedrop-workstation

Qubes-based SecureDrop Journalist Workstation environment for submission handling
GNU Affero General Public License v3.0
138 stars 42 forks source link

Move from GnuPG to Sequoia #812

Open eaon opened 2 years ago

eaon commented 2 years ago

Piggy backing off of https://github.com/freedomofpress/securedrop/issues/6499 on the server.

Once we determined how Rust fits into our overall strategy (including but not limited to dependency review), and especially if Sequoia support gets merged into the server, I think it would be a good idea to discuss replacing sd-gpg with a Sequoia based solution as well.

Such a move would also imply that the qubes.Gpg RPC call couldn't be used anymore, and we would need to replace it with our own.

legoktm commented 10 months ago

A few notes from this week:

legoktm commented 10 months ago
rocodes commented 10 months ago

I was curious, so I did as DemiMarie suggested and replaced gpg2 in qubes.Gpg with chameleon, and.... it worked.

Re upstream, there are still significant unimplemented methods that would still be needed to satisfy qubes-gpg-client, so this isn't a drop-in replacecment for gpg2 in Qubes. (I'm curious what's on the roadmap for chameleon, and if more commands will be implemented or not.) But for our purposes it's neat to check it out, since our gpg usage is quite basic and I think the commands we need are covered off (import --with colons doesn't print with colons using chameleon, but that's not a huge deal).

[user@disp9996 ~]$ echo $QUBES_GPG_DOMAIN
sq-gpg
[user@disp9996 ~]$ qubes-gpg-client --version
gpg (GnuPG-compatible Sequoia Chameleon) 2.2.40
Sequoia gpg Chameleon 0.3.2
sequoia-openpgp 1.17.0
Copyright (C) 2022 p≡p foundation
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/user/.gnupg
Supported algorithms:
Pubkey: RSA, DSA, ECDH, ECDSA, EDDSA
Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
[user@disp9996 ~]$ qubes-gpg-client -k
/home/user/.local/share/pgp.cert.d
----------------------------------
pub   rsa4096 2021-05-10 [SC] [expires: 2024-07-08]
      2359E6538C0613E652955E6C188EDD3B7B22E6A3
uid           [ unknown] SecureDrop Release Signing Key <securedrop-release-key-2021@freedom.press>
sub   rsa4096 2021-05-10 [E] [expires: 2024-07-08]

pub   rsa4096 2023-11-21 [SC]
      A4AD67A1CEA7F66D631CC3817DBCCDC9DA24ECF4
uid           [ultimate] testy (test key) <test@noreply.com>
sub   rsa4096 2023-11-21 [E]

[user@disp9996 ~]$ echo "sequoia rocks" > hi.txt && qubes-gpg-client --trust-model always --encrypt -r 2359E6538C0613E652955E6C188EDD3B7B22E6A3 -r test@noreply.com --armor hi.txt > hi.txt.asc
[user@disp9996 ~]$ head -n1 hi.txt.asc 
-----BEGIN PGP MESSAGE-----
[user@disp9996 ~]$ qubes-gpg-client --decrypt hi.txt.asc 
gpg: encrypted with 4096-bit RSA key, ID 6275A4BA4C71447A, created 2021-05-10
      "SecureDrop Release Signing Key <securedrop-release-key-2021@freedom.press>"
gpg: encrypted with 4096-bit RSA key, ID 18C3F3B6BA15BE14, created 2023-11-21
      "testy (test key) <test@noreply.com>"
sequoia rocks

Few examples of things that aren't implemented:

user@sq-gpg:~/sequoia-chameleon-gnupg$ gpg --full-generate-key  # it's not a qubes-gpg-client command either, I was just curious 
Greetings from the people of earth!
gpg: Command aFullKeygen is not implemented.

also

user@disp9996 ~]$ qubes-gpg-client --list-sig 
gpg: Command aListSigs is not implemented.
nwalfield commented 9 months ago

Thanks for this interesting feedback about the chameleon!

(cc: @teythoon)

there are still significant unimplemented methods that would still be needed to satisfy qubes-gpg-client

If you are thinking of using the chameleon, then it would be helpful for us if you could open an issue with the list of methods that you need so that we can prioritize them. If not, we'll get to them eventually.

I'm curious what's on the roadmap for chameleon, and if more commands will be implemented or not.

The chameleon is intended to be a drop-in replacement for gpg. So anything not yet implemented is on the to do list.

Import --with colons doesn't print with colons using chameleon, but that's not a huge deal

As an aside: please don't work around any limitations of the chameleon. These are bugs in the chameleon.

Thanks!

teythoon commented 9 months ago

I'm curious what's on the roadmap for chameleon, and if more commands will be implemented or not.

The chameleon is intended to be a drop-in replacement for gpg. So anything not yet implemented is on the to do list.

The best way to drive the chameleon development into the direction you want is to propose a test suite that it should pass.

Import --with colons doesn't print with colons using chameleon, but that's not a huge deal

As an aside: please don't work around any limitations of the chameleon. These are bugs in the chameleon.

If you find divergences, please do file bugs. In this particular case, I'm not sure there is a divergence, because GnuPG also doesn't emit colon delimited output, at least not the version I'm testing:

% /bin/gpg --with-colons --import damian.pgp
gpg: keybox '/tmp/tmp.L00Zzx1LlL/pubring.kbx' created
gpg: /tmp/tmp.L00Zzx1LlL/trustdb.gpg: trustdb created
gpg: key 10246E144519DA63: public key "damian-nils@probier.email" imported
gpg: key 10246E144519DA63: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
% /bin/gpg --version
gpg (GnuPG) 2.2.40
libgcrypt 1.10.1
Copyright (C) 2022 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /tmp/tmp.L00Zzx1LlL
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
rocodes commented 9 months ago

Hi @nwalfield @teythoon thanks so much for your fast responses :) Look forward to spending more time looking at chameleon and at Sequoia generally, and great to hear about your plans.

Qubes makes use of a wrapper around gpg2 that is called qubes-gpg-client that implements a subset of gpg2 features, so those would be the commands that would be required for Qubes users to replace gpg2 with gpg-sq.

Re: test suite-- that makes sense. I/we will file bug reports as you suggest as relevant info surfaces (although I'm not sure on what timeframe, we're definitely interested in looking at this more as capacity permits). You'd also probably have a lot of interest in your comments+work in the upstream Qubes ticket that @legoktm mentioned.

Re gpg import with-colons (debian 12, but same behaviour on debian 11):

user@deb-12-test:~$ gpg --import-options import-show --with-colons --import test.asc 
pub:-:4096:1:43B760F197CA1BF5:1488853415:::-:::scSC::::::23::0:
fpr:::::::::A55DC100FFD712ADB92B5B1043B760F197CA1BF5:
uid:-::::1488853415::D82AF4D6CF20CCE151A3AF00046E5D1C0FE15EFF::Qubes OS 4 Debian Packages Signing Key::::::::::0:
gpg: Total number processed: 1
gpg:              unchanged: 1
user@deb-12-test:~$ gpg --version
gpg (GnuPG) 2.2.40
libgcrypt 1.10.1
Copyright (C) 2022 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/user/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
teythoon commented 9 months ago

Ah, I didn't know about --import-options import-show, that is indeed not implemented yet. I'll put that into the queue.

teythoon commented 8 months ago

@rocodes by the way, the latest release of the Chameleon now supports --import-options import-show.

legoktm commented 1 month ago

Just some more verbose notes on how to move forward here.

encryption

Journalists write replies to sources, which are encrypted to the source's public key and sent to the server. Currently this goes over qubes-split-gpg in the offline sd-gpg VM, and then back to the client. (And the source's public key has to be imported into the sd-gpg keyring.)

The source's public key is already stored in our sd-app VM's SQLite database, so I think we should adopt Sequoia in a similar way to how we did it on the server, with a module like redwood. (here: https://github.com/freedomofpress/securedrop-client/blob/b8c2970ed9177e34ce45d4e922d58646e4d7544e/client/securedrop_client/crypto.py#L187)

This should provide a noticable performance improvement because 1) we no longer need to import the source's PGP key into the sd-gpg keyring 2) we no longer need to roundtrip through the sd-gpg VM for encrypting messages.

decryption

To decrypt messages from sources, the encrypted file is sent to the sd-gpg VM, decrypted using the instance secret key, and then passed back to the sd-app VM. This must go over the VM boundary because the PGP secret key is kept in a separate, offline VM.

I think we have two options here:

Chameleon

Continue using qubes-split-gpg but have the Chameleon inside the sd-gpg VM.

Pros:

Cons:

Custom RPC with Sequoia

We write our own Qubes RPC protocol that invokes Sequoia (maybe via sq)

Pros:

Cons:

I think we could probably do...both? Start with the Chameleon to get the Sequoia benefits right away and then figure out a custom RPC protocol later on.

packages

Chameleon isn't in bookworm (just trixie) and via IRC it was mentioned that sq in bookworm is outdated too. We can build/ship our own binaries via, e.g. cargo install sequoia-chameleon-gnupg --version $version --locked. (Maybe we'd clone via git first to check cargo vet or something.)