Hi,
Nikos pointed out to me that there's a slight difference between curve25519 as implemented by Nettle and the spec in RFC 7748.
As far as I see, the difference is that RFC 7748 says that bit 255 of an encoded x coordinates is ignored. Or more precisely, the high bit of the 31:st octet in the x input string is cleared before convertion into an integer. While nettle's curve25519_mul includes it in the computation, with the usual wrap-around, 2^255 = 19 (mod p). I don't see any difference in handling scalars. Do you agree?
So I'm considering this change,
diff --git a/curve25519-mul.c b/curve25519-mul.c index adb20cb..f5127d7 100644 --- a/curve25519-mul.c +++ b/curve25519-mul.c @@ -72,7 +72,11 @@ curve25519_mul (uint8_t *q, const uint8_t *n, const uint8_t *p) itch = ecc->p.size * 12; scratch = gmp_alloc_limbs (itch);
+ /* Note that 255 % GMP_NUMB_BITS == 0 isn't supported, so x1 always + holds at least 256 bits. */ mpn_set_base256_le (x1, ecc->p.size, p, CURVE25519_SIZE); + /* Clear bit 255, as required by RFC 7748. */ + x1[255/GMP_NUMB_BITS] &= ~((mp_limb_t) 1 << (255 % GMP_NUMB_BITS));
/* Initialize, x2 = x1, z2 = 1 */ mpn_copyi (x2, x1, ecc->p.size);
I wouldn't expect any problems from this, its a corner case with input values which are arguably invalid.
The motivation in the RFC, as I understand it, is to leave open for protocols to use the top bit for their own, without bothering to clear it before invoking curve25519. Which at first seems a bit silly, but there's some value in not leaving corner cases implementation defined, and it would maybe have been even more silly to require that implementations do wraparound of that improper high bit.
This change would also need some updates of testcases and documentation.
Regards, /Niels
On Mon, 2016-04-25 at 21:43 +0200, Niels Möller wrote:
Hi,
I wouldn't expect any problems from this, its a corner case with input values which are arguably invalid.
The motivation in the RFC, as I understand it, is to leave open for protocols to use the top bit for their own, without bothering to clear it before invoking curve25519. Which at first seems a bit silly, but there's some value in not leaving corner cases implementation defined, and it would maybe have been even more silly to require that implementations do wraparound of that improper high bit.
This change would also need some updates of testcases and documentation.
It would make sense to document the version of nettle after which this behavior is followed, and probably add some ifdef similarly to FIPS202 for sha3.
regards, Nikos
Nikos Mavrogiannopoulos n.mavrogiannopoulos@gmail.com writes:
It would make sense to document the version of nettle after which this behavior is followed,
Makes sense, I guess. Note that current behaviour is quite explicitly undocumented, "The output value is defined only when the input @var{p} is a string produced by @code{curve25519_mul_g}", and that function shouldn't produce any strings with the top bit set.
It would also be relevant to compare with NaCl's crypto_scalar_mult_base function, does anyone on the list know how it behaves in this respect?
Regards, /Niels
nisse@lysator.liu.se (Niels Möller) writes:
So I'm considering this change,
diff --git a/curve25519-mul.c b/curve25519-mul.c index adb20cb..f5127d7 100644 --- a/curve25519-mul.c +++ b/curve25519-mul.c @@ -72,7 +72,11 @@ curve25519_mul (uint8_t *q, const uint8_t *n, const uint8_t *p) itch = ecc->p.size * 12; scratch = gmp_alloc_limbs (itch);
/* Note that 255 % GMP_NUMB_BITS == 0 isn't supported, so x1 always
holds at least 256 bits. */
mpn_set_base256_le (x1, ecc->p.size, p, CURVE25519_SIZE);
/* Clear bit 255, as required by RFC 7748. */
x1[255/GMP_NUMB_BITS] &= ~((mp_limb_t) 1 << (255 % GMP_NUMB_BITS));
/* Initialize, x2 = x1, z2 = 1 */ mpn_copyi (x2, x1, ecc->p.size);
Checked in now, together with updates of tests and docs.
Nikos Mavrogiannopoulos n.mavrogiannopoulos@gmail.com writes:
It would make sense to document the version of nettle after which this behavior is followed, and probably add some ifdef similarly to FIPS202 for sha3.
Not done yet.
Regards, /Niels
nettle-bugs@lists.lysator.liu.se