Add readcert command.
[gnupg.git] / g10 / parse-packet.c
index 6b8e79e..324ab5e 100644 (file)
@@ -139,9 +139,19 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
       p[i+2] = iobuf_get(inp) & 0xff;
       nread++;
     }
-  if ( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) )
-    a = NULL;
-    
+
+  if (nread >= 2 && !(buf[0] << 8 | buf[1]))
+    {
+      /* Libgcrypt < 1.5.0 accidently rejects zero-length (i.e. zero)
+         MPIs.  We fix this here.  */
+      a = gcry_mpi_new (0);
+    }
+  else
+    {
+      if ( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) )
+        a = NULL;
+    }
+
  leave:
   gcry_free(buf);
   if ( nread > *ret_nread )
@@ -395,12 +405,20 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
            rc = gpg_error (GPG_ERR_INV_PACKET);
            goto leave;
        }
-        if (pkttype == PKT_COMPRESSED) {
-             iobuf_set_partial_block_mode(inp, c & 0xff);
-             pktlen = 0;/* to indicate partial length */
-            partial=1;
-        }
-        else {
+
+/* The follwing code has been here for ages (2002-08-30) but it is
+   clearly wrong: For example passing a 0 as second argument to
+   iobuf_set_partial_block_mode stops the partial block mode which we
+   definitely do not want.  Also all values < 224 or 255 are not
+   valid.  Let's disable it and put PKT_COMPRESSED into the list of
+   allowed packets with partial header until someone complains. */
+/*         if (pkttype == PKT_COMPRESSED) { */
+/*              iobuf_set_partial_block_mode(inp, c & 0xff); */
+/*              pktlen = 0;  /\* to indicate partial length *\/ */
+/*          partial=1; */
+/*         } */
+/*         else  */
+        {
              hdr[hdrlen++] = c;
              if( c < 192 )
               pktlen = c;
@@ -433,19 +451,21 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
               }
              else
               {
-                /* Partial body length.  Note that we handled
-                   PKT_COMPRESSED earlier. */
-                if(pkttype==PKT_PLAINTEXT || pkttype==PKT_ENCRYPTED
-                   || pkttype==PKT_ENCRYPTED_MDC)
-                  {
+                /* Partial body length.  */
+                 switch (pkttype)
+                   {
+                   case PKT_PLAINTEXT:
+                   case PKT_ENCRYPTED:
+                  case PKT_ENCRYPTED_MDC:
+                   case PKT_COMPRESSED:
                     iobuf_set_partial_block_mode(inp, c & 0xff);
-                    pktlen = 0;/* to indicate partial length */
+                    pktlen = 0;/* To indicate partial length.  */
                     partial=1;
-                  }
-                else
-                  {
+                     break;
+
+                  default:
                     log_error("%s: partial length for invalid"
-                              " packet type %d\n",iobuf_where(inp),pkttype);
+                              " packet type %d\n", iobuf_where(inp),pkttype);
                      rc = gpg_error (GPG_ERR_INV_PACKET);
                     goto leave;
                   }
@@ -692,6 +712,8 @@ read_rest( IOBUF inp, size_t pktlen, int partial )
 static int
 parse_marker( IOBUF inp, int pkttype, unsigned long pktlen )
 {
+  (void)pkttype;
+
   if(pktlen!=3)
     goto fail;
 
@@ -1651,8 +1673,8 @@ read_protected_v3_mpi (IOBUF inp, unsigned long *length)
 
 
 static int
-parse_keyIOBUF inp, int pkttype, unsigned long pktlen,
-                             byte *hdr, int hdrlen, PACKET *pkt )
+parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
+           byte *hdr, int hdrlen, PACKET *pkt)
 {
     int i, version, algorithm;
     unsigned n;
@@ -1660,6 +1682,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     int npkey, nskey;
     int is_v4=0;
     int rc=0;
+    u32 keyid[2];
+
+    (void)hdr;
 
     version = iobuf_get_noeof(inp); pktlen--;
     if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
@@ -1901,18 +1926,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
             * of the IV here in cases we are not aware of the algorithm.
             * so a
             *   sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo);
-            * won't work.  The only solution I see is to hardwire it here.
+            * won't work.  The only solution I see is to hardwire it.
             * NOTE: if you change the ivlen above 16, don't forget to
             * enlarge temp.
             */
-           switch( sk->protect.algo ) {
-             case 7: case 8: case 9: /* reserved for AES */
-             case 10: /* Twofish */
-               sk->protect.ivlen = 16;
-               break;
-             default:
-               sk->protect.ivlen = 8;
-           }
+            sk->protect.ivlen = openpgp_cipher_blocklen (sk->protect.algo);
+            assert (sk->protect.ivlen <= sizeof (temp));
+
            if( sk->protect.s2k.mode == 1001 )
                sk->protect.ivlen = 0;
            else if( sk->protect.s2k.mode == 1002 )
@@ -1988,6 +2008,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                fprintf (listfp, "\tchecksum: %04hx\n", sk->csum);
            }
        }
