summaryrefslogtreecommitdiff
path: root/cipher/ecc-curves.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/ecc-curves.c')
-rw-r--r--cipher/ecc-curves.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index a019e054..63a38fec 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -1155,7 +1155,7 @@ mpi_ec_setup_elliptic_curve (mpi_ec_t ec, int flags,
errc = mpi_from_keyparam (&ec->d, keyparam, "d", is_opaque_bytes);
/* Size of opaque bytes should match size of P. */
- if (ec->d && is_opaque_bytes)
+ if (!errc && ec->d && is_opaque_bytes)
{
unsigned int n = mpi_get_nbits (ec->d);
unsigned int len;
@@ -1167,11 +1167,36 @@ mpi_ec_setup_elliptic_curve (mpi_ec_t ec, int flags,
if ((n+7)/8 != len)
{
- if (DBG_CIPHER)
- log_debug ("scalar size (%d) != prime size (%d)",
- (n+7)/8, len);
+ if ((n+7)/8 < len && ec->dialect == ECC_DIALECT_ED25519)
+ {
+ /*
+ * GnuPG (<= 2.2) or OpenPGP implementations with no
+ * SOS support may remove zeros at the beginning.
+ * Recover those zeros.
+ */
+ const unsigned char *buf;
+ unsigned char *value;
+
+ buf = mpi_get_opaque (ec->d, &n);
+ if (!buf)
+ return GPG_ERR_INV_OBJ;
+
+ value = xtrycalloc_secure (1, len);
+ if (!value)
+ return gpg_err_code_from_syserror ();
+
+ memset (value, 0, len - (n+7)/8);
+ memcpy (value + len - (n+7)/8, buf, (n+7)/8);
+ mpi_set_opaque (ec->d, value, len);
+ }
+ else
+ {
+ if (DBG_CIPHER)
+ log_debug ("scalar size (%d) != prime size (%d)",
+ (n+7)/8, len);
- errc = GPG_ERR_INV_OBJ;
+ errc = GPG_ERR_INV_OBJ;
+ }
}
}
}