summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/Readme.html14
-rw-r--r--crypto/crypto.csproj10
-rw-r--r--crypto/src/asn1/ocsp/CertStatus.cs2
-rw-r--r--crypto/src/crypto/tls/DtlsClientProtocol.cs16
-rw-r--r--crypto/src/crypto/tls/DtlsRecordLayer.cs12
-rw-r--r--crypto/src/crypto/tls/DtlsServerProtocol.cs34
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs1
-rw-r--r--crypto/src/math/ec/multiplier/WNafUtilities.cs2
-rw-r--r--crypto/src/math/raw/Nat128.cs8
-rw-r--r--crypto/src/math/raw/Nat160.cs16
-rw-r--r--crypto/src/math/raw/Nat192.cs24
-rw-r--r--crypto/src/math/raw/Nat224.cs32
-rw-r--r--crypto/src/math/raw/Nat256.cs40
-rw-r--r--crypto/src/x509/extension/X509ExtensionUtil.cs4
-rw-r--r--crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs181
-rw-r--r--crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs146
16 files changed, 472 insertions, 70 deletions
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 0cbd91daa..b26937714 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,6 +294,18 @@ We state, where EC MQV has not otherwise been disabled or removed:
 
         <h4><a class="mozTocH4" name="mozTocId85316"></a>Release 1.8.2, Release Date TBD</h4>
 
+        <h5>Security Advisory</h5>
+        <ul>
+            <li>
+                Carry propagation bugs in the implementation of squaring for several raw math classes have been fixed (Org.BouncyCastle.Math.Raw.Nat???).
+                These classes are used by our custom elliptic curve implementations (Org.BouncyCastle.Math.Ec.Custom.**), so there was the possibility
+                of rare (in general usage) spurious calculations for elliptic curve scalar multiplications. Such errors would have been detected with
+                high probability by the output validation for our scalar multipliers. We consider these bugs to be exploitable for static ECDH with
+                long-term keys, per <a href="https://eprint.iacr.org/2011/633">"Practical realisation and elimination of an ECC-related software bug attack",
+                Brumley et.al.</a>
+            </li>
+        </ul>
+
         <h5>IMPORTANT</h5>
         <ul>
             <li>
@@ -381,7 +393,7 @@ We state, where EC MQV has not otherwise been disabled or removed:
             <li>RFC 6637 ECDSA and ECDH support has been added to the OpenPGP API.</li>
             <li>Implementations of Threefish and Skein have been added.</li>
             <li>Implementation of the SM3 digest has been added.</li>
-            <li>Implementations of XSalsa20 and ChaCha have been added. Support for reduced round Salas20 has been added.</li>
+            <li>Implementations of XSalsa20 and ChaCha have been added. Support for reduced round Salsa20 has been added.</li>
             <li>Support has been added for RFC 6979 Deterministic DSA/ECDSA.</li>
             <li>Support for the Poly1305 MAC has been added.</li>
             <li>GCM and GMAC now support tag lengths down to 32 bits.</li>
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index fcb52bb20..6f1fdcf61 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -12055,6 +12055,16 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\math\ec\custom\sec\test\SecP256R1FieldTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "test\src\math\ec\custom\sec\test\SecP384R1FieldTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\math\ec\test\AllTests.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs
index b524364c9..7dd99b844 100644
--- a/crypto/src/asn1/ocsp/CertStatus.cs
+++ b/crypto/src/asn1/ocsp/CertStatus.cs
@@ -48,6 +48,8 @@ namespace Org.BouncyCastle.Asn1.Ocsp
 				case 2:
 					value = DerNull.Instance;
 					break;
+				default:
+					throw new ArgumentException("Unknown tag encountered: " + choice.TagNo);
             }
         }
 
diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs
index abb402077..90430d772 100644
--- a/crypto/src/crypto/tls/DtlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs
@@ -53,19 +53,29 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
             catch (TlsFatalAlert fatalAlert)
             {
-                recordLayer.Fail(fatalAlert.AlertDescription);
+                AbortClientHandshake(state, recordLayer, fatalAlert.AlertDescription);
                 throw fatalAlert;
             }
             catch (IOException e)
             {
-                recordLayer.Fail(AlertDescription.internal_error);
+                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                 throw e;
             }
             catch (Exception e)
             {
-                recordLayer.Fail(AlertDescription.internal_error);
+                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
+            finally
+            {
+                securityParameters.Clear();
+            }
+        }
+
+        internal virtual void AbortClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
+        {
+            recordLayer.Fail(alertDescription);
+            InvalidateSession(state);
         }
 
         internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer)
diff --git a/crypto/src/crypto/tls/DtlsRecordLayer.cs b/crypto/src/crypto/tls/DtlsRecordLayer.cs
index 6796f4cbb..4a781b5b5 100644
--- a/crypto/src/crypto/tls/DtlsRecordLayer.cs
+++ b/crypto/src/crypto/tls/DtlsRecordLayer.cs
@@ -237,7 +237,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                             if (alertLevel == AlertLevel.fatal)
                             {
-                                Fail(alertDescription);
+                                Failed();
                                 throw new TlsFatalAlert(alertDescription);
                             }
 
@@ -375,6 +375,16 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
         }
 
+        internal virtual void Failed()
+        {
+            if (!mClosed)
+            {
+                mFailed = true;
+
+                CloseTransport();
+            }
+        }
+
         internal virtual void Fail(byte alertDescription)
         {
             if (!mClosed)
diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs
index d05af193c..fbf33045b 100644
--- a/crypto/src/crypto/tls/DtlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs
@@ -54,19 +54,29 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
             catch (TlsFatalAlert fatalAlert)
             {
-                recordLayer.Fail(fatalAlert.AlertDescription);
+                AbortServerHandshake(state, recordLayer, fatalAlert.AlertDescription);
                 throw fatalAlert;
             }
             catch (IOException e)
             {
-                recordLayer.Fail(AlertDescription.internal_error);
+                AbortServerHandshake(state, recordLayer, AlertDescription.internal_error);
                 throw e;
             }
             catch (Exception e)
             {
-                recordLayer.Fail(AlertDescription.internal_error);
+                AbortServerHandshake(state, recordLayer, AlertDescription.internal_error);
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
+            finally
+            {
+                securityParameters.Clear();
+            }
+        }
+
+        internal virtual void AbortServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
+        {
+            recordLayer.Fail(alertDescription);
+            InvalidateSession(state);
         }
 
         internal virtual DtlsTransport ServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer)
@@ -263,6 +273,21 @@ namespace Org.BouncyCastle.Crypto.Tls
             return new DtlsTransport(recordLayer);
         }
 
+        protected virtual void InvalidateSession(ServerHandshakeState state)
+        {
+            if (state.sessionParameters != null)
+            {
+                state.sessionParameters.Clear();
+                state.sessionParameters = null;
+            }
+
+            if (state.tlsSession != null)
+            {
+                state.tlsSession.Invalidate();
+                state.tlsSession = null;
+            }
+        }
+
         protected virtual byte[] GenerateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
         {
             MemoryStream buf = new MemoryStream();
@@ -650,6 +675,9 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             internal TlsServer server = null;
             internal TlsServerContextImpl serverContext = null;
+            internal TlsSession tlsSession = null;
+            internal SessionParameters sessionParameters = null;
+            internal SessionParameters.Builder sessionParametersBuilder = null;
             internal int[] offeredCipherSuites = null;
             internal byte[] offeredCompressionMethods = null;
             internal IDictionary clientExtensions = null;
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 25908d163..d51a8ff48 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1246,6 +1246,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             case EncryptionAlgorithm.SEED_CBC:
                 return CipherType.block;
 
+            case EncryptionAlgorithm.NULL:
             case EncryptionAlgorithm.RC4_40:
             case EncryptionAlgorithm.RC4_128:
                 return CipherType.stream;
diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs
index 5491297d7..7d565dfbd 100644
--- a/crypto/src/math/ec/multiplier/WNafUtilities.cs
+++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs
@@ -423,7 +423,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                              *      1) additions do not use the curve's A, B coefficients.
                              *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
                              */
