summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs55
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs55
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs1
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs51
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs1
-rw-r--r--crypto/src/math/ec/rfc7748/X25519.cs80
-rw-r--r--crypto/src/math/ec/rfc7748/X448.cs88
-rw-r--r--crypto/src/math/ec/rfc8032/Ed25519.cs132
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs118
9 files changed, 301 insertions, 280 deletions
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
index 1b3142c7b..ef8714188 100644
--- a/crypto/src/crypto/signers/Ed25519Signer.cs
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -80,49 +79,55 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey)
             {
+                lock (this)
+                {
 #if PORTABLE
-                byte[] buf = ToArray();
-                int count = buf.Length;
+                    byte[] buf = ToArray();
+                    int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0);
-                Reset();
-                return signature;
+                    byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0);
+                    Reset();
+                    return signature;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] signature)
             {
+                lock (this)
+                {
 #if PORTABLE
-                byte[] buf = ToArray();
-                int count = buf.Length;
+                    byte[] buf = ToArray();
+                    int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] pk = publicKey.GetEncoded();
-                bool result = Ed25519.Verify(signature, 0, pk, 0, buf, 0, count);
-                Reset();
-                return result;
+                    byte[] pk = publicKey.GetEncoded();
+                    bool result = Ed25519.Verify(signature, 0, pk, 0, buf, 0, count);
+                    Reset();
+                    return result;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                long count = Position;
+                lock (this)
+                {
+                    long count = Position;
 #if PORTABLE
-                this.Position = 0L;
-                Streams.WriteZeroes(this, count);
+                    this.Position = 0L;
+                    Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)count);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
-                this.Position = 0L;
+                    this.Position = 0L;
+                }
             }
         }
     }
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
index 965453011..60c708019 100644
--- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -82,49 +81,55 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx)
             {
+                lock (this)
+                {
 #if PORTABLE
-                byte[] buf = ToArray();
-                int count = buf.Length;
+                    byte[] buf = ToArray();
+                    int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0);
-                Reset();
-                return signature;
+                    byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0);
+                    Reset();
+                    return signature;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
             {
+                lock (this)
+                {
 #if PORTABLE
-                byte[] buf = ToArray();
-                int count = buf.Length;
+                    byte[] buf = ToArray();
+                    int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] pk = publicKey.GetEncoded();
-                bool result = Ed25519.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
-                Reset();
-                return result;
+                    byte[] pk = publicKey.GetEncoded();
+                    bool result = Ed25519.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
+                    Reset();
+                    return result;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                long count = Position;
+                lock (this)
+                {
+                    long count = Position;
 #if PORTABLE
-                this.Position = 0L;
-                Streams.WriteZeroes(this, count);
+                    this.Position = 0L;
+                    Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)count);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
-                this.Position = 0L;
+                    this.Position = 0L;
+                }
             }
         }
     }
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
index 3318f6438..548ca1f29 100644
--- a/crypto/src/crypto/signers/Ed25519phSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
index d18f956a8..0863e5dd1 100644
--- a/crypto/src/crypto/signers/Ed448Signer.cs
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -82,49 +81,55 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx)
             {
+                lock (this)
+                {
 #if PORTABLE
                 byte[] buf = ToArray();
                 int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
-                privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0);
-                Reset();
-                return signature;
+                    byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
+                    privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0);
+                    Reset();
+                    return signature;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
             {
+                lock (this)
+                {
 #if PORTABLE
-                byte[] buf = ToArray();
-                int count = buf.Length;
+                    byte[] buf = ToArray();
+                    int count = buf.Length;
 #else
-                byte[] buf = GetBuffer();
-                int count = (int)Position;
+                    byte[] buf = GetBuffer();
+                    int count = (int)Position;
 #endif
-                byte[] pk = publicKey.GetEncoded();
-                bool result = Ed448.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
-                Reset();
-                return result;
+                    byte[] pk = publicKey.GetEncoded();
+                    bool result = Ed448.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
+                    Reset();
+                    return result;
+                }
             }
 
