summary refs log tree commit diff
path: root/crypto/src/math
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-20 22:02:29 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-20 22:02:29 +0700
commitd12fb5ae13783ce259ee0960551dcd1413ac8516 (patch)
tree452f8636ab5244e7233ce275af5e531e105f6640 /crypto/src/math
parentEd25519: Reject small order public keys (diff)
downloadBouncyCastle.NET-ed25519-d12fb5ae13783ce259ee0960551dcd1413ac8516.tar.xz
Ed448: Reject small order public keys
Diffstat (limited to 'crypto/src/math')
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs65
1 files changed, 48 insertions, 17 deletions
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index 75629c293..cc189615b 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -190,15 +190,6 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             }
             return false;
         }
-
-        private static bool CheckScalarVar(ReadOnlySpan<byte> s, Span<uint> n)
-        {
-            if (s[ScalarBytes - 1] != 0x00)
-                return false;
-
-            DecodeScalar(s, n);
-            return !Nat.Gte(ScalarUints, n, L);
-        }
 #else
         private static bool CheckPointVar(byte[] p)
         {
@@ -215,7 +206,54 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             }
             return false;
         }
+#endif
+
+
+        private static bool CheckPointFullVar(byte[] p)
+        {
+            if ((p[PointBytes - 1] & 0x7F) != 0x00)
+                return false;
+
+            uint y13 = Codec.Decode32(p, 52);
+
+            uint t0 = y13;
+            uint t1 = y13 ^ P[13];
+
+            for (int i = CoordUints - 2; i > 0; --i)
+            {
+                uint yi = Codec.Decode32(p, i * 4);
+
+                // Reject non-canonical encodings (i.e. >= P)
+                if (t1 == 0 && yi > P[i])
+                    return false;
+
+                t0 |= yi;
+                t1 |= yi ^ P[i];
+            }
 
+            uint y0 = Codec.Decode32(p, 0);
+
+            // Reject 0 and 1
+            if (t0 == 0 && y0 <= 1U)
+                return false;
+
+            // Reject P - 1 and non-canonical encodings (i.e. >= P)
+            if (t1 == 0 && y0 >= (P[0] - 1U))
+                return false;
+
+            return true;
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        private static bool CheckScalarVar(ReadOnlySpan<byte> s, Span<uint> n)
+        {
+            if (s[ScalarBytes - 1] != 0x00)
+                return false;
+
+            DecodeScalar(s, n);
+            return !Nat.Gte(ScalarUints, n, L);
+        }
+#else
         private static bool CheckScalarVar(byte[] s, uint[] n)
         {
             if (s[ScalarBytes - 1] != 0x00)
@@ -246,7 +284,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
         private static bool DecodePointVar(byte[] p, int pOff, bool negate, ref PointProjective r)
         {
             byte[] py = Copy(p, pOff, PointBytes);
-            if (!CheckPointVar(py))
+            if (!CheckPointFullVar(py))
                 return false;
 
             int x_0 = (py[PointBytes - 1] & 0x80) >> 7;
@@ -2042,13 +2080,6 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             if (!DecodePointVar(pk, pkOff, false, ref p))
                 return false;
 
-            F.Normalize(p.x);
-            F.Normalize(p.y);
-            F.Normalize(p.z);
-
-            if (IsNeutralElementVar(p.x, p.y, p.z))
-                return false;
-
             Init(out PointProjective r);
             ScalarMultOrderVar(ref p, ref r);