summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.gitignore1
-rw-r--r--crypto/BouncyCastle.Android.csproj4
-rw-r--r--crypto/BouncyCastle.csproj4
-rw-r--r--crypto/BouncyCastle.iOS.csproj4
-rw-r--r--crypto/NBuild.build2
-rw-r--r--crypto/Readme.html42
-rw-r--r--crypto/crypto.csproj30
-rw-r--r--crypto/src/AssemblyInfo.cs9
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs4
-rw-r--r--crypto/src/asn1/Asn1TaggedObject.cs10
-rw-r--r--crypto/src/asn1/DERExternal.cs15
-rw-r--r--crypto/src/asn1/DerApplicationSpecific.cs2
-rw-r--r--crypto/src/asn1/DerGraphicString.cs103
-rw-r--r--crypto/src/asn1/DerVideotexString.cs103
-rw-r--r--crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs35
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs8
-rw-r--r--crypto/src/crypto/engines/SerpentEngineBase.cs9
-rw-r--r--crypto/src/crypto/macs/VMPCMac.cs2
-rw-r--r--crypto/src/crypto/signers/Iso9796d2PssSigner.cs9
-rw-r--r--crypto/src/crypto/signers/PssSigner.cs57
-rw-r--r--crypto/src/crypto/tls/AbstractTlsClient.cs11
-rw-r--r--crypto/src/crypto/tls/AbstractTlsKeyExchange.cs11
-rw-r--r--crypto/src/crypto/tls/DeferredHash.cs2
-rw-r--r--crypto/src/crypto/tls/DtlsClientProtocol.cs11
-rw-r--r--crypto/src/crypto/tls/DtlsRecordLayer.cs30
-rw-r--r--crypto/src/crypto/tls/DtlsServerProtocol.cs38
-rw-r--r--crypto/src/crypto/tls/HashAlgorithm.cs28
-rw-r--r--crypto/src/crypto/tls/TlsClient.cs12
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsECDheKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsServerProtocol.cs20
-rw-r--r--crypto/src/crypto/tls/TlsSrpKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs42
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113Field.cs16
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193Field.cs23
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233Field.cs41
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239Field.cs42
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283Field.cs32
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409Field.cs36
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571Field.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571FieldElement.cs4
-rw-r--r--crypto/src/math/raw/Interleave.cs12
-rw-r--r--crypto/test/UnitTests.csproj4
-rw-r--r--crypto/test/src/asn1/test/DERApplicationSpecificTest.cs67
-rw-r--r--crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs6
-rw-r--r--crypto/test/src/crypto/test/NaccacheSternTest.cs5
-rw-r--r--crypto/test/src/crypto/test/PSSTest.cs38
-rw-r--r--crypto/test/src/crypto/test/PaddingTest.cs6
-rw-r--r--crypto/test/src/crypto/test/VMPCMacTest.cs11
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestCase.cs9
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs28
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs18
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestSuite.cs157
-rw-r--r--crypto/test/src/crypto/tls/test/MockDtlsClient.cs9
-rw-r--r--crypto/test/src/crypto/tls/test/MockTlsClient.cs9
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestCase.cs8
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs22
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs29
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestConfig.cs30
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs45
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs19
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestSuite.cs103
-rw-r--r--crypto/test/src/math/ec/test/ECPointTest.cs13
-rw-r--r--crypto/test/src/test/ECEncodingTest.cs11
74 files changed, 1432 insertions, 202 deletions
diff --git a/.gitignore b/.gitignore
index 3b2c97a3b..bc7a62d4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 *.suo
 *.swp
 *.user
+*.userprefs
 *.vsp
 
 *.nupkg
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 6ceeac8bd..70d09cc6e 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -109,6 +109,7 @@
     <Compile Include="src\asn1\DerEnumerated.cs" />
     <Compile Include="src\asn1\DerGeneralString.cs" />
     <Compile Include="src\asn1\DerGeneralizedTime.cs" />
+    <Compile Include="src\asn1\DerGraphicString.cs" />
     <Compile Include="src\asn1\DerIA5String.cs" />
     <Compile Include="src\asn1\DerInteger.cs" />
     <Compile Include="src\asn1\DerNull.cs" />
@@ -125,6 +126,7 @@
     <Compile Include="src\asn1\DerUTCTime.cs" />
     <Compile Include="src\asn1\DerUTF8String.cs" />
     <Compile Include="src\asn1\DerUniversalString.cs" />
+    <Compile Include="src\asn1\DerVideotexString.cs" />
     <Compile Include="src\asn1\DerVisibleString.cs" />
     <Compile Include="src\asn1\IAsn1ApplicationSpecificParser.cs" />
     <Compile Include="src\asn1\IAsn1Choice.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index b3aefa8e9..f57dd2011 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -103,6 +103,7 @@
     <Compile Include="src\asn1\DerEnumerated.cs" />
     <Compile Include="src\asn1\DerGeneralString.cs" />
     <Compile Include="src\asn1\DerGeneralizedTime.cs" />
+    <Compile Include="src\asn1\DerGraphicString.cs" />
     <Compile Include="src\asn1\DerIA5String.cs" />
     <Compile Include="src\asn1\DerInteger.cs" />
     <Compile Include="src\asn1\DerNull.cs" />
@@ -119,6 +120,7 @@
     <Compile Include="src\asn1\DerUTCTime.cs" />
     <Compile Include="src\asn1\DerUTF8String.cs" />
     <Compile Include="src\asn1\DerUniversalString.cs" />
+    <Compile Include="src\asn1\DerVideotexString.cs" />
     <Compile Include="src\asn1\DerVisibleString.cs" />
     <Compile Include="src\asn1\IAsn1ApplicationSpecificParser.cs" />
     <Compile Include="src\asn1\IAsn1Choice.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index f5bef5bb4..4c499db46 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -104,6 +104,7 @@
     <Compile Include="src\asn1\DerEnumerated.cs" />
     <Compile Include="src\asn1\DerGeneralString.cs" />
     <Compile Include="src\asn1\DerGeneralizedTime.cs" />
+    <Compile Include="src\asn1\DerGraphicString.cs" />
     <Compile Include="src\asn1\DerIA5String.cs" />
     <Compile Include="src\asn1\DerInteger.cs" />
     <Compile Include="src\asn1\DerNull.cs" />
@@ -120,6 +121,7 @@
     <Compile Include="src\asn1\DerUTCTime.cs" />
     <Compile Include="src\asn1\DerUTF8String.cs" />
     <Compile Include="src\asn1\DerUniversalString.cs" />
+    <Compile Include="src\asn1\DerVideotexString.cs" />
     <Compile Include="src\asn1\DerVisibleString.cs" />
     <Compile Include="src\asn1\IAsn1ApplicationSpecificParser.cs" />
     <Compile Include="src\asn1\IAsn1Choice.cs" />
diff --git a/crypto/NBuild.build b/crypto/NBuild.build
index 984fd6758..71096cbf0 100644
--- a/crypto/NBuild.build
+++ b/crypto/NBuild.build
@@ -16,7 +16,7 @@
   <property name="dist-path" value="./dist"/>
 
   <!-- Version -->
-  <property name="version" value="1.8.0"/>
+  <property name="version" value="1.8.1"/>
   <property name="name" value="BouncyCastle.Crypto"/>
 
   <property name="OPTIONAL_STRONG_NAME" value="" />
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 67116c815..d5cda3032 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -31,6 +31,8 @@
 				<a href="#mozTocId3413">Notes:</a>
 		<ol>
             <li>
+                <a href="#mozTocId85315">Release 1.8.1</a>
+            <li>
                 <a href="#mozTocId85314">Release 1.8.0</a>
             <li>
 				<a href="#mozTocId85313">Release 1.7</a>
@@ -288,6 +290,38 @@ We state, where EC MQV has not otherwise been disabled or removed:
 		<hr style="WIDTH: 100%; HEIGHT: 2px">
 		<h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3>
 
+        <h4><a class="mozTocH4" name="mozTocId85315"></a>Release 1.8.1, Monday December 28, 2015</h4>
+
+        <h5>Security Advisory</h5>
+        <ul>
+            <li>
+                (D)TLS 1.2: Motivated by <a href="https://www.google.com/search?q=CVE-2015-7575">CVE-2015-7575</a>, we have added validation that
+                the signature algorithm received in DigitallySigned structures is actually one of those offered (in signature_algorithms extension
+                or CertificateRequest). With our default TLS configuration, we do not believe there is an exploitable vulnerability in any earlier
+                releases. Users that are customizing the signature_algorithms extension, or running a server supporting client authentication, are
+                advised to double-check that they are not offering any signature algorithms involving MD5.
+            </li>
+        </ul>
+        <h5>Additional Features and Functionality</h5>
+        <ul>
+            <li>Added support for ASN.1 GraphicString and VideotexString types.</li>
+            <li>
+                Problems with DTLS record-layer version handling were resolved via <a href="http://www.bouncycastle.org/jira/browse/BJA-584">BJA-584</a>,
+                making version negotiation work properly.
+            </li>
+        </ul>
+        <h5>Additional Notes</h5>
+        <ul>
+            <li>
+                See list of resolved issues at
+                <a href="http://www.bouncycastle.org/jira/secure/ReleaseNote.jspa?projectId=10001&version=10510">Bouncy Castle JIRA C# 1.8.1</a>.
+            </li>
+            <li>
+                See the (cumulative) list of GitHub pull requests that we have accepted at
+                <a href="https://github.com/bcgit/bc-csharp/pulls?q=is%3Apr+is%3Aclosed">bcgit/bc-csharp</a>.
+            </li>
+        </ul>
+
         <h4><a class="mozTocH4" name="mozTocId85314"></a>Release 1.8.0, Sunday November 22, 2015</h4>
 
         <h5>IMPORTANT</h5>
@@ -348,15 +382,11 @@ We state, where EC MQV has not otherwise been disabled or removed:
         <ul>
             <li>
                 See list of resolved issues at
-                <a href="http://www.bouncycastle.org/jira/secure/IssueNavigator.jspa?reset=true&mode=hide&jqlQuery=project+%3D+BMA+AND+fixVersion+%3D+1.8.0">
-                    Bouncy Castle JIRA C# 1.8.0
-                </a>
+                <a href="http://www.bouncycastle.org/jira/secure/ReleaseNote.jspa?projectId=10001&version=10170">Bouncy Castle JIRA C# 1.8.0</a>.
             </li>
             <li>
                 See the (cumulative) list of GitHub pull requests that we have accepted at
-                <a href="https://github.com/bcgit/bc-csharp/pulls?q=is%3Apr+is%3Aclosed">
-                    bcgit/bc-csharp    
-                </a>
+                <a href="https://github.com/bcgit/bc-csharp/pulls?q=is%3Apr+is%3Aclosed">bcgit/bc-csharp</a>.
             </li>
         </ul>
 
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index e6ab94ee2..73afed47e 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -384,6 +384,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\asn1\DerGraphicString.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\asn1\DERIA5String.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -489,6 +494,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\asn1\DerVideotexString.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\asn1\DERVisibleString.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -11840,6 +11850,16 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\crypto\tls\test\DtlsTestClientProtocol.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "test\src\crypto\tls\test\DtlsTestServerProtocol.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\crypto\tls\test\DtlsTestSuite.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -11950,6 +11970,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\crypto\tls\test\TlsTestClientProtocol.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\crypto\tls\test\TlsTestConfig.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -11960,6 +11985,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\crypto\tls\test\TlsTestServerProtocol.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\crypto\tls\test\TlsTestSuite.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs
index 239347365..bb9811d83 100644
--- a/crypto/src/AssemblyInfo.cs
+++ b/crypto/src/AssemblyInfo.cs
@@ -33,9 +33,9 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Revision and Build Numbers
 // by using the '*' as shown below:
 
