Subject: [openpgp] subkey revocation signatures -- RFC compliance?

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 27 Jul 2012 00:39:52 -0400

Hi folks--

I think i'm seeing a discrepancy between packets generated by a popular
OpenPGP implementation (GnuPG) and RFC 4880.  I'm wondering if anyone
can help clarify my understanding of the RFC.

https://tools.ietf.org/html/rfc4880#section-5.2.4 says:

[...]
   When a signature is made over a key, the hash data starts with the
   octet 0x99, followed by a two-octet length of the key, and then body
   of the key packet.  (Note that this is an old-style packet header for
   a key packet with two-octet length.)  A subkey binding signature
   (type 0x18) or primary key binding signature (type 0x19) then hashes
   the subkey using the same format as the main key (also using 0x99 as
   the first octet).  Key revocation signatures (types 0x20 and 0x28)
   hash only the key being revoked.
[...]

Note that 0x28 is a subkey revocation signature.

The subkey revocation packet generated by GnuPG 1.4.12 appears to be
made over a digest that includes both the primary key and the subkey.

This seems to be in contrast to the idea that it "revocation signatures
hash only the key being revoked."

Attached is a test key with a single subkey that has been revoked by gpg
1.4.12.  I haven't been able to figure out how to revoke a subkey with
any other OpenPGP implementation yet.

I tried loading the attached key into PGP 6.5.8 (fetched from [0]) and
GnuPG 1.4.12 (in an otherwise clean gpg home), and it does look like
that version of pgp is willing to accept this form of subkey revocation:

0 wt215@pip:~/src/pgp/pgp-6.5.8$ GNUPGHOME=../gpgtest gpg --check-sigs --verbose
gpg: using PGP trust model
../gpgtest/pubring.gpg
----------------------
pub   1024D/51902F1E 2012-07-27
uid                  test key <[email-masked]>
sig!3        51902F1E 2012-07-27  test key <[email-masked]>
sub   1024g/02CA3054 2012-07-27 [revoked: 2012-07-27]
sig!         51902F1E 2012-07-27  test key <[email-masked]>
rev!         51902F1E 2012-07-27  test key <[email-masked]>

0 wt215@pip:~/src/pgp/pgp-6.5.8$ LD_PRELOAD=./x/usr/lib/libstdc++.so.2.8 ./pgp -kvv
Pretty Good Privacy(tm) Version 6.5.8
(c) 1999 Network Associates Inc.
Uses the RSAREF(tm) Toolkit, which is copyright RSA Data Security, Inc.
Export of this software may be restricted by the U.S. government.

Type bits      keyID      Date       User ID
DSS  1024      0x51902F1E 2012/07/27 
 DH  1024      0x51902F1E 2012/07/27 *** KEY REVOKED ***
                                      test key <[email-masked]>
sig            0x51902F1E             test key <[email-masked]>
1 matching key found.
0 wt215@pip:~/src/pgp/pgp-6.5.8$ 

I also made a bogus subkey revocation packet and tried loading that into
a clean PGP 6.5.8 profile instead of the gpg-generated one, and PGP did
*not* think that the subkey was properly revoked.

So it looks to me like there are at least two implementations that hash
more than the key being revoked for subkey revocations.

Any pointers to something i've missed in the spec?  Or does this warrant
an errata?

Regards,

        --dkg

[0] http://www.pgpi.org/cgi/download.cgi?filename=PGPcmdln_6.5.8.Lnx_FW.tar.gz

---

From: Werner Koch <[email-masked]>
Date: Fri, 27 Jul 2012 10:09:29 +0200

>    hash only the key being revoked.

This text goes back to the very first published draft from March 98 (the
I-D states 1997, but this is a typo).

> made over a digest that includes both the primary key and the subkey.

So PGP and GnuPG we have never been OpenPGP compliant.  Good catch.

I don't have that old OpenPGP toolkit implementation anymore around.  We
should check what it does.

The way it is implemented by GnuPG and PGP might technically be
justified by:

   0x28: Subkey revocation signature
       The signature is calculated directly on the subkey being revoked.
       A revoked subkey is not to be used.  Only revocation signatures
       by the top-level signature key that is bound to this subkey, or
       by an authorized revocation key, should be considered valid
       revocation signatures.

With the exception of an authorized revocation key, the primary key is
required to check the signature and thus it needs to be available.
Hashing the primary key along with the subkey is what we have to do for
other key signatures anyway.

We would need to dive into the WG archives to see why we came up with
the specific requirement.

Salam-Shalom,

   Werner

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.

---

From: David Shaw <[email-masked]>
Date: Fri, 27 Jul 2012 08:53:54 -0400

> hash only the key being revoked."

Interesting.  Digging around a bit, it seems that this was noticed by Marc Horowitz in 2000 (see http://www.mhonarc.org/archive/html/ietf-openpgp/2000-12/msg00001.html ), but for one reason or another it wasn't resolved before publication.

Nice catch!  I think this would be a good errata item for the RFC.  http://www.rfc-editor.org/how_to_report.html

David

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 27 Jul 2012 12:59:14 -0400

On 07/27/2012 08:53 AM, David Shaw wrote:
> it seems that this was noticed by Marc Horowitz in 2000 (see http://www.mhonarc.org/archive/html/ietf-openpgp/2000-12/msg00001.html ), but for one reason or another it wasn't resolved before publication.

thanks for digging that up.

> Nice catch!  I think this would be a good errata item for the RFC.  http://www.rfc-editor.org/how_to_report.html

I've now reported it:

http://www.rfc-editor.org/errata_search.php?rfc=4880&eid=3298

Has anyone else tried to implement this corner of the spec?  If so, how
did you handle subkey revocation signatures?  I'd like to be more
confident that we aren't breaking interoperability with anyone by making
this clarification (though arguably the interoperability is probably
already broken if anyone was writing to spec).

	--dkg