On Tue, Feb 20, 2024 at 8:14 AM Norman Feske norman.feske@genode-labs.com wrote:
Hi Nathan,
thank you for your interest in participation and for asking about areas of interest.
Would there be a project that would be able to help achieve this goal?
In my opinion, the port of the Sequoia-PGP project [1] via Goa's Rust support [2] would be the most appreciated direction. Not only have I high hopes in the future relevance of this particular project, but it also fits perfectly with our ambition to come up with a solution for handling emails directly on Genode by the end of the year. For this, we have the pressing need for OpenPGP. It would be splendid to address this need via the Sequoia-PGP project.
On technical grounds, I think it would be an intriguing topic because it is far from trivial while still being approachable in smaller steps. One could start with test-driving the library primitives, maybe crafting a custom application for checking PGP signatures as a kind of showcase along the way. If that works out well, one could proceed towards making the 'sq' command line tool available, complementing Goa's Unix example. At the advanced stage, one could investigate a way to map the concept of a PGP daemon (think of a virtual smart card) to Genode's concepts.
Succeeding in any of those steps would be a valuable contribution.
[1] https://sequoia-pgp.org/ [2] https://genodians.org/atopia/2023-10-26-a-first-complex-rust-package
Cheers Norman
Relating to Norman's last point (a 'PGP daemon' or so), it is perhaps worth pointing out the "split GPG" functionality of Qubes OS for reference and potential inspiration: - https://www.qubes-os.org/doc/split-gpg/ - https://github.com/QubesOS/qubes-app-linux-split-gpg - https://github.com/QubesOS/qubes-app-linux-split-gpg2
The implementation is somewhat tightly coupled to GnuPG and either its command-line interface (for version 1) or agent protocol (for version 2). So, it's not necessarily a useful reference from an implementation perspective if aiming for non-GnuPG implementations of PGP, but perhaps still useful from a conceptual and user-experience perspective. The implementation is admittedly undesirably fragile in ways that I don't think anyone particularly likes (for example the command-filtering approach taken in version 1 is brittle when considering the (sometimes latent) complexity of the GnuPG command line interface, which has resulted in real vulns [1]), but it has been useful to many users while nothing better / practical existed.
[1]: https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-071-2021.txt
The rest of this email provides some (perhaps premature) unsolicited advice of lessons learned while working on the above, offered in the hope that we might collectively avoid repeating what I perceive to be certain mistakes leading to unfortunate consequences in this design space. If I didn't write it up now, it's unlikely I would have later, and am unlikely to be following subsequent implementation discussions to bring it up at a more timely point, so, here it is... Feel free to skip and ignore until/unless relevant.
If there's one thing I wish would have been done differently, especially in the design of the GnuPG agent protocol used in version 2, it would have been to make it easier to add appropriate hooks to be able to inspect the content of a message about to be signed and confirm user intent. By this I mean not only intent to make some arbitrary/unknown signature at a given moment, but rather intent to sign a specific message content, as confirmed in a trustworthy manner, before any signature is made. Trying to have such explicit confirmation at all doesn't necessarily make sense for every use case. For many use cases, it would just be useless noise and lead to decision fatigue and bad UX. However, if you do want to support any use cases where this is desirable, then it is made much easier if the following is considered from the beginning: When designing the protocol / interface between a less-trusted cryptographic-operation-requesting client and a more-trusted back-end key-using agent, then it is desirable to either send the entire message rather than only its hash, or, if only sending its hash (for reasons of size, opaque binary formats, or whatever the case may be), then to still provide a (hopefully convenient and reliable) way to obtain the contents of the message corresponding to said hash. GnuPG's agent protocol (at least last I checked) only sent hashes of messages when requesting signatures, not the message itself [2]. It is much easier and more maintainable to expose the full information an agent may wish to use over a client-independent interface/protocol (such as that which needs to exist anyway if the operation is being performed across a trust boundary) rather than end up needing to patch every potential client of said protocol to expose the same additional information (the message to be signed) out-of-band.
[2]: https://www.gnupg.org/documentation/manuals/gnupg/Agent-PKSIGN.html
OpenSSH has done a better job at this (from my perspective) than GnuPG, in the design of the SSH agent protocol [3][4]. The OpenSSH ssh-agent implementation [5] has long had functionality to be able to require explicit user confirmation before a key is used [6], however, the authors also acknowledge that this is of limited utility and easy to phish. This means that agent forwarding has, for most of its existence, been nearly impossible to expose/enable/use in anything resembling a safe manner... that is, until recently, when they added extensions to be able to restrict how a forwarded agent may be used [7]. This is only possible because the agent actually sees the full message of what it is trying to sign, and can inspect it [8], and do useful things with that information like ask the user to confirm with an explicit trustworthy indication of what user / host identity it's trying to sign a request regarding (at least it could be done, even if it isn't plumbed through to any UI yet [9]), or make the agent aware of forwarding and use it for automated authorization constraints without user involvement (already today in practice). These things would not be possible (or at least, would require additional plumbing and be much harder) if the agent only ever saw a hash of the message it's supposed to sign rather than the message itself. Note that any such message inspection certainly does not need to be done in the same process as what's holding the keys, and arguably it shouldn't be (due to risk of parsing / processing the message potentially leading to exploitation of the agent). Fortunately, having any such domain-specific message inspection (and perhaps rendering, etc.) be delegated to a separate pluggable privilege-separated component[s] feels more natural in Genode than perhaps anything else.
[3]: https://tools.ietf.org/html/draft-miller-ssh-agent [4]: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.agent [5]: https://github.com/openssh/openssh-portable/blob/master/ssh-agent.c [6]: https://man.openbsd.org/ssh-add#c [7]: https://www.openssh.com/agent-restrict.html [8]: https://github.com/openssh/openssh-portable/blob/V_9_6_P1/ssh-agent.c#L676-L... [9]: https://github.com/openssh/openssh-portable/blob/V_9_6_P1/ssh-agent.c#L882
Regards, Jean-Philippe