-[assembly: AssemblyVersion("1.8.0.0")]
-[assembly: AssemblyFileVersion("1.8.0.0")]
-[assembly: AssemblyInformationalVersion("1.8.0.0")]
+[assembly: AssemblyVersion("1.8.1.0")]
+[assembly: AssemblyFileVersion("1.8.15362.1")]
+[assembly: AssemblyInformationalVersion("1.8.1")]
 
 //
 // In order to sign your assembly you must specify a key to use. Refer to the
@@ -65,10 +65,7 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyDelaySign(false)]
 #if STRONG_NAME
 [assembly: AssemblyKeyFile(@"../BouncyCastle.snk")]
-#else
-[assembly: AssemblyKeyFile("")]
 #endif
-[assembly: AssemblyKeyName("")]
 
 [assembly: CLSCompliant(true)]
 #if !PORTABLE
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 501e788a0..a94ae5235 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -337,6 +337,8 @@ namespace Org.BouncyCastle.Asn1
                     return new DerGeneralizedTime(bytes);
                 case Asn1Tags.GeneralString:
                     return new DerGeneralString(bytes);
+                case Asn1Tags.GraphicString:
+                    return new DerGraphicString(bytes);
                 case Asn1Tags.IA5String:
                     return new DerIA5String(bytes);
                 case Asn1Tags.Integer:
@@ -357,6 +359,8 @@ namespace Org.BouncyCastle.Asn1
                     return new DerUtcTime(bytes);
                 case Asn1Tags.Utf8String:
                     return new DerUtf8String(bytes);
+                case Asn1Tags.VideotexString:
+                    return new DerVideotexString(bytes);
                 case Asn1Tags.VisibleString:
                     return new DerVisibleString(bytes);
                 default:
diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index fdf5b651a..a6d4b2c28 100644
--- a/crypto/src/asn1/Asn1TaggedObject.cs
+++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -12,6 +12,16 @@ namespace Org.BouncyCastle.Asn1
     public abstract class Asn1TaggedObject
 		: Asn1Object, Asn1TaggedObjectParser
     {
+        internal static bool IsConstructed(bool isExplicit, Asn1Object obj)
+        {
+            if (isExplicit || obj is Asn1Sequence || obj is Asn1Set)
+                return true;
+            Asn1TaggedObject tagged = obj as Asn1TaggedObject;
+            if (tagged == null)
+                return false;
+            return IsConstructed(tagged.IsExplicit(), tagged.GetObject());
+        }
+
         internal int            tagNo;
 //        internal bool           empty;
         internal bool           explicitly = true;
diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs
index a342d6520..c29975193 100644
--- a/crypto/src/asn1/DERExternal.cs
+++ b/crypto/src/asn1/DERExternal.cs
@@ -34,25 +34,20 @@ namespace Org.BouncyCastle.Asn1
 				offset++;
 				enc = GetObjFromVector(vector, offset);
 			}
-			if (!(enc is DerTaggedObject))
+			if (!(enc is Asn1TaggedObject))
 			{
-				dataValueDescriptor = (Asn1Object) enc;
+				dataValueDescriptor = enc;
 				offset++;
 				enc = GetObjFromVector(vector, offset);
 			}
-			if (!(enc is DerTaggedObject))
-			{
-				throw new InvalidOperationException(
-					"No tagged object found in vector. Structure doesn't seem to be of type External");
-			}
 
-			if (vector.Count != offset + 1)
+            if (vector.Count != offset + 1)
 				throw new ArgumentException("input vector too large", "vector");
 
-			if (!(enc is DerTaggedObject))
+            if (!(enc is Asn1TaggedObject))
 				throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector");
 
-			DerTaggedObject obj = (DerTaggedObject)enc;
+            Asn1TaggedObject obj = (Asn1TaggedObject)enc;
 
 			// Use property accessor to include check on value
 			Encoding = obj.TagNo;
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index 9149930e0..52467fabe 100644
--- a/crypto/src/asn1/DerApplicationSpecific.cs
+++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1
 
             byte[] data = asn1Obj.GetDerEncoded();
 
-			this.isConstructed = isExplicit || asn1Obj is Asn1Set || asn1Obj is Asn1Sequence;
+            this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj);
 			this.tag = tag;
 
 			if (isExplicit)
diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs
new file mode 100644
index 000000000..f213f461d
--- /dev/null
+++ b/crypto/src/asn1/DerGraphicString.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerGraphicString
+        : DerStringBase
+    {
+        private readonly byte[] mString;
+
+        /**
+         * return a Graphic String from the passed in object
+         *
+         * @param obj a DerGraphicString or an object that can be converted into one.
+         * @exception IllegalArgumentException if the object cannot be converted.
+         * @return a DerGraphicString instance, or null.
+         */
+        public static DerGraphicString GetInstance(object obj)
+        {
+            if (obj == null || obj is DerGraphicString)
+            {
+                return (DerGraphicString)obj;
+            }
+
+            if (obj is byte[])
+            {
+                try
+                {
+                    return (DerGraphicString)FromByteArray((byte[])obj);
+                }
+                catch (Exception e)
+                {
+                    throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj");
+                }
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
+        }
+
+        /**
+         * return a Graphic String from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicit true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception IllegalArgumentException if the tagged object cannot
+         *               be converted.
+         * @return a DerGraphicString instance, or null.
+         */
+        public static DerGraphicString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+            if (isExplicit || o is DerGraphicString)
+			{
+				return GetInstance(o);
+			}
+
+            return new DerGraphicString(((Asn1OctetString)o).GetOctets());
+        }
+
+        /**
+         * basic constructor - with bytes.
+         * @param string the byte encoding of the characters making up the string.
+         */
+        public DerGraphicString(byte[] encoding)
+        {
+            this.mString = Arrays.Clone(encoding);
+        }
+
+        public override string GetString()
+        {
+            return Strings.FromByteArray(mString);
+        }
+
+        public byte[] GetOctets()
+        {
+            return Arrays.Clone(mString);
+        }
+
+        internal override void Encode(DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.GraphicString, mString);
+        }
+
+        protected override int Asn1GetHashCode()
+		{
+            return Arrays.GetHashCode(mString);
+        }
+
+		protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+			DerGraphicString other = asn1Object as DerGraphicString;
+
+            if (other == null)
+				return false;
+
+            return Arrays.AreEqual(mString, other.mString);
+        }
+    }
+}
diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs
new file mode 100644
index 000000000..b25401044
--- /dev/null
+++ b/crypto/src/asn1/DerVideotexString.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerVideotexString
+        : DerStringBase
+    {
+        private readonly byte[] mString;
+
+        /**
+         * return a Videotex String from the passed in object
+         *
+         * @param obj a DERVideotexString or an object that can be converted into one.
+         * @exception IllegalArgumentException if the object cannot be converted.
+         * @return a DERVideotexString instance, or null.
+         */
+        public static DerVideotexString GetInstance(object obj)
+        {
+            if (obj == null || obj is DerVideotexString)
+            {
+                return (DerVideotexString)obj;
+            }
+
+            if (obj is byte[])
+            {
+                try
+                {
+                    return (DerVideotexString)FromByteArray((byte[])obj);
+                }
+                catch (Exception e)
+                {
+                    throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj");
+                }
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
+        }
+
+        /**
+         * return a Videotex String from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicit true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception IllegalArgumentException if the tagged object cannot
+         *               be converted.
+         * @return a DERVideotexString instance, or null.
+         */
+        public static DerVideotexString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+            if (isExplicit || o is DerVideotexString)
+			{
+				return GetInstance(o);
+			}
+
+            return new DerVideotexString(((Asn1OctetString)o).GetOctets());
+        }
+
+        /**
+         * basic constructor - with bytes.
+         * @param string the byte encoding of the characters making up the string.
+         */
+        public DerVideotexString(byte[] encoding)
+        {
+            this.mString = Arrays.Clone(encoding);
+        }
+
+        public override string GetString()
+        {
+            return Strings.FromByteArray(mString);
+        }
+
+        public byte[] GetOctets()
+        {
+            return Arrays.Clone(mString);
+        }
+
+        internal override void Encode(DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.VideotexString, mString);
+        }
+
+        protected override int Asn1GetHashCode()
+		{
+            return Arrays.GetHashCode(mString);
+        }
+
+		protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            DerVideotexString other = asn1Object as DerVideotexString;
+
+            if (other == null)
+				return false;
+
+            return Arrays.AreEqual(mString, other.mString);
+        }
+    }
+}
diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
index 0b2ffa0d1..042911a06 100644
--- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
+++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -118,6 +118,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         public static readonly DerObjectIdentifier Pkcs9AtSigningDescription			= new DerObjectIdentifier(Pkcs9 + ".13");
         public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest				= new DerObjectIdentifier(Pkcs9 + ".14");
         public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities				= new DerObjectIdentifier(Pkcs9 + ".15");
+        public static readonly DerObjectIdentifier IdSmime                              = new DerObjectIdentifier(Pkcs9 + ".16");
+
         public static readonly DerObjectIdentifier Pkcs9AtFriendlyName					= new DerObjectIdentifier(Pkcs9 + ".20");
         public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID					= new DerObjectIdentifier(Pkcs9 + ".21");
 
@@ -131,19 +133,37 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 		public const string CrlTypes = Pkcs9 + ".23";
 		public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1");
 
-		public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9");
+        public static readonly DerObjectIdentifier IdAlg = IdSmime.Branch("3");
+
+        public static readonly DerObjectIdentifier IdAlgEsdh        = IdAlg.Branch("5");
+        public static readonly DerObjectIdentifier IdAlgCms3DesWrap = IdAlg.Branch("6");
+        public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap  = IdAlg.Branch("7");
+        public static readonly DerObjectIdentifier IdAlgPwriKek     = IdAlg.Branch("9");
+        public static readonly DerObjectIdentifier IdAlgSsdh        = IdAlg.Branch("10");
+
+        /*
+         * <pre>
+         * -- RSA-KEM Key Transport Algorithm
+         *
+         * id-rsa-kem OID ::= {
+         *      iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
+         *      pkcs-9(9) smime(16) alg(3) 14
+         *   }
+         * </pre>
+         */
+        public static readonly DerObjectIdentifier IdRsaKem = IdAlg.Branch("14");
 
         //
         // SMIME capability sub oids.
         //
-        public static readonly DerObjectIdentifier PreferSignedData				= new DerObjectIdentifier(Pkcs9 + ".15.1");
-        public static readonly DerObjectIdentifier CannotDecryptAny				= new DerObjectIdentifier(Pkcs9 + ".15.2");
-        public static readonly DerObjectIdentifier SmimeCapabilitiesVersions	= new DerObjectIdentifier(Pkcs9 + ".15.3");
+        public static readonly DerObjectIdentifier PreferSignedData				= Pkcs9AtSmimeCapabilities.Branch("1");
+        public static readonly DerObjectIdentifier CannotDecryptAny             = Pkcs9AtSmimeCapabilities.Branch("2");
+        public static readonly DerObjectIdentifier SmimeCapabilitiesVersions    = Pkcs9AtSmimeCapabilities.Branch("3");
 
         //
         // other SMIME attributes
         //
-		public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1");
+        public static readonly DerObjectIdentifier IdAAReceiptRequest = IdSmime.Branch("2.1");
 
         //
         // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
@@ -249,8 +269,5 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc	= new DerObjectIdentifier(Pkcs12PbeIds + ".4");
         public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc		= new DerObjectIdentifier(Pkcs12PbeIds + ".5");
         public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc			= new DerObjectIdentifier(Pkcs12PbeIds + ".6");
-
-		public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6");
-		public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7");
-	}
+    }
 }
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 36b17c8fd..6a21ee2af 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -198,6 +198,14 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine);
             }
