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