[git] GnuPG - branch, master, updated. gnupg-2.1.11-72-g87515e3

by Neal H. Walfield cvs at cvs.gnupg.org
Thu Feb 25 21:28:32 CET 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  87515e39295e4b7eaec1641c38e1ac32e8d39a91 (commit)
       via  960f5e26f2cda3ac6e6b30548fa808a690c39ffc (commit)
       via  105a5629c7e938ec7b3c9c338ebe7bdfee4cfdad (commit)
       via  b7b4a1bdd9da28827980c64c623bcb0654736828 (commit)
       via  c9636a1acc952eb8e1355089bc2e229dece98165 (commit)
       via  512bc72e1f8544341529174142273d857f45540c (commit)
      from  75861b663bbb37214143c2ff7b1b4d1d10ba2657 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 87515e39295e4b7eaec1641c38e1ac32e8d39a91
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 21:22:55 2016 +0100

    gpg: Show debugging info if a sig with an unsupported sig class is used.
    
    * g10/sig-check.c (check_key_signature2): If SIG->CLASS is
    unsupported, show some debugging information.  Don't use BUG to fail.
    Just return GPG_ERR_BAD_SIGNATURE.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/sig-check.c b/g10/sig-check.c
index 4530a64..087222a 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -1086,7 +1086,12 @@ check_key_signature2 (kbnode_t root, kbnode_t node, PKT_public_key *check_pk,
 	  }
       }
   else
-      BUG ();
+    {
+      log_info ("sig issued by %s with class %d (digest: %x %x) is not valid over a user id or a key id, ignoring.\n",
+                keystr (sig->keyid), sig->sig_class,
+                sig->digest_start[0], sig->digest_start[1]);
+      rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
+    }
 
   cache_sig_result  (sig, rc);
 

commit 960f5e26f2cda3ac6e6b30548fa808a690c39ffc
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 21:20:32 2016 +0100

    gpg: More carefully encode a packet's length.
    
    * g10/build-packet.c (write_header2): Make sure the length bits are
    cleared.  Fail if HDRLEN is set and the specified length can't be
    encoded in the available space.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index fe6234f..feb7b44 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1450,6 +1450,10 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
   /* An old format packet.  Refer to RFC 4880, Section 4.2.1 to
      understand how lengths are encoded in this case.  */
 
+  /* The length encoding is stored in the two least significant bits.
+     Make sure they are cleared.  */
+  log_assert ((ctb & 3) == 0);
+
   log_assert (hdrlen == 0 || hdrlen == 2 || hdrlen == 3 || hdrlen == 5);
 
   if (hdrlen)
@@ -1462,10 +1466,13 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
         /* 01 => 2 byte length.  If len < 256, this is not the most
            compact encoding, but it is a correct encoding.  */
 	ctb |= 1;
-      else
+      else if (hdrlen == 5)
         /* 10 => 4 byte length.  If len < 65536, this is not the most
            compact encoding, but it is a correct encoding.  */
 	ctb |= 2;
+      else
+        log_bug ("Can't encode length=%d in a %d byte header!\n",
+                 len, hdrlen);
     }
   else
     {

commit 105a5629c7e938ec7b3c9c338ebe7bdfee4cfdad
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 21:16:41 2016 +0100

    gpg: Avoid directly twiddling bits.
    
    * g10/build-packet.c (do_plaintext): Use ctb_new_format_p to check the
    packet's format.
    (write_header2): Likewise.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index 5bcfae1..fe6234f 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -638,8 +638,9 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
       return rc;
 
     nbytes = iobuf_copy (out, pt->buf);
-    if( (ctb&0x40) && !pt->len )
-      iobuf_set_partial_body_length_mode(out, 0 ); /* turn off partial */
+    if(ctb_new_format_p (ctb) && !pt->len)
+      /* Turn off partial body length mode.  */
+      iobuf_set_partial_body_length_mode (out, 0);
     if( pt->len && nbytes != pt->len )
       log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
 		(ulong)nbytes, (ulong)pt->len );