+            else if (obj is DerGraphicString)
+            {
+                buf.Append(indent + "GraphicString(" + ((DerGraphicString)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerVideotexString)
+            {
+                buf.Append(indent + "VideotexString(" + ((DerVideotexString)obj).GetString() + ") " + NewLine);
+            }
             else if (obj is DerUtcTime)
             {
                 buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine);
diff --git a/crypto/src/crypto/engines/SerpentEngineBase.cs b/crypto/src/crypto/engines/SerpentEngineBase.cs
index a5d91b3be..9de552233 100644
--- a/crypto/src/crypto/engines/SerpentEngineBase.cs
+++ b/crypto/src/crypto/engines/SerpentEngineBase.cs
@@ -101,12 +101,13 @@ namespace Org.BouncyCastle.Crypto.Engines
             return ( (int)((uint)x >> bits) | (x << (32 - bits)));
         }
 
-        /**
+        /*
          * The sboxes below are based on the work of Brian Gladman and
          * Sam Simpson, whose original notice appears below.
          * <p>
          * For further details see:
          *      http://fp.gladman.plus.com/cryptography_technology/serpent/
+         * </p>
          */
 
         /* Partially optimised Serpent S Box boolean functions derived  */
@@ -124,9 +125,9 @@ namespace Org.BouncyCastle.Crypto.Engines
         /* We hereby give permission for information in this file to be */
         /* used freely subject only to acknowledgement of its origin.    */
 
-        /**
-        * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
-        */
+        /*
+         * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+         */
         protected void Sb0(int a, int b, int c, int d)
         {
             int t1 = a ^ d;
diff --git a/crypto/src/crypto/macs/VMPCMac.cs b/crypto/src/crypto/macs/VMPCMac.cs
index 89916355c..6f2da075c 100644
--- a/crypto/src/crypto/macs/VMPCMac.cs
+++ b/crypto/src/crypto/macs/VMPCMac.cs
@@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Macs
 
 			for (int i = 0; i < len; i++)
 			{
-				Update(input[i]);
+				Update(input[inOff + i]);
 			}
 		}
 	}
diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
index fb117c19d..3aa2e3719 100644
--- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
+++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
@@ -486,7 +486,14 @@ namespace Org.BouncyCastle.Crypto.Signers
             digest.BlockUpdate(m2Hash, 0, m2Hash.Length);
 
             // Update for the salt
-            digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength);
+            if (standardSalt != null)
+            {
+                digest.BlockUpdate(standardSalt, 0, standardSalt.Length);
+            }
+            else
+            {
+                digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength);
+            }
 
             byte[] hash = new byte[digest.GetDigestSize()];
             digest.DoFinal(hash, 0);
diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs
index 03890902b..23b7c0f49 100644
--- a/crypto/src/crypto/signers/PssSigner.cs
+++ b/crypto/src/crypto/signers/PssSigner.cs
@@ -25,6 +25,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 		private int hLen;
 		private int mgfhLen;
 		private int sLen;
+        private bool sSet;
 		private int emBits;
 		private byte[] salt;
 		private byte[] mDash;
@@ -35,7 +36,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 			IAsymmetricBlockCipher	cipher,
 			IDigest					digest)
 		{
-			return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), TrailerImplicit);
+			return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), null, TrailerImplicit);
 		}
 
 		public static PssSigner CreateRawSigner(
@@ -45,7 +46,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 			int						saltLen,
 			byte					trailer)
 		{
-			return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, trailer);
+			return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, null, trailer);
 		}
 
 		public PssSigner(
@@ -67,7 +68,19 @@ namespace Org.BouncyCastle.Crypto.Signers
 		{
 		}
 
-		public PssSigner(
+        /// <summary>Basic constructor</summary>
+        /// <param name="cipher">the asymmetric cipher to use.</param>
+        /// <param name="digest">the digest to use.</param>
+        /// <param name="salt">the fixed salt to be used.</param>
+        public PssSigner(
+            IAsymmetricBlockCipher cipher,
+            IDigest digest,
+            byte[] salt)
+            : this(cipher, digest, digest, digest, salt.Length, salt, TrailerImplicit)
+        {
+        }
+
+        public PssSigner(
 			IAsymmetricBlockCipher	cipher,
 			IDigest					contentDigest,
 			IDigest					mgfDigest,
@@ -76,7 +89,16 @@ namespace Org.BouncyCastle.Crypto.Signers
 		{
 		}
 
-		public PssSigner(
+        public PssSigner(
+            IAsymmetricBlockCipher cipher,
+            IDigest contentDigest,
+            IDigest mgfDigest,
+            byte[] salt)
+            : this(cipher, contentDigest, contentDigest, mgfDigest, salt.Length, salt, TrailerImplicit)
+        {
+        }
+
+        public PssSigner(
 			IAsymmetricBlockCipher	cipher,
 			IDigest					digest,
 			int						saltLen,
@@ -91,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 			IDigest					mgfDigest,
 			int						saltLen,
 			byte					trailer)
-			: this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, trailer)
+			: this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, null, trailer)
 		{
 		}
 
@@ -101,6 +123,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 			IDigest					contentDigest2,
 			IDigest					mgfDigest,
 			int						saltLen,
+            byte[]                  salt,
 			byte					trailer)
 		{
 			this.cipher = cipher;
@@ -110,7 +133,15 @@ namespace Org.BouncyCastle.Crypto.Signers
 			this.hLen = contentDigest2.GetDigestSize();
 			this.mgfhLen = mgfDigest.GetDigestSize();
 			this.sLen = saltLen;
-			this.salt = new byte[saltLen];
+            this.sSet = salt != null;
+            if (sSet)
+            {
+                this.salt = salt;
+            }
+            else
+            {
+                this.salt = new byte[saltLen];
+            }
 			this.mDash = new byte[8 + saltLen + hLen];
 			this.trailer = trailer;
 		}
@@ -197,7 +228,10 @@ namespace Org.BouncyCastle.Crypto.Signers
 
 			if (sLen != 0)
 			{
-				random.NextBytes(salt);
+                if (!sSet)
+                {
+                    random.NextBytes(salt);
+                }
 				salt.CopyTo(mDash, mDash.Length - sLen);
 			}
 
@@ -270,7 +304,14 @@ namespace Org.BouncyCastle.Crypto.Signers
 				return false;
 			}
 
-			Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen);
+            if (sSet)
+            {
+                Array.Copy(salt, 0, mDash, mDash.Length - sLen, sLen);
+            }
+            else
+            {
+                Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen);
+            }
 
 			contentDigest2.BlockUpdate(mDash, 0, mDash.Length);
 			contentDigest2.DoFinal(mDash, mDash.Length - hLen);
diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs
index 046feb78c..fedca0934 100644
--- a/crypto/src/crypto/tls/AbstractTlsClient.cs
+++ b/crypto/src/crypto/tls/AbstractTlsClient.cs
@@ -66,22 +66,15 @@ namespace Org.BouncyCastle.Crypto.Tls
             return null;
         }
 
