gpg: Improve documentation and comments related to OpenPGP packets.
authorNeal H. Walfield <neal@g10code.com>
Thu, 25 Feb 2016 20:08:56 +0000 (21:08 +0100)
committerNeal H. Walfield <neal@g10code.com>
Thu, 25 Feb 2016 20:08:56 +0000 (21:08 +0100)
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
g10/build-packet.c
g10/packet.h
g10/parse-packet.c

index a257e69..5bcfae1 100644 (file)
@@ -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 )
 {
index dfd3a00..1be9ec3 100644 (file)
@@ -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;
 };
 
index 1be49b1..3407848 100644 (file)
@@ -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;