@@ -1443,7 +1444,7 @@ write_sign_packet_header (IOBUF out, int ctb, u32 len)
 static int
 write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
 {
-  if( ctb & 0x40 )
+  if (ctb_new_format_p (ctb))
     return write_new_header( out, ctb, len, hdrlen );
 
   /* An old format packet.  Refer to RFC 4880, Section 4.2.1 to

commit b7b4a1bdd9da28827980c64c623bcb0654736828
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 21:08:56 2016 +0100

    gpg: Improve documentation and comments related to OpenPGP packets.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index a257e69..5bcfae1 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 at domain.name=value - Normal notation
+     - !name at 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 dfd3a00..1be9ec3 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 1be49b1..3407848 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;

commit c9636a1acc952eb8e1355089bc2e229dece98165
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 15:19:04 2016 +0100

    gpg: Add some asserts.
    
    * g10/build-packet.c (ctb_new_format_p): New function.
    (ctb_pkttype): New function.
    (do_user_id): Add some asserts.
    (do_key): Likewise.
    (do_symkey_enc): Likewise.
    (do_pubkey_enc): Likewise.
    (do_plaintext): Likewise.
    (do_encrypted): Likewise.
    (do_encrypted_mdc): Likewise.
    (do_compressed): Likewise.
    (do_signature): Likewise.
    (do_signature): Likewise.
    (write_header2): Likewise.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index c821ed6..a257e69 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -54,6 +54,29 @@ static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
 static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen );
 static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
 
+/* Returns 1 if CTB is a new format ctb and 0 if CTB is an old format
+   ctb.  */
+static int
+ctb_new_format_p (int ctb)
+{
+  /* Bit 7 must always be set.  */
+  log_assert ((ctb & (1 << 7)));
+  /* Bit 6 indicates whether the packet is a new format packet.  */
+  return (ctb & (1 << 6));
+}
+
+/* Extract the packet type from a CTB.  */
+static int
+ctb_pkttype (int ctb)
+{
+  if (ctb_new_format_p (ctb))
+    /* Bits 0 through 5 are the packet type.  */
+    return (ctb & ((1 << 6) - 1));
+  else
+    /* Bits 2 through 5 are the packet type.  */
+    return (ctb & ((1 << 6) - 1)) >> 2;
+}
+
 /****************
  * Build a packet and write it to INP
  * Returns: 0 := okay
@@ -292,6 +315,9 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
 {
   int rc;
 
+  log_assert (ctb_pkttype (ctb) == PKT_USER_ID
+              || ctb_pkttype (ctb) == PKT_ATTRIBUTE);
+
   if (uid->attrib_data)
     {
       write_header(out, ctb, uid->attrib_len);
@@ -313,6 +339,12 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
   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
+              || ctb_pkttype (ctb) == PKT_PUBLIC_SUBKEY
+              || ctb_pkttype (ctb) == PKT_SECRET_KEY
+              || ctb_pkttype (ctb) == PKT_SECRET_SUBKEY);
+
   /* Write the version number - if none is specified, use 4 */
   if ( !pk->version )
     iobuf_put ( a, 4 );
@@ -335,7 +367,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
       write_fake_data (a, pk->pkey[0]);
       goto leave;
     }
-  assert (npkey < nskey);
+  log_assert (npkey < nskey);
 
   for (i=0; i < npkey; i++ )
     {
@@ -445,6 +477,8 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
     int rc = 0;
     IOBUF a = iobuf_temp();
 
+    log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC);
+
     assert( enc->version == 4 );
     switch( enc->s2k.mode ) {
       case 0: case 1: case 3: break;
@@ -477,6 +511,8 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
   int n, i;
   IOBUF a = iobuf_temp();
 
+  log_assert (ctb_pkttype (ctb) == PKT_PUBKEY_ENC);
+
   iobuf_put (a, 3); /* Version.  */
 
   if ( enc->throw_keyid )
@@ -531,7 +567,11 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
     int rc = 0;
     size_t nbytes;
 
+    log_assert (ctb_pkttype (ctb) == PKT_PLAINTEXT);
+
     write_header(out, ctb, calc_plaintext( pt ) );
+    log_assert (pt->mode == 'b' || pt->mode == 't' || pt->mode == 'u'
+                || pt->mode == 'l' || pt->mode == '1');
     iobuf_put(out, pt->mode );
     iobuf_put(out, pt->namelen );
     iobuf_write (out, pt->name, pt->namelen);
@@ -557,6 +597,9 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
     int rc = 0;
     u32 n;
 
+    log_assert (! ed->mdc_method);
+    log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED);
+
     n = ed->len ? (ed->len + ed->extralen) : 0;
     write_header(out, ctb, n );
 