-            [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                long count = Position;
+                lock (this)
+                {
+                    long count = Position;
 #if PORTABLE
-                this.Position = 0L;
-                Streams.WriteZeroes(this, count);
+                    this.Position = 0L;
+                    Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)count);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
-                this.Position = 0L;
+                    this.Position = 0L;
+                }
             }
         }
     }
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
index b86d0855c..8f451f9e8 100644
--- a/crypto/src/crypto/signers/Ed448phSigner.cs
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs
index 6b6acdecd..d8db2527a 100644
--- a/crypto/src/math/ec/rfc7748/X25519.cs
+++ b/crypto/src/math/ec/rfc7748/X25519.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Utilities;
 
@@ -21,6 +20,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
         private static readonly int[] PsubS_x = { 0x03D48290, 0x02C7804D, 0x01207816, 0x028F5A68, 0x00881ED4, 0x00A2B71D,
             0x0217D1B7, 0x014CB523, 0x0088EC1A, 0x0042A264 };
 
+        private static readonly object precompLock = new object();
         private static int[] precompBase = null;
 
         public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
@@ -65,63 +65,65 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             X25519Field.Mul(z, A, z);
         }
 
-        [MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            if (precompBase != null)
-                return;
+            lock (precompLock)
+            {
+                if (precompBase != null)
+                    return;
 
-            precompBase = new int[X25519Field.Size * 252];
+                precompBase = new int[X25519Field.Size * 252];
 
-            int[] xs = precompBase;
-            int[] zs = new int[X25519Field.Size * 251];
+                int[] xs = precompBase;
+                int[] zs = new int[X25519Field.Size * 251];
 
-            int[] x = X25519Field.Create();     x[0] = 9;          
-            int[] z = X25519Field.Create();     z[0] = 1;
+                int[] x = X25519Field.Create(); x[0] = 9;
+                int[] z = X25519Field.Create(); z[0] = 1;
 
-            int[] n = X25519Field.Create();
-            int[] d = X25519Field.Create();
+                int[] n = X25519Field.Create();
+                int[] d = X25519Field.Create();
 
-            X25519Field.Apm(x, z, n, d);
+                X25519Field.Apm(x, z, n, d);
 
-            int[] c = X25519Field.Create();     X25519Field.Copy(d, 0, c, 0);
+                int[] c = X25519Field.Create(); X25519Field.Copy(d, 0, c, 0);
 
-            int off = 0;
-            for (;;)
-            {
-                X25519Field.Copy(n, 0, xs, off);
+                int off = 0;
+                for (; ; )
+                {
+                    X25519Field.Copy(n, 0, xs, off);
 
-                if (off == (X25519Field.Size * 251))
-                    break;
+                    if (off == (X25519Field.Size * 251))
+                        break;
 
-                PointDouble(x, z);
+                    PointDouble(x, z);
 
-                X25519Field.Apm(x, z, n, d);
-                X25519Field.Mul(n, c, n);
-                X25519Field.Mul(c, d, c);
+                    X25519Field.Apm(x, z, n, d);
+                    X25519Field.Mul(n, c, n);
+                    X25519Field.Mul(c, d, c);
 
-                X25519Field.Copy(d, 0, zs, off);
+                    X25519Field.Copy(d, 0, zs, off);
 
-                off += X25519Field.Size;
-            }
+                    off += X25519Field.Size;
+                }
 
-            int[] u = X25519Field.Create();
-            X25519Field.Inv(c, u);
+                int[] u = X25519Field.Create();
+                X25519Field.Inv(c, u);
 
-            for (;;)
-            {
-                X25519Field.Copy(xs, off, x, 0);
+                for (; ; )
+                {
+                    X25519Field.Copy(xs, off, x, 0);
 
-                X25519Field.Mul(x, u, x);
-                //X25519Field.Normalize(x);
-                X25519Field.Copy(x, 0, precompBase, off);
+                    X25519Field.Mul(x, u, x);
+                    //X25519Field.Normalize(x);
+                    X25519Field.Copy(x, 0, precompBase, off);
 
-                if (off == 0)
-                    break;
+                    if (off == 0)
+                        break;
 
-                off -= X25519Field.Size;
-                X25519Field.Copy(zs, off, z, 0);
-                X25519Field.Mul(u, z, u);
+                    off -= X25519Field.Size;
+                    X25519Field.Copy(zs, off, z, 0);
+                    X25519Field.Mul(u, z, u);
+                }
             }
         }
 
diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs
index b93cb24c5..63d34d1cf 100644
--- a/crypto/src/math/ec/rfc7748/X448.cs
+++ b/crypto/src/math/ec/rfc7748/X448.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Utilities;
 
@@ -24,6 +23,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             0x0643ACE1U, 0x03F1BD65U, 0x084C1F82U, 0x0954459DU, 0x081B9672U, 0x0DD1031CU, 0x0EB7BDACU, 0x03881AFFU, 0x0423ACF0U,
             0x05013244U, 0x0F0FAB72U };
 
