Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18825884
D502.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
19 KB
Subscribers
None
D502.id.diff
View Options
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
Details
Attached
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
Attached To
D502: ECC change for SOS
Event Timeline
Log In to Comment