-        /**
-         * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value
-         * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest
-         * version number supported by the client, and the value of ClientHello.client_version. No
-         * single value will guarantee interoperability with all old servers, but this is a complex
-         * topic beyond the scope of this document."
-         */
         public virtual ProtocolVersion ClientHelloRecordLayerVersion
         {
             get
             {
                 // "{03,00}"
-                // return ProtocolVersion.SSLv3;
+                //return ProtocolVersion.SSLv3;
 
                 // "the lowest version number supported by the client"
-                // return getMinimumVersion();
+                //return MinimumVersion;
 
                 // "the value of ClientHello.client_version"
                 return ClientVersion;
diff --git a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs
index c9ec06107..09fb8782d 100644
--- a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs
+++ b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs
@@ -18,6 +18,17 @@ namespace Org.BouncyCastle.Crypto.Tls
             this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
         }
 
+        protected virtual DigitallySigned ParseSignature(Stream input)
+        {
+            DigitallySigned signature = DigitallySigned.Parse(mContext, input);
+            SignatureAndHashAlgorithm signatureAlgorithm = signature.Algorithm;
+            if (signatureAlgorithm != null)
+            {
+                TlsUtilities.VerifySupportedSignatureAlgorithm(mSupportedSignatureAlgorithms, signatureAlgorithm);
+            }
+            return signature;
+        }
+
         public virtual void Init(TlsContext context)
         {
             this.mContext = context;
diff --git a/crypto/src/crypto/tls/DeferredHash.cs b/crypto/src/crypto/tls/DeferredHash.cs
index 1112d4a3c..f402f26d2 100644
--- a/crypto/src/crypto/tls/DeferredHash.cs
+++ b/crypto/src/crypto/tls/DeferredHash.cs
@@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             IDigest d = (IDigest)mHashes[hashAlgorithm];
             if (d == null)
-                throw new InvalidOperationException("HashAlgorithm " + hashAlgorithm + " is not being tracked");
+                throw new InvalidOperationException("HashAlgorithm." + HashAlgorithm.GetText(hashAlgorithm) + " is not being tracked");
 
             d = TlsUtilities.CloneHash(hashAlgorithm, d);
             if (mBuf != null)
diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs
index 411e7cca2..7cb554ae8 100644
--- a/crypto/src/crypto/tls/DtlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs
@@ -74,13 +74,16 @@ namespace Org.BouncyCastle.Crypto.Tls
             DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.clientContext, recordLayer);
 
             byte[] clientHelloBody = GenerateClientHello(state, state.client);
+
+            recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10);
+
             handshake.SendMessage(HandshakeType.client_hello, clientHelloBody);
 
             DtlsReliableHandshake.Message serverMessage = handshake.ReceiveMessage();
 
             while (serverMessage.Type == HandshakeType.hello_verify_request)
             {
-                ProtocolVersion recordLayerVersion = recordLayer.ResetDiscoveredPeerVersion();
+                ProtocolVersion recordLayerVersion = recordLayer.ReadVersion;
                 ProtocolVersion client_version = state.clientContext.ClientVersion;
 
                 /*
@@ -92,6 +95,8 @@ namespace Org.BouncyCastle.Crypto.Tls
                 if (!recordLayerVersion.IsEqualOrEarlierVersionOf(client_version))
                     throw new TlsFatalAlert(AlertDescription.illegal_parameter);
 
+                recordLayer.ReadVersion = null;
+
                 byte[] cookie = ProcessHelloVerifyRequest(state, serverMessage.Body);
                 byte[] patched = PatchClientHelloWithCookie(clientHelloBody, cookie);
 
@@ -103,7 +108,9 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (serverMessage.Type == HandshakeType.server_hello)
             {
-                ReportServerVersion(state, recordLayer.DiscoveredPeerVersion);
+                ProtocolVersion recordLayerVersion = recordLayer.ReadVersion;
+                ReportServerVersion(state, recordLayerVersion);
+                recordLayer.SetWriteVersion(recordLayerVersion);
 
                 ProcessServerHello(state, serverMessage.Body);
             }
diff --git a/crypto/src/crypto/tls/DtlsRecordLayer.cs b/crypto/src/crypto/tls/DtlsRecordLayer.cs
index 70befd9e4..6796f4cbb 100644
--- a/crypto/src/crypto/tls/DtlsRecordLayer.cs
+++ b/crypto/src/crypto/tls/DtlsRecordLayer.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         private volatile bool mClosed = false;
         private volatile bool mFailed = false;
-        private volatile ProtocolVersion mDiscoveredPeerVersion = null;
+        private volatile ProtocolVersion mReadVersion = null, mWriteVersion = null;
         private volatile bool mInHandshake;
         private volatile int mPlaintextLimit;
         private DtlsEpoch mCurrentEpoch, mPendingEpoch;
@@ -52,16 +52,15 @@ namespace Org.BouncyCastle.Crypto.Tls
             this.mPlaintextLimit = plaintextLimit;
         }
 
-        internal virtual ProtocolVersion DiscoveredPeerVersion
+        internal virtual ProtocolVersion ReadVersion
         {
-            get { return mDiscoveredPeerVersion; }
+            get { return mReadVersion; }
+            set { this.mReadVersion = value; }
         }
 
-        internal virtual ProtocolVersion ResetDiscoveredPeerVersion()
+        internal virtual void SetWriteVersion(ProtocolVersion writeVersion)
         {
-            ProtocolVersion result = mDiscoveredPeerVersion;
-            mDiscoveredPeerVersion = null;
-            return result;
+            this.mWriteVersion = writeVersion;
         }
 
         internal virtual void InitPendingEpoch(TlsCipher pendingCipher)
@@ -199,7 +198,12 @@ namespace Org.BouncyCastle.Crypto.Tls
                     }
 
                     ProtocolVersion version = TlsUtilities.ReadVersion(record, 1);
-                    if (mDiscoveredPeerVersion != null && !mDiscoveredPeerVersion.Equals(version))
+                    if (!version.IsDtls)
+                    {
+                        continue;
+                    }
+
+                    if (mReadVersion != null && !mReadVersion.Equals(version))
                     {
                         continue;
                     }
@@ -215,9 +219,9 @@ namespace Org.BouncyCastle.Crypto.Tls
                         continue;
                     }
 
-                    if (mDiscoveredPeerVersion == null)
+                    if (mReadVersion == null)
                     {
-                        mDiscoveredPeerVersion = version;
+                        mReadVersion = version;
                     }
 
                     switch (type)
@@ -469,6 +473,10 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         private void SendRecord(byte contentType, byte[] buf, int off, int len)
         {
+            // Never send anything until a valid ClientHello has been received
+            if (mWriteVersion == null)
+                return;
+
             if (len > this.mPlaintextLimit)
                 throw new TlsFatalAlert(AlertDescription.internal_error);
 
@@ -489,7 +497,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             byte[] record = new byte[ciphertext.Length + RECORD_HEADER_LENGTH];
             TlsUtilities.WriteUint8(contentType, record, 0);
-            ProtocolVersion version = mDiscoveredPeerVersion != null ? mDiscoveredPeerVersion : mContext.ClientVersion;
+            ProtocolVersion version = mWriteVersion;
             TlsUtilities.WriteVersion(version, record, 1);
             TlsUtilities.WriteUint16(recordEpoch, record, 3);
             TlsUtilities.WriteUint48(recordSequenceNumber, record, 5);
diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs
index 9c7caf290..171984b6f 100644
--- a/crypto/src/crypto/tls/DtlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs
@@ -76,12 +76,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             DtlsReliableHandshake.Message clientMessage = handshake.ReceiveMessage();
 
-            {
-                // NOTE: After receiving a record from the client, we discover the record layer version
-                ProtocolVersion client_version = recordLayer.DiscoveredPeerVersion;
-                // TODO Read RFCs for guidance on the expected record layer version number
-                state.serverContext.SetClientVersion(client_version);
-            }
+            // NOTE: DTLSRecordLayer requires any DTLS version, we don't otherwise constrain this
+            //ProtocolVersion recordLayerVersion = recordLayer.ReadVersion;
 
             if (clientMessage.Type == HandshakeType.client_hello)
             {
@@ -97,6 +93,10 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                 ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength);
 
+                ProtocolVersion recordLayerVersion = state.serverContext.ServerVersion;
+                recordLayer.ReadVersion = recordLayerVersion;
+                recordLayer.SetWriteVersion(recordLayerVersion);
+
                 handshake.SendMessage(HandshakeType.server_hello, serverHelloBody);
             }
 
@@ -156,6 +156,9 @@ namespace Org.BouncyCastle.Crypto.Tls
                 state.certificateRequest = state.server.GetCertificateRequest();
                 if (state.certificateRequest != null)
                 {
+                    if (TlsUtilities.IsTlsV12(state.serverContext) != (state.certificateRequest.SupportedSignatureAlgorithms != null))
+                        throw new TlsFatalAlert(AlertDescription.internal_error);
+
                     state.keyExchange.ValidateCertificateRequest(state.certificateRequest);
 
                     byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest);
@@ -458,6 +461,9 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual void ProcessCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
         {
+            if (state.certificateRequest == null)
+                throw new InvalidOperationException();
+
             MemoryStream buf = new MemoryStream(body, false);
 
             TlsServerContextImpl context = state.serverContext;
@@ -466,13 +472,15 @@ namespace Org.BouncyCastle.Crypto.Tls
             TlsProtocol.AssertEmpty(buf);
 
             // Verify the CertificateVerify message contains a correct signature.
-            bool verified = false;
             try
             {
+                SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm;
+
                 byte[] hash;
                 if (TlsUtilities.IsTlsV12(context))
                 {
-                    hash = prepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash);
+                    TlsUtilities.VerifySupportedSignatureAlgorithm(state.certificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm);
+                    hash = prepareFinishHash.GetFinalHash(signatureAlgorithm.Hash);
                 }
                 else
                 {
@@ -485,15 +493,17 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                 TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)state.clientCertificateType);
                 tlsSigner.Init(context);
-                verified = tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm,
-                    clientCertificateVerify.Signature, publicKey, hash);
+                if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash))
+                    throw new TlsFatalAlert(AlertDescription.decrypt_error);
             }
-            catch (Exception)
+            catch (TlsFatalAlert e)
             {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.decrypt_error, e);
             }
-
-            if (!verified)
-                throw new TlsFatalAlert(AlertDescription.decrypt_error);
         }
 
         protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body)
diff --git a/crypto/src/crypto/tls/HashAlgorithm.cs b/crypto/src/crypto/tls/HashAlgorithm.cs
index ac6def26f..ff540d2e0 100644
--- a/crypto/src/crypto/tls/HashAlgorithm.cs
+++ b/crypto/src/crypto/tls/HashAlgorithm.cs
@@ -12,5 +12,33 @@ namespace Org.BouncyCastle.Crypto.Tls
         public const byte sha256 = 4;
         public const byte sha384 = 5;
         public const byte sha512 = 6;
+
+        public static string GetName(byte hashAlgorithm)
+        {
+            switch (hashAlgorithm)
+            {
+            case none:
+                return "none";
+            case md5:
+                return "md5";
+            case sha1:
+                return "sha1";
+            case sha224:
+                return "sha224";
+            case sha256:
+                return "sha256";
+            case sha384:
+                return "sha384";
+            case sha512:
+                return "sha512";
+            default:
+                return "UNKNOWN";
+            }
+        }
+
+        public static string GetText(byte hashAlgorithm)
+        {
+            return GetName(hashAlgorithm) + "(" + hashAlgorithm + ")";
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs
index 116f6a779..73f169054 100644
--- a/crypto/src/crypto/tls/TlsClient.cs
+++ b/crypto/src/crypto/tls/TlsClient.cs
@@ -23,6 +23,18 @@ namespace Org.BouncyCastle.Crypto.Tls
         /// </returns>
         TlsSession GetSessionToResume();
 
+        /// <summary>
+        /// Return the <see cref="ProtocolVersion"/> to use for the <c>TLSPlaintext.version</c> field prior to
+        /// receiving the server version. NOTE: This method is <b>not</b> called for DTLS.
+        /// </summary>
+        /// <remarks>
+        /// See RFC 5246 E.1.: "TLS clients that wish to negotiate with older servers MAY send any value
+        /// {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest
+        /// version number supported by the client, and the value of ClientHello.client_version. No
+        /// single value will guarantee interoperability with all old servers, but this is a complex
+        /// topic beyond the scope of this document."
+        /// </remarks>
+        /// <returns>The <see cref="ProtocolVersion"/> to use.</returns>
         ProtocolVersion ClientHelloRecordLayerVersion { get; }
 
         ProtocolVersion ClientVersion { get; }
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index 9831e8cd7..cdd629247 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             ServerDHParams dhParams = ServerDHParams.Parse(teeIn);
 
-            DigitallySigned signed_params = DigitallySigned.Parse(mContext, input);
+            DigitallySigned signed_params = ParseSignature(input);
 
             ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
             buf.UpdateSigner(signer);
diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
index b681aada3..e0553b3f0 100644
--- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -73,7 +73,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             byte[] point = TlsUtilities.ReadOpaque8(teeIn);
 
-            DigitallySigned signed_params = DigitallySigned.Parse(mContext, input);
+            DigitallySigned signed_params = ParseSignature(input);
 
             ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
             buf.UpdateSigner(signer);
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index 4ab628b13..1b790c9e0 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -200,6 +200,9 @@ namespace Org.BouncyCastle.Crypto.Tls
                         this.mCertificateRequest = mTlsServer.GetCertificateRequest();
                         if (this.mCertificateRequest != null)
                         {
+                            if (TlsUtilities.IsTlsV12(Context) != (mCertificateRequest.SupportedSignatureAlgorithms != null))
+                                throw new TlsFatalAlert(AlertDescription.internal_error);
+
                             this.mKeyExchange.ValidateCertificateRequest(mCertificateRequest);
 
                             SendCertificateRequestMessage(mCertificateRequest);
@@ -460,6 +463,9 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf)
         {
+            if (mCertificateRequest == null)
+                throw new InvalidOperationException();
+
             DigitallySigned clientCertificateVerify = DigitallySigned.Parse(Context, buf);
 
             AssertEmpty(buf);
@@ -467,10 +473,13 @@ namespace Org.BouncyCastle.Crypto.Tls
             // Verify the CertificateVerify message contains a correct signature.
             try
             {
+                SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm;
+
                 byte[] hash;
                 if (TlsUtilities.IsTlsV12(Context))
                 {
-                    hash = mPrepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash);
+                    TlsUtilities.VerifySupportedSignatureAlgorithm(mCertificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm);
+                    hash = mPrepareFinishHash.GetFinalHash(signatureAlgorithm.Hash);
                 }
                 else
                 {
@@ -483,11 +492,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
                 TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)mClientCertificateType);
                 tlsSigner.Init(Context);
-                if (!tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm,
-                    clientCertificateVerify.Signature, publicKey, hash))
-                {
+                if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash))
                     throw new TlsFatalAlert(AlertDescription.decrypt_error);
-                }
+            }
+            catch (TlsFatalAlert e)
+            {
+                throw e;
             }
             catch (Exception e)
             {
diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
index ce8e4834a..09fa72348 100644
--- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
@@ -189,7 +189,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (buf != null)
             {
-                DigitallySigned signed_params = DigitallySigned.Parse(mContext, input);
+                DigitallySigned signed_params = ParseSignature(input);
 
                 ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
                 buf.UpdateSigner(signer);
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 26fb0d5e8..7d1d488d7 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -129,14 +129,24 @@ namespace Org.BouncyCastle.Crypto.Tls
             return context.ServerVersion.IsSsl;
         }
 
+        public static bool IsTlsV11(ProtocolVersion version)
+        {
+            return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion());
+        }
+
         public static bool IsTlsV11(TlsContext context)
         {
-            return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+            return IsTlsV11(context.ServerVersion);
+        }
+
+        public static bool IsTlsV12(ProtocolVersion version)
+        {
+            return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion());
         }
 
         public static bool IsTlsV12(TlsContext context)
         {
-            return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+            return IsTlsV12(context.ServerVersion);
         }
 
         public static void WriteUint8(byte i, Stream output)
@@ -712,11 +722,10 @@ namespace Org.BouncyCastle.Crypto.Tls
         public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, bool allowAnonymous,
             Stream output)
         {
-            if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
-                || supportedSignatureAlgorithms.Count >= (1 << 15))
-            {
+            if (supportedSignatureAlgorithms == null)
+                throw new ArgumentNullException("supportedSignatureAlgorithms");
+            if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15))
                 throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
-            }
 
             // supported_signature_algorithms
             int length = 2 * supportedSignatureAlgorithms.Count;
@@ -762,6 +771,27 @@ namespace Org.BouncyCastle.Crypto.Tls
             return supportedSignatureAlgorithms;
         }
 
+        public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm)
+        {
+            if (supportedSignatureAlgorithms == null)
+                throw new ArgumentNullException("supportedSignatureAlgorithms");
+            if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15))
+                throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
+            if (signatureAlgorithm == null)
+                throw new ArgumentNullException("signatureAlgorithm");
+
+            if (signatureAlgorithm.Signature != SignatureAlgorithm.anonymous)
+            {
+                foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
+                {
+                    if (entry.Hash == signatureAlgorithm.Hash && entry.Signature == signatureAlgorithm.Signature)
+                        return;
+                }
+            }
+
+            throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+        }
+
         public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size)
         {
             ProtocolVersion version = context.ServerVersion;
diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs
index 640c6e787..49773b66d 100644
--- a/crypto/src/math/ec/custom/sec/SecT113Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs
@@ -102,6 +102,16 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 1]  = z1 & M49;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong u0 = Interleave.Unshuffle(x[0]), u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c0  = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            z[0] = e0 ^ (c0 << 57) ^ (c0 <<  5);
+            z[1] =      (c0 >>  7) ^ (c0 >> 59); 
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat128.CreateExt64();
@@ -131,6 +141,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0
+            return (uint)(x[0]) & 1U;
+        }
+
         protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
         {
             /*
diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
index f217e28cb..9ba25d987 100644
--- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat128.Create64();
+            SecT113Field.Sqrt(x, z);
+            return new SecT113FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs
index 47f97078c..1b6697afe 100644
--- a/crypto/src/math/ec/custom/sec/SecT131Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         private const ulong M03 = ulong.MaxValue >> 61;
         private const ulong M44 = ulong.MaxValue >> 20;
 
+        private static readonly ulong[] ROOT_Z = new ulong[]{ 0x26BC4D789AF13523UL, 0x26BC4D789AF135E2UL, 0x6UL };
+
         public static void Add(ulong[] x, ulong[] y, ulong[] z)
         {
             z[0] = x[0] ^ y[0];
@@ -109,6 +111,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 2]  = z2 & M03;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong[] odd = Nat192.Create64();
+
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            odd[0]   = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL);
+            odd[1]   = (u0 >> 32);
+
+            Multiply(odd, ROOT_Z, z);
+
+            z[0] ^= e0;
+            z[1] ^= e1;
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat.Create64(5);
@@ -138,6 +159,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 123, 129
+            return (uint)(x[0] ^ (x[1] >> 59) ^ (x[2] >> 1)) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5];
diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
index 0ea00ea07..e0ecc100f 100644
--- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat192.Create64();
+            SecT131Field.Sqrt(x, z);
+            return new SecT131FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs
index f921a5bc7..b1e9aa725 100644
--- a/crypto/src/math/ec/custom/sec/SecT163Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         private const ulong M35 = ulong.MaxValue >> 29;
         private const ulong M55 = ulong.MaxValue >> 9;
 
+        private static readonly ulong[] ROOT_Z = new ulong[]{ 0xB6DB6DB6DB6DB6B0UL, 0x492492492492DB6DUL, 0x492492492UL };
+
         public static void Add(ulong[] x, ulong[] y, ulong[] z)
         {
             z[0] = x[0] ^ y[0];
@@ -122,6 +124,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 2]  = z2 & M35;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong[] odd = Nat192.Create64();
+
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            odd[0]   = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL);
+            odd[1]   = (u0 >> 32);
+
+            Multiply(odd, ROOT_Z, z);
+
+            z[0] ^= e0;
+            z[1] ^= e1;
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat192.CreateExt64();
@@ -151,6 +172,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 157
+            return (uint)(x[0] ^ (x[2] >> 29)) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5];
diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
index c7a0b5639..8953fb529 100644
--- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat192.Create64();
+            SecT163Field.Sqrt(x, z);
+            return new SecT163FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs
index 5154f1e0a..41acb4f94 100644
--- a/crypto/src/math/ec/custom/sec/SecT193Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs
@@ -132,6 +132,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 3]  = z3 & M01;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL) ^ (x[3] << 32);
+            ulong c1 = (u0 >> 32);
+
+            z[0] = e0 ^ (c0 << 8);
+            z[1] = e1 ^ (c1 << 8) ^ (c0 >> 56) ^ (c0 << 33);
+            z[2] =                  (c1 >> 56) ^ (c1 << 33) ^ (c0 >> 31);
+            z[3] =                                            (c1 >> 31);
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat256.CreateExt64();
@@ -161,6 +178,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0
+            return (uint)(x[0]) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
index eba4d10e6..a1150b3f9 100644
--- a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat256.Create64();
+            SecT193Field.Sqrt(x, z);
+            return new SecT193FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs
index a2f73fd5d..870dade50 100644
--- a/crypto/src/math/ec/custom/sec/SecT233Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs
@@ -128,6 +128,41 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 3]  = z3 & M41;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            ulong c2;
+            c2  = (c1 >> 27);
+            c1 ^= (c0 >> 27) | (c1 << 37);
+            c0 ^=              (c0 << 37);
+
+            ulong[] tt = Nat256.CreateExt64();
+
+            int[] shifts = { 32, 117, 191 };
+            for (int i = 0; i < shifts.Length; ++i)
+            {
+                int w = shifts[i] >> 6, s = shifts[i] & 63;
+                Debug.Assert(s != 0);
+                tt[w    ] ^= (c0 << s);
+                tt[w + 1] ^= (c1 << s) | (c0 >> -s);
+                tt[w + 2] ^= (c2 << s) | (c1 >> -s);
+                tt[w + 3] ^=             (c2 >> -s);
+            }
+
+            Reduce(tt, z);
+
+            z[0] ^= e0;
+            z[1] ^= e1;
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat256.CreateExt64();
@@ -157,6 +192,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 159
+            return (uint)(x[0] ^ (x[2] >> 31)) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
index a9041efde..91b8e2f1c 100644
--- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat256.Create64();
+            SecT233Field.Sqrt(x, z);
+            return new SecT233FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs
index 6b8ad696f..2e6ed2ad6 100644
--- a/crypto/src/math/ec/custom/sec/SecT239Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs
@@ -136,6 +136,42 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 3]  = z3 & M47;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            ulong c2, c3;
+            c3  = (c1 >> 49);
+            c2  = (c0 >> 49) | (c1 << 15);
+            c1 ^=              (c0 << 15);
+
+            ulong[] tt = Nat256.CreateExt64();
+
+            int[] shifts = { 39, 120 };
+            for (int i = 0; i < shifts.Length; ++i)
+            {
+                int w = shifts[i] >> 6, s = shifts[i] & 63;
+                Debug.Assert(s != 0);
+                tt[w    ] ^= (c0 << s);
+                tt[w + 1] ^= (c1 << s) | (c0 >> -s);
+                tt[w + 2] ^= (c2 << s) | (c1 >> -s);
+                tt[w + 3] ^= (c3 << s) | (c2 >> -s);
+                tt[w + 4] ^=             (c3 >> -s);
+            }
+
+            Reduce(tt, z);
+
+            z[0] ^= e0;
+            z[1] ^= e1;
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat256.CreateExt64();
@@ -165,6 +201,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 81, 162
+            return (uint)(x[0] ^ (x[1] >> 17) ^ (x[2] >> 34)) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
index de074c55f..a32ffc5d2 100644
--- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat256.Create64();
+            SecT239Field.Sqrt(x, z);
+            return new SecT239FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs
index 903ea02ff..22b7eaaab 100644
--- a/crypto/src/math/ec/custom/sec/SecT283Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         private const ulong M27 = ulong.MaxValue >> 37;
         private const ulong M57 = ulong.MaxValue >> 7;
 
+        private static readonly ulong[] ROOT_Z = new ulong[]{ 0x0C30C30C30C30808UL, 0x30C30C30C30C30C3UL, 0x820820820820830CUL, 0x0820820820820820UL, 0x2082082UL };
+
         public static void Add(ulong[] x, ulong[] y, ulong[] z)
         {
             z[0] = x[0] ^ y[0];
@@ -129,6 +131,30 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 4]  = z4 & M27;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong[] odd = Nat320.Create64();
+
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            odd[0]   = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            odd[1]   = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[4]);
+            ulong e2 = (u0 & 0x00000000FFFFFFFFUL);
+            odd[2]   = (u0 >> 32);
+
+            Multiply(odd, ROOT_Z, z);
+
+            z[0] ^= e0;
+            z[1] ^= e1;
+            z[2] ^= e2;
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat.Create64(9);
@@ -158,6 +184,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 271
+            return (uint)(x[0] ^ (x[4] >> 15)) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4];
diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
index e02108f73..adfd4e0ed 100644
--- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat320.Create64();
+            SecT283Field.Sqrt(x, z);
+            return new SecT283FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs
index 84eada96e..861b77aa1 100644
--- a/crypto/src/math/ec/custom/sec/SecT409Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs
@@ -165,6 +165,36 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 6]  = z6 & M25;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong u0, u1;
+            u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]);
+            ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]);
+            ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[4]); u1 = Interleave.Unshuffle(x[5]);
+            ulong e2 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+            ulong c2 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+
+            u0 = Interleave.Unshuffle(x[6]);
+            ulong e3 = (u0 & 0x00000000FFFFFFFFUL);
+            ulong c3 = (u0 >> 32);
+
+            z[0] = e0 ^ (c0 << 44);
+            z[1] = e1 ^ (c1 << 44) ^ (c0 >> 20);
+            z[2] = e2 ^ (c2 << 44) ^ (c1 >> 20);
+            z[3] = e3 ^ (c3 << 44) ^ (c2 >> 20) ^ (c0 << 13);
+            z[4] =                   (c3 >> 20) ^ (c1 << 13) ^ (c0 >> 51);
+            z[5] =                                (c2 << 13) ^ (c1 >> 51);
+            z[6] =                                (c3 << 13) ^ (c2 >> 51);
+
+            Debug.Assert((c3 >> 51) == 0);
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat.Create64(13);
@@ -194,6 +224,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0
+            return (uint)(x[0]) & 1U;
+        }
+
         protected static void ImplCompactExt(ulong[] zz)
         {
             ulong z00 = zz[ 0], z01 = zz[ 1], z02 = zz[ 2], z03 = zz[ 3], z04 = zz[ 4], z05 = zz[ 5], z06 = zz[ 6];
diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
index 581ea73df..f954f46e7 100644
--- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat448.Create64();
+            SecT409Field.Sqrt(x, z);
+            return new SecT409FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index fc84e336b..98f4f7fc2 100644
--- a/crypto/src/math/ec/custom/sec/SecT571Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -11,6 +11,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         private const ulong RM = 0xEF7BDEF7BDEF7BDEUL;
 
+        private static readonly ulong[] ROOT_Z = new ulong[]{ 0x2BE1195F08CAFB99UL, 0x95F08CAF84657C23UL, 0xCAF84657C232BE11UL, 0x657C232BE1195F08UL,
+            0xF84657C2308CAF84UL, 0x7C232BE1195F08CAUL, 0xBE1195F08CAF8465UL, 0x5F08CAF84657C232UL, 0x784657C232BE119UL };
+
         public static void Add(ulong[] x, ulong[] y, ulong[] z)
         {
             for (int i = 0; i < 9; ++i)
@@ -156,6 +159,28 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             z[zOff + 8]  = z8 & M59;
         }
 
+        public static void Sqrt(ulong[] x, ulong[] z)
+        {
+            ulong[] evn = Nat576.Create64(), odd = Nat576.Create64();
+
+            int pos = 0;
+            for (int i = 0; i < 4; ++i)
+            {
+                ulong u0 = Interleave.Unshuffle(x[pos++]);
+                ulong u1 = Interleave.Unshuffle(x[pos++]);
+                evn[i] = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32);
+                odd[i] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL);
+            }
+            {
+                ulong u0 = Interleave.Unshuffle(x[pos]);
+                evn[4] = (u0 & 0x00000000FFFFFFFFUL);
+                odd[4] = (u0 >> 32);
+            }
+
+            Multiply(odd, ROOT_Z, z);
+            Add(z, evn, z);
+        }
+
         public static void Square(ulong[] x, ulong[] z)
         {
             ulong[] tt = Nat576.CreateExt64();
@@ -185,6 +210,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static uint Trace(ulong[] x)
+        {
+            // Non-zero-trace bits: 0, 561, 569
+            return (uint)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1U;
+        }
+
         protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
         {
             //for (int i = 0; i < 9; ++i)
diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
index 5d5458412..c43b8dc3a 100644
--- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public override ECFieldElement Sqrt()
         {
-            return SquarePow(M - 1);
+            ulong[] z = Nat576.Create64();
+            SecT571Field.Sqrt(x, z);
+            return new SecT571FieldElement(z);
         }
 
         public virtual int Representation
diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index a45ee1e08..d21840644 100644
--- a/crypto/src/math/raw/Interleave.cs
+++ b/crypto/src/math/raw/Interleave.cs
@@ -91,5 +91,17 @@ namespace Org.BouncyCastle.Math.Raw
             z[zOff    ] = (x     ) & M64;
             z[zOff + 1] = (x >> 1) & M64;
         }
+
+        internal static ulong Unshuffle(ulong x)
+        {
+            // "unshuffle" even bits to low half and odd bits to high half
+            ulong t;
+            t = (x ^ (x >>  1)) & 0x2222222222222222UL; x ^= (t ^ (t <<  1));
+            t = (x ^ (x >>  2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t <<  2));
+            t = (x ^ (x >>  4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t <<  4));
+            t = (x ^ (x >>  8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t <<  8));
+            t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16));
+            return x;
+        }
     }
 }
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index 71896d203..24a60346e 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -277,6 +277,8 @@
     <Compile Include="src\crypto\tls\test\ByteQueueStreamTest.cs" />
     <Compile Include="src\crypto\tls\test\DtlsProtocolTest.cs" />
     <Compile Include="src\crypto\tls\test\DtlsTestCase.cs" />
+    <Compile Include="src\crypto\tls\test\DtlsTestClientProtocol.cs" />
+    <Compile Include="src\crypto\tls\test\DtlsTestServerProtocol.cs" />
     <Compile Include="src\crypto\tls\test\DtlsTestSuite.cs" />
     <Compile Include="src\crypto\tls\test\LoggingDatagramTransport.cs" />
     <Compile Include="src\crypto\tls\test\MockDatagramAssociation.cs" />
@@ -299,8 +301,10 @@
     <Compile Include="src\crypto\tls\test\TlsSrpProtocolTest.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestCase.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestClientImpl.cs" />
+    <Compile Include="src\crypto\tls\test\TlsTestClientProtocol.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestConfig.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestServerImpl.cs" />
+    <Compile Include="src\crypto\tls\test\TlsTestServerProtocol.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestSuite.cs" />
     <Compile Include="src\crypto\tls\test\TlsTestUtilities.cs" />
     <Compile Include="src\crypto\tls\test\UnreliableDatagramTransport.cs" />
diff --git a/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs b/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs
index a61ae87e8..e505acd9d 100644
--- a/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs
+++ b/crypto/test/src/asn1/test/DERApplicationSpecificTest.cs
@@ -30,14 +30,73 @@ namespace Org.BouncyCastle.Asn1.Tests
 			+ "75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310"
 			+ "7F9B0DADA16414FFA204516AEE2B");
 
-		public override string Name
+        private static readonly byte[] sampleData = Hex.Decode(
+            "613280020780a106060456000104a203020101a305a103020101be80288006025101020109a080b2800a01000000000000000000");
+
+        public override string Name
 		{
 			get { return "DerApplicationSpecific"; }
 		}
 
-		public override void PerformTest()
+        private void TestTaggedObject()
+        {
+            // boolean explicit, int tagNo, ASN1Encodable obj
+            bool isExplicit = false;
+
+            // Type1 ::= VisibleString
+            DerVisibleString type1 = new DerVisibleString("Jones");
+            if (!Arrays.AreEqual(Hex.Decode("1A054A6F6E6573"), type1.GetEncoded()))
+            {
+                Fail("ERROR: expected value doesn't match!");
+            }
+
+            // Type2 ::= [APPLICATION 3] IMPLICIT Type1
+            isExplicit = false;
+            DerApplicationSpecific type2 = new DerApplicationSpecific(isExplicit, 3, type1);
+            // type2.isConstructed()
+            if (!Arrays.AreEqual(Hex.Decode("43054A6F6E6573"), type2.GetEncoded()))
+            {
+                Fail("ERROR: expected value doesn't match!");
+            }
+
+            // Type3 ::= [2] Type2
+            isExplicit = true;
+            DerTaggedObject type3 = new DerTaggedObject(isExplicit, 2, type2);
+            if (!Arrays.AreEqual(Hex.Decode("A20743054A6F6E6573"), type3.GetEncoded()))
+            {
+                Fail("ERROR: expected value doesn't match!");
+            }
+
+            // Type4 ::= [APPLICATION 7] IMPLICIT Type3
+            isExplicit = false;
+            DerApplicationSpecific type4 = new DerApplicationSpecific(isExplicit, 7, type3);
+            if (!Arrays.AreEqual(Hex.Decode("670743054A6F6E6573"), type4.GetEncoded()))
+            {
+                Fail("ERROR: expected value doesn't match!");
+            }
+
+            // Type5 ::= [2] IMPLICIT Type2
+            isExplicit = false;
+            DerTaggedObject type5 = new DerTaggedObject(isExplicit, 2, type2);
+            // type5.isConstructed()
+            if (!Arrays.AreEqual(Hex.Decode("82054A6F6E6573"), type5.GetEncoded()))
+            {
+                Fail("ERROR: expected value doesn't match!");
+            }
+        }
+
+        public override void PerformTest()
 		{
-			DerInteger val = new DerInteger(9);
+            TestTaggedObject();
+
+            DerApplicationSpecific appSpec = (DerApplicationSpecific)Asn1Object.FromByteArray(sampleData);
+
+            if (1 != appSpec.ApplicationTag)
+            {
+                Fail("wrong tag detected");
+            }
+
+            DerInteger val = new DerInteger(9);
 
 			DerApplicationSpecific tagged = new DerApplicationSpecific(false, 3, val);
 
@@ -65,8 +124,6 @@ namespace Org.BouncyCastle.Asn1.Tests
 
 			if (!Arrays.AreEqual(certData, encoded))
 			{
-				Console.WriteLine(Encoding.ASCII.GetString(certData, 0, certData.Length).Substring(0, 20));
-				Console.WriteLine(Encoding.ASCII.GetString(encoded, 0, encoded.Length).Substring(0, 20));
 				Fail("re-encoding of certificate data failed");
 			}
 		}
diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
index 7e0695341..91329fbd5 100644
--- a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
+++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
@@ -3,6 +3,8 @@ using System.IO;
 
 using NUnit.Framework;
 
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Asn1.Tests
@@ -43,7 +45,9 @@ namespace Org.BouncyCastle.Asn1.Tests
                 new DerUniversalString(data),
                 new DerUtcTime(new DateTime()),
                 new DerUtf8String("hello world"),
-                new DerVisibleString("hello world")
+                new DerVisibleString("hello world"),
+                new DerGraphicString(Hex.Decode("deadbeef")),
+                new DerVideotexString(Strings.ToByteArray("Hello World"))
             };
 
 			MemoryStream bOut = new MemoryStream();
diff --git a/crypto/test/src/crypto/test/NaccacheSternTest.cs b/crypto/test/src/crypto/test/NaccacheSternTest.cs
index 4fa256f12..9168adced 100644
--- a/crypto/test/src/crypto/test/NaccacheSternTest.cs
+++ b/crypto/test/src/crypto/test/NaccacheSternTest.cs
@@ -78,9 +78,6 @@ namespace Org.BouncyCastle.Crypto.Tests
 
         static NaccacheSternTest()
         {
-            cryptEng.Debug = debug;
-            decryptEng.Debug = debug;
-
             // First the Parameters from the NaccacheStern Paper
             // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf )
 
@@ -145,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 			// specify key generation parameters
 			NaccacheSternKeyGenerationParameters genParam
-				= new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30, debug);
+				= new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30);
 
 			// Initialize Key generator and generate key pair
 			NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator();
diff --git a/crypto/test/src/crypto/test/PSSTest.cs b/crypto/test/src/crypto/test/PSSTest.cs
index 91d8d3a6e..8578d254f 100644
--- a/crypto/test/src/crypto/test/PSSTest.cs
+++ b/crypto/test/src/crypto/test/PSSTest.cs
@@ -319,9 +319,45 @@ namespace Org.BouncyCastle.Crypto.Tests
 			{
 				Fail("loop test failed - failures: " + failed);
 			}
+
+            fixedSaltTest();
 		}
 
-		public static void Main(
+        private void fixedSaltTest()
+        {
+            byte[] data = Hex.Decode("010203040506070809101112131415");
+
+            PssSigner eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("deadbeef"));
+
+            eng.Init(true, prv8);
+
+            eng.BlockUpdate(data, 0, data.Length);
+
+            byte[] s = eng.GenerateSignature();
+
+            eng.Init(false, pub8);
+
+            eng.BlockUpdate(data, 0, data.Length);
+
+            if (!eng.VerifySignature(s))
+            {
+                Fail("fixed salt failed");
+            }
+
+            // test failure
+            eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("beefbeef"));
+
+            eng.Init(false, pub8);
+
+            eng.BlockUpdate(data, 0, data.Length);
+
+            if (eng.VerifySignature(s))
+            {
+                Fail("fixed salt failure verfied");
+            }
+        }
+
+        public static void Main(
 			string[] args)
 		{
 			RunTest(new PssTest());
diff --git a/crypto/test/src/crypto/test/PaddingTest.cs b/crypto/test/src/crypto/test/PaddingTest.cs
index 6f41d754c..ed53d9228 100644
--- a/crypto/test/src/crypto/test/PaddingTest.cs
+++ b/crypto/test/src/crypto/test/PaddingTest.cs
@@ -105,11 +105,9 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 		public override void PerformTest()
 		{
-			SecureRandom    rand = new SecureRandom(new byte[20]);
+            SecureRandom rand = SecureRandom.GetInstance("SHA1PRNG");
 
-			rand.SetSeed(DateTime.Now.Ticks);
-
-			doTestPadding(new Pkcs7Padding(), rand,
+            doTestPadding(new Pkcs7Padding(), rand,
 				Hex.Decode("ffffff0505050505"),
 				Hex.Decode("0000000004040404"));
 
diff --git a/crypto/test/src/crypto/test/VMPCMacTest.cs b/crypto/test/src/crypto/test/VMPCMacTest.cs
index 0ddb5506f..b9a5e3a93 100644
--- a/crypto/test/src/crypto/test/VMPCMacTest.cs
+++ b/crypto/test/src/crypto/test/VMPCMacTest.cs
@@ -35,16 +35,17 @@ namespace Org.BouncyCastle.Crypto.Tests
 			ICipherParameters kpwiv = new ParametersWithIV(kp,
 				Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155"));
 
-			byte[] m = new byte[256];
+            int offset = 117;
+            byte[] m = new byte[512];
 			for (int i = 0; i < 256; i++)
 			{
-				m[i] = (byte) i;
+				m[offset + i] = (byte)i;
 			}
 
-			VmpcMac mac = new VmpcMac();
+            VmpcMac mac = new VmpcMac();
 			mac.Init(kpwiv);
 
-			mac.BlockUpdate(m, 0, m.Length);
+			mac.BlockUpdate(m, offset, 256);
 
 			byte[] output = new byte[20];
 			mac.DoFinal(output, 0);
@@ -57,7 +58,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 			}
 		}
 
-		[Test]
+        [Test]
 		public void TestFunction()
 		{
 			string resultText = Perform().ToString();
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
index d4af04fac..5e43337f4 100644
--- a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
+++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
@@ -28,8 +28,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
 
             SecureRandom secureRandom = new SecureRandom();
 
-            DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom);
-            DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom);
+            DtlsTestClientProtocol clientProtocol = new DtlsTestClientProtocol(secureRandom, config);
+            DtlsTestServerProtocol serverProtocol = new DtlsTestServerProtocol(secureRandom, config);
 
             MockDatagramAssociation network = new MockDatagramAssociation(1500);
 
@@ -101,14 +101,15 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
         internal class Server
         {
             private readonly DtlsTestCase mOuter;
-            private readonly DtlsServerProtocol mServerProtocol;
+            private readonly DtlsTestServerProtocol mServerProtocol;
             private readonly DatagramTransport mServerTransport;
             private readonly TlsTestServerImpl mServerImpl;
 
             private volatile bool isShutdown = false;
             internal Exception mCaught = null;
 
-            internal Server(DtlsTestCase outer, DtlsServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl)
+            internal Server(DtlsTestCase outer, DtlsTestServerProtocol serverProtocol,
+                DatagramTransport serverTransport, TlsTestServerImpl serverImpl)
             {
                 this.mOuter = outer;
                 this.mServerProtocol = serverProtocol;
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs b/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs
new file mode 100644
index 000000000..41ed93eb0
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class DtlsTestClientProtocol
+        :   DtlsClientProtocol
+    {
+        protected readonly TlsTestConfig config;
+
+        public DtlsTestClientProtocol(SecureRandom secureRandom, TlsTestConfig config)
+            : base(secureRandom)
+        {
+            this.config = config;
+        }
+
+        protected override byte[] GenerateCertificateVerify(ClientHandshakeState state, DigitallySigned certificateVerify)
+        {
+            if (certificateVerify.Algorithm != null && config.clientAuthSigAlgClaimed != null)
+            {
+                certificateVerify = new DigitallySigned(config.clientAuthSigAlgClaimed, certificateVerify.Signature);
+            }
+
+            return base.GenerateCertificateVerify(state, certificateVerify);
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs b/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs
new file mode 100644
index 000000000..006473cef
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs
@@ -0,0 +1,18 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class DtlsTestServerProtocol
+        :   DtlsServerProtocol
+    {
+        protected readonly TlsTestConfig config;
+
+        public DtlsTestServerProtocol(SecureRandom secureRandom, TlsTestConfig config)
+            : base(secureRandom)
+        {
+            this.config = config;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
index eb9d42e5f..a1ba62dde 100644
--- a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
+++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
@@ -31,7 +31,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
                 c.clientFallback = true;
 
-                testSuite.Add(new TestCaseData(c).SetName("FallbackGood"));
+                AddTestCase(testSuite, c, "FallbackGood");
             }
 
             /*
@@ -40,20 +40,22 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
              * alerts being raised
              */
 
-            //{
-            //    TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
-            //    c.clientOfferVersion = ProtocolVersion.DTLSv10;
-            //    c.clientFallback = true;
-            //    c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
+#if false
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+                c.clientOfferVersion = ProtocolVersion.DTLSv10;
+                c.clientFallback = true;
+                c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
 
-            //    testSuite.Add(new TestCaseData(c).SetName("FallbackBad"));
-            //}
+                AddTestCase(testSuite, c, "FallbackBad");
+            }
+#endif
 
             {
                 TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
                 c.clientOfferVersion = ProtocolVersion.DTLSv10;
 
-                testSuite.Add(new TestCaseData(c).SetName("FallbackNone"));
+                AddTestCase(testSuite, c, "FallbackNone");
             }
         }
 