+        private static readonly object precompLock = new object();
         private static uint[] precompBase = null;
 
         public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
@@ -69,67 +69,69 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             X448Field.Mul(z, A, z);
         }
 
-        [MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            if (precompBase != null)
-                return;
+            lock (precompLock)
+            {
+                if (precompBase != null)
+                    return;
 
-            precompBase = new uint[X448Field.Size * 446];
+                precompBase = new uint[X448Field.Size * 446];
 
-            uint[] xs = precompBase;
-            uint[] zs = new uint[X448Field.Size * 445];
+                uint[] xs = precompBase;
+                uint[] zs = new uint[X448Field.Size * 445];
 
-            uint[] x = X448Field.Create();     x[0] = 5;          
-            uint[] z = X448Field.Create();     z[0] = 1;
+                uint[] x = X448Field.Create();     x[0] = 5;          
+                uint[] z = X448Field.Create();     z[0] = 1;
 
-            uint[] n = X448Field.Create();
-            uint[] d = X448Field.Create();
+                uint[] n = X448Field.Create();
+                uint[] d = X448Field.Create();
 
-            //X448Field.Apm(x, z, n, d);
-            X448Field.Add(x, z, n);
-            X448Field.Sub(x, z, d);
+                //X448Field.Apm(x, z, n, d);
+                X448Field.Add(x, z, n);
+                X448Field.Sub(x, z, d);
 
-            uint[] c = X448Field.Create();     X448Field.Copy(d, 0, c, 0);
+                uint[] c = X448Field.Create();     X448Field.Copy(d, 0, c, 0);
 
-            int off = 0;
-            for (;;)
-            {
-                X448Field.Copy(n, 0, xs, off);
+                int off = 0;
+                for (;;)
+                {
+                    X448Field.Copy(n, 0, xs, off);
 
-                if (off == (X448Field.Size * 445))
-                    break;
+                    if (off == (X448Field.Size * 445))
+                        break;
 
-                PointDouble(x, z);
+                    PointDouble(x, z);
 
-                //X448Field.Apm(x, z, n, d);
-                X448Field.Add(x, z, n);
-                X448Field.Sub(x, z, d);
-                X448Field.Mul(n, c, n);
-                X448Field.Mul(c, d, c);
+                    //X448Field.Apm(x, z, n, d);
+                    X448Field.Add(x, z, n);
+                    X448Field.Sub(x, z, d);
+                    X448Field.Mul(n, c, n);
+                    X448Field.Mul(c, d, c);
 
-                X448Field.Copy(d, 0, zs, off);
+                    X448Field.Copy(d, 0, zs, off);
 
-                off += X448Field.Size;
-            }
+                    off += X448Field.Size;
+                }
 
-            uint[] u = X448Field.Create();
-            X448Field.Inv(c, u);
+                uint[] u = X448Field.Create();
+                X448Field.Inv(c, u);
 
-            for (;;)
-            {
-                X448Field.Copy(xs, off, x, 0);
+                for (;;)
+                {
+                    X448Field.Copy(xs, off, x, 0);
 
-                X448Field.Mul(x, u, x);
-                //X448Field.Normalize(x);
-                X448Field.Copy(x, 0, precompBase, off);
+                    X448Field.Mul(x, u, x);
+                    //X448Field.Normalize(x);
+                    X448Field.Copy(x, 0, precompBase, off);
 
-                if (off == 0)
-                    break;
+                    if (off == 0)
+                        break;
 
-                off -= X448Field.Size;
-                X448Field.Copy(zs, off, z, 0);
-                X448Field.Mul(u, z, u);
+                    off -= X448Field.Size;
+                    X448Field.Copy(zs, off, z, 0);
+                    X448Field.Mul(u, z, u);
+                }
             }
         }
 
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index f9ba1ff97..403f11f50 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
@@ -61,6 +60,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
         private const int PrecompPoints = 1 << (PrecompTeeth - 1);
         private const int PrecompMask = PrecompPoints - 1;
 
+        private static readonly object precompLock = new object();
         // TODO[ed25519] Convert to PointPrecomp
         private static PointExt[] precompBaseTable = null;
         private static int[] precompBase = null;
@@ -631,98 +631,100 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X25519Field.Zero(p.t);
         }
 
