Page MenuHome GnuPG

D502.id.diff
No OneTemporary

D502.id.diff

diff --git a/g10/build-packet.c b/g10/build-packet.c
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -364,7 +364,71 @@
/*
- * Write an opaque MPI to the output stream without length info.
+ * Write the mpi A to the output stream OUT as "SOS" (Strange Octet
+ * String). If R_NWRITTEN is not NULL the number of bytes written is
+ * stored there. To only get the number of bytes which would be
+ * written, NULL may be passed for OUT.
+ */
+static gpg_error_t
+sos_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten)
+{
+ gpg_error_t err;
+ unsigned int nwritten = 0;
+
+ if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+ {
+ unsigned int nbits;
+ const unsigned char *p;
+ unsigned char lenhdr[2];
+
+ /* gcry_log_debugmpi ("a", a); */
+ p = gcry_mpi_get_opaque (a, &nbits);
+ /* gcry_log_debug (" [%u bit]\n", nbits); */
+ /* gcry_log_debughex (" ", p, (nbits+7)/8); */
+
+ if (p && *p)
+ {
+ nbits = ((nbits + 7) / 8) * 8;
+
+ if (nbits >= 8 && !(*p & 0x80))
+ if (--nbits >= 7 && !(*p & 0x40))
+ if (--nbits >= 6 && !(*p & 0x20))
+ if (--nbits >= 5 && !(*p & 0x10))
+ if (--nbits >= 4 && !(*p & 0x08))
+ if (--nbits >= 3 && !(*p & 0x04))
+ if (--nbits >= 2 && !(*p & 0x02))
+ if (--nbits >= 1 && !(*p & 0x01))
+ --nbits;
+ }
+
+ lenhdr[0] = nbits >> 8;
+ lenhdr[1] = nbits;
+ err = out? iobuf_write (out, lenhdr, 2) : 0;
+ if (!err)
+ {
+ nwritten += 2;
+ if (p)
+ {
+ err = out? iobuf_write (out, p, (nbits+7)/8) : 0;
+ if (!err)
+ nwritten += (nbits+7)/8;
+ }
+ }
+ }
+ else
+ {
+ log_info ("non-opaque MPI (%u bits) for SOS\n", gcry_mpi_get_nbits (a));
+ err = gpg_error (GPG_ERR_INV_DATA);
+ }
+
+ if (r_nwritten)
+ *r_nwritten = nwritten;
+ return err;
+}
+
+
+/*
+ * Write an opaque string to the output stream without length info.
*/
gpg_error_t
gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a)
@@ -575,6 +639,10 @@
|| (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && (i == 0))
|| (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2)))
err = gpg_mpi_write_nohdr (a, pk->pkey[i]);
+ else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ err = sos_write (a, pk->pkey[i], NULL);
else
err = gpg_mpi_write (a, pk->pkey[i], NULL);
if (err)
@@ -691,8 +759,18 @@
for (j=i; j < nskey; j++ )
{
- if ((err = gpg_mpi_write (NULL, pk->pkey[j], &n)))
- goto leave;
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ {
+ if ((err = sos_write (NULL, pk->pkey[j], &n)))
+ goto leave;
+ }
+ else
+ {
+ if ( (err = gpg_mpi_write (a, pk->pkey[i], NULL)))
+ goto leave;
+ }
skbytes += n;
}
@@ -700,8 +778,16 @@
}
for ( ; i < nskey; i++ )
- if ( (err = gpg_mpi_write (a, pk->pkey[i], NULL)))
- goto leave;
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ {
+ if ((err = sos_write (a, pk->pkey[i], NULL)))
+ goto leave;
+ }
+ else
+ if ((err = gpg_mpi_write (a, pk->pkey[i], NULL)))
+ goto leave;
write_16 (a, ski->csum );
}
@@ -817,6 +903,8 @@
{
if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
rc = gpg_mpi_write_nohdr (a, enc->data[i]);
+ else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH)
+ rc = sos_write (a, enc->data[i], NULL);
else
rc = gpg_mpi_write (a, enc->data[i], NULL);
}
@@ -1696,8 +1784,13 @@
n = pubkey_get_nsig( sig->pubkey_algo );
if ( !n )
write_fake_data( a, sig->data[0] );
- for (i=0; i < n && !rc ; i++ )
- rc = gpg_mpi_write (a, sig->data[i], NULL);
+ if (sig->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || sig->pubkey_algo == PUBKEY_ALGO_EDDSA)
+ for (i=0; i < n && !rc ; i++ )
+ rc = sos_write (a, sig->data[i], NULL);
+ else
+ for (i=0; i < n && !rc ; i++ )
+ rc = gpg_mpi_write (a, sig->data[i], NULL);
if (!rc)
{
diff --git a/g10/export.c b/g10/export.c
--- a/g10/export.c
+++ b/g10/export.c
@@ -42,6 +42,7 @@
#include "trustdb.h"
#include "call-agent.h"
#include "key-clean.h"
+#include "pkglue.h"
/* An object to keep track of subkeys. */
@@ -750,10 +751,8 @@
err = match_curve_skey_pk (key, pk);
if (err)
goto leave;
- if (!err)
- err = gcry_sexp_extract_param (key, NULL, "q",
- &pub_params[0],
- NULL);
+ else
+ err = sexp_extract_param_sos (key, "q", &pub_params[0]);
if (!err && (gcry_mpi_cmp(pk->pkey[1], pub_params[0])))
err = gpg_error (GPG_ERR_BAD_PUBKEY);
@@ -764,9 +763,7 @@
{
gcry_mpi_release (pk->pkey[sec_start]);
pk->pkey[sec_start] = NULL;
- err = gcry_sexp_extract_param (key, NULL, "d",
- &pk->pkey[sec_start],
- NULL);
+ err = sexp_extract_param_sos (key, "d", &pk->pkey[sec_start]);
}
if (!err)
@@ -978,15 +975,16 @@
value = gcry_sexp_nth_data (list, ++idx, &valuelen);
if (!value || !valuelen)
goto bad_seckey;
- if (is_enc)
+ if (is_enc
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- void *p = xtrymalloc (valuelen);
- if (!p)
- goto outofmem;
- memcpy (p, value, valuelen);
- skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
+ skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
if (!skey[skeyidx])
goto outofmem;
+ if (is_enc)
+ gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
}
else
{
@@ -1144,7 +1142,7 @@
/* Check that the first secret key parameter in SKEY is encrypted
and that there are no more secret key parameters. The latter is
guaranteed by the v4 packet format. */
- if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE))
+ if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_USER1))
goto bad_seckey;
if (npkey+1 < DIM (skey) && skey[npkey+1])
goto bad_seckey;
diff --git a/g10/keygen.c b/g10/keygen.c
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1329,19 +1329,10 @@
if (err)
goto leave;
- l2 = gcry_sexp_find_token (list, "q", 0);
- if (!l2)
- {
- err = gpg_error (GPG_ERR_NO_OBJ);
- goto leave;
- }
- array[1] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (l2);
- if (!array[1])
- {
- err = gpg_error (GPG_ERR_INV_OBJ);
- goto leave;
- }
+ err = sexp_extract_param_sos (list, "q", &array[1]);
+ if (err)
+ goto leave;
+
gcry_sexp_release (list);
if (algo == PUBKEY_ALGO_ECDH)
diff --git a/g10/keyid.c b/g10/keyid.c
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -181,14 +181,23 @@
else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{
const void *p;
+ int is_sos = 0;
+
+ if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER2))
+ is_sos = 2;
p = gcry_mpi_get_opaque (pk->pkey[i], &nbits);
- pp[i] = xmalloc ((nbits+7)/8);
+ pp[i] = xmalloc ((nbits+7)/8 + is_sos);
if (p)
- memcpy (pp[i], p, (nbits+7)/8);
+ memcpy (pp[i] + is_sos, p, (nbits+7)/8);
else
pp[i] = NULL;
- nn[i] = (nbits+7)/8;
+ if (is_sos)
+ {
+ pp[i][0] = (nbits >> 8);
+ pp[i][1] = nbits;
+ }
+ nn[i] = (nbits+7)/8 + is_sos;
n += nn[i];
}
else
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -188,6 +188,76 @@
}
+/* 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 @@
{
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 @@
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 @@
|| (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 @@
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 @@
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)
{
diff --git a/g10/pkglue.h b/g10/pkglue.h
--- a/g10/pkglue.h
+++ b/g10/pkglue.h
@@ -24,6 +24,8 @@
/*-- pkglue.c --*/
gcry_mpi_t get_mpi_from_sexp (gcry_sexp_t sexp, const char *item, int mpifmt);
+gpg_error_t sexp_extract_param_sos (gcry_sexp_t sexp, const char *param,
+ gcry_mpi_t *r_sos);
int pk_verify (pubkey_algo_t algo, gcry_mpi_t hash, gcry_mpi_t *data,
gcry_mpi_t *pkey);
diff --git a/g10/pkglue.c b/g10/pkglue.c
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -47,6 +47,56 @@
}
+/* Extract SOS representation from SEXP for PARAM, return the result
+ in R_SOS. */
+gpg_error_t
+sexp_extract_param_sos (gcry_sexp_t sexp, const char *param, gcry_mpi_t *r_sos)
+{
+ gpg_error_t err;
+ gcry_sexp_t l2 = gcry_sexp_find_token (sexp, param, 0);
+
+ *r_sos = NULL;
+ if (!l2)
+ err = gpg_error (GPG_ERR_NO_OBJ);
+ else
+ {
+ size_t buflen;
+ void *p0 = gcry_sexp_nth_buffer (l2, 1, &buflen);
+
+ if (!p0)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ gcry_mpi_t sos;
+ unsigned int nbits = buflen*8;
+ unsigned char *p = p0;
+
+ if (nbits >= 8 && !(*p & 0x80))
+ if (--nbits >= 7 && !(*p & 0x40))
+ if (--nbits >= 6 && !(*p & 0x20))
+ if (--nbits >= 5 && !(*p & 0x10))
+ if (--nbits >= 4 && !(*p & 0x08))
+ if (--nbits >= 3 && !(*p & 0x04))
+ if (--nbits >= 2 && !(*p & 0x02))
+ if (--nbits >= 1 && !(*p & 0x01))
+ --nbits;
+
+ sos = gcry_mpi_set_opaque (NULL, p0, nbits);
+ if (sos)
+ {
+ gcry_mpi_set_flag (sos, GCRYMPI_FLAG_USER2);
+ *r_sos = sos;
+ err = 0;
+ }
+ else
+ err = gpg_error_from_syserror ();
+ }
+ gcry_sexp_release (l2);
+ }
+
+ return err;
+}
+
/****************
* Emulate our old PK interface here - sometime in the future we might
@@ -152,6 +202,7 @@
gcry_mpi_t s = data[1];
size_t rlen, slen, n; /* (bytes) */
char buf[64];
+ unsigned int nbits;
log_assert (neededfixedlen <= sizeof buf);
@@ -182,6 +233,17 @@
memset (buf, 0, neededfixedlen - n);
r = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8);
}
+ else if (rlen < neededfixedlen
+ && gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE))
+ {
+ const unsigned char *p;
+
+ p = gcry_mpi_get_opaque (r, &nbits);
+ n = (nbits+7)/8;
+ memcpy (buf + (neededfixedlen - n), p, n);
+ memset (buf, 0, neededfixedlen - n);
+ gcry_mpi_set_opaque_copy (r, buf, neededfixedlen * 8);
+ }
if (slen < neededfixedlen
&& !gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, s)))
@@ -191,6 +253,17 @@
memset (buf, 0, neededfixedlen - n);
s = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8);
}
+ else if (slen < neededfixedlen
+ && gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE))
+ {
+ const unsigned char *p;
+
+ p = gcry_mpi_get_opaque (s, &nbits);
+ n = (nbits+7)/8;
+ memcpy (buf + (neededfixedlen - n), p, n);
+ memset (buf, 0, neededfixedlen - n);
+ gcry_mpi_set_opaque_copy (s, buf, neededfixedlen * 8);
+ }
if (!rc)
rc = gcry_sexp_build (&s_sig, NULL,
@@ -315,7 +388,7 @@
/* Get the shared point and the ephemeral public key. */
shared = get_mpi_from_sexp (s_ciph, "s", GCRYMPI_FMT_USG);
- public = get_mpi_from_sexp (s_ciph, "e", GCRYMPI_FMT_USG);
+ rc = sexp_extract_param_sos (s_ciph, "e", &public);
gcry_sexp_release (s_ciph);
s_ciph = NULL;
if (DBG_CRYPTO)
@@ -329,7 +402,8 @@
fingerprint_from_pk (pk, fp, &fpn);
if (fpn != 20)
rc = gpg_error (GPG_ERR_INV_LENGTH);
- else
+
+ if (!rc)
rc = pk_ecdh_encrypt_with_shared_point (shared,
fp, data, pkey, &result);
gcry_mpi_release (shared);
diff --git a/g10/seskey.c b/g10/seskey.c
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -82,7 +82,6 @@
byte *frame;
int i,n;
u16 csum;
- gcry_mpi_t a;
if (DBG_CRYPTO)
log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
@@ -124,10 +123,7 @@
(int) nframe, frame[0], frame[1], frame[2],
frame[nframe-3], frame[nframe-2], frame[nframe-1]);
- if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe))
- BUG();
- xfree(frame);
- return a;
+ return gcry_mpi_set_opaque (NULL, frame, 8*nframe);
}
/* The current limitation is that we can only use a session key
@@ -195,10 +191,7 @@
frame[n++] = csum >>8;
frame[n++] = csum;
log_assert (n == nframe);
- if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
- BUG();
- xfree (frame);
- return a;
+ return gcry_mpi_set_opaque (NULL, frame, 8*n);
}
diff --git a/g10/sign.c b/g10/sign.c
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -505,10 +505,12 @@
else if (pksk->pubkey_algo == GCRY_PK_RSA
|| pksk->pubkey_algo == GCRY_PK_RSA_S)
sig->data[0] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_USG);
- else if (openpgp_oid_is_ed25519 (pksk->pkey[0]))
+ else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
{
- sig->data[0] = get_mpi_from_sexp (s_sigval, "r", GCRYMPI_FMT_OPAQUE);
- sig->data[1] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_OPAQUE);
+ err = sexp_extract_param_sos (s_sigval, "r", &sig->data[0]);
+ if (!err)
+ err = sexp_extract_param_sos (s_sigval, "s", &sig->data[1]);
}
else
{

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 22, 3:33 PM (52 m, 33 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
da/be/da4df6b50d931eda7bcc345cac98

Event Timeline