@@ -571,7 +614,8 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
     int rc = 0;
     u32 n;
 
-    assert( ed->mdc_method );
+    log_assert (ed->mdc_method);
+    log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED_MDC);
 
     /* Take version number and the following MDC packet in account. */
     n = ed->len ? (ed->len + ed->extralen + 1 + 22) : 0;
@@ -589,6 +633,8 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
 {
     int rc = 0;
 
+    log_assert (ctb_pkttype (ctb) == PKT_COMPRESSED);
+
     /* We must use the old convention and don't use blockmode for the
        sake of PGP 2 compatibility.  However if the new_ctb flag was
        set, CTB is already formatted as new style and write_header2
@@ -1111,8 +1157,16 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
   int n, i;
   IOBUF a = iobuf_temp();
 
-  if ( !sig->version )
-    iobuf_put( a, 3 );
+  log_assert (ctb_pkttype (ctb) == PKT_SIGNATURE);
+
+  if ( !sig->version || sig->version == 3)
+    {
+      iobuf_put( a, 3 );
+
+      /* Version 3 packets don't support subpackets.  */
+      log_assert (! sig->hashed);
+      log_assert (! sig->unhashed);
+    }
   else
     iobuf_put( a, sig->version );
   if ( sig->version < 4 )
@@ -1166,6 +1220,8 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
 static int
 do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
 {
+  log_assert (ctb_pkttype (ctb) == PKT_ONEPASS_SIG);
+
     write_header(out, ctb, 4 + 8 + 1);
 
     iobuf_put (out, 3);  /* Version.  */
@@ -1264,6 +1320,8 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
   if( ctb & 0x40 )
     return write_new_header( out, ctb, len, hdrlen );
 
+  log_assert (hdrlen == 0 || hdrlen == 2 || hdrlen == 3 || hdrlen == 5);
+
   if( hdrlen )
     {
       if( hdrlen == 2 && len < 256 )

commit 512bc72e1f8544341529174142273d857f45540c
Author: Neal H. Walfield <neal at g10code.com>
Date:   Thu Feb 25 14:51:55 2016 +0100

    gpg: Avoid an unnecessary copy.
    
    * g10/build-packet.c (sig_to_notation): Avoid an unnecessary copy of
    the data: the size of the packet is fixed.
    
    --
    Signed-off-by: Neal H. Walfield <neal at g10code.com>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index a6d5881..c821ed6 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1166,22 +1166,17 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
 static int
 do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
 {
-    int rc = 0;
-    IOBUF a = iobuf_temp();
+    write_header(out, ctb, 4 + 8 + 1);
 
-    iobuf_put (a, 3);  /* Version.  */
-    iobuf_put(a, ops->sig_class );
-    iobuf_put(a, ops->digest_algo );
-    iobuf_put(a, ops->pubkey_algo );
-    write_32(a, ops->keyid[0] );
-    write_32(a, ops->keyid[1] );
-    iobuf_put(a, ops->last );
-
-    write_header(out, ctb, iobuf_get_temp_length(a) );
-    rc = iobuf_write_temp( out, a );
+    iobuf_put (out, 3);  /* Version.  */
+    iobuf_put(out, ops->sig_class );
+    iobuf_put(out, ops->digest_algo );
+    iobuf_put(out, ops->pubkey_algo );
+    write_32(out, ops->keyid[0] );
+    write_32(out, ops->keyid[1] );
+    iobuf_put(out, ops->last );
 
-    iobuf_close(a);
-    return rc;
+    return 0;
 }
 
 

-----------------------------------------------------------------------

Summary of changes:
 g10/build-packet.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++-------
 g10/packet.h       | 249 +++++++++++++++++++++++++++++++++++++----------
 g10/parse-packet.c |   2 +-
 g10/sig-check.c    |   7 +-
 4 files changed, 450 insertions(+), 88 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list