-        [MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            if (precompBase != null)
-                return;
-
-            // Precomputed table for the base point in verification ladder
+            lock (precompLock)
             {
-                PointExt b = new PointExt();
-                X25519Field.Copy(B_x, 0, b.x, 0);
-                X25519Field.Copy(B_y, 0, b.y, 0);
-                PointExtendXY(b);
-
-                precompBaseTable = PointPrecompVar(b, 1 << (WnafWidthBase - 2));
-            }
+                if (precompBase != null)
+                    return;
 
-            PointAccum p = new PointAccum();
-            X25519Field.Copy(B_x, 0, p.x, 0);
-            X25519Field.Copy(B_y, 0, p.y, 0);
-            PointExtendXY(p);
+                // Precomputed table for the base point in verification ladder
+                {
+                    PointExt b = new PointExt();
+                    X25519Field.Copy(B_x, 0, b.x, 0);
+                    X25519Field.Copy(B_y, 0, b.y, 0);
+                    PointExtendXY(b);
 
-            precompBase = new int[PrecompBlocks * PrecompPoints * 3 * X25519Field.Size];
+                    precompBaseTable = PointPrecompVar(b, 1 << (WnafWidthBase - 2));
+                }
 
-            int off = 0;
-            for (int b = 0; b < PrecompBlocks; ++b)
-            {
-                PointExt[] ds = new PointExt[PrecompTeeth];
+                PointAccum p = new PointAccum();
+                X25519Field.Copy(B_x, 0, p.x, 0);
+                X25519Field.Copy(B_y, 0, p.y, 0);
+                PointExtendXY(p);
 
-                PointExt sum = new PointExt();
-                PointSetNeutral(sum);
+                precompBase = new int[PrecompBlocks * PrecompPoints * 3 * X25519Field.Size];
 
-                for (int t = 0; t < PrecompTeeth; ++t)
+                int off = 0;
+                for (int b = 0; b < PrecompBlocks; ++b)
                 {
-                    PointExt q = PointCopy(p);
-                    PointAddVar(true, sum, q, sum);
-                    PointDouble(p);
+                    PointExt[] ds = new PointExt[PrecompTeeth];
 
-                    ds[t] = PointCopy(p);
+                    PointExt sum = new PointExt();
+                    PointSetNeutral(sum);
 
-                    if (b + t != PrecompBlocks + PrecompTeeth - 2)
+                    for (int t = 0; t < PrecompTeeth; ++t)
                     {
-                        for (int s = 1; s < PrecompSpacing; ++s)
+                        PointExt q = PointCopy(p);
+                        PointAddVar(true, sum, q, sum);
+                        PointDouble(p);
+
+                        ds[t] = PointCopy(p);
+
+                        if (b + t != PrecompBlocks + PrecompTeeth - 2)
                         {
-                            PointDouble(p);
+                            for (int s = 1; s < PrecompSpacing; ++s)
+                            {
+                                PointDouble(p);
+                            }
                         }
                     }
-                }
 
-                PointExt[] points = new PointExt[PrecompPoints];
-                int k = 0;
-                points[k++] = sum;
+                    PointExt[] points = new PointExt[PrecompPoints];
+                    int k = 0;
+                    points[k++] = sum;
 
-                for (int t = 0; t < (PrecompTeeth - 1); ++t)
-                {
-                    int size = 1 << t;
-                    for (int j = 0; j < size; ++j, ++k)
+                    for (int t = 0; t < (PrecompTeeth - 1); ++t)
                     {
-                        PointAddVar(false, points[k - size], ds[t], points[k] = new PointExt());
+                        int size = 1 << t;
+                        for (int j = 0; j < size; ++j, ++k)
+                        {
+                            PointAddVar(false, points[k - size], ds[t], points[k] = new PointExt());
+                        }
                     }
-                }
 
-                Debug.Assert(k == PrecompPoints);
+                    Debug.Assert(k == PrecompPoints);
 
-                for (int i = 0; i < PrecompPoints; ++i)
-                {
-                    PointExt q = points[i];
+                    for (int i = 0; i < PrecompPoints; ++i)
+                    {
+                        PointExt q = points[i];
 
-                    int[] x = X25519Field.Create();
-                    int[] y = X25519Field.Create();
+                        int[] x = X25519Field.Create();
+                        int[] y = X25519Field.Create();
 
-                    X25519Field.Add(q.z, q.z, x);
-                    // TODO[ed25519] Batch inversion
-                    X25519Field.Inv(x, y);
-                    X25519Field.Mul(q.x, y, x);
-                    X25519Field.Mul(q.y, y, y);
+                        X25519Field.Add(q.z, q.z, x);
+                        // TODO[ed25519] Batch inversion
+                        X25519Field.Inv(x, y);
+                        X25519Field.Mul(q.x, y, x);
+                        X25519Field.Mul(q.y, y, y);
 
-                    PointPrecomp r = new PointPrecomp();
-                    X25519Field.Apm(y, x, r.ypx_h, r.ymx_h);
-                    X25519Field.Mul(x, y, r.xyd);
-                    X25519Field.Mul(r.xyd, C_d4, r.xyd);
+                        PointPrecomp r = new PointPrecomp();
+                        X25519Field.Apm(y, x, r.ypx_h, r.ymx_h);
+                        X25519Field.Mul(x, y, r.xyd);
+                        X25519Field.Mul(r.xyd, C_d4, r.xyd);
 
-                    X25519Field.Normalize(r.ypx_h);
-                    X25519Field.Normalize(r.ymx_h);
-                    //X25519Field.Normalize(r.xyd);
+                        X25519Field.Normalize(r.ypx_h);
+                        X25519Field.Normalize(r.ymx_h);
+                        //X25519Field.Normalize(r.xyd);
 
-                    X25519Field.Copy(r.ypx_h, 0, precompBase, off); off += X25519Field.Size;
-                    X25519Field.Copy(r.ymx_h, 0, precompBase, off); off += X25519Field.Size;
-                    X25519Field.Copy(r.xyd, 0, precompBase, off);   off += X25519Field.Size;
+                        X25519Field.Copy(r.ypx_h, 0, precompBase, off); off += X25519Field.Size;
+                        X25519Field.Copy(r.ymx_h, 0, precompBase, off); off += X25519Field.Size;
+                        X25519Field.Copy(r.xyd, 0, precompBase, off); off += X25519Field.Size;
+                    }
                 }
-            }
 
-            Debug.Assert(off == precompBase.Length);
+                Debug.Assert(off == precompBase.Length);
+            }
         }
 
         private static void PruneScalar(byte[] n, int nOff, byte[] r)
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index a1f0e93b0..10ebe8f15 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
@@ -70,6 +69,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
         private const int PrecompPoints = 1 << (PrecompTeeth - 1);
         private const int PrecompMask = PrecompPoints - 1;
 
