gpg: Do not allow creation of user ids larger than our parser allows.
authorWerner Koch <wk@gnupg.org>
Tue, 21 May 2019 14:25:56 +0000 (16:25 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 21 May 2019 14:25:56 +0000 (16:25 +0200)
* g10/parse-packet.c: Move max packet lengths constants to ...
* g10/packet.h: ... here.
* g10/build-packet.c (do_user_id): Return an error if too data is too
large.
* g10/keygen.c (write_uid): Return an error for too large data.
--

This can lead to keyring corruption becuase we expect that our parser
is abale to parse packts created by us.  Test case is

  gpg --batch --passphrase 'abc' -v  \
      --quick-gen-key $(yes 'a'| head -4000|tr -d '\n')

GnuPG-bug-id: 4532
Signed-off-by: Werner Koch <wk@gnupg.org>
g10/build-packet.c
g10/keygen.c
g10/packet.h
g10/parse-packet.c

index 07fccb0..2a95df6 100644 (file)
@@ -447,15 +447,21 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
    * Without forcing HDRLEN to 2 in this case an indeterminate length
    * packet would be written which is not allowed.  Note that we are
    * always called with a CTB indicating an old packet header format,
-   * so that forcing a 2 octet header works.  */
+   * so that forcing a 2 octet header works.  We also check for the
+   * maximum allowed packet size by the parser using an arbitrary
+   * extra 10 bytes for header data. */
   if (uid->attrib_data)
     {
+      if (uid->attrib_len > MAX_ATTR_PACKET_LENGTH - 10)
+        return gpg_error (GPG_ERR_TOO_LARGE);
       hdrlen = uid->attrib_len? 0 : 2;
       write_header2 (out, ctb, uid->attrib_len, hdrlen);
       rc = iobuf_write( out, uid->attrib_data, uid->attrib_len );
     }
   else
     {
+      if (uid->len > MAX_UID_PACKET_LENGTH - 10)
+        return gpg_error (GPG_ERR_TOO_LARGE);
       hdrlen = uid->len? 0 : 2;
       write_header2 (out, ctb, uid->len, hdrlen);
       rc = iobuf_write( out, uid->name, uid->len );
index ac6bcc8..d9037d2 100644 (file)
@@ -227,18 +227,22 @@ print_status_key_not_created (const char *handle)
 
 
 
-static void
-write_uid( KBNODE root, const char *s )
+static gpg_error_t
+write_uid (kbnode_t root, const char *s)
 {
-    PACKET *pkt = xmalloc_clear(sizeof *pkt );
-    size_t n = strlen(s);
-
-    pkt->pkttype = PKT_USER_ID;
-    pkt->pkt.user_id = xmalloc_clear (sizeof *pkt->pkt.user_id + n);
-    pkt->pkt.user_id->len = n;
-    pkt->pkt.user_id->ref = 1;
-    strcpy(pkt->pkt.user_id->name, s);
-    add_kbnode( root, new_kbnode( pkt ) );
+  PACKET *pkt = xmalloc_clear (sizeof *pkt);
+  size_t n = strlen (s);
+
+  if (n > MAX_UID_PACKET_LENGTH - 10)
+    return gpg_error (GPG_ERR_INV_USER_ID);
+
+  pkt->pkttype = PKT_USER_ID;
+  pkt->pkt.user_id = xmalloc_clear (sizeof *pkt->pkt.user_id + n);
+  pkt->pkt.user_id->len = n;
+  pkt->pkt.user_id->ref = 1;
+  strcpy (pkt->pkt.user_id->name, s);
+  add_kbnode (root, new_kbnode (pkt));
+  return 0;
 }
 
 static void
@@ -5092,10 +5096,11 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
 
   if (!err && (s = get_parameter_value (para, pUSERID)))
     {
-      write_uid (pub_root, s );
-      err = write_selfsigs (ctrl, pub_root, pri_psk,
-                            get_parameter_uint (para, pKEYUSAGE), timestamp,
-                            cache_nonce);
+      err = write_uid (pub_root, s );
+      if (!err)
+        err = write_selfsigs (ctrl, pub_root, pri_psk,
+                              get_parameter_uint (para, pKEYUSAGE), timestamp,
+                              cache_nonce);
     }
 
   /* Write the auth key to the card before the encryption key.  This
index d787bde..479f250 100644 (file)
 
 #define DEBUG_PARSE_PACKET 1
 
+/* Maximum length of packets to avoid excessive memory allocation.  */
+#define MAX_KEY_PACKET_LENGTH     (256 * 1024)
+#define MAX_UID_PACKET_LENGTH     (  2 * 1024)
+#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
+#define MAX_ATTR_PACKET_LENGTH    ( 16 * 1024*1024)
 
 /* Constants to allocate static MPI arrays.  */
 #define PUBKEY_MAX_NPKEY  OPENPGP_MAX_NPKEY
index f67edc5..ab82d47 100644 (file)
 #include "../common/mbox-util.h"
 
 
-/* Maximum length of packets to avoid excessive memory allocation.  */
-#define MAX_KEY_PACKET_LENGTH     (256 * 1024)
-#define MAX_UID_PACKET_LENGTH     (  2 * 1024)
-#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
-#define MAX_ATTR_PACKET_LENGTH    ( 16 * 1024*1024)
-
 static int mpi_print_mode;
 static int list_mode;
 static estream_t listfp;