aboutsummaryrefslogtreecommitdiffstats
path: root/g10/pkglue.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/pkglue.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/pkglue.c')
-rw-r--r--g10/pkglue.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/g10/pkglue.c b/g10/pkglue.c
index d266fef61..741a93735 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -47,6 +47,56 @@ get_mpi_from_sexp (gcry_sexp_t sexp, const char *item, int mpifmt)
}
+/* 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 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
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 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
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 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
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 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
/* 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 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
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);