Get closer to Ed25519 boundary conditions.

If I perturb kOrder in the malleability check, our and Wycheproof's
tests don't easily notice. This adds some tests with s above and below
the order. EdDSA hashes the public key with the message, which
frustrates constructing actual boundary cases. Instead, these inputs
were found by generating many signatures.

This isn't ideal, but it is sensitive to the most significant 32 bits.

Change-Id: I7fc03758ab97650d0e94478f355ea7085ae0559a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44346
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/curve25519/ed25519_test.cc b/crypto/curve25519/ed25519_test.cc
index 4f34675..d56abe6 100644
--- a/crypto/curve25519/ed25519_test.cc
+++ b/crypto/curve25519/ed25519_test.cc
@@ -64,6 +64,48 @@
   };
 
   EXPECT_FALSE(ED25519_verify(kMsg, sizeof(kMsg), kSig, kPub));
+
+  // The following inputs try to exercise the boundaries of the order check,
+  // where s is near the order above and below. EdDSA hashes the public key with
+  // the message, which frustrates constructing actual boundary cases. Instead,
+  // these inputs were found by randomly generating signatures. kSigValid had
+  // the highest s value. kSigInvalid had the lowest s value, and then the order
+  // was added.
+  //
+  // This isn't ideal, but it is sensitive to the most significant 32 bits.
+  //
+  // The private key seed for kPub2 is
+  // a59a4130fcfd293c9737db8f14177ce034305cf34bdc4346f24b4d262e07b5c2.
+  static const uint8_t kPub2[] = {
+      0x10, 0x0f, 0xdf, 0x47, 0xfb, 0x94, 0xf1, 0x53, 0x6a, 0x4f, 0x7c,
+      0x3f, 0xda, 0x27, 0x38, 0x3f, 0xa0, 0x33, 0x75, 0xa8, 0xf5, 0x27,
+      0xc5, 0x37, 0xe6, 0xf1, 0x70, 0x3c, 0x47, 0xf9, 0x4f, 0x86};
+  static const uint8_t kMsgValid[] = {
+      0x12, 0x4e, 0x58, 0x3f, 0x8b, 0x8e, 0xca, 0x58, 0xbb, 0x29, 0xc2,
+      0x71, 0xb4, 0x1d, 0x36, 0x98, 0x6b, 0xbc, 0x45, 0x54, 0x1f, 0x8e,
+      0x51, 0xf9, 0xcb, 0x01, 0x33, 0xec, 0xa4, 0x47, 0x60, 0x1e};
+  static const uint8_t kSigValid[] = {
+      0xda, 0xc1, 0x19, 0xd6, 0xca, 0x87, 0xfc, 0x59, 0xae, 0x61, 0x1c,
+      0x15, 0x70, 0x48, 0xf4, 0xd4, 0xfc, 0x93, 0x2a, 0x14, 0x9d, 0xbe,
+      0x20, 0xec, 0x6e, 0xff, 0xd1, 0x43, 0x6a, 0xbf, 0x83, 0xea, 0x05,
+      0xc7, 0xdf, 0x0f, 0xef, 0x06, 0x14, 0x72, 0x41, 0x25, 0x91, 0x13,
+      0x90, 0x9b, 0xc7, 0x1b, 0xd3, 0xc5, 0x3b, 0xa4, 0x46, 0x4f, 0xfc,
+      0xad, 0x3c, 0x09, 0x68, 0xf2, 0xff, 0xff, 0xff, 0x0f};
+  static const uint8_t kMsgInvalid[] = {
+      0x6a, 0x0b, 0xc2, 0xb0, 0x05, 0x7c, 0xed, 0xfc, 0x0f, 0xa2, 0xe3,
+      0xf7, 0xf7, 0xd3, 0x92, 0x79, 0xb3, 0x0f, 0x45, 0x4a, 0x69, 0xdf,
+      0xd1, 0x11, 0x7c, 0x75, 0x8d, 0x86, 0xb1, 0x9d, 0x85, 0xe0};
+  static const uint8_t kSigInvalid[] = {
+      0x09, 0x71, 0xf8, 0x6d, 0x2c, 0x9c, 0x78, 0x58, 0x25, 0x24, 0xa1,
+      0x03, 0xcb, 0x9c, 0xf9, 0x49, 0x52, 0x2a, 0xe5, 0x28, 0xf8, 0x05,
+      0x4d, 0xc2, 0x01, 0x07, 0xd9, 0x99, 0xbe, 0x67, 0x3f, 0xf4, 0xe2,
+      0x5e, 0xbf, 0x2f, 0x29, 0x28, 0x76, 0x6b, 0x12, 0x48, 0xbe, 0xc6,
+      0xe9, 0x16, 0x97, 0x77, 0x5f, 0x84, 0x46, 0x63, 0x9e, 0xde, 0x46,
+      0xad, 0x4d, 0xf4, 0x05, 0x30, 0x00, 0x00, 0x00, 0x10};
+
+  EXPECT_TRUE(ED25519_verify(kMsgValid, sizeof(kMsgValid), kSigValid, kPub2));
+  EXPECT_FALSE(
+      ED25519_verify(kMsgInvalid, sizeof(kMsgInvalid), kSigInvalid, kPub2));
 }
 
 TEST(Ed25519Test, KeypairFromSeed) {