[openssl-commits] [openssl] OpenSSL_1_1_1-stable update

Matt Caswell matt at openssl.org
Mon Dec 3 14:29:50 UTC 2018


The branch OpenSSL_1_1_1-stable has been updated
       via  cc4e37f1e4af060dc41a3c84041a183ecd7aa80e (commit)
       via  f3243f22298045de3bd31bf47cdf0abe8394843a (commit)
      from  2561eeb6b9cea581d4bbbc0d2574998f0590f53c (commit)


- Log -----------------------------------------------------------------
commit cc4e37f1e4af060dc41a3c84041a183ecd7aa80e
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Nov 23 14:24:17 2018 +0000

    Add an Ed25519 signature maleability test
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7697)
    
    (cherry picked from commit e65a79d2aae76c27d68587ff66cb6b65a3283e50)

commit f3243f22298045de3bd31bf47cdf0abe8394843a
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Nov 23 13:50:43 2018 +0000

    Disallow Ed25519 signature maleability
    
    Check that s is less than the order before attempting to verify the
    signature as per RFC8032 5.1.7
    
    Fixes #7693
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7697)
    
    (cherry picked from commit 0ac8f35c04c4fcdee421170ae6351e42b9e84ce4)

-----------------------------------------------------------------------

Summary of changes:
 crypto/ec/curve25519.c                    | 53 +++++++++++++++++++++++++------
 test/recipes/30-test_evp_data/evppkey.txt |  8 +++++
 2 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c
index abe9b9c..d6a2bb6 100644
--- a/crypto/ec/curve25519.c
+++ b/crypto/ec/curve25519.c
@@ -5371,40 +5371,73 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
   return 1;
 }
 
+static const char allzeroes[15];
+
 int ED25519_verify(const uint8_t *message, size_t message_len,
                    const uint8_t signature[64], const uint8_t public_key[32]) {
+  int i;
   ge_p3 A;
-  uint8_t rcopy[32];
-  uint8_t scopy[32];
+  const uint8_t *r, *s;
   SHA512_CTX hash_ctx;
   ge_p2 R;
   uint8_t rcheck[32];
   uint8_t h[SHA512_DIGEST_LENGTH];
+  /* 27742317777372353535851937790883648493 in little endian format */
+  const uint8_t l_low[16] = {
+    0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2,
+    0xDE, 0xF9, 0xDE, 0x14
+  };
+
+  r = signature;
+  s = signature + 32;
 
-  if ((signature[63] & 224) != 0 ||
-      ge_frombytes_vartime(&A, public_key) != 0) {
+  /*
+   * Check 0 <= s < L where L = 2^252 + 27742317777372353535851937790883648493
+   *
+   * If not the signature is publicly invalid. Since it's public we can do the
+   * check in variable time.
+   *
+   * First check the most significant byte
+   */
+  if (s[31] > 0x10)
+    return 0;
+  if (s[31] == 0x10) {
+      /*
+       * Most significant byte indicates a value close to 2^252 so check the
+       * rest
+       */
+      if (memcmp(s + 16, allzeroes, sizeof(allzeroes)) != 0)
+        return 0;
+      for (i = 15; i >= 0; i--) {
+          if (s[i] < l_low[i])
+            break;
+          if (s[i] > l_low[i])
+            return 0;
+      }
+      if (i < 0)
+        return 0;
+  }
+
+  if (ge_frombytes_vartime(&A, public_key) != 0) {
     return 0;
   }
 
   fe_neg(A.X, A.X);
   fe_neg(A.T, A.T);
 
-  memcpy(rcopy, signature, 32);
-  memcpy(scopy, signature + 32, 32);
-
   SHA512_Init(&hash_ctx);
-  SHA512_Update(&hash_ctx, signature, 32);
+  SHA512_Update(&hash_ctx, r, 32);
   SHA512_Update(&hash_ctx, public_key, 32);
   SHA512_Update(&hash_ctx, message, message_len);
   SHA512_Final(h, &hash_ctx);
 
   x25519_sc_reduce(h);
 
-  ge_double_scalarmult_vartime(&R, h, &A, scopy);
+  ge_double_scalarmult_vartime(&R, h, &A, s);
 
   ge_tobytes(rcheck, &R);
 
-  return CRYPTO_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
+  return CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0;
 }
 
 void ED25519_public_from_private(uint8_t out_public_key[32],
diff --git a/test/recipes/30-test_evp_data/evppkey.txt b/test/recipes/30-test_evp_data/evppkey.txt
index f4470ff..dc50dc8 100644
--- a/test/recipes/30-test_evp_data/evppkey.txt
+++ b/test/recipes/30-test_evp_data/evppkey.txt
@@ -17601,6 +17601,14 @@ Key = ED25519-1-PUBLIC-Raw
 Input = ""
 Output = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b
 
+#Signature maleability test.
+#Same as the verify operation above but with the order added to s
+OneShotDigestVerify = NULL
+Key = ED25519-1-PUBLIC-Raw
+Input = ""
+Output = e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901554c8c7872aa064e049dbb3013fbf29380d25bf5f0595bbe24655141438e7a101b
+Result = VERIFY_ERROR
+
 Title = ED448 tests from RFC8032
 
 PrivateKey=ED448-1


More information about the openssl-commits mailing list