| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 | 
#------------------------------------------------------------------------------# $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 Key0	ubyte			=0xC6	OpenPGP Public Key>&0	use			primary_key_length_new# New-Style Secret Key0	ubyte			=0xC5	OpenPGP Secret Key>&0	use			primary_key_length_new# Old-Style Public Key0	ubyte&0xFC		=0x98	OpenPGP Public Key>&-1	use			primary_key_length_old# Old-Style Secret Key0	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.20		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 encoding0		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_end0		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
 |