<p dir="ltr"><br>
On Nov 13, 2015 8:44 AM, "Nicholas Wilson" <<a href="mailto:nicholas@nicholaswilson.me.uk">nicholas@nicholaswilson.me.uk</a>> wrote:<br>
><br>
> Hi,<br>
><br>
> I have some questions about implementing Curve448, having implemented<br>
> it for mbedTLS in a pull request here:<br>
> <a href="https://github.com/ARMmbed/mbedtls/pull/348">https://github.com/ARMmbed/mbedtls/pull/348</a><br>
><br>
> I've been following the discussion around the IRTF standard, but I'm<br>
> still not quite sure what the recommended behaviour is for validating<br>
> public points.<br>
><br>
> In the latest standard, regarding public u-values:<br>
><br>
> "When receiving such an array, implementations of X25519 (but not<br>
> X448) MUST mask the most-significant bit in the final byte."<br>
> (<a href="https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-4.2">https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-4.2</a><br>
><br>
> This suggests, but doesn't state, that implementations shouldn't do<br>
> any masking for Curve448, but should instead just reduce the public<br>
> value mod P448 (or issue an error if it's not in canonical form,<br>
> probably my preferred implementation choice). Is that correct?</p>
<p dir="ltr">Yes. But note that Curve448 is designed to work correctly with all inputs. There are issues with TLS because of requirements on contributory behavior.</p>
<p dir="ltr">><br>
> Secondly, I have a question about the implementation of the arithmetic<br>
> itself. I've had a hunt for Mike's various papers and presentations on<br>
> Ed448-Goldilocks, and I think I understand the rationale for the<br>
> choice of prime. What I can't find though is a simple do-this-do-that<br>
> guide for implementers, like NIST publishes for their primes.</p>
<p dir="ltr">NIST guide is hard to make constant time. I'm not Mike, but as I recall the division is into 56 bit limbs to avoid carries and permit vectorised additions. The formula isn't that hard to work out from there: it's a matter of adding the top pieces to the bottom in the right places. Safety analysis is a bit trickier.</p>
<p dir="ltr">The big benefit is you avoid carries and dependent instruction chains.</p>
<p dir="ltr">><br>
> In the end, I've come up with my own modular reduction formula after<br>
> playing around with the equations, and it seems to be reasonable<br>
> (three 448-sized additions), but I wondered if I'm missing any tricks<br>
> that should make it even quicker.<br>
><br>
> I'm aware that for 32-bit machines, you can split the numbers up into<br>
> 32-bit limbs and write q=2^32, p = q^14 - q^7 - 1 and come up with a<br>
> big complex formula to explictly do your reduction in terms of the<br>
> limb values.<br>
><br>
> I'm more interested in optimising for 64-bit though, so I've chosen to<br>
> split the input into four "limbs" of 2^224 and do a few bignum<br>
> additions on those limbs, which will use the bignum library's 64-bit<br>
> CPU operations, and may come out quicker. The code is certainly<br>
> simpler, and I don't think anyone deploying Curve448 really cares<br>
> about performance as long as it's "good enough".<br>
><br>
> Let N = A0 + 2^448 A1, let A1 = B0 + 2^224 B1. Then N (or N+P) mod P<br>
> is A0+A1+B1+(B0+B1)*2^224. This works on paper, and produces the<br>
> expected output on the test vectors from the IRTF spec.<br>
><br>
> So my question is whether this is the expected reduction formula, or<br>
> whether there's some method which is simpler still.<br>
><br>
> Thanks for your help,<br>
> Nick<br>
><br>
> ----<br>
> Nicholas Wilson: <a href="mailto:nicholas@nicholaswilson.me.uk">nicholas@nicholaswilson.me.uk</a><br>
> _______________________________________________<br>
> Curves mailing list<br>
> <a href="mailto:Curves@moderncrypto.org">Curves@moderncrypto.org</a><br>
> <a href="https://moderncrypto.org/mailman/listinfo/curves">https://moderncrypto.org/mailman/listinfo/curves</a><br>
</p>