@@ -71,61 +73,144 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
              * alerts being raised
              */
 
-            //{
-            //    TlsTestConfig c = CreateDtlsTestConfig(version);
-            //    c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
-            //    c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
+#if false
+            /*
+             * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is
+             * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms();
+                c.ExpectClientFatalAlert(AlertDescription.internal_error);
+
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg");
+            }
+
+            /*
+             * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is
+             * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server
+             * when it verifies the selected algorithm against the CertificateRequest supported
+             * algorithms.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
+                c.ExpectServerFatalAlert(AlertDescription.illegal_parameter);
 
-            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify"));
-            //}
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg");
+            }
 
-            //{
-            //    TlsTestConfig c = CreateDtlsTestConfig(version);
-            //    c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
-            //    c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
+            /*
+             * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends
+             * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the
+             * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms,
+             * we expect fatal alert to come from the server when it finds the claimed algorithm
+             * doesn't match the client certificate.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa);
+                c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
+                c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
 
-            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate"));
-            //}
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch");
+            }
 
-            //{
-            //    TlsTestConfig c = CreateDtlsTestConfig(version);
-            //    c.clientAuth = C.CLIENT_AUTH_NONE;
-            //    c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
-            //    c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+                c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
 
-            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined"));
-            //}
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature");
+            }
 
             {
                 TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+                c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault"));
+                AddTestCase(testSuite, c, prefix + "BadClientCertificate");
+            }
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_NONE;
+                c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+                c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
+
+                AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined");
+            }
+
+            /*
+             * Server selects MD5/RSA for ServerKeyExchange signature, which is not in the default
+             * supported signature algorithms that the client sent. We expect fatal alert from the
+             * client when it verifies the selected algorithm against the supported algorithms.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.ExpectClientFatalAlert(AlertDescription.illegal_parameter);
+
+                AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg");
+            }
+
+            /*
+             * Server selects MD5/RSA for ServerKeyExchange signature, which is not the default {sha1,rsa}
+             * implied by the absent signature_algorithms extension. We expect fatal alert from the
+             * client when it verifies the selected algorithm against the implicit default.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientSendSignatureAlgorithms = false;
+                c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.ExpectClientFatalAlert(AlertDescription.illegal_parameter);
+
+                AddTestCaseDebug(testSuite, c, prefix + "BadServerKeyExchangeSigAlg2");
+            }
+#endif
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+
+                AddTestCase(testSuite, c, prefix + "GoodDefault");
             }
 
             {
                 TlsTestConfig c = CreateDtlsTestConfig(version);
                 c.serverCertReq = C.SERVER_CERT_REQ_NONE;
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq"));
+                AddTestCase(testSuite, c, prefix + "GoodNoCertReq");
             }
 
             {
                 TlsTestConfig c = CreateDtlsTestConfig(version);
                 c.clientAuth = C.CLIENT_AUTH_NONE;
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined"));
+                AddTestCase(testSuite, c, prefix + "GoodOptionalCertReqDeclined");
             }
         }
 
+        private static void AddTestCase(IList testSuite, TlsTestConfig config, String name)
+        {
+            testSuite.Add(new TestCaseData(config).SetName(name));
+        }
+
         private static TlsTestConfig CreateDtlsTestConfig(ProtocolVersion version)
         {
             TlsTestConfig c = new TlsTestConfig();
             c.clientMinimumVersion = ProtocolVersion.DTLSv10;
-            /*
-             * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with
-             * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server
-             */
-            c.clientOfferVersion = version;
+            c.clientOfferVersion = ProtocolVersion.DTLSv12;
             c.serverMaximumVersion = version;
             c.serverMinimumVersion = ProtocolVersion.DTLSv10;
             return c;
diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
index e3c604db7..25057b8ce 100644
--- a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
@@ -73,8 +73,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
             TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
             TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
-            TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
-            TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            {
+                /*
+                 * NOTE: If you are copying test code, do not blindly set these extensions in your own client.
+                 */
+                TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+                TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            }
             return clientExtensions;
         }
 
diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
index 7c1198632..35c5b3599 100644
--- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
@@ -63,8 +63,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
             TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
             TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
-            TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
-            TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            {
+                /*
+                 * NOTE: If you are copying test code, do not blindly set these extensions in your own client.
+                 */
+                TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+                TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            }
             return clientExtensions;
         }
 
diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
index 4b0c12710..7fb5db6ce 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestCase.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
@@ -35,8 +35,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             NetworkStream clientNet = new NetworkStream(clientPipe);
             NetworkStream serverNet = new NetworkStream(serverPipe);
 
-            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNet, secureRandom);
-            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNet, secureRandom);
+            TlsTestClientProtocol clientProtocol = new TlsTestClientProtocol(clientNet, secureRandom, config);
+            TlsTestServerProtocol serverProtocol = new TlsTestServerProtocol(serverNet, secureRandom, config);
 
             TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
             TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
@@ -104,13 +104,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
         internal class Server
         {
             protected readonly TlsTestCase mOuter;
-            protected readonly TlsServerProtocol mServerProtocol;
+            protected readonly TlsTestServerProtocol mServerProtocol;
             protected readonly TlsTestServerImpl mServerImpl;
 
             internal bool mCanExit = false;
             internal Exception mCaught = null;
 
-            internal Server(TlsTestCase outer, TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl)
+            internal Server(TlsTestCase outer, TlsTestServerProtocol serverProtocol, TlsTestServerImpl serverImpl)
             {
                 this.mOuter = outer;
                 this.mServerProtocol = serverProtocol;
diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
index 0cc1883ba..864a0a5cc 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.IO;
 
 using Org.BouncyCastle.Asn1;
@@ -56,6 +57,17 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
 	        }
         }
 
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = base.GetClientExtensions();
+            if (clientExtensions != null && !mConfig.clientSendSignatureAlgorithms)
+            {
+                clientExtensions.Remove(ExtensionType.signature_algorithms);
+                this.mSupportedSignatureAlgorithms = null;
+            }
+            return clientExtensions;
+        }
+
         public override bool IsFallback
         {
             get { return mConfig.clientFallback; }
@@ -201,9 +213,15 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                     return null;
                 }
 