+        private static readonly object precompLock = new object();
         // TODO[ed448] Convert to PointPrecomp
         private static PointExt[] precompBaseTable = null;
         private static uint[] precompBase = null;
@@ -463,12 +463,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.Mul(p.y, r.y, D);
             X448Field.Mul(C, D, E);
             X448Field.Mul(E, -C_d, E);
-    //        X448Field.Apm(B, E, F, G);
+            //X448Field.Apm(B, E, F, G);
             X448Field.Add(B, E, f);
             X448Field.Sub(B, E, g);
             X448Field.Add(r.x, r.y, E);
             X448Field.Mul(H, E, H);
-    //        X448Field.Apm(D, C, B, E);
+            //X448Field.Apm(D, C, B, E);
             X448Field.Add(D, C, b);
             X448Field.Sub(D, C, e);
             X448Field.Carry(b);
@@ -495,13 +495,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.Mul(p.y, r.y, D);
             X448Field.Mul(C, D, E);
             X448Field.Mul(E, -C_d, E);
-    //        X448Field.Apm(B, E, F, G);
+            //X448Field.Apm(B, E, F, G);
             X448Field.Add(B, E, F);
             X448Field.Sub(B, E, G);
             X448Field.Add(p.x, p.y, B);
             X448Field.Add(r.x, r.y, E);
             X448Field.Mul(B, E, H);
