]> git.codecow.com Git - Monocypher.git/commitdiff
Less error prone EdDSA verification building blocks
authorLoup Vaillant <loup@loup-vaillant.fr>
Wed, 7 Dec 2022 18:39:02 +0000 (19:39 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Wed, 7 Dec 2022 18:39:02 +0000 (19:39 +0100)
crypto_eddsa_r_check() is replaced by crypto_eddsa_check_equation().
This has two advantages:

- Users now only need to return the value of crypto_eddsa_r_check().
  No need for an additional check we may forget, much safer.
- Verifying the equation give better optimisation opportunities.

src/monocypher.c
src/monocypher.h
src/optional/monocypher-ed25519.c

index e603b73e55eee07785450eddb429723f8116fe4b..3c0bf96c7bb436668a4bde5cb74b4df2ef772e1d 100644 (file)
@@ -2218,20 +2218,21 @@ void crypto_eddsa_scalarbase(u8 point[32], const u8 scalar[32])
        WIPE_CTX(&P);
 }
 
-int crypto_eddsa_r_check(u8 r_check[32], const u8 public_key[32],
-                         const u8 h_ram[32], const u8 s[32])
+int crypto_eddsa_check_equation(const u8 signature[64], const u8 public_key[32],
+                                const u8 h_ram[32])
 {
        ge A;
+       const u8 *s = signature + 32;
        u32 s32[8];                                      // s (different encoding)
        load32_le_buf(s32, s, 8);
-
        if (ge_frombytes_neg_vartime(&A, public_key) ||  // A = -pk
            is_above_l(s32)) {                           // prevent s malleability
                return -1;
        }
        ge_double_scalarmult_vartime(&A, h_ram, s);      // A = [s]B - [h_ram]pk
+       u8 r_check[32];
        ge_tobytes(r_check, &A);                         // r_check = A
-       return 0;
+       return crypto_verify32(r_check, signature);      // R == R_check ? OK : fail
 }
 
 void crypto_eddsa_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
@@ -2337,29 +2338,20 @@ void crypto_eddsa_sign(u8 signature [64], const u8 secret_key[32],
        WIPE_BUFFER(r);
 }
 
-// To verify a signature, there are 3 steps:
-//
-//   S, R = signature
-//   h    = HASH(R || public_key || message) % L
-//   R'   = [s]B - [h]public_key
+// To check the signature R, S of the message M with the public key A,
+// there are 3 steps:
 //
-// For the signature to be valid, **TWO** conditions must hold:
+//   compute h = HASH(R || A || message) % L
+//   check that A is on the curve.
+//   check that R == [s]B - [h]A
 //
-// - Computing R' must succeed.
-// - R and R' must be identical (duh).
-//
-// Don't you **ever** forget to check the return value of
-// `crypto_eddsa_r_check()`.
+// The last two steps are done in crypto_eddsa_check_equation()
 int crypto_eddsa_check(const u8  signature[64], const u8 public_key[32],
                        const u8 *message, size_t message_size)
 {
        u8 h_ram  [32];
-       u8 r_check[32];
        hash_reduce(h_ram, signature, 32, public_key, 32, message, message_size);
-       if (crypto_eddsa_r_check(r_check, public_key, h_ram, signature + 32)) {
-               return -1;
-       }
-       return crypto_verify32(r_check, signature);  // R == R_check ? OK : fail
+       return crypto_eddsa_check_equation(signature, public_key, h_ram);
 }
 
 ///////////////////////
index 7a25a0a898225c2b273a2828de3d716eb05d6263..941fa0471292f079c361d0225b2547cfc61ce9ab 100644 (file)
@@ -289,11 +289,9 @@ void crypto_eddsa_mul_add(uint8_t r[32],
                                                  const uint8_t b[32],
                                                  const uint8_t c[32]);
 void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
-int crypto_eddsa_r_check(uint8_t r_check[32],
-                                                const uint8_t public_key[32],
-                         const uint8_t h_ram[32],
-                                                const uint8_t s[32]);
-
+int crypto_eddsa_check_equation(const uint8_t signature[64],
+                                const uint8_t public_key[32],
+                                const uint8_t h_ram[32]);
 
 // EdDSA to X25519
 // ---------------
index ec9d4417e4b18a9ecc70061280eb3ba92f550aac..4602615336281369069436a42f69e09e1aae9b2f 100644 (file)
@@ -390,12 +390,8 @@ int crypto_ed25519_check(const u8  signature[64], const u8 public_key[32],
                          const u8 *message, size_t message_size)
 {
        u8 h_ram  [32];
-       u8 r_check[32];
        hash_reduce(h_ram, signature, 32, public_key, 32, message, message_size);
-       if (crypto_eddsa_r_check(r_check, public_key, h_ram, signature + 32)) {
-               return -1;
-       }
-       return crypto_verify32(r_check, signature);  // R == R_check ? OK : fail
+       return crypto_eddsa_check_equation(signature, public_key, h_ram);
 }
 
 void crypto_from_ed25519_private(u8 x25519[32], const u8 eddsa[32])