+
+        if (list_mode)
+          keyid_from_sk (sk, keyid);
     }
     else {
        PKT_public_key *pk = pkt->pkt.public_key;
@@ -2012,8 +2035,14 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        }
         if (rc)
             goto leave;
+        if (list_mode)
+          keyid_from_pk (pk, keyid);
     }
 
+    if (list_mode)
+      fprintf (listfp, "\tkeyid: %08lX%08lX\n", 
+               (ulong)keyid[0], (ulong)keyid[1]);
+
   leave:
     iobuf_skip_rest(inp, pktlen, 0);
     return rc;
@@ -2165,6 +2194,8 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
+    (void)pkttype;
+
 #define EXTRA_UID_NAME_SPACE 71
     packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id
                                        + EXTRA_UID_NAME_SPACE);
@@ -2232,6 +2263,8 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
 {
   int c;
 
+  (void)pkttype;
+
   if (pktlen)
     {
       c = iobuf_get_noeof(inp);
@@ -2327,20 +2360,22 @@ static int
 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
                  PACKET *pkt, int new_ctb )
 {
-    PKT_compressed *zd;
-
-    /* pktlen is here 0, but data follows
-     * (this should be the last object in a file or
-     * the compress algorithm should know the length)
-     */
-    zd = pkt->pkt.compressed = xmalloc(sizeof *pkt->pkt.compressed );
-    zd->algorithm = iobuf_get_noeof(inp);
-    zd->len = 0; /* not used */ 
-    zd->new_ctb = new_ctb;
-    zd->buf = inp;
-    if( list_mode )
-       fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm);
-    return 0;
+  PKT_compressed *zd;
+  
+  /* PKTLEN is here 0, but data follows (this should be the last
+     object in a file or the compress algorithm should know the
+     length).  */
+  (void)pkttype;
+  (void)pktlen;
+
+  zd = pkt->pkt.compressed = xmalloc (sizeof *pkt->pkt.compressed);
+  zd->algorithm = iobuf_get_noeof(inp);
+  zd->len = 0; /* not used */ 
+  zd->new_ctb = new_ctb;
+  zd->buf = inp;
+  if (list_mode)
+    fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm);
+  return 0;
 }
 
 
@@ -2407,27 +2442,30 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
    the MDC checking is done right after the encryption in
    decrypt_data. */
 static int
-parse_mdcIOBUF inp, int pkttype, unsigned long pktlen,
-                                  PACKET *pkt, int new_ctb )
+parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen,
+           PACKET *pkt, int new_ctb)
 {
-    int rc = 0;
-    PKT_mdc *mdc;
-    byte *p;
+  int rc = 0;
+  PKT_mdc *mdc;
+  byte *p;
 
-    mdc = pkt->pkt.mdc = xmalloc(sizeof *pkt->pkt.mdc );
-    if( list_mode )
-       fprintf (listfp, ":mdc packet: length=%lu\n", pktlen);
-    if( !new_ctb || pktlen != 20 ) {
-       log_error("mdc_packet with invalid encoding\n");
-        rc = gpg_error (GPG_ERR_INV_PACKET);
-       goto leave;
-    }
-    p = mdc->hash;
-    for( ; pktlen; pktlen--, p++ )
-       *p = iobuf_get_noeof(inp);
+  (void)pkttype;
 
-  leave:
-    return rc;
+  mdc = pkt->pkt.mdc = xmalloc(sizeof *pkt->pkt.mdc );
+  if (list_mode)
+    fprintf (listfp, ":mdc packet: length=%lu\n", pktlen);
+  if (!new_ctb || pktlen != 20)
+    {
+      log_error("mdc_packet with invalid encoding\n");
+      rc = gpg_error (GPG_ERR_INV_PACKET);
+      goto leave;
+    }
+  p = mdc->hash;
+  for (; pktlen; pktlen--, p++)
+    *p = iobuf_get_noeof(inp);
+  
+ leave:
+  return rc;
 }
 
 
@@ -2443,14 +2481,16 @@ parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
  */
 
 static int
-parse_gpg_control( IOBUF inp, int pkttype,
-                  unsigned long pktlen, PACKET *packet, int partial )
+parse_gpg_control (IOBUF inp, int pkttype, unsigned long pktlen,
+                   PACKET *packet, int partial)
 {
     byte *p;
     const byte *sesmark;
     size_t sesmarklen;
     int i;
 
+    (void)pkttype;
+
     if ( list_mode )
         fprintf (listfp, ":packet 63: length %lu ",  pktlen);