-    //        X448Field.Apm(D, C, B, E);
+            //X448Field.Apm(D, C, B, E);
             X448Field.Add(D, C, B);
             X448Field.Sub(D, C, E);
             X448Field.Carry(B);
@@ -592,78 +592,80 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.One(p.z);
         }
 
-        [MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            if (precompBase != null)
-                return;
-
-            PointExt p = new PointExt();
-            X448Field.Copy(B_x, 0, p.x, 0);
-            X448Field.Copy(B_y, 0, p.y, 0);
-            PointExtendXY(p);
-
-            precompBaseTable = PointPrecompVar(p, 1 << (WnafWidthBase - 2));
+            lock (precompLock)
+            {
+                if (precompBase != null)
+                    return;
 
-            precompBase = new uint[PrecompBlocks * PrecompPoints * 2 * X448Field.Size];
+                PointExt p = new PointExt();
+                X448Field.Copy(B_x, 0, p.x, 0);
+                X448Field.Copy(B_y, 0, p.y, 0);
+                PointExtendXY(p);
 
-            int off = 0;
-            for (int b = 0; b < PrecompBlocks; ++b)
-            {
-                PointExt[] ds = new PointExt[PrecompTeeth];
+                precompBaseTable = PointPrecompVar(p, 1 << (WnafWidthBase - 2));
 
-                PointExt sum = new PointExt();
-                PointSetNeutral(sum);
+                precompBase = new uint[PrecompBlocks * PrecompPoints * 2 * X448Field.Size];
 
-                for (int t = 0; t < PrecompTeeth; ++t)
+                int off = 0;
+                for (int b = 0; b < PrecompBlocks; ++b)
                 {
-                    PointAddVar(true, p, sum);
-                    PointDouble(p);
+                    PointExt[] ds = new PointExt[PrecompTeeth];
 
-                    ds[t] = PointCopy(p);
+                    PointExt sum = new PointExt();
+                    PointSetNeutral(sum);
 
-                    if (b + t != PrecompBlocks + PrecompTeeth - 2)
+                    for (int t = 0; t < PrecompTeeth; ++t)
                     {
-                        for (int s = 1; s < PrecompSpacing; ++s)
+                        PointAddVar(true, p, sum);
+                        PointDouble(p);
+
+                        ds[t] = PointCopy(p);
+
+                        if (b + t != PrecompBlocks + PrecompTeeth - 2)
                         {
-                            PointDouble(p);
+                            for (int s = 1; s < PrecompSpacing; ++s)
+                            {
+                                PointDouble(p);
+                            }
                         }
                     }
-                }
 
-                PointExt[] points = new PointExt[PrecompPoints];
-                int k = 0;
-                points[k++] = sum;
+                    PointExt[] points = new PointExt[PrecompPoints];
+                    int k = 0;
+                    points[k++] = sum;
 
-                for (int t = 0; t < (PrecompTeeth - 1); ++t)
-                {
-                    int size = 1 << t;
-                    for (int j = 0; j < size; ++j, ++k)
+                    for (int t = 0; t < (PrecompTeeth - 1); ++t)
                     {
-                        points[k] = PointCopy(points[k - size]);
-                        PointAddVar(false, ds[t], points[k]);
+                        int size = 1 << t;
+                        for (int j = 0; j < size; ++j, ++k)
+                        {
+                            points[k] = PointCopy(points[k - size]);
+                            PointAddVar(false, ds[t], points[k]);
+                        }
                     }
-                }
 
-                Debug.Assert(k == PrecompPoints);
+                    Debug.Assert(k == PrecompPoints);
 
-                for (int i = 0; i < PrecompPoints; ++i)
-                {
-                    PointExt q = points[i];
-                    // TODO[ed448] Batch inversion
-                    X448Field.Inv(q.z, q.z);
-                    X448Field.Mul(q.x, q.z, q.x);
-                    X448Field.Mul(q.y, q.z, q.y);
+                    for (int i = 0; i < PrecompPoints; ++i)
+                    {
+                        PointExt q = points[i];
+                        // TODO[ed448] Batch inversion
+                        X448Field.Inv(q.z, q.z);
+                        X448Field.Mul(q.x, q.z, q.x);
+                        X448Field.Mul(q.y, q.z, q.y);
 
-    //                X448Field.Normalize(q.x);
-    //                X448Field.Normalize(q.y);
+                        //X448Field.Normalize(q.x);
+                        //X448Field.Normalize(q.y);
 
-                    X448Field.Copy(q.x, 0, precompBase, off);   off += X448Field.Size;
-                    X448Field.Copy(q.y, 0, precompBase, off);   off += X448Field.Size;
+                        X448Field.Copy(q.x, 0, precompBase, off); off += X448Field.Size;
+                        X448Field.Copy(q.y, 0, precompBase, off); off += X448Field.Size;
+                    }
                 }
-            }
 
-            Debug.Assert(off == precompBase.Length);
+                Debug.Assert(off == precompBase.Length);
+            }
         }
 
         private static void PruneScalar(byte[] n, int nOff, byte[] r)