+                IList supportedSigAlgs = certificateRequest.SupportedSignatureAlgorithms;
+                if (supportedSigAlgs != null && mOuter.mConfig.clientAuthSigAlg != null)
+                {
+                    supportedSigAlgs = new ArrayList(1);
+                    supportedSigAlgs.Add(mOuter.mConfig.clientAuthSigAlg);
+                }
+
                 TlsSignerCredentials signerCredentials = TlsTestUtilities.LoadSignerCredentials(mContext,
-                    certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
-                    "x509-client.pem", "x509-client-key.pem");
+                    supportedSigAlgs, SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem");
 
                 if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID)
                 {
diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs b/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs
new file mode 100644
index 000000000..97b7c91bc
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs
@@ -0,0 +1,29 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class TlsTestClientProtocol
+        :   TlsClientProtocol
+    {
+        protected readonly TlsTestConfig config;
+
+        public TlsTestClientProtocol(Stream stream, SecureRandom secureRandom, TlsTestConfig config)
+            : base(stream, secureRandom)
+        {
+            this.config = config;
+        }
+
+        protected override void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
+        {
+            if (certificateVerify.Algorithm != null && config.clientAuthSigAlgClaimed != null)
+            {
+                certificateVerify = new DigitallySigned(config.clientAuthSigAlgClaimed, certificateVerify.Signature);
+            }
+
+            base.SendCertificateVerifyMessage(certificateVerify);
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs
index 0d1e7badb..ccbb919d2 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 
 namespace Org.BouncyCastle.Crypto.Tls.Tests
 {
@@ -47,6 +48,18 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
         public int clientAuth = CLIENT_AUTH_VALID;
 
         /**
+         * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to
+         * be used for the CertificateVerify signature (if one is sent).
+         */
+        public SignatureAndHashAlgorithm clientAuthSigAlg = null;
+
+        /**
+         * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to
+         * be _claimed_ in the CertificateVerify (if one is sent), independently of what was actually used.
+         */
+        public SignatureAndHashAlgorithm clientAuthSigAlgClaimed = null;
+
+        /**
          * Configures the minimum protocol version the client will accept. If null, uses the library's default.
          */
         public ProtocolVersion clientMinimumVersion = null;
@@ -62,11 +75,28 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
         public bool clientFallback = false;
 
         /**
+         * Configures whether a (TLS 1.2+) client will send the signature_algorithms extension in ClientHello.
+         */
+        public bool clientSendSignatureAlgorithms = true;
+
+        /**
+         * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to
+         * be used for the ServerKeyExchange signature (if one is sent).
+         */
+        public SignatureAndHashAlgorithm serverAuthSigAlg = null;
+
+        /**
          * Configures whether the test server will send a certificate request.
          */
         public int serverCertReq = SERVER_CERT_REQ_OPTIONAL;
 
         /**
+         * If TLS 1.2 or higher is negotiated, configures the set of supported signature algorithms in the
+         * CertificateRequest (if one is sent). If null, uses a default set.
+         */
+        public IList serverCertReqSigAlgs = null;
+
+        /**
          * Configures the maximum protocol version the server will accept. If null, uses the library's default.
          */
         public ProtocolVersion serverMaximumVersion = null;
diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs
index 152d5dbdc..9edd2e524 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections;
 using System.IO;
+using System.Threading;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
@@ -72,11 +73,11 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                     + ", " + AlertDescription.GetText(alertDescription));
                 if (message != null)
                 {
-                    output.WriteLine("> " + message);
+                    SafeWriteLine(output, "> " + message);
                 }
                 if (cause != null)
                 {
-                    output.WriteLine(cause);
+                    SafeWriteLine(output, cause);
                 }
             }
         }
@@ -92,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             if (TlsTestConfig.DEBUG)
             {
                 TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
-                output.WriteLine("TLS server received alert: " + AlertLevel.GetText(alertLevel)
+                SafeWriteLine(output, "TLS server received alert: " + AlertLevel.GetText(alertLevel)
                     + ", " + AlertDescription.GetText(alertDescription));
             }
         }
@@ -122,7 +123,11 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             IList serverSigAlgs = null;
             if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
             {
-                serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
+                serverSigAlgs = mConfig.serverCertReqSigAlgs;
+                if (serverSigAlgs == null)
+                {
+                    serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
+                }
             }
 
             IList certificateAuthorities = new ArrayList();
@@ -167,15 +172,27 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             }
         }
 
