aboutsummaryrefslogtreecommitdiffstats
path: root/g10/parse-packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/parse-packet.c')
-rw-r--r--g10/parse-packet.c201
1 files changed, 71 insertions, 130 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index a0844c7ac..83be15d8c 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -741,51 +741,57 @@ read_rest (IOBUF inp, size_t pktlen, int partial)
}
-/*
- * Read a special size+body from inp into body[body_max_size] and
- * return it in a buffer and as MPI. On success the number of
- * consumed bytes will body[0]+1. The format of the content of the
- * returned MPI is one byte LEN, following by LEN bytes. Caller is
- * expected to pre-allocate fixed-size 255 byte buffer (or smaller
- * when appropriate).
- */
-static int
-read_size_body (iobuf_t inp, byte *body, int body_max_size,
- int pktlen, gcry_mpi_t *out )
+/* Read a special size+body from INP. On success store an opaque MPI
+ with it at R_DATA. On error return an error code and store NULL at
+ R_DATA. Even in the error case store the number of read bytes at
+ R_NREAD. The caller shall pass the remaining size of the packet in
+ PKTLEN. */
+static gpg_error_t
+read_size_body (iobuf_t inp, int pktlen, size_t *r_nread,
+ gcry_mpi_t *r_data)
{
- unsigned int n;
- int rc;
- gcry_mpi_t result;
+ char buffer[256];
+ char *tmpbuf;
+ int i, c, nbytes;
+
+ *r_nread = 0;
+ *r_data = NULL;
+
+ if (!pktlen)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ c = iobuf_readbyte (inp);
+ if (c < 0)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ pktlen--;
+ ++*r_nread;
+ nbytes = c;
+ if (nbytes < 2 || nbytes > 254)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ if (nbytes > pktlen)
+ return gpg_error (GPG_ERR_INV_PACKET);
- *out = NULL;
+ buffer[0] = nbytes;
- if( (n = iobuf_readbyte(inp)) == -1 )
- {
- return G10ERR_INVALID_PACKET;
- }
- if ( n >= body_max_size || n < 2)
- {
- log_error("invalid size+body field\n");
- return G10ERR_INVALID_PACKET;
- }
- body[0] = n;
- if ((n = iobuf_read(inp, body+1, n)) == -1)
+ for (i = 0; i < nbytes; i++)
{
- log_error("invalid size+body field\n");
- return G10ERR_INVALID_PACKET;
+ c = iobuf_get (inp);
+ if (c < 0)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ ++*r_nread;
+ buffer[1+i] = c;
}
- if (n+1 > pktlen)
+
+ tmpbuf = xtrymalloc (1 + nbytes);
+ if (!tmpbuf)
+ return gpg_error_from_syserror ();
+ memcpy (tmpbuf, buffer, 1 + nbytes);
+ *r_data = gcry_mpi_set_opaque (NULL, tmpbuf, 8 * (1 + nbytes));
+ if (!*r_data)
{
- log_error("size+body field is larger than the packet\n");
- return G10ERR_INVALID_PACKET;
+ xfree (tmpbuf);
+ return gpg_error_from_syserror ();
}
- rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL);
- if (rc)
- log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc));
-
- *out = result;
-
- return rc;
+ return 0;
}
@@ -988,46 +994,29 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
}
else
{
- if (k->pubkey_algo == PUBKEY_ALGO_ECDH)
+ for (i = 0; i < ndata; i++)
{
- byte encr_buf[255];
-
- assert (ndata == 2);
- n = pktlen;
- k->data[0] = mpi_read (inp, &n, 0);
- pktlen -= n;
- rc = read_size_body (inp, encr_buf, sizeof(encr_buf),
- pktlen, k->data+1);
- if (rc)
- goto leave;
-
- if (list_mode)
+ if (k->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
{
- es_fprintf (listfp, "\tdata: ");
- mpi_print (listfp, k->data[0], mpi_print_mode );
- es_putc ('\n', listfp);
- es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1);
- mpi_print (listfp, k->data[1], mpi_print_mode );
- es_putc ('\n', listfp);
+ rc = read_size_body (inp, pktlen, &n, k->data+i);
+ pktlen -= n;
}
- pktlen -= (encr_buf[0]+1);
- }
- else
- {
- for (i = 0; i < ndata; i++)
+ else
{
n = pktlen;
k->data[i] = mpi_read (inp, &n, 0);
pktlen -= n;
- if (list_mode)
- {
- es_fprintf (listfp, "\tdata: ");
- mpi_print (listfp, k->data[i], mpi_print_mode);
- es_putc ('\n', listfp);
- }
if (!k->data[i])
rc = gpg_error (GPG_ERR_INV_PACKET);
}
+ if (rc)
+ goto leave;
+ if (list_mode)
+ {
+ es_fprintf (listfp, "\tdata: ");
+ mpi_print (listfp, k->data[i], mpi_print_mode);
+ es_putc ('\n', listfp);
+ }
}
}
@@ -1989,7 +1978,6 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
unknown_pubkey_warning (algorithm);
}
-
if (!npkey)
{
/* Unknown algorithm - put data into an opaque MPI. */
@@ -2001,79 +1989,32 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
}
else
{
- /* Fill in public key parameters. */
- if (algorithm == PUBKEY_ALGO_ECDSA || algorithm == PUBKEY_ALGO_ECDH)
+ for (i = 0; i < npkey; i++)
{
- /* FIXME: The code in this function ignores the errors. */
- byte name_oid[256];
-
- err = read_size_body (inp, name_oid, sizeof(name_oid),
- pktlen, pk->pkey+0);
- if (err)
- goto leave;
- n = name_oid[0];
- if (list_mode)
- es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n",
- n, name_oid[1+n-2], name_oid[1+n-1]);
- pktlen -= (n+1);
- /* Set item [1], which corresponds to the public key; these
- two fields are all we need to uniquely define the key/ */
- n = pktlen;
- pk->pkey[1] = mpi_read( inp, &n, 0 );
- pktlen -=n;
- if (!pk->pkey[1])
- err = gpg_error (GPG_ERR_INV_PACKET);
- else if (list_mode)
+ if ((algorithm == PUBKEY_ALGO_ECDSA
+ || algorithm == PUBKEY_ALGO_ECDH) && (i==0 || i == 2))
{
- es_fprintf (listfp, "\tpkey[1]: ");
- mpi_print (listfp, pk->pkey[1], mpi_print_mode);
- es_putc ('\n', listfp);
- }
- /* One more field for ECDH. */
- if (algorithm == PUBKEY_ALGO_ECDH)
- {
- /* (NAMEOID holds the KEK params.) */
- err = read_size_body (inp, name_oid, sizeof(name_oid),
- pktlen, pk->pkey+2);
- if (err)
- goto leave;
- n = name_oid[0];
- if (name_oid[1] != 1)
- {
- log_error ("invalid ecdh KEK parameters field type in "
- "private key: understand type 1, "
- "but found 0x%02x\n", name_oid[1]);
- err = gpg_error (GPG_ERR_INV_PACKET);
- goto leave;
- }
- if (list_mode)
- es_fprintf (listfp, "\tpkey[2]: KEK params type=01 "
- "hash:%d sym-algo:%d\n",
- name_oid[1+n-2], name_oid[1+n-1]);
- pktlen -= (n+1);
+ err = read_size_body (inp, pktlen, &n, pk->pkey+i);
+ pktlen -= n;
}
- }
- else
- {
- for (i = 0; i < npkey; i++)
+ else
{
n = pktlen;
pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
- if (list_mode)
- {
- es_fprintf (listfp, "\tpkey[%d]: ", i);
- mpi_print (listfp, pk->pkey[i], mpi_print_mode);
- es_putc ('\n', listfp);
- }
if (!pk->pkey[i])
err = gpg_error (GPG_ERR_INV_PACKET);
}
+ if (err)
+ goto leave;
+ if (list_mode)
+ {
+ es_fprintf (listfp, "\tpkey[%d]: ", i);
+ mpi_print (listfp, pk->pkey[i], mpi_print_mode);
+ es_putc ('\n', listfp);
+ }
}
- if (err)
- goto leave;
}
-
if (list_mode)
keyid_from_pk (pk, keyid);