From b7b4a1bdd9da28827980c64c623bcb0654736828 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 25 Feb 2016 21:08:56 +0100 Subject: [PATCH] gpg: Improve documentation and comments related to OpenPGP packets. -- Signed-off-by: Neal H. Walfield --- g10/build-packet.c | 177 +++++++++++++++++++++++++++++--- g10/packet.h | 249 +++++++++++++++++++++++++++++++++++---------- g10/parse-packet.c | 2 +- 3 files changed, 362 insertions(+), 66 deletions(-) diff --git a/g10/build-packet.c b/g10/build-packet.c index a257e69ef..5bcfae182 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -310,6 +310,11 @@ write_fake_data (IOBUF out, gcry_mpi_t a) } +/* Serialize the user id (RFC 4880, Section 5.11) or the user + attribute UID (Section 5.12) and write it to OUT. + + CTB is the serialization's CTB. It specifies the header format and + the packet's type. The header length must not be set. */ static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { @@ -332,12 +337,31 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) } +/* Serialize the key (RFC 4880, Section 5.5) described by PK and write + it to OUT. + + This function serializes both primary keys and subkeys with or + without a secret part. + + CTB is the serialization's CTB. It specifies the header format and + the packet's type. The header length must not be set. + + PK->VERSION specifies the serialization format. A value of 0 means + to use the default version. Currently, only version 4 packets are + supported. + */ static int do_key (iobuf_t out, int ctb, PKT_public_key *pk) { gpg_error_t err = 0; + /* The length of the body is stored in the packet's header, which + occurs before the body. Unfortunately, we don't know the length + of the packet's body until we've written all of the data! To + work around this, we first write the data into this temporary + buffer, then generate the header, and finally copy the contents + of this buffer to OUT. */ + iobuf_t a = iobuf_temp(); int i, nskey, npkey; - iobuf_t a = iobuf_temp(); /* Build in a self-enlarging buffer. */ log_assert (pk->version == 0 || pk->version == 4); log_assert (ctb_pkttype (ctb) == PKT_PUBLIC_KEY @@ -355,7 +379,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) iobuf_put (a, pk->pubkey_algo ); /* Get number of secret and public parameters. They are held in one - array first the public ones, then the secret ones. */ + array: the public ones followed by the secret ones. */ nskey = pubkey_get_nskey (pk->pubkey_algo); npkey = pubkey_get_npkey (pk->pubkey_algo); @@ -463,7 +487,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) writing all the other stuff, so that we know the length of the packet */ write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes); - /* And finally write it out to the real stream. */ + /* And finally write it out to the real stream. */ err = iobuf_write_temp (out, a); } @@ -471,6 +495,11 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) return err; } +/* Serialize the symmetric-key encrypted session key packet (RFC 4880, + 5.3) described by ENC and write it to OUT. + + CTB is the serialization's CTB. It specifies the header format and + the packet's type. The header length must not be set. */ static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) { @@ -479,10 +508,23 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC); + /* The only acceptable version. */ assert( enc->version == 4 ); - switch( enc->s2k.mode ) { - case 0: case 1: case 3: break; - default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); + + /* RFC 4880, Section 3.7. */ + switch( enc->s2k.mode ) + { + /* Simple S2K. */ + case 0: + /* Salted S2K. */ + case 1: + /* Iterated and salted S2K. */ + case 3: + /* Reasonable values. */ + break; + + default: + log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); } iobuf_put( a, enc->version ); iobuf_put( a, enc->cipher_algo ); @@ -504,6 +546,11 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) } +/* Serialize the public-key encrypted session key packet (RFC 4880, + 5.1) described by ENC and write it to OUT. + + CTB is the serialization's CTB. It specifies the header format and + the packet's type. The header length must not be set. */ static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) { @@ -548,6 +595,8 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) } +/* Calculate the length of the serialized plaintext packet PT (RFC + 4480, Section 5.9). */ static u32 calc_plaintext( PKT_plaintext *pt ) { @@ -561,6 +610,15 @@ calc_plaintext( PKT_plaintext *pt ) return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; } +/* Serialize the plaintext packet (RFC 4880, 5.9) described by PT and + write it to OUT. + + The body of the message is stored in PT->BUF. The amount of data + to write is PT->LEN. (PT->BUF should be configured to return EOF + after this much data has been read.) If PT->LEN is 0 and CTB + indicates that this is a new format packet, then partial block mode + is assumed to have been enabled on OUT. On success, partial block + mode is disabled. */ static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { @@ -591,6 +649,13 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) +/* Serialize the symmetrically encrypted data packet (RFC 4880, + Section 5.7) described by ED and write it to OUT. + + Note: this only writes the packets header! The call must then + follow up and write the initial random data and the body to OUT. + (If you use the encryption iobuf filter (cipher_filter), then this + is done automatically.) */ static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) { @@ -608,6 +673,14 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) return rc; } +/* Serialize the symmetrically encrypted integrity protected data + packet (RFC 4880, Section 5.13) described by ED and write it to + OUT. + + Note: this only writes the packet's header! The caller must then + follow up and write the initial random data, the body and the MDC + packet to OUT. (If you use the encryption iobuf filter + (cipher_filter), then this is done automatically.) */ static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) { @@ -628,6 +701,11 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) } +/* Serialize the compressed packet (RFC 4880, Section 5.6) described + by CD and write it to OUT. + + Note: this only writes the packet's header! The caller must then + follow up and write the body to OUT. */ static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) { @@ -983,6 +1061,15 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, uid->attrib_len+=idx+headerlen+buflen; } +/* Turn the notation described by the string STRING into a notation. + + STRING has the form: + + - -name - Delete the notation. + - name@domain.name=value - Normal notation + - !name@domain.name=value - Notation with critical bit set. + + The caller must free the result using free_notation(). */ struct notation * string_to_notation(const char *string,int is_utf8) { @@ -1073,6 +1160,8 @@ string_to_notation(const char *string,int is_utf8) return NULL; } +/* Return all of the notations stored in the signature SIG. The + caller must free them using free_notation(). */ struct notation * sig_to_notation(PKT_signature *sig) { @@ -1081,6 +1170,15 @@ sig_to_notation(PKT_signature *sig) int seq=0,crit; struct notation *list=NULL; + /* See RFC 4880, 5.2.3.16 for the format of notation data. In + short, a notation has: + + - 4 bytes of flags + - 2 byte name length (n1) + - 2 byte value length (n2) + - n1 bytes of name data + - n2 bytes of value data + */ while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) { int n1,n2; @@ -1092,7 +1190,9 @@ sig_to_notation(PKT_signature *sig) continue; } + /* name length. */ n1=(p[4]<<8)|p[5]; + /* value length. */ n2=(p[6]<<8)|p[7]; if(8+n1+n2!=len) @@ -1108,12 +1208,14 @@ sig_to_notation(PKT_signature *sig) n->name[n1]='\0'; if(p[0]&0x80) + /* The value is human-readable. */ { n->value=xmalloc(n2+1); memcpy(n->value,&p[8+n1],n2); n->value[n2]='\0'; } else + /* Binary data. */ { n->bdat=xmalloc(n2); n->blen=n2; @@ -1134,6 +1236,9 @@ sig_to_notation(PKT_signature *sig) return list; } +/* Release the resources associated with the *list* of notations. To + release a single notation, make sure that notation->next is + NULL. */ void free_notation(struct notation *notation) { @@ -1150,6 +1255,8 @@ free_notation(struct notation *notation) } } +/* Serialize the signature packet (RFC 4880, Section 5.2) described by + SIG and write it to OUT. */ static int do_signature( IOBUF out, int ctb, PKT_signature *sig ) { @@ -1217,6 +1324,8 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) } +/* Serialize the one-pass signature packet (RFC 4880, Section 5.4) + described by OPS and write it to OUT. */ static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) { @@ -1236,6 +1345,7 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) } +/* Write a 16-bit quantity to OUT in big endian order. */ static int write_16(IOBUF out, u16 a) { @@ -1245,6 +1355,7 @@ write_16(IOBUF out, u16 a) return 0; } +/* Write a 32-bit quantity to OUT in big endian order. */ static int write_32(IOBUF out, u32 a) { @@ -1308,11 +1419,26 @@ write_sign_packet_header (IOBUF out, int ctb, u32 len) } /**************** - * If HDRLEN is > 0, try to build a header of this length. We need - * this so that we can hash packets without reading them again. If - * len is 0, write a partial or indeterminate length header, unless - * hdrlen is specified in which case write an actual zero length - * (using the specified hdrlen). + * Write a packet header to OUT. + * + * CTB is the ctb. It determines whether a new or old format packet + * header should be written. The length field is adjusted, but the + * CTB is otherwise written out as is. + * + * LEN is the length of the packet's body. + * + * If HDRLEN is set, then we don't necessarily use the most efficient + * encoding to store LEN, but the specified length. (If this is not + * possible, this is a bug.) In this case, LEN=0 means a 0 length + * packet. Note: setting HDRLEN is only supported for old format + * packets! + * + * If HDRLEN is not set, then the shortest encoding is used. In this + * case, LEN=0 means the body has an indeterminate length and a + * partial body length header (if a new format packet) or an + * indeterminate length header (if an old format packet) is written + * out. Further, if using partial body lengths, this enables partial + * body length mode on OUT. */ static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) @@ -1320,26 +1446,39 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) if( ctb & 0x40 ) return write_new_header( out, ctb, len, hdrlen ); + /* An old format packet. Refer to RFC 4880, Section 4.2.1 to + understand how lengths are encoded in this case. */ + log_assert (hdrlen == 0 || hdrlen == 2 || hdrlen == 3 || hdrlen == 5); - if( hdrlen ) + if (hdrlen) + /* Header length is given. */ { if( hdrlen == 2 && len < 256 ) + /* 00 => 1 byte length. */ ; else if( hdrlen == 3 && len < 65536 ) + /* 01 => 2 byte length. If len < 256, this is not the most + compact encoding, but it is a correct encoding. */ ctb |= 1; else + /* 10 => 4 byte length. If len < 65536, this is not the most + compact encoding, but it is a correct encoding. */ ctb |= 2; } else { if( !len ) + /* 11 => Indeterminate length. */ ctb |= 3; else if( len < 256 ) + /* 00 => 1 byte length. */ ; else if( len < 65536 ) + /* 01 => 2 byte length. */ ctb |= 1; else + /* 10 => 4 byte length. */ ctb |= 2; } @@ -1368,6 +1507,20 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) } +/* Write a new format header to OUT. + + CTB is the ctb. + + LEN is the length of the packet's body. If LEN is 0, then enables + partial body length mode (i.e., the body is of an indeterminant + length) on OUT. Note: this function cannot be used to generate a + header for a zero length packet. + + HDRLEN is the length of the packet's header. If HDRLEN is 0, the + shortest encoding is chosen based on the length of the packet's + body. Currently, values other than 0 are not supported. + + Returns 0 on success. */ static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) { diff --git a/g10/packet.h b/g10/packet.h index dfd3a0008..1be9ec389 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -79,49 +79,91 @@ typedef struct { byte value; } prefitem_t; +/* A string-to-key specifier as defined in RFC 4880, Section 3.7. */ typedef struct { int mode; /* Must be an integer due to the GNU modes 1001 et al. */ byte hash_algo; byte salt[8]; + /* The *coded* (i.e., the serialized version) iteration count. */ u32 count; } STRING2KEY; +/* A symmetric-key encrypted session key packet as defined in RFC + 4880, Section 5.3. All fields are serialized. */ typedef struct { - byte version; - byte cipher_algo; /* cipher algorithm used */ - STRING2KEY s2k; - byte seskeylen; /* keylength in byte or 0 for no seskey */ - byte seskey[1]; + /* RFC 4880: this must be 4. */ + byte version; + /* The cipher algorithm used. */ + byte cipher_algo; + /* The string-to-key specifier. */ + STRING2KEY s2k; + /* The length of SESKEY in bytes or 0 if this packet does not + encrypt a session key. (In the latter case, the results of the + S2K function on the password is the session key. See RFC 4880, + Section 5.3.) */ + byte seskeylen; + /* The session key as encrypted by the S2K specifier. */ + byte seskey[1]; } PKT_symkey_enc; +/* A public-key encrypted session key packet as defined in RFC 4880, + Section 5.1. All fields are serialized. */ typedef struct { - u32 keyid[2]; /* 64 bit keyid */ - byte version; - byte pubkey_algo; /* algorithm used for public key scheme */ - byte throw_keyid; - gcry_mpi_t data[PUBKEY_MAX_NENC]; + /* The 64-bit keyid. */ + u32 keyid[2]; + /* The packet's version. Currently, only version 3 is defined. */ + byte version; + /* The algorithm used for the public key encryption scheme. */ + byte pubkey_algo; + /* Whether to hide the key id. This value is not directly + serialized. */ + byte throw_keyid; + /* The session key. */ + gcry_mpi_t data[PUBKEY_MAX_NENC]; } PKT_pubkey_enc; +/* A one-pass signature packet as defined in RFC 4880, Section + 5.4. All fields are serialized. */ typedef struct { - u32 keyid[2]; /* 64 bit keyid */ - byte sig_class; /* sig classification */ + u32 keyid[2]; /* The 64-bit keyid */ + /* The signature's classification (RFC 4880, Section 5.2.1). */ + byte sig_class; byte digest_algo; /* algorithm used for digest */ byte pubkey_algo; /* algorithm used for public key scheme */ - byte last; /* a stupid flag */ + /* A message can be signed by multiple keys. In this case, there + are n one-pass signature packets before the message to sign and + n signatures packets after the message. It is conceivable that + someone wants to not only sign the message, but all of the + signatures. Now we need to distinguish between signing the + message and signing the message plus the surrounding + signatures. This is the point of this flag. If set, it means: + I sign all of the data starting at the next packet. */ + byte last; } PKT_onepass_sig; +/* A v4 OpenPGP signature has a hashed and unhashed area containing + co-called signature subpackets (RFC 4880, Section 5.2.3). These + areas are described by this data structure. Use enum_sig_subpkt to + parse this area. */ typedef struct { size_t size; /* allocated */ - size_t len; /* used */ - byte data[1]; + size_t len; /* used (serialized) */ + byte data[1]; /* the serialized subpackes (serialized) */ } subpktarea_t; +/* The in-memory representation of a designated revoker signature + subpacket (RFC 4880, Section 5.2.3.15). */ struct revocation_key { + /* A bit field. 0x80 must be set. 0x40 means this information is + sensitive (and should not be uploaded to a keyserver by + default). */ byte class; + /* The public-key algorithm ID. */ byte algid; + /* The fingerprint of the authorized key. */ byte fpr[MAX_FINGERPRINT_LEN]; }; @@ -139,7 +181,11 @@ typedef struct } pka_info_t; -/* Object to keep information pertaining to a signature. */ +/* A signature packet (RFC 4880, Section 5.2). Only a subset of these + fields are directly serialized (these are marked as such); the rest + are read from the subpackets, which are not synthesized when + serializing this data structure (i.e., when using build_packet()). + Instead, the subpackets must be created by hand. */ typedef struct { struct @@ -156,14 +202,26 @@ typedef struct unsigned expired:1; unsigned pka_tried:1; /* Set if we tried to retrieve the PKA record. */ } flags; - u32 keyid[2]; /* 64 bit keyid */ - u32 timestamp; /* Signature made (seconds since Epoch). */ + /* The key that allegedly generated this signature. (Directly + serialized in v3 sigs; for v4 sigs, this must be explicitly added + as an issuer subpacket (5.2.3.5.) */ + u32 keyid[2]; + /* When the signature was made (seconds since the Epoch). (Directly + serialized in v3 sigs; for v4 sigs, this must be explicitly added + as a signature creation time subpacket (5.2.3.4).) */ + u32 timestamp; u32 expiredate; /* Expires at this date or 0 if not at all. */ + /* The serialization format used / to use. If 0, then defaults to + version 3. (Serialized.) */ byte version; - byte sig_class; /* Sig classification, append for MD calculation. */ - byte pubkey_algo; /* Algorithm used for public key scheme */ - /* (PUBKEY_ALGO_xxx) */ - byte digest_algo; /* Algorithm used for digest (DIGEST_ALGO_xxxx). */ + /* The signature type. (See RFC 4880, Section 5.2.1.) */ + byte sig_class; + /* Algorithm used for public key scheme (e.g., PUBKEY_ALGO_RSA). + (Serialized.) */ + byte pubkey_algo; + /* Algorithm used for digest (e.g., DIGEST_ALGO_SHA1). + (Serialized.) */ + byte digest_algo; byte trust_depth; byte trust_value; const byte *trust_regexp; @@ -173,7 +231,10 @@ typedef struct available. See also flags.pka_tried. */ subpktarea_t *hashed; /* All subpackets with hashed data (v4 only). */ subpktarea_t *unhashed; /* Ditto for unhashed data. */ - byte digest_start[2]; /* First 2 bytes of the digest. */ + /* First 2 bytes of the digest. (Serialized. Note: this is not + automatically filled in when serializing a signature!) */ + byte digest_start[2]; + /* The signature. (Serialized.) */ gcry_mpi_t data[PUBKEY_MAX_NSIG]; /* The message digest and its length (in bytes). Note the maximum digest length is 512 bits (64 bytes). If DIGEST_LEN is 0, then @@ -192,14 +253,21 @@ struct user_attribute { }; -/* (See also keybox-search-desc.h) */ -struct gpg_pkt_user_id_s +/* A user id (RFC 4880, Section 5.11) or a user attribute packet (RFC + 4880, Section 5.12). Only a subset of these fields are directly + serialized (these are marked as such); the rest are read from the + self-signatures in merge_keys_and_selfsig()). */ +typedef struct { int ref; /* reference counter */ - int len; /* length of the name */ + /* The length of NAME. */ + int len; struct user_attribute *attribs; int numattribs; - byte *attrib_data; /* if this is not NULL, the packet is an attribute */ + /* If this is not NULL, the packet is a user attribute rather than a + user id. (Serialized.) */ + byte *attrib_data; + /* The length of ATTRIB_DATA. */ unsigned long attrib_len; byte *namehash; int help_key_usage; @@ -220,9 +288,11 @@ struct gpg_pkt_user_id_s unsigned int ks_modify:1; unsigned int compacted:1; } flags; + /* The text contained in the user id packet, which is normally the + name and email address of the key holder (See RFC 4880 5.11). + (Serialized.) */ char name[1]; -}; -typedef struct gpg_pkt_user_id_s PKT_user_id; +} PKT_user_id; @@ -254,6 +324,14 @@ struct seckey_info /**************** + * The in-memory representation of a public key (RFC 4880, Section + * 5.5). Note: this structure contains significantly more information + * thatn is contained in an OpenPGP public key packet. This + * information is derived from the self-signed signatures (by + * merge_keys_and_selfsig()) and is ignored when serializing the + * packet. The fields that are actually written out when serializing + * this packet are marked as accordingly. + * * We assume that secret keys have the same number of parameters as * the public key and that the public parameters are the first items * in the PKEY array. Thus NPKEY is always less than NSKEY and it is @@ -268,14 +346,22 @@ struct seckey_info */ typedef struct { - u32 timestamp; /* key made */ + /* When the key was created. (Serialized.) */ + u32 timestamp; u32 expiredate; /* expires at this date or 0 if not at all */ u32 max_expiredate; /* must not expire past this date */ struct revoke_info revoked; - byte hdrbytes; /* number of header bytes */ + /* An OpenPGP packet consists of a header and a body. This is the + size of the header. If this is 0, an appropriate size is + automatically chosen based on the size of the body. + (Serialized.) */ + byte hdrbytes; + /* The serialization format. If 0, the default version (4) is used + when serializing. (Serialized.) */ byte version; byte selfsigversion; /* highest version of all of the self-sigs */ - byte pubkey_algo; /* algorithm used for public key scheme */ + /* The public key algorithm. (Serialized.) */ + byte pubkey_algo; byte pubkey_usage; /* for now only used to pass it to getkey() */ byte req_usage; /* hack to pass a request to getkey() */ u32 has_expired; /* set to the expiration date if expired */ @@ -314,9 +400,13 @@ typedef struct char *serialno; /* Malloced hex string or NULL if it is likely not on a card. See also flags.serialno_valid. */ - struct seckey_info *seckey_info; /* If not NULL this malloced - structure describes a secret - key. */ + /* If not NULL this malloced structure describes a secret key. + (Serialized.) */ + struct seckey_info *seckey_info; + /* The public key. Contains pubkey_get_npkey (pubkey_algo) + + pubkey_get_nskey (pubkey_algo) MPIs. (If pubkey_get_npkey + returns 0, then the algorithm is not understood and the PKEY + contains a single opaque MPI.) (Serialized.) */ gcry_mpi_t pkey[PUBKEY_MAX_NSKEY]; /* Right, NSKEY elements. */ } PKT_public_key; @@ -332,20 +422,46 @@ typedef struct { char data[1]; } PKT_comment; +/* A compression packet (RFC 4880, Section 5.6). */ typedef struct { - u32 len; /* reserved */ - byte new_ctb; - byte algorithm; - iobuf_t buf; /* IOBUF reference */ + /* Not used. */ + u32 len; + /* Whether the serialized version of the packet used / should use + the new format. */ + byte new_ctb; + /* The compression algorithm. */ + byte algorithm; + /* An iobuf holding the data to be decompressed. (This is not used + for compression!) */ + iobuf_t buf; } PKT_compressed; +/* A symmetrically encrypted data packet (RFC 4880, Section 5.7) or a + symmetrically encrypted integrity protected data packet (Section + 5.13) */ typedef struct { - u32 len; /* Remaining length of encrypted data. */ - int extralen; /* This is (blocksize+2). Used by build_packet. */ - byte new_ctb; /* uses a new CTB */ - byte is_partial; /* partial length encoded */ - byte mdc_method; /* > 0: integrity protected encrypted data packet */ - iobuf_t buf; /* IOBUF reference */ + /* Remaining length of encrypted data. */ + u32 len; + /* When encrypting, the first block size bytes of data are random + data and the following 2 bytes are copies of the last two bytes + of the random data (RFC 4880, Section 5.7). This provides a + simple check that the key is correct. extralen is the size of + this extra data. This is used by build_packet when writing out + the packet's header. */ + int extralen; + /* Whether the serialized version of the packet used / should use + the new format. */ + byte new_ctb; + /* Whether the packet has an indeterminate length (old format) or + was encoded using partial body length headers (new format). + Note: this is ignored when encrypting. */ + byte is_partial; + /* If 0, MDC is disabled. Otherwise, the MDC method that was used + (currently, only DIGEST_ALGO_SHA1 is supported). */ + byte mdc_method; + /* An iobuf holding the data to be decrypted. (This is not used for + encryption!) */ + iobuf_t buf; } PKT_encrypted; typedef struct { @@ -357,15 +473,22 @@ typedef struct { unsigned int sigcache; } PKT_ring_trust; +/* A plaintext packet (see RFC 4880, 5.9). */ typedef struct { - u32 len; /* length of encrypted data */ - iobuf_t buf; /* IOBUF reference */ - byte new_ctb; - byte is_partial; /* partial length encoded */ - int mode; - u32 timestamp; - int namelen; - char name[1]; + /* The length of data in BUF or 0 if unknown. */ + u32 len; + /* A buffer containing the data stored in the packet's body. */ + iobuf_t buf; + byte new_ctb; + byte is_partial; /* partial length encoded */ + /* The data's formatting. This is either 'b', 't', 'u', 'l' or '1' + (however, the last two are deprecated). */ + int mode; + u32 timestamp; + /* The name of the file. This can be at most 255 characters long, + since namelen is just a byte in the serialized format. */ + int namelen; + char name[1]; } PKT_plaintext; typedef struct { @@ -401,18 +524,38 @@ struct packet_struct { } while(0) +/* A notation. See RFC 4880, Section 5.2.3.16. */ struct notation { + /* The notation's name. */ char *name; + /* If the notation is human readable, then the value is stored here + as a NUL-terminated string. */ char *value; + /* Sometimes we want to %-expand the value. In these cases, we save + that transformed value here. */ char *altvalue; + /* If the notation is not human readable, then the value is strored + here. */ unsigned char *bdat; + /* The amount of data stored in BDAT. + + Note: if this is 0 and BDAT is NULL, this does not necessarily + mean that the value is human readable. It could be that we have + a 0-length value. To determine whether the notation is human + readable, always check if VALUE is not NULL. This works, because + if a human-readable value has a length of 0, we will still + allocate space for the NUL byte. */ size_t blen; struct { + /* The notation is critical. */ unsigned int critical:1; + /* The notation should be deleted. */ unsigned int ignore:1; } flags; + + /* A field to facilitate creating a list of notations. */ struct notation *next; }; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 1be49b12a..3407848bc 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1668,7 +1668,7 @@ enum_sig_subpkt (const subpktarea_t * pktbuf, sigsubpkttype_t reqtype, } if (reqtype == SIGSUBPKT_TEST_CRITICAL) /* Returning NULL means we found a subpacket with the critical bit - set that we dn't grok. We've iterated over all the subpackets + set that we don't grok. We've iterated over all the subpackets and haven't found such a packet so we need to return a non-NULL value. */ return buffer;