summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-10-06 16:44:01 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-10-06 16:44:01 +0700
commitf5078e451501d43882308d8322b9c8863e2a2723 (patch)
tree6fe93ae3363b7a7492e099a363286fee29bc8115
parentFix initialization checks (diff)
downloadBouncyCastle.NET-ed25519-f5078e451501d43882308d8322b9c8863e2a2723.tar.xz
RFC 7748: Exclude all-zeroes agreement value
-rw-r--r--crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs3
-rw-r--r--crypto/src/crypto/parameters/X448PrivateKeyParameters.cs3
-rw-r--r--crypto/src/math/ec/rfc7748/X25519.cs8
-rw-r--r--crypto/src/math/ec/rfc7748/X448.cs8
-rw-r--r--crypto/src/util/Arrays.cs10
5 files changed, 30 insertions, 2 deletions
diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
index c25ab9364..fb49a02b3 100644
--- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X25519.PointSize];
             publicKey.Encode(encoded, 0);
-            X25519.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X25519.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X25519 agreement failed");
         }
     }
 }
diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
index 291eac10f..d17aa7947 100644
--- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X448.PointSize];
             publicKey.Encode(encoded, 0);
-            X448.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X448.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X448 agreement failed");
         }
     }
 }
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs
index d63cc5a3e..6b6acdecd 100644
--- a/crypto/src/math/ec/rfc7748/X25519.cs
+++ b/crypto/src/math/ec/rfc7748/X25519.cs
@@ -2,6 +2,8 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
     public abstract class X25519
@@ -21,6 +23,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
 
         private static int[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs
index aac603b08..b93cb24c5 100644
--- a/crypto/src/math/ec/rfc7748/X448.cs
+++ b/crypto/src/math/ec/rfc7748/X448.cs
@@ -2,6 +2,8 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
     public abstract class X448
@@ -24,6 +26,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
 
         private static uint[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 3df908240..a9a574dbf 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -11,6 +11,16 @@ namespace Org.BouncyCastle.Utilities
         public static readonly byte[] EmptyBytes = new byte[0];
         public static readonly int[] EmptyInts = new int[0];
 
+        public static bool AreAllZeroes(byte[] buf, int off, int len)
+        {
+            uint bits = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                bits |= buf[off + i];
+            }
+            return bits == 0;
+        }
+
         public static bool AreEqual(
             bool[]  a,
             bool[]  b)