+        protected virtual IList GetSupportedSignatureAlgorithms()
+        {
+            if (TlsUtilities.IsTlsV12(mContext) && mConfig.serverAuthSigAlg != null)
+            {
+                IList signatureAlgorithms = new ArrayList(1);
+                signatureAlgorithms.Add(mConfig.serverAuthSigAlg);
+                return signatureAlgorithms;
+            }
+
+            return mSupportedSignatureAlgorithms;
+        }
+
         protected override TlsSignerCredentials GetDsaSignerCredentials()
         {
-            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa,
+            return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), SignatureAlgorithm.dsa,
                 "x509-server-dsa.pem", "x509-server-key-dsa.pem");
         }
 
         protected override TlsSignerCredentials GetECDsaSignerCredentials()
         {
-            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.ecdsa,
+            return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), SignatureAlgorithm.ecdsa,
                 "x509-server-ecdsa.pem", "x509-server-key-ecdsa.pem");
         }
 
@@ -187,8 +204,22 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
 
         protected override TlsSignerCredentials GetRsaSignerCredentials()
         {
-            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+            return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), SignatureAlgorithm.rsa,
                 "x509-server.pem", "x509-server-key.pem");
         }
+
+        private static void SafeWriteLine(TextWriter output, object line)
+        {
+            try
+            {
+                output.WriteLine(line);
+            }
+            catch (ThreadInterruptedException)
+            {
+                /*
+                 * For some reason the NUnit plugin in Visual Studio started throwing these during alert logging
+                 */
+            }
+        }
     }
 }
diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs b/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs
new file mode 100644
index 000000000..845b7f0b9
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class TlsTestServerProtocol
+        :   TlsServerProtocol
+    {
+        protected readonly TlsTestConfig config;
+
+        public TlsTestServerProtocol(Stream stream, SecureRandom secureRandom, TlsTestConfig config)
+            : base(stream, secureRandom)
+        {
+            this.config = config;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs
index dfd09d06e..77cebe0a6 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs
@@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12);
                 c.clientFallback = true;
 
-                testSuite.Add(new TestCaseData(c).SetName("FallbackGood"));
+                AddTestCase(testSuite, c, "FallbackGood");
             }
 
             {
@@ -41,14 +41,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 c.clientFallback = true;
                 c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
 
-                testSuite.Add(new TestCaseData(c).SetName("FallbackBad"));
+                AddTestCase(testSuite, c, "FallbackBad");
             }
 
             {
                 TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12);
                 c.clientOfferVersion = ProtocolVersion.TLSv11;
 
-                testSuite.Add(new TestCaseData(c).SetName("FallbackNone"));
+                AddTestCase(testSuite, c, "FallbackNone");
             }
         }
 
@@ -63,7 +63,58 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             {
                 TlsTestConfig c = CreateTlsTestConfig(version);
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault"));
+                AddTestCase(testSuite, c, prefix + "GoodDefault");
+            }
+
+            /*
+             * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is
+             * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms();
+                c.ExpectClientFatalAlert(AlertDescription.internal_error);
+
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg");
+            }
+
+            /*
+             * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is
+             * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server
+             * when it verifies the selected algorithm against the CertificateRequest supported
+             * algorithms.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
+                c.ExpectServerFatalAlert(AlertDescription.illegal_parameter);
+
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg");
+            }
+
+            /*
+             * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends
+             * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the
+             * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms,
+             * we expect fatal alert to come from the server when it finds the claimed algorithm
+             * doesn't match the client certificate.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_VALID;
+                c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa);
+                c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa);
+                c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
+                c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
+
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch");
             }
 
             {
@@ -71,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
                 c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify"));
+                AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature");
             }
 
             {
@@ -79,7 +130,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
                 c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate"));
+                AddTestCase(testSuite, c, prefix + "BadClientCertificate");
             }
 
             {
@@ -88,24 +139,58 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
                 c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined"));
+                AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined");
+            }
+
+            /*
+             * Server selects MD5/RSA for ServerKeyExchange signature, which is not in the default
+             * supported signature algorithms that the client sent. We expect fatal alert from the
+             * client when it verifies the selected algorithm against the supported algorithms.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.ExpectClientFatalAlert(AlertDescription.illegal_parameter);
+
+                AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg");
+            }
+
+            /*
+             * Server selects MD5/RSA for ServerKeyExchange signature, which is not the default {sha1,rsa}
+             * implied by the absent signature_algorithms extension. We expect fatal alert from the
+             * client when it verifies the selected algorithm against the implicit default.
+             */
+            if (TlsUtilities.IsTlsV12(version))
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientSendSignatureAlgorithms = false;
+                c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa);
+                c.ExpectClientFatalAlert(AlertDescription.illegal_parameter);
+
+                AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg2");
             }
 
             {
                 TlsTestConfig c = CreateTlsTestConfig(version);
                 c.serverCertReq = C.SERVER_CERT_REQ_NONE;
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq"));
+                AddTestCase(testSuite, c, prefix + "GoodNoCertReq");
             }
 
             {
                 TlsTestConfig c = CreateTlsTestConfig(version);
                 c.clientAuth = C.CLIENT_AUTH_NONE;
 
-                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined"));
+                AddTestCase(testSuite, c, prefix + "GoodOptionalCertReqDeclined");
             }
         }
 
+        private static void AddTestCase(IList testSuite, TlsTestConfig config, string name)
+        {
+            testSuite.Add(new TestCaseData(config).SetName(name));
+        }
+
         private static TlsTestConfig CreateTlsTestConfig(ProtocolVersion version)
         {
             TlsTestConfig c = new TlsTestConfig();
diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs
index 3c10170f7..57f838f9f 100644
--- a/crypto/test/src/math/ec/test/ECPointTest.cs
+++ b/crypto/test/src/math/ec/test/ECPointTest.cs
@@ -437,6 +437,19 @@ namespace Org.BouncyCastle.Math.EC.Tests
                     }
                 }
             }
+            else if (ECAlgorithms.IsF2mCurve(c))
+            {
+                int m = c.FieldSize;
+                BigInteger x = new BigInteger(m, secRand);
+                ECFieldElement fe = c.FromBigInteger(x);
+                for (int i = 0; i < 100; ++i)
+                {
+                    ECFieldElement sq = fe.Square();
+                    ECFieldElement check = sq.Sqrt();
+                    Assert.AreEqual(fe, check);
+                    fe = sq;
+                }
+            }
         }
 
         private void ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(X9ECParameters x9ECParameters)
diff --git a/crypto/test/src/test/ECEncodingTest.cs b/crypto/test/src/test/ECEncodingTest.cs
index f1a4d5e3a..8d993c15e 100644
--- a/crypto/test/src/test/ECEncodingTest.cs
+++ b/crypto/test/src/test/ECEncodingTest.cs
@@ -109,7 +109,7 @@ namespace Org.BouncyCastle.Tests
 				if (!compress)
 				{
 					//pubKey.setPointFormat("UNCOMPRESSED");
-					pubKey = SetPublicUncompressed(pubKey, false);
+					pubKey = SetPublicUncompressed(pubKey);
 				}
 
 				byte[] x = pubKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned();
@@ -154,7 +154,7 @@ namespace Org.BouncyCastle.Tests
 				// TODO Private key compression?
 				//newKey.setPointFormat("UNCOMPRESSED");
 				//newPubKey.setPointFormat("UNCOMPRESSED");
-				newPubKey = SetPublicUncompressed(newPubKey, false);
+				newPubKey = SetPublicUncompressed(newPubKey);
 			}
 
 //			string newPrivateKey = new string(Hex.encode(newKey.getEncoded()));
@@ -201,7 +201,7 @@ namespace Org.BouncyCastle.Tests
 				// TODO Private key compression?
 				//privECKey.setPointFormat("UNCOMPRESSED");
 				//pubECKey.setPointFormat("UNCOMPRESSED");
-				pubECKey = SetPublicUncompressed(pubECKey, false);
+				pubECKey = SetPublicUncompressed(pubECKey);
 			}
 
 			certGen.SetSignatureAlgorithm("ECDSAwithSHA1");
@@ -216,13 +216,12 @@ namespace Org.BouncyCastle.Tests
 		}
 
 		private ECPublicKeyParameters SetPublicUncompressed(
-			ECPublicKeyParameters	key,
-			bool					withCompression)
+			ECPublicKeyParameters	key)
 		{
 			ECPoint p = key.Q.Normalize();
 			return new ECPublicKeyParameters(
 				key.AlgorithmName,
-				p.Curve.CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), withCompression),
+				p.Curve.CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger()),
 				key.Parameters);
 		}