gpgparsemail: Allow weirdly-mixed pkcs7 signatures.
[gnupg.git] / kbx / keybox-openpgp.c
index 37e2771..a0e4ab9 100644 (file)
@@ -36,7 +36,7 @@
 #include <gcrypt.h>
 
 #include "../common/openpgpdefs.h"
-
+#include "host2net.h"
 
 /* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
    which has a maximum length as stored at BUFLEN.  Return the header
@@ -71,7 +71,6 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
   if ( !(ctb & 0x80) )
     return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */
 
-  pktlen = 0;
   if ((ctb & 0x40))  /* New style (OpenPGP) CTB.  */
     {
       pkttype = (ctb & 0x3f);
@@ -94,10 +93,8 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
         {
           if (len <4 )
             return gpg_error (GPG_ERR_INV_PACKET); /* No length bytes. */
-          pktlen  = (*buf++) << 24;
-          pktlen |= (*buf++) << 16;
-          pktlen |= (*buf++) << 8;
-          pktlen |= (*buf++);
+          pktlen = buf32_to_ulong (buf);
+          buf += 4;
           len -= 4;
       }
       else /* Partial length encoding is not allowed for key packets. */
@@ -141,7 +138,14 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
       return gpg_error (GPG_ERR_UNEXPECTED);
     }
 
-  if (pktlen == (unsigned long)(-1))
+  if (pkttype == 63 && pktlen == 0xFFFFFFFF)
+    /* Sometimes the decompressing layer enters an error state in
+       which it simply outputs 0xff for every byte read.  If we have a
+       stream of 0xff bytes, then it will be detected as a new format
+       packet with type 63 and a 4-byte encoded length that is 4G-1.
+       Since packets with type 63 are private and we use them as a
+       control packet, which won't be 4 GB, we reject such packets as
+       invalid.  */
     return gpg_error (GPG_ERR_INV_PACKET);
 
   if (pktlen > len)
@@ -199,23 +203,24 @@ parse_key (const unsigned char *data, size_t datalen,
 
   switch (algorithm)
     {
-    case 1:
-    case 2:
-    case 3: /* RSA */
+    case PUBKEY_ALGO_RSA:
+    case PUBKEY_ALGO_RSA_E:
+    case PUBKEY_ALGO_RSA_S:
       npkey = 2;
       break;
-    case 16:
-    case 20: /* Elgamal */
+    case PUBKEY_ALGO_ELGAMAL_E:
+    case PUBKEY_ALGO_ELGAMAL:
       npkey = 3;
       break;
-    case 17: /* DSA */
+    case PUBKEY_ALGO_DSA:
       npkey = 4;
       break;
-    case 18: /* ECDH */
+    case PUBKEY_ALGO_ECDH:
       npkey = 3;
       is_ecc = 1;
       break;
-    case 19: /* ECDSA */
+    case PUBKEY_ALGO_ECDSA:
+    case PUBKEY_ALGO_EDDSA:
       npkey = 2;
       is_ecc = 1;
       break;
@@ -223,6 +228,8 @@ parse_key (const unsigned char *data, size_t datalen,
       return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
     }
 
+  ki->algo = algorithm;
+
   for (i=0; i < npkey; i++ )
     {
       unsigned int nbits, nbytes;