aboutsummaryrefslogtreecommitdiffstats
path: root/g10/parse-packet.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2020-06-09 01:32:47 +0000
committerNIIBE Yutaka <[email protected]>2020-06-09 01:32:47 +0000
commitf5bc94555458123f93d8b07816a68fb7485421e1 (patch)
treed2e27f1eb0c027721847acc498affb536981e1e1 /g10/parse-packet.c
parentgpg: If possible TRUST values now depend on signer's UID or --sender. (diff)
downloadgnupg-f5bc94555458123f93d8b07816a68fb7485421e1.tar.gz
gnupg-f5bc94555458123f93d8b07816a68fb7485421e1.zip
gpg,ecc: Handle external representation as SOS with opaque MPI.
* g10/pkglue.h (sexp_extract_param_sos): New. * g10/build-packet.c (sos_write): New. (do_key, do_pubkey_enc, do_signature): Use sos_write for ECC. * g10/export.c (cleartext_secret_key_to_openpgp): Use sexp_extract_param_sos. (transfer_format_to_openpgp): Use opaque MPI for ECC. * g10/keygen.c (ecckey_from_sexp): Use sexp_extract_param_sos. * g10/keyid.c (hash_public_key): Handle opaque MPI for SOS. * g10/parse-packet.c (sos_read): New. (parse_pubkeyenc,parse_signature,parse_key): Use sos_read for ECC. * g10/pkglue.c (sexp_extract_param_sos): New. (pk_verify): Handle opaque MPI for SOS. (pk_encrypt): Use sexp_extract_param_sos. * g10/seskey.c (encode_session_key): Use opaque MPI. * g10/sign.c (do_sign): Use sexp_extract_param_sos. Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to 'g10/parse-packet.c')
-rw-r--r--g10/parse-packet.c111
1 files changed, 103 insertions, 8 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index fc37c095d..c3f6b544d 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -188,6 +188,76 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
}
+/* Read an external representation of an SOS and return the opaque MPI
+ with GCRYMPI_FLAG_USER2. The external format is a 16-bit unsigned
+ value stored in network byte order giving information for the
+ following octets.
+
+ The caller must set *RET_NREAD to the maximum number of bytes to
+ read from the pipeline INP. This function sets *RET_NREAD to be
+ the number of bytes actually read from the pipeline.
+
+ If SECURE is true, the integer is stored in secure memory
+ (allocated using gcry_xmalloc_secure). */
+static gcry_mpi_t
+sos_read (iobuf_t inp, unsigned int *ret_nread, int secure)
+{
+ int c, c1, c2, i;
+ unsigned int nmax = *ret_nread;
+ unsigned int nbits, nbytes;
+ size_t nread = 0;
+ gcry_mpi_t a = NULL;
+ byte *buf = NULL;
+ byte *p;
+
+ if (!nmax)
+ goto overflow;
+
+ if ((c = c1 = iobuf_get (inp)) == -1)
+ goto leave;
+ if (++nread == nmax)
+ goto overflow;
+ nbits = c << 8;
+ if ((c = c2 = iobuf_get (inp)) == -1)
+ goto leave;
+ ++nread;
+ nbits |= c;
+ if (nbits > MAX_EXTERN_MPI_BITS)
+ {
+ log_error ("mpi too large (%u bits)\n", nbits);
+ goto leave;
+ }
+
+ nbytes = (nbits + 7) / 8;
+ buf = secure ? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes);
+ p = buf;
+ for (i = 0; i < nbytes; i++)
+ {
+ if (nread == nmax)
+ goto overflow;
+
+ c = iobuf_get (inp);
+ if (c == -1)
+ goto leave;
+
+ p[i] = c;
+ nread ++;
+ }
+
+ a = gcry_mpi_set_opaque (NULL, buf, nbits);
+ gcry_mpi_set_flag (a, GCRYMPI_FLAG_USER2);
+ *ret_nread = nread;
+ return a;
+
+ overflow:
+ log_error ("mpi larger than indicated length (%u bits)\n", 8*nmax);
+ leave:
+ *ret_nread = nread;
+ gcry_free(buf);
+ return a;
+}
+
+
/* Register STRING as a known critical notation name. */
void
register_known_notation (const char *string)
@@ -1328,11 +1398,22 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
{
for (i = 0; i < ndata; i++)
{
- if (k->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
+ if (k->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- size_t n;
- rc = read_size_body (inp, pktlen, &n, k->data+i);
- pktlen -= n;
+ if (i == 1)
+ {
+ size_t n;
+ rc = read_size_body (inp, pktlen, &n, k->data+i);
+ pktlen -= n;
+ }
+ else
+ {
+ int n = pktlen;
+ k->data[i] = sos_read (inp, &n, 0);
+ pktlen -= n;
+ if (!k->data[i])
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ }
}
else
{
@@ -2282,7 +2363,11 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
for (i = 0; i < ndata; i++)
{
n = pktlen;
- sig->data[i] = mpi_read (inp, &n, 0);
+ if (sig->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || sig->pubkey_algo == PUBKEY_ALGO_EDDSA)
+ sig->data[i] = sos_read (inp, &n, 0);
+ else
+ sig->data[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
{
@@ -2510,7 +2595,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|| (algorithm == PUBKEY_ALGO_EDDSA && (i == 0))
|| (algorithm == PUBKEY_ALGO_ECDH && (i == 0 || i == 2)))
{
- /* Read the OID (i==1) or the KDF params (i==2). */
+ /* Read the OID (i==0) or the KDF params (i==2). */
size_t n;
err = read_size_body (inp, pktlen, &n, pk->pkey+i);
pktlen -= n;
@@ -2518,7 +2603,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
else
{
unsigned int n = pktlen;
- pk->pkey[i] = mpi_read (inp, &n, 0);
+ if (algorithm == PUBKEY_ALGO_ECDSA
+ || algorithm == PUBKEY_ALGO_EDDSA
+ || algorithm == PUBKEY_ALGO_ECDH)
+ pk->pkey[i] = sos_read (inp, &n, 0);
+ else
+ pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (!pk->pkey[i])
err = gpg_error (GPG_ERR_INV_PACKET);
@@ -2830,7 +2920,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
goto leave;
}
n = pktlen;
- pk->pkey[i] = mpi_read (inp, &n, 0);
+ if (algorithm == PUBKEY_ALGO_ECDSA
+ || algorithm == PUBKEY_ALGO_EDDSA
+ || algorithm == PUBKEY_ALGO_ECDH)
+ pk->pkey[i] = sos_read (inp, &n, 0);
+ else
+ pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
{