@@ -731,7 +733,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x21 += x31 * L4_6;                          // x21:55/53
             x22 += x31 * L4_7;                          // x22:57/53
 
-    //        x30 += (x29 >> 28); x29 &= M28UL;
+            //x30 += (x29 >> 28); x29 &= M28UL;
             x14 += x30 * L4_0;                          // x14:54/--
             x15 += x30 * L4_1;                          // x15:54/53
             x16 += x30 * L4_2;                          // x16:56/--
@@ -751,7 +753,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x19 += x29 * L4_6;                          // x19:57/52
             x20 += x29 * L4_7;                          // x20:58/52
 
-    //        x28 += (x27 >> 28); x27 &= M28UL;
+            //x28 += (x27 >> 28); x27 &= M28UL;
             x12 += x28 * L4_0;                          // x12:54/--
             x13 += x28 * L4_1;                          // x13:54/53
             x14 += x28 * L4_2;                          // x14:56/--
@@ -771,7 +773,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x17 += x27 * L4_6;                          // x17:58/56
             x18 += x27 * L4_7;                          // x18:59/--
 
-    //        x26 += (x25 >> 28); x25 &= M28UL;
+            //x26 += (x25 >> 28); x25 &= M28UL;
             x10 += x26 * L4_0;                          // x10:54/--
             x11 += x26 * L4_1;                          // x11:54/53
             x12 += x26 * L4_2;                          // x12:56/--
@@ -948,7 +950,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             Encode56(x10 | (x11 << 28), r, 35);
             Encode56(x12 | (x13 << 28), r, 42);
             Encode56(x14 | (x15 << 28), r, 49);
-    //        r[ScalarBytes - 1] = 0;
+            //r[ScalarBytes - 1] = 0;
             return r;
         }