-                            if (ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
+                            if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
                             {
                                 switch (c.CoordinateSystem)
                                 {
diff --git a/crypto/src/math/raw/Nat128.cs b/crypto/src/math/raw/Nat128.cs
index 819c52062..1d3b64d32 100644
--- a/crypto/src/math/raw/Nat128.cs
+++ b/crypto/src/math/raw/Nat128.cs
@@ -626,8 +626,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[3];
-            ulong zz_5 = zz[5];
-            ulong zz_6 = zz[6];
+            ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -702,8 +702,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[xOff + 3];
-            ulong zz_5 = zz[zzOff + 5];
-            ulong zz_6 = zz[zzOff + 6];
+            ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
diff --git a/crypto/src/math/raw/Nat160.cs b/crypto/src/math/raw/Nat160.cs
index 153ac0a43..1fd00e576 100644
--- a/crypto/src/math/raw/Nat160.cs
+++ b/crypto/src/math/raw/Nat160.cs
@@ -604,8 +604,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[3];
-            ulong zz_5 = zz[5];
-            ulong zz_6 = zz[6];
+            ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -619,8 +619,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[4];
-            ulong zz_7 = zz[7];
-            ulong zz_8 = zz[8];
+            ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -699,8 +699,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[xOff + 3];
-            ulong zz_5 = zz[zzOff + 5];
-            ulong zz_6 = zz[zzOff + 6];
+            ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -714,8 +714,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[xOff + 4];
-            ulong zz_7 = zz[zzOff + 7];
-            ulong zz_8 = zz[zzOff + 8];
+            ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
diff --git a/crypto/src/math/raw/Nat192.cs b/crypto/src/math/raw/Nat192.cs
index 4797609ee..3099bafab 100644
--- a/crypto/src/math/raw/Nat192.cs
+++ b/crypto/src/math/raw/Nat192.cs
@@ -706,8 +706,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[3];
-            ulong zz_5 = zz[5];
-            ulong zz_6 = zz[6];
+            ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -721,8 +721,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[4];
-            ulong zz_7 = zz[7];
-            ulong zz_8 = zz[8];
+            ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -738,8 +738,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[5];
-            ulong zz_9 = zz[9];
-            ulong zz_10 = zz[10];
+            ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
@@ -822,8 +822,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[xOff + 3];
-            ulong zz_5 = zz[zzOff + 5];
-            ulong zz_6 = zz[zzOff + 6];
+            ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -837,8 +837,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[xOff + 4];
-            ulong zz_7 = zz[zzOff + 7];
-            ulong zz_8 = zz[zzOff + 8];
+            ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -854,8 +854,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[xOff + 5];
-            ulong zz_9 = zz[zzOff + 9];
-            ulong zz_10 = zz[zzOff + 10];
+            ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
diff --git a/crypto/src/math/raw/Nat224.cs b/crypto/src/math/raw/Nat224.cs
index 940e930ac..978caf265 100644
--- a/crypto/src/math/raw/Nat224.cs
+++ b/crypto/src/math/raw/Nat224.cs
@@ -786,8 +786,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[3];
-            ulong zz_5 = zz[5];
-            ulong zz_6 = zz[6];
+            ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -801,8 +801,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[4];
-            ulong zz_7 = zz[7];
-            ulong zz_8 = zz[8];
+            ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -818,8 +818,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[5];
-            ulong zz_9 = zz[9];
-            ulong zz_10 = zz[10];
+            ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
@@ -837,8 +837,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_6 = x[6];
-            ulong zz_11 = zz[11];
-            ulong zz_12 = zz[12];
+            ulong zz_11 = zz[11] + (zz_10 >> 32); zz_10 &= M;
+            ulong zz_12 = zz[12] + (zz_11 >> 32); zz_11 &= M;
             {
                 zz_6 += x_6 * x_0;
                 w = (uint)zz_6;
@@ -925,8 +925,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[xOff + 3];
-            ulong zz_5 = zz[zzOff + 5];
-            ulong zz_6 = zz[zzOff + 6];
+            ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -940,8 +940,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[xOff + 4];
-            ulong zz_7 = zz[zzOff + 7];
-            ulong zz_8 = zz[zzOff + 8];
+            ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -957,8 +957,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[xOff + 5];
-            ulong zz_9 = zz[zzOff + 9];
-            ulong zz_10 = zz[zzOff + 10];
+            ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
@@ -976,8 +976,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_6 = x[xOff + 6];
-            ulong zz_11 = zz[zzOff + 11];
-            ulong zz_12 = zz[zzOff + 12];
+            ulong zz_11 = zz[zzOff + 11] + (zz_10 >> 32); zz_10 &= M;
+            ulong zz_12 = zz[zzOff + 12] + (zz_11 >> 32); zz_11 &= M;
             {
                 zz_6 += x_6 * x_0;
                 w = (uint)zz_6;
diff --git a/crypto/src/math/raw/Nat256.cs b/crypto/src/math/raw/Nat256.cs
index 19455031a..09c751a5a 100644
--- a/crypto/src/math/raw/Nat256.cs
+++ b/crypto/src/math/raw/Nat256.cs
@@ -917,8 +917,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[3];
-            ulong zz_5 = zz[5];
-            ulong zz_6 = zz[6];
+            ulong zz_5 = zz[5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -932,8 +932,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[4];
-            ulong zz_7 = zz[7];
-            ulong zz_8 = zz[8];
+            ulong zz_7 = zz[7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -949,8 +949,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[5];
-            ulong zz_9 = zz[9];
-            ulong zz_10 = zz[10];
+            ulong zz_9 = zz[9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
@@ -968,8 +968,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_6 = x[6];
-            ulong zz_11 = zz[11];
-            ulong zz_12 = zz[12];
+            ulong zz_11 = zz[11] + (zz_10 >> 32); zz_10 &= M;
+            ulong zz_12 = zz[12] + (zz_11 >> 32); zz_11 &= M;
             {
                 zz_6 += x_6 * x_0;
                 w = (uint)zz_6;
@@ -989,8 +989,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_7 = x[7];
-            ulong zz_13 = zz[13];
-            ulong zz_14 = zz[14];
+            ulong zz_13 = zz[13] + (zz_12 >> 32); zz_12 &= M;
+            ulong zz_14 = zz[14] + (zz_13 >> 32); zz_13 &= M;
             {
                 zz_7 += x_7 * x_0;
                 w = (uint)zz_7;
@@ -1081,8 +1081,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_3 = x[xOff + 3];
-            ulong zz_5 = zz[zzOff + 5];
-            ulong zz_6 = zz[zzOff + 6];
+            ulong zz_5 = zz[zzOff + 5] + (zz_4 >> 32); zz_4 &= M;
+            ulong zz_6 = zz[zzOff + 6] + (zz_5 >> 32); zz_5 &= M;
             {
                 zz_3 += x_3 * x_0;
                 w = (uint)zz_3;
@@ -1096,8 +1096,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_4 = x[xOff + 4];
-            ulong zz_7 = zz[zzOff + 7];
-            ulong zz_8 = zz[zzOff + 8];
+            ulong zz_7 = zz[zzOff + 7] + (zz_6 >> 32); zz_6 &= M;
+            ulong zz_8 = zz[zzOff + 8] + (zz_7 >> 32); zz_7 &= M;
             {
                 zz_4 += x_4 * x_0;
                 w = (uint)zz_4;
@@ -1113,8 +1113,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_5 = x[xOff + 5];
-            ulong zz_9 = zz[zzOff + 9];
-            ulong zz_10 = zz[zzOff + 10];
+            ulong zz_9 = zz[zzOff + 9] + (zz_8 >> 32); zz_8 &= M;
+            ulong zz_10 = zz[zzOff + 10] + (zz_9 >> 32); zz_9 &= M;
             {
                 zz_5 += x_5 * x_0;
                 w = (uint)zz_5;
@@ -1132,8 +1132,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_6 = x[xOff + 6];
-            ulong zz_11 = zz[zzOff + 11];
-            ulong zz_12 = zz[zzOff + 12];
+            ulong zz_11 = zz[zzOff + 11] + (zz_10 >> 32); zz_10 &= M;
+            ulong zz_12 = zz[zzOff + 12] + (zz_11 >> 32); zz_11 &= M;
             {
                 zz_6 += x_6 * x_0;
                 w = (uint)zz_6;
@@ -1153,8 +1153,8 @@ namespace Org.BouncyCastle.Math.Raw
             }
 
             ulong x_7 = x[xOff + 7];
-            ulong zz_13 = zz[zzOff + 13];
-            ulong zz_14 = zz[zzOff + 14];
+            ulong zz_13 = zz[zzOff + 13] + (zz_12 >> 32); zz_12 &= M;
+            ulong zz_14 = zz[zzOff + 14] + (zz_13 >> 32); zz_13 &= M;
             {
                 zz_7 += x_7 * x_0;
                 w = (uint)zz_7;
diff --git a/crypto/src/x509/extension/X509ExtensionUtil.cs b/crypto/src/x509/extension/X509ExtensionUtil.cs
index 845a87bad..5f65ebfda 100644
--- a/crypto/src/x509/extension/X509ExtensionUtil.cs
+++ b/crypto/src/x509/extension/X509ExtensionUtil.cs
@@ -44,9 +44,11 @@ namespace Org.BouncyCastle.X509.Extension
 				{
 					Asn1Sequence seq = DerSequence.GetInstance(FromExtensionValue(extVal));
 
-					foreach (GeneralName genName in seq)
+					foreach (Asn1Encodable primName in seq)
 					{
                         IList list = Platform.CreateArrayList();
+                        GeneralName genName = GeneralName.GetInstance(primName);
+
 						list.Add(genName.TagNo);
 
 						switch (genName.TagNo)
diff --git a/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs b/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs
new file mode 100644
index 000000000..374b1ecd1
--- /dev/null
+++ b/crypto/test/src/math/ec/custom/sec/test/SecP256R1FieldTest.cs
@@ -0,0 +1,181 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec.Tests
+{
+    [TestFixture]
+    public class SecP256R1FieldTest
+    {
+        private static readonly SecureRandom Random = new SecureRandom();
+
+        private static readonly X9ECParameters DP = CustomNamedCurves
+            .GetByOid(SecObjectIdentifiers.SecP256r1);
+        private static readonly BigInteger Q = DP.Curve.Field.Characteristic;
+
+        [Test]
+        public void TestMultiply1()
+        {
+            int COUNT = 1000;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateMultiplyInput_Random();
+                ECFieldElement y = GenerateMultiplyInput_Random();
+
+                BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+                BigInteger R = X.Multiply(Y).Mod(Q);
+
+                ECFieldElement z = x.Multiply(y);
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        [Test]
+        public void TestMultiply2()
+        {
+            int COUNT = 100;
+            ECFieldElement[] inputs = new ECFieldElement[COUNT];
+            BigInteger[] INPUTS = new BigInteger[COUNT];
+
+            for (int i = 0; i < inputs.Length; ++i)
+            {
+                inputs[i] = GenerateMultiplyInput_Random();
+                INPUTS[i] = inputs[i].ToBigInteger();
+            }
+
+            for (int j = 0; j < inputs.Length; ++j)
+            {
+                for (int k = 0; k < inputs.Length; ++k)
+                {
+                    BigInteger R = INPUTS[j].Multiply(INPUTS[k]).Mod(Q);
+
+                    ECFieldElement z = inputs[j].Multiply(inputs[k]);
+                    BigInteger Z = z.ToBigInteger();
+
+                    Assert.AreEqual(R, Z);
+                }
+            }
+        }
+
+        [Test]
+        public void TestSquare()
+        {
+            int COUNT = 1000;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateMultiplyInput_Random();
+
+                BigInteger X = x.ToBigInteger();
+                BigInteger R = X.Multiply(X).Mod(Q);
+
+                ECFieldElement z = x.Square();
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        /**
+         * Test multiplication with specifically selected values that triggered a bug in the modular
+         * reduction in OpenSSL (last affected version 0.9.8g).
+         *
+         * See "Practical realisation and elimination of an ECC-related software bug attack", B. B.
+         * Brumley, M. Barbarosa, D. Page, F. Vercauteren.
+         */
+        [Test]
+        public void TestMultiply_OpenSSLBug()
+        {
+            int COUNT = 100;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateMultiplyInputA_OpenSSLBug();
+                ECFieldElement y = GenerateMultiplyInputB_OpenSSLBug();
+
+                BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+                BigInteger R = X.Multiply(Y).Mod(Q);
+
+                ECFieldElement z = x.Multiply(y);
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        /**
+         * Test squaring with specifically selected values that triggered a bug in the modular reduction
+         * in OpenSSL (last affected version 0.9.8g).
+         *
+         * See "Practical realisation and elimination of an ECC-related software bug attack", B. B.
+         * Brumley, M. Barbarosa, D. Page, F. Vercauteren.
+         */
+        [Test]
+        public void TestSquare_OpenSSLBug()
+        {
+            int COUNT = 100;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateSquareInput_OpenSSLBug();
+
+                BigInteger X = x.ToBigInteger();
+                BigInteger R = X.Multiply(X).Mod(Q);
+
+                ECFieldElement z = x.Square();
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        private ECFieldElement FE(BigInteger x)
+        {
+            return DP.Curve.FromBigInteger(x);
+        }
+
+        private ECFieldElement GenerateMultiplyInput_Random()
+        {
+            return FE(new BigInteger(DP.Curve.FieldSize + 32, Random).Mod(Q));
+        }
+
+        private ECFieldElement GenerateMultiplyInputA_OpenSSLBug()
+        {
+            uint[] x = Nat256.Create();
+            x[0] = (uint)Random.NextInt() >> 1;
+            x[4] = 3;
+            x[7] = 0xFFFFFFFF;
+
+            return FE(Nat256.ToBigInteger(x));
+        }
+
+        private ECFieldElement GenerateMultiplyInputB_OpenSSLBug()
+        {
+            uint[] x = Nat256.Create();
+            x[0] = (uint)Random.NextInt() >> 1;
+            x[3] = 1;
+            x[7] = 0xFFFFFFFF;
+
+            return FE(Nat256.ToBigInteger(x));
+        }
+
+        private ECFieldElement GenerateSquareInput_OpenSSLBug()
+        {
+            uint[] x = Nat256.Create();
+            x[0] = (uint)Random.NextInt() >> 1;
+            x[4] = 2;
+            x[7] = 0xFFFFFFFF;
+
+            return FE(Nat256.ToBigInteger(x));
+        }
+    }
+}
diff --git a/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs b/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs
new file mode 100644
index 000000000..86ec4894f
--- /dev/null
+++ b/crypto/test/src/math/ec/custom/sec/test/SecP384R1FieldTest.cs
@@ -0,0 +1,146 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec.Tests
+{
+    [TestFixture]
+    public class SecP384R1FieldTest
+    {
+        private static readonly SecureRandom Random = new SecureRandom();
+
+        private static readonly X9ECParameters DP = CustomNamedCurves
+            .GetByOid(SecObjectIdentifiers.SecP384r1);
+        private static readonly BigInteger Q = DP.Curve.Field.Characteristic;
+
+        [Test]
+        public void TestMultiply1()
+        {
+            int COUNT = 1000;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateMultiplyInput_Random();
+                ECFieldElement y = GenerateMultiplyInput_Random();
+
+                BigInteger X = x.ToBigInteger(), Y = y.ToBigInteger();
+                BigInteger R = X.Multiply(Y).Mod(Q);
+
+                ECFieldElement z = x.Multiply(y);
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        [Test]
+        public void TestMultiply2()
+        {
+            int COUNT = 100;
+            ECFieldElement[] inputs = new ECFieldElement[COUNT];
+            BigInteger[] INPUTS = new BigInteger[COUNT];
+
+            for (int i = 0; i < inputs.Length; ++i)
+            {
+                inputs[i] = GenerateMultiplyInput_Random();
+                INPUTS[i] = inputs[i].ToBigInteger();
+            }
+
+            for (int j = 0; j < inputs.Length; ++j)
+            {
+                for (int k = 0; k < inputs.Length; ++k)
+                {
+                    BigInteger R = INPUTS[j].Multiply(INPUTS[k]).Mod(Q);
+
+                    ECFieldElement z = inputs[j].Multiply(inputs[k]);
+                    BigInteger Z = z.ToBigInteger();
+
+                    Assert.AreEqual(R, Z);
+                }
+            }
+        }
+
+        [Test]
+        public void TestSquare()
+        {
+            int COUNT = 1000;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateMultiplyInput_Random();
+
+                BigInteger X = x.ToBigInteger();
+                BigInteger R = X.Multiply(X).Mod(Q);
+
+                ECFieldElement z = x.Square();
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        [Test]
+        public void TestSquare_CarryBug()
+        {
+            int COUNT = 100;
+
+            for (int i = 0; i < COUNT; ++i)
+            {
+                ECFieldElement x = GenerateSquareInput_CarryBug();
+
+                BigInteger X = x.ToBigInteger();
+                BigInteger R = X.Multiply(X).Mod(Q);
+
+                ECFieldElement z = x.Square();
+                BigInteger Z = z.ToBigInteger();
+
+                Assert.AreEqual(R, Z);
+            }
+        }
+
+        /*
+         * Based on another example input demonstrating the carry propagation bug in Nat192.square, as
+         * reported by Joseph Friel on dev-crypto.
+         */
+        [Test]
+        public void TestSquare_CarryBug_Reported()
+        {
+            ECFieldElement x = FE(new BigInteger("2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", 16));
+
+            BigInteger X = x.ToBigInteger();
+            BigInteger R = X.Multiply(X).Mod(Q);
+
+            ECFieldElement z = x.Square();
+            BigInteger Z = z.ToBigInteger();
+
+            Assert.AreEqual(R, Z);
+        }
+
+        private ECFieldElement FE(BigInteger x)
+        {
+            return DP.Curve.FromBigInteger(x);
+        }
+
+        private ECFieldElement GenerateMultiplyInput_Random()
+        {
+            return FE(new BigInteger(DP.Curve.FieldSize + 32, Random).Mod(Q));
+        }
+
+        private ECFieldElement GenerateSquareInput_CarryBug()
+        {
+            uint[] x = Nat.Create(12);
+            x[0] = (uint)Random.NextInt() >> 1;
+            x[6] = 2;
+            x[10] = 0xFFFF0000;
+            x[11] = 0xFFFFFFFF;
+
+            return FE(Nat.ToBigInteger(12, x));
+        }
+    }
+}