summaryrefslogtreecommitdiffstats
path: root/g10/parse-packet.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-01-31 09:27:06 +0100
committerWerner Koch <wk@gnupg.org>2011-01-31 09:27:06 +0100
commit0fb0bb8d9a960a2473ab70a021d20639a43227e0 (patch)
tree8dcce4f17931a3da45890db635a6474231224db0 /g10/parse-packet.c
parentUpdate gitignore (diff)
downloadgnupg2-0fb0bb8d9a960a2473ab70a021d20639a43227e0.tar.xz
gnupg2-0fb0bb8d9a960a2473ab70a021d20639a43227e0.zip
Reworked the ECC changes to better fit into the Libgcrypt API.
See ChangeLog for details. Key generation, signing and verification works. Encryption does not yet work. Requires latest Libgcrypt changes.
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);