1
2#------------------------------------------------------------------------------
3# $File: pgp-binary-keys,v 1.2 2021/04/26 15:56:00 christos Exp $
4# pgp-binary-keys: This file handles pgp binary keys.
5#
6# An PGP certificate or message doesn't have a fixed header.  Instead,
7# they are sequences of packets:
8#
9#   https://tools.ietf.org/html/rfc4880#section-4.3
10#
11# whose order conforms to a grammar:
12#
13#   https://tools.ietf.org/html/rfc4880#section-11
14#
15# Happily most packets have a few fields that are constrained, which
16# allow us to fingerprint them with relatively high certainty.
17#
18# A PGP packet is described by a single byte: the so-called CTB.  The
19# high-bit is always set.  If bit 6 is set, then it is a so-called
20# new-style CTB; if bit 6 is clear, then it is a so-called old-style
21# CTB.  Old-style CTBs have only four bits of type information; bits
22# 1-0 are used to describe the length.  New-style CTBs have 6 bits of
23# type information.
24#
25# Following the CTB is the packet's length in bytes.  If we blindly
26# advance the file cursor by this amount past the end of the length
27# information we come to the next packet.
28#
29# Data Structures
30# ===============
31#
32# New Style CTB
33# -------------
34#
35# https://tools.ietf.org/html/rfc4880#section-4.2.2
36#
37#   76543210
38#   ||\----/
39#   ||  tag
40#   |always 1
41#   always 1
42#
43#      Tag   bits 7 and 6 set
44#       0       0xC0        -- Reserved - a packet tag MUST NOT have this value
45#       1       0xC1        -- Public-Key Encrypted Session Key Packet
46#       2       0xC2        -- Signature Packet
47#       3       0xC3        -- Symmetric-Key Encrypted Session Key Packet
48#       4       0xC4        -- One-Pass Signature Packet
49#       5       0xC5        -- Secret-Key Packet
50#       6       0xC6        -- Public-Key Packet
51#       7       0xC7        -- Secret-Subkey Packet
52#       8       0xC8        -- Compressed Data Packet
53#       9       0xC9        -- Symmetrically Encrypted Data Packet
54#       10      0xCA        -- Marker Packet
55#       11      0xCB        -- Literal Data Packet
56#       12      0xCC        -- Trust Packet
57#       13      0xCD        -- User ID Packet
58#       14      0xCE        -- Public-Subkey Packet
59#       17      0xD1        -- User Attribute Packet
60#       18      0xD2        -- Sym. Encrypted and Integrity Protected Data Packet
61#       19      0xD3        -- Modification Detection Code Packet
62#       60 to 63 -- Private or Experimental Values
63#
64# The CTB is followed by the length header, which is densely encoded:
65#
66#   if length[0] is:
67#     0..191: one byte length (length[0])
68#     192..223: two byte length ((length[0] - 192) * 256 + length[2] + 192
69#     224..254: four byte length (big endian interpretation of length[1..5])
70#     255: partial body encoding
71#
72# The partial body encoding is similar to HTTP's chunk encoding.  It
73# is only allowed for container packets (SEIP, Compressed Data and
74# Literal).
75#
76# Old Style CTB
77# -------------
78#
79#  https://tools.ietf.org/html/rfc4880#section-4.2.1
80#
81# CTB:
82#
83#   76543210
84#   ||\--/\/
85#   ||  |  length encoding
86#   ||  tag
87#   |always 0
88#   always 1
89#
90# Tag:
91#
92#      Tag   bit 7 set, bits 6, 1, 0 clear
93#       0       0x80        -- Reserved - a packet tag MUST NOT have this value
94#       1       0x84        -- Public-Key Encrypted Session Key Packet
95#       2       0x88        -- Signature Packet
96#       3       0x8C        -- Symmetric-Key Encrypted Session Key Packet
97#       4       0x90        -- One-Pass Signature Packet
98#       5       0x94        -- Secret-Key Packet
99#       6       0x98        -- Public-Key Packet
100#       7       0x9C        -- Secret-Subkey Packet
101#       8       0xA0        -- Compressed Data Packet
102#       9       0xA4        -- Symmetrically Encrypted Data Packet
103#       10      0xA8        -- Marker Packet
104#       11      0xAC        -- Literal Data Packet
105#       12      0xB0        -- Trust Packet
106#       13      0xB4        -- User ID Packet
107#       14      0xB8        -- Public-Subkey Packet
108#
109# Length encoding:
110#
111#     Value
112#       0      1 byte length (following byte is the length)
113#       1      2 byte length (following two bytes are the length)
114#       2      4 byte length (following four bytes are the length)
115#       3      indeterminate length: natural end of packet, e.g., EOF
116#
117# An indeterminate length is only allowed for container packets
118# (SEIP, Compressed Data and Literal).
119#
120# Certificates
121# ------------
122#
123# We check the first three packets to determine if a sequence of
124# OpenPGP packets is likely to be a certificate.  The grammar allows
125# the following prefixes:
126#
127#   [Primary Key] [SIG] (EOF or another certificate)
128#   [Primary Key] [SIG]            [User ID]        [SIG]...
129#   [Primary Key] [SIG]            [User Attribute] [SIG]...
130#   [Primary Key] [SIG]            [Subkey]         [SIG]...
131#   [Primary Key] [User ID]        [SIG]...
132#   [Primary Key] [User Attribute] [SIG]...
133#   [Primary Key] [Subkey]         [SIG]...
134#
135# Any number of marker packets are also allowed between each packet,
136# but they are not normally used and we don't currently check for
137# them.
138#
139# The keys and subkeys may be public or private.
140#
141
142# Key packets and signature packets are versioned.  There are two
143# packet versions that we need to worry about in practice: v3 and v4.
144# v4 packets were introduced in RFC 2440, which was published in 1998.
145# It also deprecated v3 packets.  There are no actively used v3
146# certificates (GnuPG removed the code to support them in November
147# 2014).  But there are v3 keys lying around and it is useful to
148# identify them.  The next version of OpenPGP will introduce v5 keys.
149# The document has not yet been standardized so changes are still
150# possible.  But, for our purposes, it appears that v5 data structures
151# will be identical to v4 data structures modulo the version number.
152#
153#   https://tools.ietf.org/html/rfc2440
154#   https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000358.html
155#   https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-key-material-packet
156
157
158
159
160# The first packet has to be a public key or a secret key.
161#
162# New-Style Public Key
1630         ubyte                         =0xC6     OpenPGP Public Key
164>&0       use                           primary_key_length_new
165# New-Style Secret Key
1660         ubyte                         =0xC5     OpenPGP Secret Key
167>&0       use                           primary_key_length_new
168# Old-Style Public Key
1690         ubyte&0xFC                    =0x98     OpenPGP Public Key
170>&-1      use                           primary_key_length_old
171# Old-Style Secret Key
1720         ubyte&0xFC                    =0x94     OpenPGP Secret Key
173>&-1      use                           primary_key_length_old
174
175# Parse the length, check the packet's body and finally advance to the
176# next packet.
177
178# There are 4 different new-style length encodings, but the partial
179# body encoding is only acceptable for the SEIP, Compressed Data, and
180# Literal packets, which isn't valid for any packets in a certificate
181# so we ignore it.
1820                   name                primary_key_length_new
183>&0                 ubyte               <192
184#>>&0               ubyte               x                   (1 byte length encoding, %d bytes)
185>>&0                use                 pgp_binary_key_pk_check
186>>>&(&-1.B)         use                 sig_or_component_1
187>&0                 ubyte               >191
188>>&-1               ubyte               <225
189# offset = ((offset[0] - 192) << 8) + offset[1] + 192 (for the length header)
190# raw - (192 * 256 - 192)
191# = 48960
192#>>>&0              ubeshort            x         (2 byte length encoding, %d bytes)
193>>>&1               use                 pgp_binary_key_pk_check
194>>>>&(&-2.S-48960)  use       sig_or_component_1
195>&0                 ubyte               =255
196#>>&0     belong              x                   (5 byte length encoding, %d bytes)
197>>&4                use                 pgp_binary_key_pk_check
198>>>&(&-4.L)         use                 sig_or_component_1
199# Partial body encoding (only valid for container packets).
200# >&0               ubyte     >224
201# >>&0              ubyte               <255                partial body encoding
202
203# There are 4 different old-style length encodings, but the
204# indeterminate length encoding is only acceptable for the SEIP,
205# Compressed Data, and Literal packets, which isn't valid for any
206# packets in a certificate.
2070                   name                primary_key_length_old
208#>&0                ubyte               x                   (ctb: %x)
209>&0                 ubyte&0x3 =0
210#>>&0     ubyte               x                   (1 byte length encoding, %d bytes)
211>>&1                use                 pgp_binary_key_pk_check
212>>>&(&-1.B)         use                 sig_or_component_1
213>&0                 ubyte&0x3 =1
214#>>&0     ubeshort  x                   (2 byte length encoding, %d bytes)
215>>&2                use                 pgp_binary_key_pk_check
216>>>&(&-2.S)         use                 sig_or_component_1
217>&0                 ubyte&0x3 =2
218#>>&0     ubelong   x                   (4 byte length encoding, %d bytes)
219>>&4                use                 pgp_binary_key_pk_check
220>>>&(&-4.L)         use                 sig_or_component_1
221
222# Check the Key.
223#
224# https://tools.ietf.org/html/rfc4880#section-5.5.2
2250                   name                pgp_binary_key_pk_check
226# Valid versions are: 2, 3, 4.  5 is proposed in RFC 4880bis.
227# Anticipate a v6 / v7 format that like v5 is compatible with v4.
228# key format in a decade or so :D.
229>&0                 ubyte               >1
230>>&-1               ubyte               <8
231>>>&-1              byte                x                   Version %d
232# Check that keys were created after 1990.
233# (1990 - 1970) * 365.2524 * 24 * 60 * 60 = 631156147
234>>>&0               bedate              >631156147      \b, Created %s
235>>>>&-5             ubyte               >3
236>>>>>&4             use                 pgp_binary_key_algo
237>>>>&-5             ubyte               <4
238>>>>>&6             use                 pgp_binary_key_algo
239
240# Print out the key's algorithm and the number of bits, if this is
241# relevant (ECC keys are a fixed size).
2420                   name                pgp_binary_key_algo
243>0                  clear               x
244>&0                 ubyte               =1        \b, RSA (Encrypt or Sign,
245>>&0                ubeshort  x         \b %d bits)
246>&0                 ubyte               =2        \b, RSA (Encrypt,
247>>&0                ubeshort  x         \b %d bits)
248>&0                 ubyte               =3        \b, RSA (Sign,
249>>&0                ubeshort  x         \b %d bits)
250>&0                 ubyte               =16       \b, El Gamal (Encrypt,
251>>&0                ubeshort  x         \b %d bits)
252>&0                 ubyte               =17       \b, DSA
253>>&0                ubeshort  x         \b (%d bits)
254>&0                 ubyte               =18       \b, ECDH
255>&0                 ubyte               =19       \b, ECDSA
256>&0                 ubyte               =20       \b, El Gamal (Encrypt or Sign,
257>>&0                ubeshort  x         \b %d bits)
258>&0                 ubyte               =22       \b, EdDSA
259>&0                 default         x
260>>&0                ubyte               x         \b, Unknown Algorithm (%#x)
261
262# Match all possible second packets.
2630         name                sig_or_component_1
264#>0       ubyte               x         (ctb: %x)
265>&0       ubyte               =0xC2
266>>0       ubyte               x         \b; Signature
267>>&0      use                 sig_or_component_1_length_new
268>&0       ubyte               =0xCD
269>>0       ubyte               x         \b; User ID
270>>&0      use                 sig_or_component_1_length_new
271>&0       ubyte               =0xCE
272>>0       ubyte               x         \b; Public Subkey
273>>&0      use                 sig_or_component_1_length_new
274>&0       ubyte               =0xC7
275>>0       ubyte               x         \b; Secret Subkey
276>>&0      use                 sig_or_component_1_length_new
277>&0       ubyte               =0xD1
278>>0       ubyte               x         \b; User Attribute
279>>&0      use                 sig_or_component_1_length_new
280>&0       ubyte&0xFC          =0x88
281>>0       ubyte               x         \b; Signature
282>>&-1     use                 sig_or_component_1_length_old
283>&0       ubyte&0xFC          =0xB4
284>>0       ubyte               x         \b; User ID
285>>&-1     use                 sig_or_component_1_length_old
286>&0       ubyte&0xFC          =0xB8
287>>0       ubyte               x         \b; Public Subkey
288>>&-1     use                 sig_or_component_1_length_old
289>&0       ubyte&0xFC          =0x9C
290>>0       ubyte               x         \b; Secret Subkey
291>>&-1     use                 sig_or_component_1_length_old
292
293# Copy of 'primary_key_length_new', but calls cert_packet_3.
2940                   name                sig_or_component_1_length_new
295>&0                 ubyte               <192
296#>>&0               ubyte               x                   (1 byte new length encoding, %d bytes)
297>>&(&-1.B)          use                 cert_packet_3
298>&0                 ubyte               >191
299>>&-1               ubyte               <225
300# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header)
301# raw - (192 * 256 - 192 - 1)
302# = 48959
303#>>>&-1             ubeshort            x         (2 byte new length encoding, %d bytes)
304>>>&(&-1.S-48959)   use       cert_packet_3
305>&0                 ubyte               =255
306#>>&0     belong              x                   (5 byte new length encoding, %d bytes)
307>>&(&-4.L)          use                 cert_packet_3
308# Partial body encoding (only valid for container packets).
309# >&0               ubyte     >224
310# >>&0              ubyte               <255                partial body encoding
311
3120                   name                sig_or_component_1_length_old
313#>&0                ubyte               x                   (ctb: %x)
314>&0                 ubyte&0x3 =0
315#>>&0     ubyte               x                   (1 byte old length encoding, %d bytes)
316>>&(&0.B+1)         use                 cert_packet_3
317>&0                 ubyte&0x3 =1
318#>>&0     ubeshort  x                   (2 byte old length encoding, %d bytes)
319>>&(&0.S+2)         use                 cert_packet_3
320>&0                 ubyte&0x3 =2
321#>>&0     ubelong   x                   (4 byte old length encoding, %d bytes)
322>>&(&0.L+4)         use                 cert_packet_3
323
324# Copy of above.
3250         name                cert_packet_3
326#>0       ubyte               x         (ctb: %x)
327>&0       ubyte               =0xC2
328>>0       ubyte               x         \b; Signature
329>>&0      use                 cert_packet_3_length_new
330>&0       ubyte               =0xCD
331>>0       ubyte               x         \b; User ID
332>>&0      use                 cert_packet_3_length_new
333>&0       ubyte               =0xCE
334>>0       ubyte               x         \b; Public Subkey
335>>&0      use                 cert_packet_3_length_new
336>&0       ubyte               =0xC7
337>>0       ubyte               x         \b; Secret Subkey
338>>&0      use                 cert_packet_3_length_new
339>&0       ubyte               =0xD1
340>>0       ubyte               x         \b; User Attribute
341>>&0      use                 cert_packet_3_length_new
342>&0       ubyte&0xFC          =0x88
343>>0       ubyte               x         \b; Signature
344>>&-1     use                 cert_packet_3_length_old
345>&0       ubyte&0xFC          =0xB4
346>>0       ubyte               x         \b; User ID
347>>&-1     use                 cert_packet_3_length_old
348>&0       ubyte&0xFC          =0xB8
349>>0       ubyte               x         \b; Public Subkey
350>>&-1     use                 cert_packet_3_length_old
351>&0       ubyte&0xFC          =0x9C
352>>0       ubyte               x         \b; Secret Subkey
353>>&-1     use                 cert_packet_3_length_old
354
355# Copy of above.
3560                   name                cert_packet_3_length_new
357>&0                 ubyte               <192
358#>>&0               ubyte               x                   (1 byte new length encoding, %d bytes)
359>>&(&-1.B)          use                 pgp_binary_keys_end
360>&0                 ubyte               >191
361>>&-1               ubyte               <225
362# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header)
363# raw - (192 * 256 - 192 - 1)
364# = 48959
365#>>>&-1             ubeshort            x         (2 byte new length encoding, %d bytes)
366>>>&(&-1.S-48959)   use       pgp_binary_keys_end
367>&0                 ubyte               =255
368#>>&0     belong              x                   (5 byte new length encoding, %d bytes)
369>>&(&-4.L)          use                 pgp_binary_keys_end
370
3710                   name                cert_packet_3_length_old
372#>&0                ubyte               x                   (ctb: %x)
373>&0                 ubyte&0x3 =0
374#>>&0     ubyte               x                   (1 byte old length encoding, %d bytes)
375>>&(&0.B+1)         use                 pgp_binary_keys_end
376>&0                 ubyte&0x3 =1
377#>>&0     ubeshort  x                   (2 byte old length encoding, %d bytes)
378>>&(&0.S+2)         use                 pgp_binary_keys_end
379>&0                 ubyte&0x3 =2
380#>>&0     ubelong   x                   (4 byte old length encoding, %d bytes)
381>>&(&0.L+4)         use                 pgp_binary_keys_end
382
383# We managed to parse the first three packets of the certificate.  Declare
384# victory.
3850                   name                pgp_binary_keys_end
386>0                  byte                x                   \b; OpenPGP Certificate
387!:mime              application/pgp-keys
388!:ext               pgp/gpg/pkr/asd
389