openssl/crypto/ec
James Muir a822a0cb3c Simpler square-root computation for Ed25519
Description:
Mark Wooden and Franck Rondepierre noted that the square-root-mod-p
operations used in the EdDSA RFC (RFC 8032) can be simplified.  For
Ed25519, instead of computing u*v^3 * (u * v^7)^((p-5)/8), we can
compute u * (u*v)^((p-5)/8).  This saves 3 multiplications and 2
squarings.  For more details (including a proof), see the following
message from the CFRG mailing list:

  https://mailarchive.ietf.org/arch/msg/cfrg/qlKpMBqxXZYmDpXXIx6LO3Oznv4/

Note that the Ed448 implementation (see
ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio() in
./crypto/ec/curve448/curve448.c) appears to already use this simpler
method (i.e. it does not follow the method suggested in RFC 8032).

Testing:
Build and then run the test suite:

  ./Configure -Werror --strict-warnings
  make update
  make
  make test

Numerical testing of the square-root computation can be done using the
following sage script:

  def legendre(x,p):
      return kronecker(x,p)

  # Ed25519
  p = 2**255-19
  # -1 is a square
  if legendre(-1,p)==1:
      print("-1 is a square")

  # suppose u/v is a square.
  # to compute one of its square roots, find x such that
  #    x**4 == (u/v)**2 .
  # this implies
  #    x**2 ==  u/v, or
  #    x**2 == -(u/v) ,
  # which implies either x or i*x is a square-root of u/v (where i is a square root of -1).
  # we can take x equal to u * (u*v)**((p-5)/8).

  # 2 is a generator
  # this can be checked by factoring p-1
  # and then showing 2**((p-1)/q) != 1 (mod p)
  # for all primes q dividing p-1.
  g = 2
  s = p>>2  # s = (p-1)/4
  i = power_mod(g, s, p)

  t = p>>3  # t = (p-5)/8
  COUNT = 1<<18
  while COUNT > 0:
      COUNT -= 1

      r = randint(0,p-1)   # r = u/v
      v = randint(1,p-1)
      u = mod(r*v,p)

      # compute x = u * (u*v)**((p-5)/8)
      w = mod(u*v,p)
      x = mod(u*power_mod(w, t, p), p)

      # check that x**2 == r, or (i*x)**2 == r, or r is not a square
      rr = power_mod(x, 2, p)
      if rr==r:
          continue

      rr = power_mod(mod(i*x,p), 2, p)
      if rr==r:
          continue

      if legendre(r,p) != 1:
          continue

      print("failure!")
      exit()

  print("passed!")

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17544)
2022-01-20 11:03:31 +01:00
..
asm aarch64: support BTI and pointer authentication in assembly 2021-10-01 09:35:38 +02:00
curve448 Fix the parameter type of gf_serialize 2021-09-17 14:44:41 +02:00
build.info ppccap.c: Split out algorithm-specific functions 2021-06-25 08:49:45 +01:00
curve25519.c Simpler square-root computation for Ed25519 2022-01-20 11:03:31 +01:00
ec2_oct.c Fix typos 2022-01-05 12:37:20 +01:00
ec2_smpl.c fix some code with obvious wrong coding style 2021-10-28 13:10:46 +10:00
ec_ameth.c fix some code with obvious wrong coding style 2021-10-28 13:10:46 +10:00
ec_asn1.c add checks for the return values of BN_new(), sk_RSA_PRIME_INFO_new_reserve(), 2021-10-27 08:36:55 +10:00
ec_backend.c fix some code with obvious wrong coding style 2021-10-28 13:10:46 +10:00
ec_check.c Update copyright year 2021-03-11 13:27:36 +00:00
ec_curve.c [ec] Do not default to OPENSSL_EC_NAMED_CURVE for curves without OID 2021-08-30 15:18:19 +03:00
ec_cvt.c Update copyright year 2021-03-11 13:27:36 +00:00
ec_deprecated.c Fix incorrect return check of BN_bn2binpad 2021-11-08 08:53:02 +10:00
ec_err.c crypto: updates to pass size_t to RAND_bytes_ex() 2021-06-01 18:13:56 +10:00
ec_key.c fips module header inclusion fine-tunning 2021-07-06 10:52:27 +10:00
ec_kmeth.c fips module header inclusion fine-tunning 2021-07-06 10:52:27 +10:00
ec_lib.c Fix: some patches related to error exiting 2022-01-07 21:11:37 +11:00
ec_local.h ec: Fail build on big-endian with enable-ec_nistp_64_gcc_128 2021-06-22 18:27:29 +10:00
ec_mult.c ec: remove TODOs 2021-06-02 16:30:15 +10:00
ec_oct.c Update copyright year 2021-03-11 13:27:36 +00:00
ec_pmeth.c Update our EVP_PKEY_METHODs to get low level keys via public APIs 2021-07-22 13:52:46 +02:00
ec_print.c EC_POINT_hex2point: forget to free pt 2021-12-16 12:40:05 +01:00
ecdh_kdf.c Rename all getters to use get/get0 in name 2021-06-01 12:40:00 +02:00
ecdh_ossl.c Update copyright year 2021-03-11 13:27:36 +00:00
ecdsa_ossl.c add zero strenght arguments to BN and RAND RNG calls 2021-05-29 17:17:12 +10:00
ecdsa_sign.c Convert all {NAME}err() in crypto/ to their corresponding ERR_raise() call 2020-11-13 09:35:02 +01:00
ecdsa_vrf.c Convert all {NAME}err() in crypto/ to their corresponding ERR_raise() call 2020-11-13 09:35:02 +01:00
eck_prn.c Update copyright year 2021-01-28 13:54:57 +01:00
ecp_mont.c Update copyright year 2021-03-11 13:27:36 +00:00
ecp_nist.c Update copyright year 2021-03-11 13:27:36 +00:00
ecp_nistp224.c Rework and make DEBUG macros consistent. 2021-05-28 10:04:31 +02:00
ecp_nistp256.c Rework and make DEBUG macros consistent. 2021-05-28 10:04:31 +02:00
ecp_nistp521.c ppccap.c: Split out algorithm-specific functions 2021-06-25 08:49:45 +01:00
ecp_nistputil.c Update copyright year 2021-03-11 13:27:36 +00:00
ecp_nistz256_table.c Following the license change, modify the boilerplates in crypto/ec/ 2018-12-06 14:51:47 +01:00
ecp_nistz256.c fix some code with obvious wrong coding style 2021-10-28 13:10:46 +10:00
ecp_oct.c Replace some of the ERR_clear_error() calls with mark calls 2021-05-13 19:26:06 +02:00
ecp_ppc.c ppccap.c: Split out algorithm-specific functions 2021-06-25 08:49:45 +01:00
ecp_s390x_nistp.c Cleansing all the temporary data for s390x 2022-01-13 18:20:45 +01:00
ecp_smpl.c fix some code with obvious wrong coding style 2021-10-28 13:10:46 +10:00
ecx_backend.c Don't create an ECX key with short keys 2021-11-16 13:21:06 +00:00
ecx_backend.h Fix the KEYNID2TYPE macro 2020-05-04 09:30:55 +01:00
ecx_key.c Do not allow creating empty RSA keys by duplication 2021-04-15 09:23:18 +02:00
ecx_meth.c Fix malloc failure handling of X509_ALGOR_set0() 2022-01-14 18:47:20 +01:00
ecx_s390x.c Update copyright year 2020-04-23 13:55:52 +01:00