Michał Górny
2018-07-24 21:04:49 UTC
Hi, everyone.
As an experimental feature the current git version of gemato tries to
use WKD [1] to update keys by default. I'd like to request your opinion
on this and possibly a review of my implementation [2].
The problem being solved: currently gemato (and Portage via its API)
refreshes keys from keyservers before every sync. We do this to ensure
that we catch a possible key revocation before a compromised key could
be used to inject malicious data. Sadly, keyservers are far from
stable, and users are repeatedly having problems fetching keys from
them.
While debating a related problem within Infra (Infra servers failing
while updating developer keys) we weren't able to find a satisfactory
solution involving use of keyservers. It has been suggested that it
might be an actual problem with keyserver software rather than
the common network/load problems.
Therefore, I came to the conclusion that using HTTPS would probably be
the best way to distribute key updates. The WKD protocol whose
existence has been brought to my attention recently seemed a good fit
for the job, especially that I've already implemented it on Gentoo
Infrastructure. However, since GnuPG only implements WKD use for key
discovery and not key updates, I had to extend on the features provided.
In order to perform key update using WKD gemato, in order:
1. Imports the provided keyring into a dedicated GNUPGHOME.
2. Obtains fingerprints and UIDs of all keys present in that keyring.
3. Uses 'gpg --locate-key' in a separate dedicated GNUPGHOME to fetch
keys via WKD for all UIDs found.
4. Exports appropriate keys (by fingerprint) from the WKD keyring
and verifies that all keys were actually available via WKD.
5. Imports those keys to the original GNUPGHOME.
Failure on any of those steps results in the WKD update being considered
unsuccessful and a fallback to keyserver update. This includes
the cases when:
a. at least one of the UIDs found on provided keys is not available
via WKD,
b. at least one of the keys provided was not fetched via WKD (i.e. UID
provided a disjoint set of keys).
Currently, WKD update method ignores keys for UIDs that were not present
in the initial keyring. This means to match the behavior with keyserver
updates, and avoid introducing potential attack vectors.
I believe that the implementation provides the same level of security
as keyserver-based updates. WKD uses HTTPS just like HKPS -- however,
the connection is established to one of Gentoo WWW nodes rather than
an arbitrary keyserver. WKD is being updated from keyservers, so it
provides consistent information (with 1-2 hours of extra lag).
The keys are identified by fingerprints, so even if an attacker is able
to replace the WKD file with an arbitrary key, gemato will ignore it as
mismatched fingerprint. Finally, if WKD does not provide all the needed
keys, gemato considers the update unsuccessful. This especially means
that if a revoked key is removed from WKD, gemato will find
the revocation via keyservers.
Attacks based on blocking access to the WKD servers will only result
in fallback to keyservers. Blocking access to keyservers will result
in gemato reporting a failure. Replay attacks are prevented by using
HTTPS.
Does this look good to you? Is there anything I've missed?
[1]:https://wiki.gnupg.org/WKD
[2]:https://github.com/mgorny/gemato/commit/909390c25a0ab589a4ae10d20cb9e321a51163b2
As an experimental feature the current git version of gemato tries to
use WKD [1] to update keys by default. I'd like to request your opinion
on this and possibly a review of my implementation [2].
The problem being solved: currently gemato (and Portage via its API)
refreshes keys from keyservers before every sync. We do this to ensure
that we catch a possible key revocation before a compromised key could
be used to inject malicious data. Sadly, keyservers are far from
stable, and users are repeatedly having problems fetching keys from
them.
While debating a related problem within Infra (Infra servers failing
while updating developer keys) we weren't able to find a satisfactory
solution involving use of keyservers. It has been suggested that it
might be an actual problem with keyserver software rather than
the common network/load problems.
Therefore, I came to the conclusion that using HTTPS would probably be
the best way to distribute key updates. The WKD protocol whose
existence has been brought to my attention recently seemed a good fit
for the job, especially that I've already implemented it on Gentoo
Infrastructure. However, since GnuPG only implements WKD use for key
discovery and not key updates, I had to extend on the features provided.
In order to perform key update using WKD gemato, in order:
1. Imports the provided keyring into a dedicated GNUPGHOME.
2. Obtains fingerprints and UIDs of all keys present in that keyring.
3. Uses 'gpg --locate-key' in a separate dedicated GNUPGHOME to fetch
keys via WKD for all UIDs found.
4. Exports appropriate keys (by fingerprint) from the WKD keyring
and verifies that all keys were actually available via WKD.
5. Imports those keys to the original GNUPGHOME.
Failure on any of those steps results in the WKD update being considered
unsuccessful and a fallback to keyserver update. This includes
the cases when:
a. at least one of the UIDs found on provided keys is not available
via WKD,
b. at least one of the keys provided was not fetched via WKD (i.e. UID
provided a disjoint set of keys).
Currently, WKD update method ignores keys for UIDs that were not present
in the initial keyring. This means to match the behavior with keyserver
updates, and avoid introducing potential attack vectors.
I believe that the implementation provides the same level of security
as keyserver-based updates. WKD uses HTTPS just like HKPS -- however,
the connection is established to one of Gentoo WWW nodes rather than
an arbitrary keyserver. WKD is being updated from keyservers, so it
provides consistent information (with 1-2 hours of extra lag).
The keys are identified by fingerprints, so even if an attacker is able
to replace the WKD file with an arbitrary key, gemato will ignore it as
mismatched fingerprint. Finally, if WKD does not provide all the needed
keys, gemato considers the update unsuccessful. This especially means
that if a revoked key is removed from WKD, gemato will find
the revocation via keyservers.
Attacks based on blocking access to the WKD servers will only result
in fallback to keyservers. Blocking access to keyservers will result
in gemato reporting a failure. Replay attacks are prevented by using
HTTPS.
Does this look good to you? Is there anything I've missed?
[1]:https://wiki.gnupg.org/WKD
[2]:https://github.com/mgorny/gemato/commit/909390c25a0ab589a4ae10d20cb9e321a51163b2
--
Best regards,
MichaŠGórny
Best regards,
MichaŠGórny