summary refs log tree commit diff
path: root/crypto/test
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/test')
-rw-r--r--crypto/test/data/tls/x509-client-dsa.pem32
-rw-r--r--crypto/test/data/tls/x509-client-ecdsa.pem17
-rw-r--r--crypto/test/data/tls/x509-client-key-dsa.pem15
-rw-r--r--crypto/test/data/tls/x509-client-key-ecdsa.pem6
-rw-r--r--crypto/test/data/tls/x509-server-dsa.pem32
-rw-r--r--crypto/test/data/tls/x509-server-ecdsa.pem17
-rw-r--r--crypto/test/data/tls/x509-server-key-dsa.pem15
-rw-r--r--crypto/test/data/tls/x509-server-key-ecdsa.pem6
-rw-r--r--crypto/test/lib/nunit.core.dllbin90112 -> 139264 bytes
-rw-r--r--crypto/test/lib/nunit.core.interfaces.dllbin40960 -> 61440 bytes
-rw-r--r--crypto/test/lib/nunit.framework.dllbin81920 -> 139264 bytes
-rw-r--r--crypto/test/src/asn1/test/AllTests.cs28
-rw-r--r--crypto/test/src/cms/test/AllTests.cs33
-rw-r--r--crypto/test/src/crypto/io/test/AllTests.cs29
-rw-r--r--crypto/test/src/crypto/test/AllTests.cs37
-rw-r--r--crypto/test/src/crypto/test/CCMTest.cs47
-rw-r--r--crypto/test/src/crypto/test/RegressionTest.cs3
-rw-r--r--crypto/test/src/crypto/test/SRP6Test.cs49
-rw-r--r--crypto/test/src/crypto/test/X931SignerTest.cs145
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs102
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestCase.cs153
-rw-r--r--crypto/test/src/crypto/tls/test/DtlsTestSuite.cs134
-rw-r--r--crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs86
-rw-r--r--crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs110
-rw-r--r--crypto/test/src/crypto/tls/test/MockDtlsClient.cs150
-rw-r--r--crypto/test/src/crypto/tls/test/MockDtlsServer.cs100
-rw-r--r--crypto/test/src/crypto/tls/test/MockPskTlsClient.cs132
-rw-r--r--crypto/test/src/crypto/tls/test/MockPskTlsServer.cs105
-rw-r--r--crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs120
-rw-r--r--crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs113
-rw-r--r--crypto/test/src/crypto/tls/test/MockTlsClient.cs54
-rw-r--r--crypto/test/src/crypto/tls/test/MockTlsServer.cs49
-rw-r--r--crypto/test/src/crypto/tls/test/NetworkStream.cs101
-rw-r--r--crypto/test/src/crypto/tls/test/PipedStream.cs134
-rw-r--r--crypto/test/src/crypto/tls/test/PskTlsClientTest.cs79
-rw-r--r--crypto/test/src/crypto/tls/test/TlsProtocolTest.cs80
-rw-r--r--crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs80
-rw-r--r--crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs80
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestCase.cs164
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs262
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestConfig.cs101
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs194
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestSuite.cs119
-rw-r--r--crypto/test/src/crypto/tls/test/TlsTestUtilities.cs29
-rw-r--r--crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs84
-rw-r--r--crypto/test/src/math/ec/test/AllTests.cs23
-rw-r--r--crypto/test/src/math/ec/test/ECPointTest.cs4
-rw-r--r--crypto/test/src/math/ec/test/TnafTest.cs2
-rw-r--r--crypto/test/src/math/test/AllTests.cs21
-rw-r--r--crypto/test/src/ocsp/test/AllTests.cs29
-rw-r--r--crypto/test/src/openpgp/examples/test/AllTests.cs32
-rw-r--r--crypto/test/src/openssl/test/AllTests.cs37
-rw-r--r--crypto/test/src/tsp/test/AllTests.cs27
-rw-r--r--crypto/test/src/util/io/pem/test/AllTests.cs35
54 files changed, 3348 insertions, 288 deletions
diff --git a/crypto/test/data/tls/x509-client-dsa.pem b/crypto/test/data/tls/x509-client-dsa.pem
new file mode 100644
index 000000000..91d9e4415
--- /dev/null
+++ b/crypto/test/data/tls/x509-client-dsa.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFmzCCBFOgAwIBAgIMVOBtHi6d3lDIPyoMMA0GCSqGSIb3DQEBCwUAMCMxITAf
+BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5NTU0
+MloYDzIwMzUwMjEwMDk1NTQyWjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz
+dCBDbGllbnQwggNHMIICOgYHKoZIzjgEATCCAi0CggEBAPvZZVsYbqUzF5Aq5JCU
+GJtg9+Hgrab/2F8vnEKsYKWtKFY4BCalIbhbZ/e4VPAEV1SlV/GgmtkPVrOutThq
+03j/eo98t82vismks6SMupNoyOiPqDZ+HyNEZFIQV9Ur/1D/tPBQGrD7Fbh5JOmK
+QPCoo46t9Xclfm+8u8bUIhFQV4LIkug5YBm2J8wy5FeaRYno1+4Hp543oD6SkOtF
+aJCp05nfiNRtaZy/LXr22UnSggG9M/zug+u3Bi2R70TI5FJq7TwYHfAlbesbLBjH
+QHvE95WlFxK1YovmziBLfew5RClZ3kgj7f3SL/3WeRy2ittQaObwV27ZNj4enYAD
+qkkCIQDsN/jM9mS5UDmPNRR6Wby2jvJQbHdm6yMqlFiIXVAECQKCAQEAzVrnDdM6
+kPTVALWJNYC279xIEMETimJGP39o3YXMJFlyoEzFYamJPneYlYpY4jGfuetC+jFn
+HouDivtjdf/vAc+og4jaro4NcaDCjzPZBTQuvb0cFhlSbVZsit1IMv/sztJUdPcd
+QKnGP+NfiChBDh8LLskvuVefEia0Ix/xwdK764zVn9oxiP5E2sKMMYnnFoVykbKU
+W43sOONe+P2zOF3VTIOUngszcNDKJsXrFKZ+MtE9FvKduaXBmd0y9Pat7jFCodry
+127mBeIZOKb9h3YMZCf7tQBFpX6o8JX4Ltw9hVRIsspgarli3K18WmOR+6pvAzJx
+IxxiYDbo1PHMAgOCAQUAAoIBAGPk3p3hPR51sTwf2LwDrZ5Fh9tLzFoSh6ojjiR/
+FJsqwbrEEPYi4vozJOBao17qfZayMArcq7QB5eUzBaeeggvyYgYPUIUh8kBZqeLp
+WtWYBXwDqNQiRSAqX0nl35SZEnyyou4kidHFW4SWSbTQw9pkM1gtP2Q7pkxabdjt
+fQTJsilslKFhoV/zWYsa72YJ1GilnDLwPanaBDdpnX84W+TDS2Gy2wb0o15etOTU
+Ly9EoHisZZfdwdIoAd0pJbjSHAJnudB+skL2VfPwfwxQDOTV7gh6XIe5h5bLKR3x
+ruLjNx1ppcTkjKmUruTp7V+/sH9EAS8B9epiNDGwL0s8gX6jdjB0MAwGA1UdEwEB
+/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDwYDVR0PAQH/BAUDAweAADAdBgNV
+HQ4EFgQUGvXFed+UN0C5+YrVvcR+7cn9U6swHwYDVR0jBBgwFoAU9mOvr6Pi7+4O
+5bKxRihqeCkyHukwDQYJKoZIhvcNAQELBQADggExAChl15lXRB43Oh+qIeibolYt
+OBCHlUQcQcFzqK556TKNQfhWoRv1ovxbxgPokogfnLfxKdmHrb4E+aF0syxNpXGn
+gBY2G7uyuKjoJnMNsxdTiS6jzps+LlgwHMYsFac0vcJATVz1U8hoR90B4pwkNkXv
+ErVXj4WvHqB5a4gsqPpAslZvhxOgWLvjA+1V4HohspnMVTup3zG6frdmwLWZ+FPI
+LyrEaUaWiilFl83RWuVlExhxGyfLF8u/06OJYHCUNtHT4UQavFzQMz5UwruGor7x
+n8QEE84SXaQxIyWO5T2vnlxZ0+fw/0GXyJS0F0WvJ5WkK+s+y6nXZ8Hq2fDecDWn
+1nw44LpnwGb//010RdtOeAHAQmGuuEf8rf1Xiw990hAYvTzM4cT9/l22vQPR3rg=
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/tls/x509-client-ecdsa.pem b/crypto/test/data/tls/x509-client-ecdsa.pem
new file mode 100644
index 000000000..fd8bc845b
--- /dev/null
+++ b/crypto/test/data/tls/x509-client-ecdsa.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqzCCAWOgAwIBAgIMVOBhzQE9XhiRAUXpMA0GCSqGSIb3DQEBCwUAMCMxITAf
+BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5MDcy
+NVoYDzIwMzUwMjEwMDkwNzI1WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz
+dCBDbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASWdahP6F9xwnD6eABg
+2AwifyDDCw5jy5hGe+Lnvyjok/zdkw2n8lWCFdhInFC7mRcGS7aduF7dykv9C9oU
+mY17o3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA8GA1Ud
+DwEB/wQFAwMHgAAwHQYDVR0OBBYEFAg1z6i+u89U0RQrH9ApFWIklZrpMB8GA1Ud
+IwQYMBaAFPZjr6+j4u/uDuWysUYoangpMh7pMA0GCSqGSIb3DQEBCwUAA4IBMQCL
+RJIeoOlVOcseShihLd3OU7NU3tGeLDnEcwPOAPYsDN1c7V/zROTD/0W0nhSVdRfB
+AyxjjDjq3J/MTf1DrouEynoAU8SZL5OnxbceX74U2WsSaJU0PAaw9zTOaKoOuTET
+EVs/OMx00XXhZcu+lPFAKT3YNJKO1Rm7Sy4vnY4jnsuRsk9+D6E3CmDSnKQC/g90
+/0djrDTYpL9Lyd5zzekZPpzX7YgNfmq2X04521+3ahfq4bBMC8GRdAuon2h2FwFX
++aH9cjHHDgxPt5pHkg3Uk+Cl6KhVb2ilS0uYd4XaMPXOUOUOxRpmQ3/7YhNgyyaL
+IOP+fWkbOiFbUTDaOcbBo9y8gvy7+sXuGF5k4nHXNs46Ew1gThQPFtZjqgdiEi+A
+5hYd5P2j0V9L9LprzM79
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/tls/x509-client-key-dsa.pem b/crypto/test/data/tls/x509-client-key-dsa.pem
new file mode 100644
index 000000000..e4e9632c7
--- /dev/null
+++ b/crypto/test/data/tls/x509-client-key-dsa.pem
@@ -0,0 +1,15 @@
+-----BEGIN PRIVATE KEY-----
+MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQD72WVbGG6lMxeQKuSQlBibYPfh
+4K2m/9hfL5xCrGClrShWOAQmpSG4W2f3uFTwBFdUpVfxoJrZD1azrrU4atN4/3qP
+fLfNr4rJpLOkjLqTaMjoj6g2fh8jRGRSEFfVK/9Q/7TwUBqw+xW4eSTpikDwqKOO
+rfV3JX5vvLvG1CIRUFeCyJLoOWAZtifMMuRXmkWJ6NfuB6eeN6A+kpDrRWiQqdOZ
+34jUbWmcvy169tlJ0oIBvTP87oPrtwYtke9EyORSau08GB3wJW3rGywYx0B7xPeV
+pRcStWKL5s4gS33sOUQpWd5II+390i/91nkctorbUGjm8Fdu2TY+Hp2AA6pJAiEA
+7Df4zPZkuVA5jzUUelm8to7yUGx3ZusjKpRYiF1QBAkCggEBAM1a5w3TOpD01QC1
+iTWAtu/cSBDBE4piRj9/aN2FzCRZcqBMxWGpiT53mJWKWOIxn7nrQvoxZx6Lg4r7
+Y3X/7wHPqIOI2q6ODXGgwo8z2QU0Lr29HBYZUm1WbIrdSDL/7M7SVHT3HUCpxj/j
+X4goQQ4fCy7JL7lXnxImtCMf8cHSu+uM1Z/aMYj+RNrCjDGJ5xaFcpGylFuN7Djj
+Xvj9szhd1UyDlJ4LM3DQyibF6xSmfjLRPRbynbmlwZndMvT2re4xQqHa8tdu5gXi
+GTim/Yd2DGQn+7UARaV+qPCV+C7cPYVUSLLKYGq5YtytfFpjkfuqbwMycSMcYmA2
+6NTxzAIEIgIgC6eNrpVR96umhuvIbLz6sy2YwlGFpkK+LLJOL2GmQ4g=
+-----END PRIVATE KEY-----
diff --git a/crypto/test/data/tls/x509-client-key-ecdsa.pem b/crypto/test/data/tls/x509-client-key-ecdsa.pem
new file mode 100644
index 000000000..89232e303
--- /dev/null
+++ b/crypto/test/data/tls/x509-client-key-ecdsa.pem
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGUAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHoweAIBAQQhANLHM3ugk0ZTEYNx
+uKn3ytAv71M61ChZAjWdC9nW1U7zoAoGCCqGSM49AwEHoUQDQgAElnWoT+hfccJw
++ngAYNgMIn8gwwsOY8uYRnvi578o6JP83ZMNp/JVghXYSJxQu5kXBku2nbhe3cpL
+/QvaFJmNew==
+-----END PRIVATE KEY-----
diff --git a/crypto/test/data/tls/x509-server-dsa.pem b/crypto/test/data/tls/x509-server-dsa.pem
new file mode 100644
index 000000000..1078dbcbc
--- /dev/null
+++ b/crypto/test/data/tls/x509-server-dsa.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFmjCCBFKgAwIBAgIMVOBtTzLTG8B9QCZvMA0GCSqGSIb3DQEBCwUAMCMxITAf
+BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5NTYz
+MVoYDzIwMzUwMjEwMDk1NjMxWjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz
+dCBTZXJ2ZXIwggNGMIICOQYHKoZIzjgEATCCAiwCggEBANblGd/puZYWDvmSMCx0
+AnQQcbmjUhB3MN68/fhkKFwBPU1QhJRiSEVDG1bnsUP55EQKDs1vpiSXgy89P3aT
+cagq0M+urrN97MPeKoBF8sk4o6axruspxD41OyKhW68Nnk54E+3mEPABS4yYpsuE
+hFfaZhOUXdA9aUFWnPN7oo7QlI+F7la8bluz8G8j81aMsEwjBdEKg+2Mp1+33NVa
+IWEegnunVEkb0vJd/WwLZYj+OgmK4fn/qqIdRXIbjeNUvpAtklE5NrARswI0RXuX
+yWxPfBrQSbWk3DQvbuWbEeSUrhYY67YbpPGA5Rng8awpxdXhvzsSmT9c6BlrLfF6
+IN0CIQDWtWHaMmlAVZW9p0Dmsj70sNHJxOYWlqjCEzF7axV3fwKCAQAgFZojuX/n
+leri2E9C6b8cQTof46JZeAeG2Svk8I91cnIv0iXTHfyzWLWDAYnfeuMmt+nMA6/A
+1K94YI1duc3iahLa5U3fOACWJdFtL/CAFVyNth7lDeHbWTFjM5HgA76pzmAfvFtZ
+pcJp1AUZZB+3coKSr6ZrMagt1HhoefGyo7JkPpsxGiFEKB79rXkFi0AEsSnbduFE
+czrg8DBdXm9//yUQnTw2pphcwLZt6t6Eq3Wrpu364Dn+hJegpLfA6uOhtRJw+7xv
+5jkBbvIxp1PLZEn16qmPKMs3Im4QUa2u5F0nLYUGHi01i5OSn0UWnom8EcDis/0Q
+CrkyBaiMaNkkA4IBBQACggEAQob2cpVeV4uwnX8XutQLro6BkEFMhpaQLUzbI97J
+Nh1OUMnW3K2KCCdhygTYfH3j2S8ys4W30zutHyhiApUdYUZKxNXXu4+NPoLwCyAE
+rrN5db5QgVx8aOG/Gfmp4POMpeGKioXgOsSWpUB0uyedgT4sszq/vuZc455HiS07
+LTlaJjeIQFtKdVYXGKNWqP/WLRnjSY9IXA5hxBXvlNAVGS/M4TvBWURUJF33THTq
+ioS0DYJ9Ikyn2fsgLgSRRyNU7Y5945yUhY5p6E6Njk0ZBB+2YUtB6TQhPvEY/G48
+xwH4hTZppmmfu2UIE+YlsWv10buTOT+mxU/5LjDI6RQM2KN2MHQwDAYDVR0TAQH/
+BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB4AAMB0GA1Ud
+DgQWBBS8bllTQWk2fm2R6XSZEIoRTd6/+zAfBgNVHSMEGDAWgBT2Y6+vo+Lv7g7l
+srFGKGp4KTIe6TANBgkqhkiG9w0BAQsFAAOCATEAptRUkWUT+MdvD7v733B6Gad+
+wO0G9n7Au7ZsS6NVPxc4DrozFyyhPU1uOl1koUyYQP52V1lkm1+rS7tQXm4+32iz
+bLwDCYn4LD1IZQ2hTNY/g/U0oA1dp3ZOJeydZDZ9Bm1NWYeWqfHk/ZiHMdrEdIUo
+7Zkg1T0ZBvmBXTUJzeDqIV0fMotFOQBJg5avyCcX56jHXbu2AmGQsQf6NoniXG37
+wY/xiPSUUmOKjAU/B4tc24ADa5r37JzlHbpOGe1nTb8AYxjyPDdjO4Um2BugKE+K
+rq+NJMg8Ej2sXLOnS2FweCoIR+RXGAUUBizlHMKJ2UGQ5sCX7U86qvniMcO8CsXR
+7eSkBTYpxVLENxb2zf3g22972QWuL9eHyQfuO5dca2JnenZv1aIrhTH59fX8Sw==
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/tls/x509-server-ecdsa.pem b/crypto/test/data/tls/x509-server-ecdsa.pem
new file mode 100644
index 000000000..221fce99a
--- /dev/null
+++ b/crypto/test/data/tls/x509-server-ecdsa.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqzCCAWOgAwIBAgIMVOBhgRR/e3iAhKcbMA0GCSqGSIb3DQEBCwUAMCMxITAf
+BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5MDYw
+OVoYDzIwMzUwMjEwMDkwNjA5WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz
+dCBTZXJ2ZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQzME1njDHqizStYiqf
+xC45McfdqtcDFCsyik7g7JwwGBzDI3WTP5stb8gLHwGARqkaTIDr/wau+N12bIxp
+Tj6Co3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+DwEB/wQFAwMHgAAwHQYDVR0OBBYEFOaifCD845nra+asxN59LzV1LlkxMB8GA1Ud
+IwQYMBaAFPZjr6+j4u/uDuWysUYoangpMh7pMA0GCSqGSIb3DQEBCwUAA4IBMQCc
+wMTPTd/82sDeJkN6B8M2AFfLf/0uw01/2I/UQp2rJCJu1Yps9S1foHz939o4qJA3
++kieb3eVE8rcMQHMv42hagj09LmYY1Unzdu8xJDMq7gDIph72Fjy5YFqb9je79C4
+JPOadGsAsG9OY9DxTKsHyiX3Mqztx1hUQ0mNiAyaFEDGus+ZhSGMdHj0uR1LqZL9
+9OgszZY0UomZfhwnPg2sHumdh+13RZ38w33b43LpCcyu7v05szquqJ8lnol8j10r
+6sH1xXZmb6OJIXZeHTnX5Dv1z0/R8qyG3gyVU7sP+8KVk529Q/YjIJ8YEV1LSERW
+9cKbI+8DMxVE/z01gd0YLqpPcDSfzGUTww+lMWyGQ+KDUD2bC2O4LbZhzT+ZxCPN
++mw+T5KV78wcG02PThMf
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/tls/x509-server-key-dsa.pem b/crypto/test/data/tls/x509-server-key-dsa.pem
new file mode 100644
index 000000000..d6073b31f
--- /dev/null
+++ b/crypto/test/data/tls/x509-server-key-dsa.pem
@@ -0,0 +1,15 @@
+-----BEGIN PRIVATE KEY-----
+MIICZAIBADCCAjkGByqGSM44BAEwggIsAoIBAQDW5Rnf6bmWFg75kjAsdAJ0EHG5
+o1IQdzDevP34ZChcAT1NUISUYkhFQxtW57FD+eRECg7Nb6Ykl4MvPT92k3GoKtDP
+rq6zfezD3iqARfLJOKOmsa7rKcQ+NTsioVuvDZ5OeBPt5hDwAUuMmKbLhIRX2mYT
+lF3QPWlBVpzze6KO0JSPhe5WvG5bs/BvI/NWjLBMIwXRCoPtjKdft9zVWiFhHoJ7
+p1RJG9LyXf1sC2WI/joJiuH5/6qiHUVyG43jVL6QLZJROTawEbMCNEV7l8lsT3wa
+0Em1pNw0L27lmxHklK4WGOu2G6TxgOUZ4PGsKcXV4b87Epk/XOgZay3xeiDdAiEA
+1rVh2jJpQFWVvadA5rI+9LDRycTmFpaowhMxe2sVd38CggEAIBWaI7l/55Xq4thP
+Qum/HEE6H+OiWXgHhtkr5PCPdXJyL9Il0x38s1i1gwGJ33rjJrfpzAOvwNSveGCN
+XbnN4moS2uVN3zgAliXRbS/wgBVcjbYe5Q3h21kxYzOR4AO+qc5gH7xbWaXCadQF
+GWQft3KCkq+mazGoLdR4aHnxsqOyZD6bMRohRCge/a15BYtABLEp23bhRHM64PAw
+XV5vf/8lEJ08NqaYXMC2berehKt1q6bt+uA5/oSXoKS3wOrjobUScPu8b+Y5AW7y
+MadTy2RJ9eqpjyjLNyJuEFGtruRdJy2FBh4tNYuTkp9FFp6JvBHA4rP9EAq5MgWo
+jGjZJAQiAiBhYRIk49XUmvOqUx953A+n8/KWUfyZyTHPkcIXBvW+Ig==
+-----END PRIVATE KEY-----
diff --git a/crypto/test/data/tls/x509-server-key-ecdsa.pem b/crypto/test/data/tls/x509-server-key-ecdsa.pem
new file mode 100644
index 000000000..01fe38567
--- /dev/null
+++ b/crypto/test/data/tls/x509-server-key-ecdsa.pem
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGUAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHoweAIBAQQhALoiXMjOXuPkNVT6
+g/8PnBmXj8wEvWXCyrpO+fh9EMTdoAoGCCqGSM49AwEHoUQDQgAEMzBNZ4wx6os0
+rWIqn8QuOTHH3arXAxQrMopO4OycMBgcwyN1kz+bLW/ICx8BgEapGkyA6/8Grvjd
+dmyMaU4+gg==
+-----END PRIVATE KEY-----
diff --git a/crypto/test/lib/nunit.core.dll b/crypto/test/lib/nunit.core.dll
index f58c07d42..8d99c637d 100644
--- a/crypto/test/lib/nunit.core.dll
+++ b/crypto/test/lib/nunit.core.dll
Binary files differdiff --git a/crypto/test/lib/nunit.core.interfaces.dll b/crypto/test/lib/nunit.core.interfaces.dll
index cdf50b687..70a76b21c 100644
--- a/crypto/test/lib/nunit.core.interfaces.dll
+++ b/crypto/test/lib/nunit.core.interfaces.dll
Binary files differdiff --git a/crypto/test/lib/nunit.framework.dll b/crypto/test/lib/nunit.framework.dll
index c7b1c65d9..ba484ba8c 100644
--- a/crypto/test/lib/nunit.framework.dll
+++ b/crypto/test/lib/nunit.framework.dll
Binary files differdiff --git a/crypto/test/src/asn1/test/AllTests.cs b/crypto/test/src/asn1/test/AllTests.cs
index a1ae8fd48..ad2f90362 100644
--- a/crypto/test/src/asn1/test/AllTests.cs
+++ b/crypto/test/src/asn1/test/AllTests.cs
@@ -9,24 +9,22 @@ namespace Org.BouncyCastle.Asn1.Tests
     {
         public static void Main(string[] args)
         {
-//            junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            suite().Run(el);
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
         }
 
-		public static TestSuite suite()
+        [Suite]
+		public static TestSuite Suite
         {
-            TestSuite suite = new TestSuite("ASN.1 tests");
-
-			suite.Add(new AllTests());
-
-			// TODO Add these tests to RegressionTest list
-			suite.Add(new Asn1SequenceParserTest());
-			suite.Add(new OctetStringTest());
-			suite.Add(new ParseTest());
-			suite.Add(new TimeTest());
-
-			return suite;
+            get
+            {
+                TestSuite suite = new TestSuite("ASN.1 tests");
+			    // TODO Add these tests to RegressionTest list
+			    suite.Add(new Asn1SequenceParserTest());
+			    suite.Add(new OctetStringTest());
+			    suite.Add(new ParseTest());
+			    suite.Add(new TimeTest());
+			    return suite;
+            }
         }
     }
 }
diff --git a/crypto/test/src/cms/test/AllTests.cs b/crypto/test/src/cms/test/AllTests.cs
index 1ce3b7c8d..b7ac7644b 100644
--- a/crypto/test/src/cms/test/AllTests.cs
+++ b/crypto/test/src/cms/test/AllTests.cs
@@ -9,27 +9,26 @@ namespace Org.BouncyCastle.Cms.Tests
 {
     public class AllTests
     {
-        public static void Main(
-			string[] args)
+        public static void Main(string[] args)
         {
-            //junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            suite().Run(el);
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
         }
 
-		public static TestSuite suite()
+        [Suite]
+        public static TestSuite Suite
         {
-            TestSuite suite = new TestSuite("CMS Tests");
-
-			suite.Add(new CompressedDataTest());
-            suite.Add(new CompressedDataStreamTest());
-			suite.Add(new EnvelopedDataTest());
-			suite.Add(new EnvelopedDataStreamTest());
-			suite.Add(new Rfc4134Test());
-			suite.Add(new SignedDataTest());
-			suite.Add(new SignedDataStreamTest());
-
-			return suite;
+            get
+            {
+                TestSuite suite = new TestSuite("CMS Tests");
+                suite.Add(new CompressedDataTest());
+                suite.Add(new CompressedDataStreamTest());
+                suite.Add(new EnvelopedDataTest());
+                suite.Add(new EnvelopedDataStreamTest());
+                suite.Add(new Rfc4134Test());
+                suite.Add(new SignedDataTest());
+                suite.Add(new SignedDataStreamTest());
+                return suite;
+            }
         }
     }
 }
diff --git a/crypto/test/src/crypto/io/test/AllTests.cs b/crypto/test/src/crypto/io/test/AllTests.cs
index 0296a2dc0..5c8c759f9 100644
--- a/crypto/test/src/crypto/io/test/AllTests.cs
+++ b/crypto/test/src/crypto/io/test/AllTests.cs
@@ -7,21 +7,20 @@ namespace Org.BouncyCastle.Crypto.IO.Tests
 {
 	public class AllTests
 	{
-		public static void Main(
-			string[] args)
-		{
-//            junit.textui.TestRunner.run(suite());
-			EventListener el = new NullListener();
-			suite().Run(el);
-		}
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
 
-		public static TestSuite suite()
-		{
-			TestSuite suite = new TestSuite("IO tests");
-
-			suite.Add(new CipherStreamTest());
-
-			return suite;
-		}
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("IO tests");
+                suite.Add(new CipherStreamTest());
+                return suite;
+            }
+        }
 	}
 }
diff --git a/crypto/test/src/crypto/test/AllTests.cs b/crypto/test/src/crypto/test/AllTests.cs
index 1cb1b965d..3d8ef5602 100644
--- a/crypto/test/src/crypto/test/AllTests.cs
+++ b/crypto/test/src/crypto/test/AllTests.cs
@@ -10,19 +10,24 @@ namespace Org.BouncyCastle.Crypto.Tests
 	[TestFixture]
 	public class AllTests
 	{
-		[Suite]
-		public static TestSuite Suite
-		{
-			get
-			{
-				TestSuite suite = new TestSuite("Lightweight Crypto Tests");
-				suite.Add(new AllTests());
-		        suite.Add(new GcmReorderTest());
-				return suite;
-			}
-		}
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
 
-		[Test]
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("Lightweight Crypto Tests");
+                suite.Add(new AllTests());
+                suite.Add(new GcmReorderTest());
+                return suite;
+            }
+        }
+
+        [Test]
 		public void TestCrypto()
 		{
 			foreach (Org.BouncyCastle.Utilities.Test.ITest test in RegressionTest.tests)
@@ -35,13 +40,5 @@ namespace Org.BouncyCastle.Crypto.Tests
 				}
 			}
 		}
-
-        public static void Main(
-			string[] args)
-        {
-            //junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            Suite.Run(el);
-        }
 	}
 }
diff --git a/crypto/test/src/crypto/test/CCMTest.cs b/crypto/test/src/crypto/test/CCMTest.cs
index 4a54fb4f9..8c46e11e7 100644
--- a/crypto/test/src/crypto/test/CCMTest.cs
+++ b/crypto/test/src/crypto/test/CCMTest.cs
@@ -81,7 +81,38 @@ namespace Org.BouncyCastle.Crypto.Tests
 			//
 			checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
 
-			//
+            // decryption with output specified, non-zero offset.
+            ccm.Init(false, new AeadParameters(new KeyParameter(K2), 48, N2, A2));
+
+            byte[] inBuf = new byte[C2.Length + 10];
+            byte[] outBuf = new byte[ccm.GetOutputSize(C2.Length) + 10];
+
+            Array.Copy(C2, 0, inBuf, 10, C2.Length);
+
+            int len = ccm.ProcessPacket(inBuf, 10, C2.Length, outBuf, 10);
+            byte[] output = ccm.ProcessPacket(C2, 0, C2.Length);
+
+            if (len != output.Length || !isEqual(output, outBuf, 10))
+            {
+                Fail("decryption output incorrect");
+            }
+
+            // encryption with output specified, non-zero offset.
+            ccm.Init(true, new AeadParameters(new KeyParameter(K2), 48, N2, A2));
+
+            int inLen = len;
+            inBuf = outBuf;
+            outBuf = new byte[ccm.GetOutputSize(inLen) + 10];
+
+            len = ccm.ProcessPacket(inBuf, 10, inLen, outBuf, 10);
+            output = ccm.ProcessPacket(inBuf, 10, inLen);
+
+            if (len != output.Length || !isEqual(output, outBuf, 10))
+            {
+                Fail("encryption output incorrect");
+            }
+
+            //
 			// exception tests
 			//
 
@@ -121,6 +152,17 @@ namespace Org.BouncyCastle.Crypto.Tests
 			}
 		}
 
+        private bool isEqual(byte[] exp, byte[] other, int off)
+        {
+            for (int i = 0; i != exp.Length; i++)
+            {
+                if (exp[i] != other[off + i])
+                    return false;
+            }
+
+            return true;
+        }
+
 		private void checkVectors(
 			int count,
 			CcmBlockCipher ccm,
@@ -203,7 +245,8 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 			if (!AreEqual(p, dec))
 			{
-                Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType);
+                Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType,
+                    Hex.ToHexString(p), Hex.ToHexString(dec));
             }
 
 			if (!AreEqual(t, ccm.GetMac()))
diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs
index 27d6bb0e9..0b7a0f72d 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -118,7 +118,8 @@ namespace Org.BouncyCastle.Crypto.Tests
             new SipHashTest(),
             new Poly1305Test(),
             new OcbTest(),
-            new SM3DigestTest()
+            new SM3DigestTest(),
+            new X931SignerTest()
         };
 
         public static void Main(
diff --git a/crypto/test/src/crypto/test/SRP6Test.cs b/crypto/test/src/crypto/test/SRP6Test.cs
index 3b80e2c16..6b64df924 100644
--- a/crypto/test/src/crypto/test/SRP6Test.cs
+++ b/crypto/test/src/crypto/test/SRP6Test.cs
@@ -23,15 +23,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        return new BigInteger(1, Hex.Decode(hex));
 	    }
 
-		// 1024 bit example prime from RFC5054 and corresponding generator
-		private static readonly BigInteger N_1024 = FromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
-	            + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
-	            + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
-	            + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
-	            + "FD5138FE8376435B9FC61D2FC0EB06E3");
-		private static readonly BigInteger g_1024 = BigInteger.Two;
-
-		private readonly SecureRandom random = new SecureRandom();
+        private readonly SecureRandom random = new SecureRandom();
 
 	    public override string Name
 	    {
@@ -42,9 +34,9 @@ namespace Org.BouncyCastle.Crypto.Tests
 	    {
 	    	rfc5054AppendixBTestVectors();
 
-	        testMutualVerification(N_1024, g_1024);
-	        testClientCatchesBadB(N_1024, g_1024);
-	        testServerCatchesBadA(N_1024, g_1024);
+            testMutualVerification(Srp6StandardGroups.rfc5054_1024);
+            testClientCatchesBadB(Srp6StandardGroups.rfc5054_1024);
+            testServerCatchesBadA(Srp6StandardGroups.rfc5054_1024);
 
 			testWithRandomParams(256);
 			testWithRandomParams(384);
@@ -56,8 +48,8 @@ namespace Org.BouncyCastle.Crypto.Tests
 	    	byte[] I = Encoding.UTF8.GetBytes("alice");
 	    	byte[] P = Encoding.UTF8.GetBytes("password123");
 	    	byte[] s = Hex.Decode("BEB25379D1A8581EB5A727673A2441EE");
-	    	BigInteger N = N_1024;
-	    	BigInteger g = g_1024;
+            BigInteger N = Srp6StandardGroups.rfc5054_1024.N;
+            BigInteger g = Srp6StandardGroups.rfc5054_1024.G;
 	    	BigInteger a = FromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393");
 	    	BigInteger b = FromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20");
 
@@ -148,13 +140,10 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        paramGen.Init(bits, 25, random);
 	        DHParameters parameters = paramGen.GenerateParameters();
 
-	        BigInteger g = parameters.G;
-	        BigInteger p = parameters.P;
-
-	        testMutualVerification(p, g);
+            testMutualVerification(new Srp6GroupParameters(parameters.P, parameters.G));
 		}
 
-	    private void testMutualVerification(BigInteger N, BigInteger g)
+        private void testMutualVerification(Srp6GroupParameters group)
 	    {
 	        byte[] I = Encoding.UTF8.GetBytes("username");
 	        byte[] P = Encoding.UTF8.GetBytes("password");
@@ -162,16 +151,16 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        random.NextBytes(s);
 
 	        Srp6VerifierGenerator gen = new Srp6VerifierGenerator();
-	        gen.Init(N, g, new Sha256Digest());
+	        gen.Init(group, new Sha256Digest());
 	        BigInteger v = gen.GenerateVerifier(s, I, P);
 
 	        Srp6Client client = new Srp6Client();
-	        client.Init(N, g, new Sha256Digest(), random);
+	        client.Init(group, new Sha256Digest(), random);
 
 	        Srp6Server server = new Srp6Server();
-	        server.Init(N, g, v, new Sha256Digest(), random);
+	        server.Init(group, v, new Sha256Digest(), random);
 
-	        BigInteger A = client.GenerateClientCredentials(s, I, P);
+            BigInteger A = client.GenerateClientCredentials(s, I, P);
 	        BigInteger B = server.GenerateServerCredentials();
 
 	        BigInteger clientS = client.CalculateSecret(B);
@@ -183,7 +172,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        }
 	    }
 
-	    private void testClientCatchesBadB(BigInteger N, BigInteger g)
+        private void testClientCatchesBadB(Srp6GroupParameters group)
 	    {
 	        byte[] I = Encoding.UTF8.GetBytes("username");
 	        byte[] P = Encoding.UTF8.GetBytes("password");
@@ -191,7 +180,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        random.NextBytes(s);
 
 	        Srp6Client client = new Srp6Client();
-	        client.Init(N, g, new Sha256Digest(), random);
+	        client.Init(group, new Sha256Digest(), random);
 
 	        client.GenerateClientCredentials(s, I, P);
 
@@ -207,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 	        try
 	        {
-	        	client.CalculateSecret(N);
+	        	client.CalculateSecret(group.N);
 	        	Fail("Client failed to detect invalid value for 'B'");
 	        }
 	        catch (CryptoException)
@@ -216,7 +205,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        }
 	    }
 
-	    private void testServerCatchesBadA(BigInteger N, BigInteger g)
+        private void testServerCatchesBadA(Srp6GroupParameters group)
 	    {
 	        byte[] I = Encoding.UTF8.GetBytes("username");
 	        byte[] P = Encoding.UTF8.GetBytes("password");
@@ -224,11 +213,11 @@ namespace Org.BouncyCastle.Crypto.Tests
 	        random.NextBytes(s);
 
 	        Srp6VerifierGenerator gen = new Srp6VerifierGenerator();
-	        gen.Init(N, g, new Sha256Digest());
+	        gen.Init(group, new Sha256Digest());
 	        BigInteger v = gen.GenerateVerifier(s, I, P);
 
 	        Srp6Server server = new Srp6Server();
-	        server.Init(N, g, v, new Sha256Digest(), random);
+	        server.Init(group, v, new Sha256Digest(), random);
 
 	        server.GenerateServerCredentials();
 
@@ -244,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 	        try
 	        {
-	        	server.CalculateSecret(N);
+	        	server.CalculateSecret(group.N);
 	        	Fail("Client failed to detect invalid value for 'A'");
 	        }
 	        catch (CryptoException)
diff --git a/crypto/test/src/crypto/test/X931SignerTest.cs b/crypto/test/src/crypto/test/X931SignerTest.cs
new file mode 100644
index 000000000..d03cbc8e4
--- /dev/null
+++ b/crypto/test/src/crypto/test/X931SignerTest.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class X931SignerTest
+		:   SimpleTest
+    {
+        public override string Name
+        {
+            get { return "X931Signer"; }
+        }
+
+        public override void PerformTest()
+        {
+            BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
+            BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+            BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+            BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+            BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+            BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+            BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
+            RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+            byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };
+
+            X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+            signer.Init(true, rsaPrivate);
+            signer.BlockUpdate(msg, 0, msg.Length);
+            byte[] sig = signer.GenerateSignature();
+
+            signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+            signer.Init(false, rsaPublic);
+            signer.BlockUpdate(msg, 0, msg.Length);
+            if (!signer.VerifySignature(sig))
+            {
+                Fail("X9.31 Signer failed.");
+            }
+
+            ShouldPassSignatureTest1();
+            ShouldPassSignatureTest2();
+            ShouldPassSignatureTest3();
+        }
+
+        private void ShouldPassSignatureTest1()
+        {
+            BigInteger n = new BigInteger("c9be1b28f8caccca65d86cc3c9bbcc13eccc059df3b80bd2292b811eff3aa0dd75e1e85c333b8e3fa9bed53bb20f5359ff4e6900c5e9a388e3a4772a583a79e2299c76582c2b27694b65e9ba22e66bfb817f8b70b22206d7d8ae488c86dbb7137c26d5eff9b33c90e6cee640630313b7a715802e15142fef498c404a8de19674974785f0f852e2d470fe85a2e54ffca9f5851f672b71df691785a5cdabe8f14aa628942147de7593b2cf962414a5b59c632c4e14f1768c0ab2e9250824beea60a3529f11bf5e070ce90a47686eb0be1086fb21f0827f55295b4a48307db0b048c05a4aec3f488c576ca6f1879d354224c7e84cbcd8e76dd217a3de54dba73c35", 16);
+            BigInteger e = new BigInteger("e75b1b", 16);
+            byte[] msg = Hex.Decode("5bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce");
+            byte[] sig = Hex.Decode("0fe8bb8e3109a1eb7489ef35bf4c1a0780071da789c8bd226a4170538eafefdd30b732d628f0e87a0b9450051feae9754d4fb61f57862d10f0bacc4f660d13281d0cd1141c006ade5186ff7d961a4c6cd0a4b352fc1295c5afd088f80ac1f8e192ef116a010a442655fe8ff5eeacea15807906fb0f0dfa86e680d4c005872357f7ece9aa4e20b15d5f709b30f08648ecaa34f2fbf54eb6b414fa2ff6f87561f70163235e69ccb4ac82a2e46d3be214cc2ef5263b569b2d8fd839b21a9e102665105ea762bda25bb446cfd831487a6b846100dee113ae95ae64f4af22c428c87bab809541c962bb3a56d4c86588e0af4ebc7fcc66dadced311051356d3ea745f7");
+
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+            X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+
+            signer.Init(false, rsaPublic);
+
+            signer.BlockUpdate(msg, 0, msg.Length);
+
+            if (!signer.VerifySignature(sig))
+            {
+                Fail("RSA X931 verify test 1 failed.");
+            }
+        }
+
+        private void ShouldPassSignatureTest2()
+        {
+            BigInteger n = new BigInteger("b746ba6c3c0be64bbe33aa55b2929b0af4e86d773d44bfe5914db9287788c4663984b61a418d2eecca30d752ff6b620a07ec72eeb2b422d2429da352407b99982800b9dd7697be6a7b1baa98ca5f4fc2fe33400f20b9dba337ac25c987804165d4a6e0ee4d18eabd6de5abdfe578cae6713ff91d16c80a5bb20217fe614d9509e75a43e1825327b9da8f0a9f6eeaa1c04b69fb4bacc073569fff4ab491becbe6d0441d437fc3fa823239c4a0f75321666b68dd3f66e2dd394089a15bcc288a68a4eb0a48e17d639743b9dea0a91cc35820544732aff253f8ca9967c609dc01c2f8cd0313a7a91cfa94ff74289a1d2b6f19d1811f4b9a65f4cce9e5759b4cc64f", 16);
+            BigInteger e = new BigInteger("dcbbdb", 16);
+            byte[] msg = Hex.Decode("a5d3c8a060f897bbbc20ae0955052f37fbc70986b6e11c65075c9f457142bfa93856897c69020aa81a91b5e4f39e05cdeecc63395ab849c8262ca8bc5c96870aecb8edb0aba0024a9bdb71e06de6100344e5c318bc979ef32b8a49a8278ba99d4861bce42ebbc5c8c666aaa6cac39aff8779f2cae367620f9edd4cb1d80b6c8c");
+            byte[] sig = Hex.Decode("39fbbd1804c689a533b0043f84da0f06081038c0fbf31e443e46a05e58f50de5198bbca40522afefaba3aed7082a6cb93b1da39f1f5a42246bf64930781948d300549bef0f8d554ecfca60a1b1ecba95a7014ee4545ad4f0c4e3a31942c6738b4ccd6244b6a21267dadf0826a5f713f13b1f5a9ab8501d957a26d4948278ac67851071a315674bdab173bfef2c2690c8373da6bf3d69f30c0e5da8883de872f59521b40793854085641adf98d13db991c5d0a8aaa0222934fa33332e90ef0b954e195cb267d6ffb36c96e14d1ec7b915a87598b4461a3146566354dc2ae748c84ee0cd46543b53ebff8cdf47725b280a1f799fb6ebb4a31ad2bdd5178250f83a");
+
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+            X931Signer signer = new X931Signer(new RsaEngine(), new Sha224Digest());
+
+            signer.Init(false, rsaPublic);
+
+            signer.BlockUpdate(msg, 0, msg.Length);
+
+            if (!signer.VerifySignature(sig))
+            {
+                Fail("RSA X931 verify test 2 failed.");
+            }
+        }
+
+        private void ShouldPassSignatureTest3()
+        {
+            BigInteger n = new BigInteger("dcb5686a3d2063a3f9cf7b9b32d2d3765b4c449b09b4960245a9111cd3b0cbd3260496885b8e1fa5db33b03efcc759d9c1afe29d93c6faebc7e0efada334b5b9a29655e2da2c8f11103d8203be311feab7ae88e9f1b2ec7d8fc655d77202b1681dd9717ec0f525b35584987e19539635a1ed23ca482a00149c609a23dc1645fd", 16);
+            BigInteger e = new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc9f7", 16);
+            BigInteger d = new BigInteger("189d6345099098992e0c9ca5f281e1338092342fa0acc85cc2a111f30f9bd2fb4753cd1a48ef0ddca9bf1af33ec76fb2e23a9fb4896c26f2235b516f7c05ef7ae81e70f4b491a5fedba9b935e9c76d761a813ce7776ff8a1e5efe1166ff2eca26aa900da88c908d51af9de26977fe39719cc781df32216fa41b838f0c63803c3", 16);
+
+            byte[] msg = Hex.Decode("911475c6e210ef4ac65b6fe8d2bfe5e01b959771b137c4ef69b88716e0d2ff9ebc1fad0f358c1dd7d50cc99a7b893ac9a6207076f08d8467d9e48c69c683bfe64a44dabaa3f7c243880f6ab7229bf7bb587822314fc5de5131983bfb2eef8b4bc1eac36f353724b567cd1ae8cddd64ddb7057549d5c81ad5fa3b5e751f00abf5");
+            byte[] sig = Hex.Decode("02c50ec0ac8a7f38ef5630c396964d6a6daaa7e3083ab5b57fa2a2632f3b70e2e85c8456cd774d45d7e44fcb063f0f04fff9f1e3adfda11272535a92cb59320b190b5ee4261f23d6ceaa925df3a7bfa42e26bf61ea9645d9d64b3c90a820802768a6e209c9f83705375a3867afccc037e8242a98fa4c3db6b2d9877754d47289");
+
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+            X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+
+            signer.Init(true, new RsaKeyParameters(true, n, d));
+
+            signer.BlockUpdate(msg, 0, msg.Length);
+
+            byte[] s = signer.GenerateSignature();
+
+            if (!Arrays.AreEqual(sig, s))
+            {
+                Fail("RSA X931 sig test 3 failed.");
+            }
+
+            signer.Init(false, rsaPublic);
+
+            signer.BlockUpdate(msg, 0, msg.Length);
+
+            if (!signer.VerifySignature(sig))
+            {
+                Fail("RSA X931 verify test 3 failed.");
+            }
+        }
+
+        public static void Main(string[] args)
+        {
+            RunTest(new X931SignerTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs
new file mode 100644
index 000000000..bc99ccc63
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class DtlsProtocolTest
+    {
+        [Test]
+        public void TestClientServer()
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom);
+            DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom);
+
+            MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+            Server server = new Server(serverProtocol, network.Server);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            DatagramTransport clientTransport = network.Client;
+
+            clientTransport = new UnreliableDatagramTransport(clientTransport, secureRandom, 0, 0);
+
+            clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out);
+
+            MockDtlsClient client = new MockDtlsClient(null);
+
+            DtlsTransport dtlsClient = clientProtocol.Connect(client, clientTransport);
+
+            for (int i = 1; i <= 10; ++i)
+            {
+                byte[] data = new byte[i];
+                Arrays.Fill(data, (byte)i);
+                dtlsClient.Send(data, 0, data.Length);
+            }
+
+            byte[] buf = new byte[dtlsClient.GetReceiveLimit()];
+            while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0)
+            {
+            }
+
+            dtlsClient.Close();
+
+            server.Shutdown(serverThread);
+        }
+
+        internal class Server
+        {
+            private readonly DtlsServerProtocol mServerProtocol;
+            private readonly DatagramTransport mServerTransport;
+            private volatile bool isShutdown = false;
+
+            internal Server(DtlsServerProtocol serverProtocol, DatagramTransport serverTransport)
+            {
+                this.mServerProtocol = serverProtocol;
+                this.mServerTransport = serverTransport;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockDtlsServer server = new MockDtlsServer();
+                    DtlsTransport dtlsServer = mServerProtocol.Accept(server, mServerTransport);
+                    byte[] buf = new byte[dtlsServer.GetReceiveLimit()];
+                    while (!isShutdown)
+                    {
+                        int length = dtlsServer.Receive(buf, 0, buf.Length, 1000);
+                        if (length >= 0)
+                        {
+                            dtlsServer.Send(buf, 0, length);
+                        }
+                    }
+                    dtlsServer.Close();
+                }
+                catch (Exception e)
+                {
+                    Console.Error.WriteLine(e.StackTrace);
+                }
+            }
+
+            internal void Shutdown(Thread serverThread)
+            {
+                if (!isShutdown)
+                {
+                    isShutdown = true;
+                    serverThread.Join();
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
new file mode 100644
index 000000000..d4af04fac
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs
@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class DtlsTestCase
+    {
+        private static void CheckDtlsVersion(ProtocolVersion version)
+        {
+            if (version != null && !version.IsDtls)
+                throw new InvalidOperationException("Non-DTLS version");
+        }
+
+        [Test, TestCaseSource(typeof(DtlsTestSuite), "Suite")]
+        public void RunTest(TlsTestConfig config)
+        {
+            CheckDtlsVersion(config.clientMinimumVersion);
+            CheckDtlsVersion(config.clientOfferVersion);
+            CheckDtlsVersion(config.serverMaximumVersion);
+            CheckDtlsVersion(config.serverMinimumVersion);
+
+            SecureRandom secureRandom = new SecureRandom();
+
+            DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom);
+            DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom);
+
+            MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+            TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
+            TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
+
+            Server server = new Server(this, serverProtocol, network.Server, serverImpl);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            Exception caught = null;
+            try
+            {
+                DatagramTransport clientTransport = network.Client;
+
+                if (TlsTestConfig.DEBUG)
+                {
+                    clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out);
+                }
+
+                DtlsTransport dtlsClient = clientProtocol.Connect(clientImpl, clientTransport);
+
+                for (int i = 1; i <= 10; ++i)
+                {
+                    byte[] data = new byte[i];
+                    Arrays.Fill(data, (byte)i);
+                    dtlsClient.Send(data, 0, data.Length);
+                }
+    
+                byte[] buf = new byte[dtlsClient.GetReceiveLimit()];
+                while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0)
+                {
+                }
+    
+                dtlsClient.Close();
+            }
+            catch (Exception e)
+            {
+                caught = e;
+                LogException(caught);
+            }
+
+            server.Shutdown(serverThread);
+
+            // TODO Add checks that the various streams were closed
+
+            Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end");
+            Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end");
+
+            Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description");
+            Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description");
+
+            if (config.expectFatalAlertConnectionEnd == -1)
+            {
+                Assert.IsNull(caught, "Unexpected client exception");
+                Assert.IsNull(server.mCaught, "Unexpected server exception");
+            }
+        }
+
+        protected void LogException(Exception e)
+        {
+            if (TlsTestConfig.DEBUG)
+            {
+                Console.Error.WriteLine(e.StackTrace);
+            }
+        }
+
+        internal class Server
+        {
+            private readonly DtlsTestCase mOuter;
+            private readonly DtlsServerProtocol 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)
+            {
+                this.mOuter = outer;
+                this.mServerProtocol = serverProtocol;
+                this.mServerTransport = serverTransport;
+                this.mServerImpl = serverImpl;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    DtlsTransport dtlsServer = mServerProtocol.Accept(mServerImpl, mServerTransport);
+                    byte[] buf = new byte[dtlsServer.GetReceiveLimit()];
+                    while (!isShutdown)
+                    {
+                        int length = dtlsServer.Receive(buf, 0, buf.Length, 100);
+                        if (length >= 0)
+                        {
+                            dtlsServer.Send(buf, 0, length);
+                        }
+                    }
+                    dtlsServer.Close();
+                }
+                catch (Exception e)
+                {
+                    mCaught = e;
+                    mOuter.LogException(mCaught);
+                }
+            }
+
+            internal void Shutdown(Thread serverThread)
+            {
+                if (!isShutdown)
+                {
+                    isShutdown = true;
+                    serverThread.Interrupt();
+                    serverThread.Join();
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
new file mode 100644
index 000000000..eb9d42e5f
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class DtlsTestSuite
+    {
+        // Make the access to constants less verbose 
+        internal class C : TlsTestConfig {}
+
+        public DtlsTestSuite()
+        {
+        }
+
+        public static IEnumerable Suite()
+        {
+            IList testSuite = new ArrayList();
+
+            AddFallbackTests(testSuite);
+            AddVersionTests(testSuite, ProtocolVersion.DTLSv10);
+            AddVersionTests(testSuite, ProtocolVersion.DTLSv12);
+
+            return testSuite;
+        }
+
+        private static void AddFallbackTests(IList testSuite)
+        {
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+                c.clientFallback = true;
+
+                testSuite.Add(new TestCaseData(c).SetName("FallbackGood"));
+            }
+
+            /*
+             * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
+             * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
+             * alerts being raised
+             */
+
+            //{
+            //    TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+            //    c.clientOfferVersion = ProtocolVersion.DTLSv10;
+            //    c.clientFallback = true;
+            //    c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
+
+            //    testSuite.Add(new TestCaseData(c).SetName("FallbackBad"));
+            //}
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12);
+                c.clientOfferVersion = ProtocolVersion.DTLSv10;
+
+                testSuite.Add(new TestCaseData(c).SetName("FallbackNone"));
+            }
+        }
+
+        private static void AddVersionTests(IList testSuite, ProtocolVersion version)
+        {
+            string prefix = version.ToString()
+                .Replace(" ", "")
+                .Replace("\\", "")
+                .Replace(".", "")
+                + "_";
+
+            /*
+             * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
+             * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
+             * alerts being raised
+             */
+
+            //{
+            //    TlsTestConfig c = CreateDtlsTestConfig(version);
+            //    c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+            //    c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
+
+            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify"));
+            //}
+
+            //{
+            //    TlsTestConfig c = CreateDtlsTestConfig(version);
+            //    c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+            //    c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
+
+            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate"));
+            //}
+
+            //{
+            //    TlsTestConfig c = CreateDtlsTestConfig(version);
+            //    c.clientAuth = C.CLIENT_AUTH_NONE;
+            //    c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+            //    c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
+
+            //    testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined"));
+            //}
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault"));
+            }
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.serverCertReq = C.SERVER_CERT_REQ_NONE;
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq"));
+            }
+
+            {
+                TlsTestConfig c = CreateDtlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_NONE;
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined"));
+            }
+        }
+
+        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.serverMaximumVersion = version;
+            c.serverMinimumVersion = ProtocolVersion.DTLSv10;
+            return c;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs b/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs
new file mode 100644
index 000000000..a26c5bdbf
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs
@@ -0,0 +1,86 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class LoggingDatagramTransport
+        :   DatagramTransport
+    {
+        private static readonly string HEX_CHARS = "0123456789ABCDEF";
+
+        private readonly DatagramTransport transport;
+        private readonly TextWriter output;
+        private readonly long launchTimestamp;
+
+        public LoggingDatagramTransport(DatagramTransport transport, TextWriter output)
+        {
+            this.transport = transport;
+            this.output = output;
+            this.launchTimestamp = DateTimeUtilities.CurrentUnixMs();
+        }
+
+        public virtual int GetReceiveLimit()
+        {
+            return transport.GetReceiveLimit();
+        }
+
+        public virtual int GetSendLimit()
+        {
+            return transport.GetSendLimit();
+        }
+
+        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
+        {
+            int length = transport.Receive(buf, off, len, waitMillis);
+            if (length >= 0)
+            {
+                DumpDatagram("Received", buf, off, length);
+            }
+            return length;
+        }
+
+        public virtual void Send(byte[] buf, int off, int len)
+        {
+            DumpDatagram("Sending", buf, off, len);
+            transport.Send(buf, off, len);
+        }
+
+        public virtual void Close()
+        {
+        }
+
+        private void DumpDatagram(string verb, byte[] buf, int off, int len)
+        {
+            long timestamp = DateTimeUtilities.CurrentUnixMs() - launchTimestamp;
+            StringBuilder sb = new StringBuilder("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:");
+            for (int pos = 0; pos < len; ++pos)
+            {
+                if (pos % 16 == 0)
+                {
+                    sb.Append(Environment.NewLine);
+                    sb.Append("    ");
+                }
+                else if (pos % 16 == 8)
+                {
+                    sb.Append('-');
+                }
+                else
+                {
+                    sb.Append(' ');
+                }
+                int val = buf[off + pos] & 0xFF;
+                sb.Append(HEX_CHARS[val >> 4]);
+                sb.Append(HEX_CHARS[val & 0xF]);
+            }
+            Dump(sb.ToString());
+        }
+
+        private void Dump(string s)
+        {
+            lock (this) output.WriteLine(s);
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs
new file mode 100644
index 000000000..48df36ca9
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Net;
+using System.Threading;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class MockDatagramAssociation
+    {
+        private int mtu;
+        private MockDatagramTransport client, server;
+
+        public MockDatagramAssociation(int mtu)
+        {
+            this.mtu = mtu;
+
+            IList clientQueue = new ArrayList();
+            IList serverQueue = new ArrayList();
+
+            this.client = new MockDatagramTransport(this, clientQueue, serverQueue);
+            this.server = new MockDatagramTransport(this, serverQueue, clientQueue);
+        }
+
+        public virtual DatagramTransport Client
+        {
+            get { return client; }
+        }
+
+        public virtual DatagramTransport Server
+        {
+            get { return server; }
+        }
+
+        private class MockDatagramTransport
+            :   DatagramTransport
+        {
+            private readonly MockDatagramAssociation mOuter;
+
+            private IList receiveQueue, sendQueue;
+
+            internal MockDatagramTransport(MockDatagramAssociation outer, IList receiveQueue, IList sendQueue)
+            {
+                this.mOuter = outer;
+                this.receiveQueue = receiveQueue;
+                this.sendQueue = sendQueue;
+            }
+
+            public virtual int GetReceiveLimit()
+            {
+                return mOuter.mtu;
+            }
+
+            public virtual int GetSendLimit()
+            {
+                return mOuter.mtu;
+            }
+
+            public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
+            {
+                lock (receiveQueue)
+                {
+                    if (receiveQueue.Count < 1)
+                    {
+                        try
+                        {
+                            Monitor.Wait(receiveQueue, waitMillis);
+                        }
+                        catch (ThreadInterruptedException)
+                        {
+                            // TODO Keep waiting until full wait expired?
+                        }
+                        if (receiveQueue.Count < 1)
+                        {
+                            return -1;
+                        }
+                    }
+                    byte[] packet = (byte[])receiveQueue[0];
+                    receiveQueue.RemoveAt(0);
+                    int copyLength = System.Math.Min(len, packet.Length);
+                    Array.Copy(packet, 0, buf, off, copyLength);
+                    return copyLength;
+                }
+            }
+
+            public virtual void Send(byte[] buf, int off, int len)
+            {
+                if (len > mOuter.mtu)
+                {
+                    // TODO Simulate rejection?
+                }
+
+                byte[] packet = Arrays.CopyOfRange(buf, off, off + len);
+
+                lock (sendQueue)
+                {
+                    sendQueue.Add(packet);
+                    Monitor.PulseAll(sendQueue);
+                }
+            }
+
+            public virtual void Close()
+            {
+                // TODO?
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
new file mode 100644
index 000000000..e3c604db7
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class MockDtlsClient
+        :   DefaultTlsClient
+    {
+        protected TlsSession mSession;
+
+        public MockDtlsClient(TlsSession session)
+        {
+            this.mSession = session;
+        }
+
+        public override TlsSession GetSessionToResume()
+        {
+            return this.mSession;
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        public override ProtocolVersion ClientVersion
+        {
+            get { return ProtocolVersion.DTLSv12; }
+        }
+
+        public override ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.DTLSv10; }
+        }
+
+        //public override int[] GetCipherSuites()
+        //{
+        //    return Arrays.Concatenate(base.GetCipherSuites(),
+        //        new int[]
+        //        {
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+        //            CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+        //            CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+        //        });
+        //}
+
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+            TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
+            TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
+            TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+            TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            return clientExtensions;
+        }
+
+        public override void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            base.NotifyServerVersion(serverVersion);
+
+            Console.WriteLine("Negotiated " + serverVersion);
+        }
+
+        public override TlsAuthentication GetAuthentication()
+        {
+            return new MyTlsAuthentication(mContext);
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            TlsSession newSession = mContext.ResumableSession;
+            if (newSession != null)
+            {
+                byte[] newSessionID = newSession.SessionID;
+                string hex = Hex.ToHexString(newSessionID);
+
+                if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID))
+                {
+                    Console.WriteLine("Resumed session: " + hex);
+                }
+                else
+                {
+                    Console.WriteLine("Established session: " + hex);
+                }
+
+                this.mSession = newSession;
+            }
+        }
+
+        internal class MyTlsAuthentication
+            :   TlsAuthentication
+        {
+            private readonly TlsContext mContext;
+
+            internal MyTlsAuthentication(TlsContext context)
+            {
+                this.mContext = context;
+            }
+
+            public virtual void NotifyServerCertificate(Certificate serverCertificate)
+            {
+                X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+                Console.WriteLine("DTLS client received server certificate chain of length " + chain.Length);
+                for (int i = 0; i != chain.Length; i++)
+                {
+                    X509CertificateStructure entry = chain[i];
+                    // TODO Create fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                        + entry.Subject + ")");
+                }
+            }
+
+            public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+            {
+                byte[] certificateTypes = certificateRequest.CertificateTypes;
+                if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
+                    return null;
+
+                return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms,
+                    SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem");
+            }
+        };
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockDtlsServer.cs b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs
new file mode 100644
index 000000000..19062181b
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class MockDtlsServer
+        :   DefaultTlsServer
+    {
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("DTLS server raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("DTLS server received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        protected override int[] GetCipherSuites()
+        {
+            return Arrays.Concatenate(base.GetCipherSuites(),
+                new int[]
+                {
+                    CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+                });
+        }
+
+        public override CertificateRequest GetCertificateRequest()
+        {
+            byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign,
+                ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign };
+
+            IList serverSigAlgs = null;
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
+            {
+                serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
+            }
+
+            IList certificateAuthorities = new ArrayList();
+            certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject);
+
+            return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities);
+        }
+
+        public override void NotifyClientCertificate(Certificate clientCertificate)
+        {
+            X509CertificateStructure[] chain = clientCertificate.GetCertificateList();
+            Console.WriteLine("DTLS server received client certificate chain of length " + chain.Length);
+            for (int i = 0; i != chain.Length; i++)
+            {
+                X509CertificateStructure entry = chain[i];
+                // TODO Create fingerprint based on certificate signature algorithm digest
+                Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                    + entry.Subject + ")");
+            }
+        }
+
+        protected override ProtocolVersion MaximumVersion
+        {
+            get { return ProtocolVersion.DTLSv12; }
+        }
+
+        protected override ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.DTLSv10; }
+        }
+
+        protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
+        {
+            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[] { "x509-server.pem", "x509-ca.pem" },
+                "x509-server-key.pem");
+        }
+
+        protected override TlsSignerCredentials GetRsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+                "x509-server.pem", "x509-server-key.pem");
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs
new file mode 100644
index 000000000..dfc0e93a0
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockPskTlsClient
+        :   PskTlsClient
+    {
+        internal TlsSession mSession;
+
+        internal MockPskTlsClient(TlsSession session)
+            :   this(session, new BasicTlsPskIdentity("client", new byte[16]))
+        {
+        }
+
+        internal MockPskTlsClient(TlsSession session, TlsPskIdentity pskIdentity)
+            :   base(pskIdentity)
+        {
+            this.mSession = session;
+        }
+
+        public override TlsSession GetSessionToResume()
+        {
+            return this.mSession;
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-PSK client raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-PSK client received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            TlsSession newSession = mContext.ResumableSession;
+            if (newSession != null)
+            {
+                byte[] newSessionID = newSession.SessionID;
+                string hex = Hex.ToHexString(newSessionID);
+
+                if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID))
+                {
+                    Console.WriteLine("Resumed session: " + hex);
+                }
+                else
+                {
+                    Console.WriteLine("Established session: " + hex);
+                }
+
+                this.mSession = newSession;
+            }
+        }
+
+        public override int[] GetCipherSuites()
+        {
+            return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+                CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+                CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA };
+        }
+
+        public override ProtocolVersion MinimumVersion
+        {
+	        get { return ProtocolVersion.TLSv12; }
+        }
+
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+            TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
+            return clientExtensions;
+        }
+
+        public override void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            base.NotifyServerVersion(serverVersion);
+
+            Console.WriteLine("TLS-PSK client negotiated " + serverVersion);
+        }
+
+        public override TlsAuthentication GetAuthentication()
+        {
+            return new MyTlsAuthentication(mContext);
+        }
+
+        internal class MyTlsAuthentication
+            :   ServerOnlyTlsAuthentication
+        {
+            private readonly TlsContext mContext;
+
+            internal MyTlsAuthentication(TlsContext context)
+            {
+                this.mContext = context;
+            }
+
+            public override void NotifyServerCertificate(Certificate serverCertificate)
+            {
+                X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+                Console.WriteLine("TLS-PSK client received server certificate chain of length " + chain.Length);
+                for (int i = 0; i != chain.Length; i++)
+                {
+                    X509CertificateStructure entry = chain[i];
+                    // TODO Create fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                        + entry.Subject + ")");
+                }
+            }
+        };
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs
new file mode 100644
index 000000000..7394a2077
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockPskTlsServer
+        :   PskTlsServer
+    {
+        internal MockPskTlsServer()
+            :   base(new MyIdentityManager())
+        {
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-PSK server raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-PSK server received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            byte[] pskIdentity = mContext.SecurityParameters.PskIdentity;
+            if (pskIdentity != null)
+            {
+                string name = Strings.FromUtf8ByteArray(pskIdentity);
+                Console.WriteLine("TLS-PSK server completed handshake for PSK identity: " + name);
+            }
+        }
+
+        protected override int[] GetCipherSuites()
+        {
+            return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+                CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+                CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA };
+        }
+
+        protected override ProtocolVersion MaximumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        protected override ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        public override ProtocolVersion GetServerVersion()
+        {
+            ProtocolVersion serverVersion = base.GetServerVersion();
+
+            Console.WriteLine("TLS-PSK server negotiated " + serverVersion);
+
+            return serverVersion;
+        }
+
+        protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
+        {
+            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"},
+                "x509-server-key.pem");
+        }
+
+        internal class MyIdentityManager
+            :   TlsPskIdentityManager
+        {
+            public virtual byte[] GetHint()
+            {
+                return Strings.ToUtf8ByteArray("hint");
+            }
+
+            public virtual byte[] GetPsk(byte[] identity)
+            {
+                if (identity != null)
+                {
+                    string name = Strings.FromUtf8ByteArray(identity);
+                    if (name.Equals("client"))
+                    {
+                        return new byte[16];
+                    }
+                }
+                return null;
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs
new file mode 100644
index 000000000..8a6b9f496
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockSrpTlsClient
+        :   SrpTlsClient
+    {
+        internal TlsSession mSession;
+
+        internal MockSrpTlsClient(TlsSession session, byte[] identity, byte[] password)
+            :   base(identity, password)
+        {
+            this.mSession = session;
+        }
+
+        public override TlsSession GetSessionToResume()
+        {
+            return this.mSession;
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-SRP client raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-SRP client received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            TlsSession newSession = mContext.ResumableSession;
+            if (newSession != null)
+            {
+                byte[] newSessionID = newSession.SessionID;
+                string hex = Hex.ToHexString(newSessionID);
+
+                if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID))
+                {
+                    Console.WriteLine("Resumed session: " + hex);
+                }
+                else
+                {
+                    Console.WriteLine("Established session: " + hex);
+                }
+
+                this.mSession = newSession;
+            }
+        }
+
+        public override ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+            TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
+            return clientExtensions;
+        }
+
+        public override void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            base.NotifyServerVersion(serverVersion);
+
+            Console.WriteLine("TLS-SRP client negotiated " + serverVersion);
+        }
+
+        public override TlsAuthentication GetAuthentication()
+        {
+            return new MyTlsAuthentication(mContext);
+        }
+
+        internal class MyTlsAuthentication
+            : ServerOnlyTlsAuthentication
+        {
+            private readonly TlsContext mContext;
+
+            internal MyTlsAuthentication(TlsContext context)
+            {
+                this.mContext = context;
+            }
+
+            public override void NotifyServerCertificate(Certificate serverCertificate)
+            {
+                X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+                Console.WriteLine("TLS-SRP client received server certificate chain of length " + chain.Length);
+                for (int i = 0; i != chain.Length; i++)
+                {
+                    X509CertificateStructure entry = chain[i];
+                    // TODO Create fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                        + entry.Subject + ")");
+                }
+            }
+        };
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs
new file mode 100644
index 000000000..c15f63e0b
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Agreement.Srp;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockSrpTlsServer
+        :   SrpTlsServer
+    {
+        internal static readonly Srp6GroupParameters TEST_GROUP = Srp6StandardGroups.rfc5054_1024;
+        internal static readonly byte[] TEST_IDENTITY = Strings.ToUtf8ByteArray("client");
+        internal static readonly byte[] TEST_PASSWORD = Strings.ToUtf8ByteArray("password");
+        internal static readonly byte[] TEST_SALT = Strings.ToUtf8ByteArray("salt");
+        internal static readonly byte[] TEST_SEED_KEY = Strings.ToUtf8ByteArray("seed_key");
+
+        internal MockSrpTlsServer()
+            :   base(new MyIdentityManager())
+        {
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-SRP server raised alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS-SRP server received alert: " + AlertLevel.GetText(alertLevel)
+                + ", " + AlertDescription.GetText(alertDescription));
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            byte[] srpIdentity = mContext.SecurityParameters.SrpIdentity;
+            if (srpIdentity != null)
+            {
+                string name = Strings.FromUtf8ByteArray(srpIdentity);
+                Console.WriteLine("TLS-SRP server completed handshake for SRP identity: " + name);
+            }
+        }
+
+        protected override ProtocolVersion MaximumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        protected override ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        public override ProtocolVersion GetServerVersion()
+        {
+            ProtocolVersion serverVersion = base.GetServerVersion();
+
+            Console.WriteLine("TLS-SRP server negotiated " + serverVersion);
+
+            return serverVersion;
+        }
+
+        protected override TlsSignerCredentials GetDsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa,
+                "x509-server-dsa.pem", "x509-server-key-dsa.pem");
+        }
+
+        protected override TlsSignerCredentials GetRsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+                "x509-server.pem", "x509-server-key.pem");
+        }
+
+        internal class MyIdentityManager
+            :   TlsSrpIdentityManager
+        {
+            protected SimulatedTlsSrpIdentityManager unknownIdentityManager = SimulatedTlsSrpIdentityManager.GetRfc5054Default(
+                TEST_GROUP, TEST_SEED_KEY);
+
+            public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity)
+            {
+                if (Arrays.AreEqual(TEST_IDENTITY, identity))
+                {
+                    Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator();
+                    verifierGenerator.Init(TEST_GROUP, TlsUtilities.CreateHash(HashAlgorithm.sha1));
+
+                    BigInteger verifier = verifierGenerator.GenerateVerifier(TEST_SALT, identity, TEST_PASSWORD);
+
+                    return new TlsSrpLoginParameters(TEST_GROUP, verifier, TEST_SALT);
+                }
+
+                return unknownIdentityManager.GetLoginParameters(identity);
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
index a458e32e6..7c1198632 100644
--- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs
+++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs
@@ -45,25 +45,24 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 + ", " + AlertDescription.GetText(alertDescription));
         }
 
-        public override int[] GetCipherSuites()
-        {
-            return Arrays.Concatenate(base.GetCipherSuites(),
-                new int[]
-                {
-                    CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-                    CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
-                    CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
-                    CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
-                    CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
-                });
-        }
+        //public override int[] GetCipherSuites()
+        //{
+        //    return Arrays.Concatenate(base.GetCipherSuites(),
+        //        new int[]
+        //        {
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+        //            CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+        //            CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+        //            CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+        //        });
+        //}
 
         public override IDictionary GetClientExtensions()
         {
             IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
             TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
-            // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though)
-//            TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
+            TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions);
             TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
             TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
             return clientExtensions;
@@ -121,8 +120,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 for (int i = 0; i != chain.Length; i++)
                 {
                     X509CertificateStructure entry = chain[i];
-                    // TODO Create Fingerprint based on certificate signature algorithm digest
-                    Console.WriteLine("    Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                    // TODO Create fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
                         + entry.Subject + ")");
                 }
             }
@@ -133,27 +132,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
                     return null;
 
-                SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
-                IList sigAlgs = certificateRequest.SupportedSignatureAlgorithms;
-                if (sigAlgs != null)
-                {
-                    foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs)
-                    {
-                        if (sigAlg.Signature == SignatureAlgorithm.rsa)
-                        {
-                            signatureAndHashAlgorithm = sigAlg;
-                            break;
-                        }
-                    }
-
-                    if (signatureAndHashAlgorithm == null)
-                    {
-                        return null;
-                    }
-                }
-
-                return TlsTestUtilities.LoadSignerCredentials(mContext, new string[] { "x509-client.pem", "x509-ca.pem" },
-                    "x509-client-key.pem", signatureAndHashAlgorithm);
+                return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms,
+                    SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem");
             }
         };
     }
diff --git a/crypto/test/src/crypto/tls/test/MockTlsServer.cs b/crypto/test/src/crypto/tls/test/MockTlsServer.cs
index 14d6b9839..8fce95d63 100644
--- a/crypto/test/src/crypto/tls/test/MockTlsServer.cs
+++ b/crypto/test/src/crypto/tls/test/MockTlsServer.cs
@@ -61,29 +61,19 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
 
         public override CertificateRequest GetCertificateRequest()
         {
-            IList serverSigAlgs = null;
+            byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign,
+                ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign };
 
+            IList serverSigAlgs = null;
             if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
             {
-                byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
-                    HashAlgorithm.sha224, HashAlgorithm.sha1 };
-                byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa };
-
-                serverSigAlgs = new ArrayList();
-                for (int i = 0; i < hashAlgorithms.Length; ++i)
-                {
-                    for (int j = 0; j < signatureAlgorithms.Length; ++j)
-                    {
-                        serverSigAlgs.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i],
-                            signatureAlgorithms[j]));
-                    }
-                }
+                serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
             }
 
             IList certificateAuthorities = new ArrayList();
             certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject);
 
-            return new CertificateRequest(new byte[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
+            return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities);
         }
 
         public override void NotifyClientCertificate(Certificate clientCertificate)
@@ -101,37 +91,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
 
         protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
         {
-            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"},
+            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" },
                 "x509-server-key.pem");
         }
 
         protected override TlsSignerCredentials GetRsaSignerCredentials()
         {
-            /*
-             * TODO Note that this code fails to provide default value for the client supported
-             * algorithms if it wasn't sent.
-             */
-            SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
-            IList sigAlgs = mSupportedSignatureAlgorithms;
-            if (sigAlgs != null)
-            {
-                foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs)
-                {
-                    if (sigAlg.Signature == SignatureAlgorithm.rsa)
-                    {
-                        signatureAndHashAlgorithm = sigAlg;
-                        break;
-                    }
-                }
-
-                if (signatureAndHashAlgorithm == null)
-                {
-                    return null;
-                }
-            }
-
-            return TlsTestUtilities.LoadSignerCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"},
-                "x509-server-key.pem", signatureAndHashAlgorithm);
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+                "x509-server.pem", "x509-server-key.pem");
         }
     }
 }
diff --git a/crypto/test/src/crypto/tls/test/NetworkStream.cs b/crypto/test/src/crypto/tls/test/NetworkStream.cs
new file mode 100644
index 000000000..04de81e13
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/NetworkStream.cs
@@ -0,0 +1,101 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class NetworkStream
+        :   Stream
+    {
+        private readonly Stream mInner;
+        private bool mClosed = false;
+
+        internal NetworkStream(Stream inner)
+        {
+            this.mInner = inner;
+        }
+
+        internal virtual bool IsClosed
+        {
+            get { lock (this) return mClosed; }
+        }
+
+        public override bool CanRead
+        {
+            get { return mInner.CanRead; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return mInner.CanSeek; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return mInner.CanWrite; }
+        }
+
+        public override void Close()
+        {
+            lock (this) mClosed = true;
+        }
+
+        public override void Flush()
+        {
+            mInner.Flush();
+        }
+
+        public override long Length
+        {
+            get { return mInner.Length; }
+        }
+
+        public override long Position
+        {
+            get { return mInner.Position; }
+            set { mInner.Position = value; }
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return mInner.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            mInner.SetLength(value);
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            CheckNotClosed();
+            return mInner.Read(buffer, offset, count);
+        }
+
+        public override int ReadByte()
+        {
+            CheckNotClosed();
+            return mInner.ReadByte();
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            CheckNotClosed();
+            mInner.Write(buf, off, len);
+        }
+
+        public override void WriteByte(byte value)
+        {
+            CheckNotClosed();
+            mInner.WriteByte(value);
+        }
+
+        private void CheckNotClosed()
+        {
+            lock (this)
+            {
+                if (mClosed)
+                    throw new ObjectDisposedException(this.GetType().Name);
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/PipedStream.cs b/crypto/test/src/crypto/tls/test/PipedStream.cs
new file mode 100644
index 000000000..6b2c15059
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/PipedStream.cs
@@ -0,0 +1,134 @@
+using System;
+using System.IO;
+using System.Threading;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class PipedStream
+        :   Stream
+    {
+        private readonly MemoryStream mBuf = new MemoryStream();
+        private bool mClosed = false;
+
+        private PipedStream mOther = null;
+        private long mReadPos = 0;
+
+        internal PipedStream()
+        {
+        }
+
+        internal PipedStream(PipedStream other)
+        {
+            lock (other)
+            {
+                this.mOther = other;
+                other.mOther = this;
+            }
+        }
+
+        public override bool CanRead
+        {
+            get { return true; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return true; }
+        }
+
+        public override void Close()
+        {
+            lock (this)
+            {
+                mClosed = true;
+                Monitor.PulseAll(this);
+            }
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override long Length
+        {
+            get { throw new NotImplementedException(); }
+        }
+
+        public override long Position
+        {
+            get { throw new NotImplementedException(); }
+            set { throw new NotImplementedException(); }
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            lock (mOther)
+            {
+                WaitForData();
+                int len = (int)System.Math.Min(count, mOther.mBuf.Position - mReadPos);
+                Array.Copy(mOther.mBuf.GetBuffer(), mReadPos, buffer, offset, len);
+                mReadPos += len;
+                return len;
+            }
+        }
+
+        public override int ReadByte()
+        {
+            lock (mOther)
+            {
+                WaitForData();
+                bool eof = (mReadPos >= mOther.mBuf.Position);
+                return eof ? -1 : mOther.mBuf.GetBuffer()[mReadPos++];
+            }
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            lock (this)
+            {
+                CheckOpen();
+                mBuf.Write(buf, off, len);
+                Monitor.PulseAll(this);
+            }
+        }
+
+        public override void WriteByte(byte value)
+        {
+            lock (this)
+            {
+                CheckOpen();
+                mBuf.WriteByte(value);
+                Monitor.PulseAll(mBuf);
+            }
+        }
+
+        private void CheckOpen()
+        {
+            if (mClosed)
+                throw new ObjectDisposedException(this.GetType().Name);
+        }
+
+        private void WaitForData()
+        {
+            while (mReadPos >= mOther.mBuf.Position && !mOther.mClosed)
+            {
+                Monitor.Wait(mOther);
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs
new file mode 100644
index 000000000..7072c7105
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    /**
+     * A simple test designed to conduct a TLS handshake with an external TLS server.
+     * <p>
+     * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in
+     * this package (under 'src/test/resources') for help configuring an external TLS server.
+     * </p><p>
+     * In both cases, extra options are required to enable PSK ciphersuites and configure identities/keys.
+     * </p>
+     */
+    public class PskTlsClientTest
+    {
+        private static readonly SecureRandom secureRandom = new SecureRandom();
+
+        public static void Main(string[] args)
+        {
+            string hostname = "localhost";
+            int port = 5556;
+
+            long time1 = DateTime.UtcNow.Ticks;
+
+            /*
+             * Note: This is the default PSK identity for 'openssl s_server' testing, the server must be
+             * started with "-psk 6161616161" to make the keys match, and possibly the "-psk_hint"
+             * option should be present.
+             */
+            string psk_identity = "Client_identity";
+            byte[] psk = new byte[]{ 0x61, 0x61, 0x61, 0x61, 0x61 };
+
+            BasicTlsPskIdentity pskIdentity = new BasicTlsPskIdentity(psk_identity, psk);
+
+            MockPskTlsClient client = new MockPskTlsClient(null, pskIdentity);
+            TlsClientProtocol protocol = OpenTlsConnection(hostname, port, client);
+            protocol.Close();
+
+            long time2 = DateTime.UtcNow.Ticks;
+            Console.WriteLine("Elapsed 1: " + (time2 - time1)/TimeSpan.TicksPerMillisecond + "ms");
+
+            client = new MockPskTlsClient(client.GetSessionToResume(), pskIdentity);
+            protocol = OpenTlsConnection(hostname, port, client);
+
+            long time3 = DateTime.UtcNow.Ticks;
+            Console.WriteLine("Elapsed 2: " + (time3 - time2)/TimeSpan.TicksPerMillisecond + "ms");
+
+            byte[] req = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n\r\n");
+
+            Stream tlsStream = protocol.Stream;
+            tlsStream.Write(req, 0, req.Length);
+            tlsStream.Flush();
+
+            StreamReader reader = new StreamReader(tlsStream);
+
+            String line;
+            while ((line = reader.ReadLine()) != null)
+            {
+                Console.WriteLine(">>> " + line);
+            }
+
+            protocol.Close();
+        }
+
+        internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
+        {
+            TcpClient tcp = new TcpClient(hostname, port);
+
+            TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);
+            protocol.Connect(client);
+            return protocol;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs
new file mode 100644
index 000000000..ba5b90c75
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsProtocolTest
+    {
+        [Test]
+        public void TestClientServer()
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            PipedStream clientPipe = new PipedStream();
+            PipedStream serverPipe = new PipedStream(clientPipe);
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom);
+
+            Server server = new Server(serverProtocol);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            MockTlsClient client = new MockTlsClient(null);
+            clientProtocol.Connect(client);
+
+            // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+            int length = 1000;
+
+            byte[] data = new byte[length];
+            secureRandom.NextBytes(data);
+
+            Stream output = clientProtocol.Stream;
+            output.Write(data, 0, data.Length);
+
+            byte[] echo = new byte[data.Length];
+            int count = Streams.ReadFully(clientProtocol.Stream, echo);
+
+            Assert.AreEqual(count, data.Length);
+            Assert.IsTrue(Arrays.AreEqual(data, echo));
+
+            output.Close();
+
+            serverThread.Join();
+        }
+
+        internal class Server
+        {
+            private readonly TlsServerProtocol mServerProtocol;
+
+            internal Server(TlsServerProtocol serverProtocol)
+            {
+                this.mServerProtocol = serverProtocol;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockTlsServer server = new MockTlsServer();
+                    mServerProtocol.Accept(server);
+                    Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream);
+                    mServerProtocol.Close();
+                }
+                catch (Exception)
+                {
+                    //throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs
new file mode 100644
index 000000000..b059bb2cb
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsPskProtocolTest
+    {
+        [Test]
+        public void TestClientServer()
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            PipedStream clientPipe = new PipedStream();
+            PipedStream serverPipe = new PipedStream(clientPipe);
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom);
+
+            Server server = new Server(serverProtocol);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            MockPskTlsClient client = new MockPskTlsClient(null);
+            clientProtocol.Connect(client);
+
+            // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+            int length = 1000;
+
+            byte[] data = new byte[length];
+            secureRandom.NextBytes(data);
+
+            Stream output = clientProtocol.Stream;
+            output.Write(data, 0, data.Length);
+
+            byte[] echo = new byte[data.Length];
+            int count = Streams.ReadFully(clientProtocol.Stream, echo);
+
+            Assert.AreEqual(count, data.Length);
+            Assert.IsTrue(Arrays.AreEqual(data, echo));
+
+            output.Close();
+
+            serverThread.Join();
+        }
+
+        internal class Server
+        {
+            private readonly TlsServerProtocol mServerProtocol;
+
+            internal Server(TlsServerProtocol serverProtocol)
+            {
+                this.mServerProtocol = serverProtocol;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockPskTlsServer server = new MockPskTlsServer();
+                    mServerProtocol.Accept(server);
+                    Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream);
+                    mServerProtocol.Close();
+                }
+                catch (Exception)
+                {
+                    //throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs
new file mode 100644
index 000000000..32e126ff2
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsSrpProtocolTest
+    {
+        [Test]
+        public void TestClientServer()
+        {
+            SecureRandom secureRandom = new SecureRandom();
+
+            PipedStream clientPipe = new PipedStream();
+            PipedStream serverPipe = new PipedStream(clientPipe);
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom);
+
+            Server server = new Server(serverProtocol);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            MockSrpTlsClient client = new MockSrpTlsClient(null, MockSrpTlsServer.TEST_IDENTITY, MockSrpTlsServer.TEST_PASSWORD);
+            clientProtocol.Connect(client);
+
+            // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+            int length = 1000;
+
+            byte[] data = new byte[length];
+            secureRandom.NextBytes(data);
+
+            Stream output = clientProtocol.Stream;
+            output.Write(data, 0, data.Length);
+
+            byte[] echo = new byte[data.Length];
+            int count = Streams.ReadFully(clientProtocol.Stream, echo);
+
+            Assert.AreEqual(count, data.Length);
+            Assert.IsTrue(Arrays.AreEqual(data, echo));
+
+            output.Close();
+
+            serverThread.Join();
+        }
+
+        internal class Server
+        {
+            private readonly TlsServerProtocol mServerProtocol;
+
+            internal Server(TlsServerProtocol serverProtocol)
+            {
+                this.mServerProtocol = serverProtocol;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockSrpTlsServer server = new MockSrpTlsServer();
+                    mServerProtocol.Accept(server);
+                    Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream);
+                    mServerProtocol.Close();
+                }
+                catch (Exception)
+                {
+                    //throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
new file mode 100644
index 000000000..4b0c12710
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs
@@ -0,0 +1,164 @@
+using System;
+using System.IO;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    [TestFixture]
+    public class TlsTestCase
+    {
+        private static void CheckTlsVersion(ProtocolVersion version)
+        {
+            if (version != null && !version.IsTls)
+                throw new InvalidOperationException("Non-TLS version");
+        }
+
+        [Test, TestCaseSource(typeof(TlsTestSuite), "Suite")]
+        public void RunTest(TlsTestConfig config)
+        {
+            CheckTlsVersion(config.clientMinimumVersion);
+            CheckTlsVersion(config.clientOfferVersion);
+            CheckTlsVersion(config.serverMaximumVersion);
+            CheckTlsVersion(config.serverMinimumVersion);
+
+            SecureRandom secureRandom = new SecureRandom();
+
+            PipedStream clientPipe = new PipedStream();
+            PipedStream serverPipe = new PipedStream(clientPipe);
+
+            NetworkStream clientNet = new NetworkStream(clientPipe);
+            NetworkStream serverNet = new NetworkStream(serverPipe);
+
+            TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNet, secureRandom);
+            TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNet, secureRandom);
+
+            TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
+            TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
+
+            Server server = new Server(this, serverProtocol, serverImpl);
+
+            Thread serverThread = new Thread(new ThreadStart(server.Run));
+            serverThread.Start();
+
+            Exception caught = null;
+            try
+            {
+                clientProtocol.Connect(clientImpl);
+
+                // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+                int length = 1000;
+
+                byte[] data = new byte[length];
+                secureRandom.NextBytes(data);
+    
+                Stream output = clientProtocol.Stream;
+                output.Write(data, 0, data.Length);
+
+                byte[] echo = new byte[data.Length];
+                int count = Streams.ReadFully(clientProtocol.Stream, echo);
+
+                Assert.AreEqual(count, data.Length);
+                Assert.IsTrue(Arrays.AreEqual(data, echo));
+
+                output.Close();
+            }
+            catch (Exception e)
+            {
+                caught = e;
+                LogException(caught);
+            }
+
+            server.AllowExit();
+            serverThread.Join();
+
+            Assert.IsTrue(clientNet.IsClosed, "Client Stream not closed");
+            Assert.IsTrue(serverNet.IsClosed, "Server Stream not closed");
+
+            Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end");
+            Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end");
+
+            Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description");
+            Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description");
+
+            if (config.expectFatalAlertConnectionEnd == -1)
+            {
+                Assert.IsNull(caught, "Unexpected client exception");
+                Assert.IsNull(server.mCaught, "Unexpected server exception");
+            }
+        }
+
+        protected virtual void LogException(Exception e)
+        {
+            if (TlsTestConfig.DEBUG)
+            {
+                Console.Error.WriteLine(e);
+            }
+        }
+
+        internal class Server
+        {
+            protected readonly TlsTestCase mOuter;
+            protected readonly TlsServerProtocol mServerProtocol;
+            protected readonly TlsTestServerImpl mServerImpl;
+
+            internal bool mCanExit = false;
+            internal Exception mCaught = null;
+
+            internal Server(TlsTestCase outer, TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl)
+            {
+                this.mOuter = outer;
+                this.mServerProtocol = serverProtocol;
+                this.mServerImpl = serverImpl;
+            }
+
+            internal void AllowExit()
+            {
+                lock (this)
+                {
+                    mCanExit = true;
+                    Monitor.PulseAll(this);
+                }
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    mServerProtocol.Accept(mServerImpl);
+                    Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream);
+                    mServerProtocol.Close();
+                }
+                catch (Exception e)
+                {
+                    mCaught = e;
+                    mOuter.LogException(mCaught);
+                }
+
+                WaitExit();
+            }
+
+            protected void WaitExit()
+            {
+                lock (this)
+                {
+                    while (!mCanExit)
+                    {
+                        try
+                        {
+                            Monitor.Wait(this);
+                        }
+                        catch (ThreadInterruptedException)
+                        {
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
new file mode 100644
index 000000000..48af9e0f8
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
@@ -0,0 +1,262 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class TlsTestClientImpl
+        :   DefaultTlsClient
+    {
+        protected readonly TlsTestConfig mConfig;
+
+        protected int firstFatalAlertConnectionEnd = -1;
+        protected int firstFatalAlertDescription = -1;
+
+        internal TlsTestClientImpl(TlsTestConfig config)
+        {
+            this.mConfig = config;
+        }
+
+        internal int FirstFatalAlertConnectionEnd
+        {
+            get { return firstFatalAlertConnectionEnd; }
+        }
+
+        internal int FirstFatalAlertDescription
+        {
+            get { return firstFatalAlertDescription; }
+        }
+
+        public override ProtocolVersion ClientVersion
+        {
+	        get 
+	        { 
+                if (mConfig.clientOfferVersion != null)
+                {
+                    return mConfig.clientOfferVersion;
+                }
+
+                return base.ClientVersion;
+            }
+        }
+
+        public override ProtocolVersion MinimumVersion
+        {
+	        get 
+	        { 
+                if (mConfig.clientMinimumVersion != null)
+                {
+                    return mConfig.clientMinimumVersion;
+                }
+
+                return base.MinimumVersion;
+	        }
+        }
+
+        public override bool IsFallback
+        {
+            get { return mConfig.clientFallback; }
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+            {
+                firstFatalAlertConnectionEnd = ConnectionEnd.client;
+                firstFatalAlertDescription = alertDescription;
+            }
+
+            if (TlsTestConfig.DEBUG)
+            {
+                TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+                output.WriteLine("TLS client raised alert: " + AlertLevel.GetText(alertLevel)
+                    + ", " + AlertDescription.GetText(alertDescription));
+                if (message != null)
+                {
+                    output.WriteLine("> " + message);
+                }
+                if (cause != null)
+                {
+                    output.WriteLine(cause);
+                }
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+            {
+                firstFatalAlertConnectionEnd = ConnectionEnd.server;
+                firstFatalAlertDescription = alertDescription;
+            }
+
+            if (TlsTestConfig.DEBUG)
+            {
+                TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+                output.WriteLine("TLS client received alert: " + AlertLevel.GetText(alertLevel)
+                    + ", " + AlertDescription.GetText(alertDescription));
+            }
+        }
+
+        public override void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            base.NotifyServerVersion(serverVersion);
+
+            if (TlsTestConfig.DEBUG)
+            {
+                Console.WriteLine("TLS client negotiated " + serverVersion);
+            }
+        }
+
+        public override TlsAuthentication GetAuthentication()
+        {
+            return new MyTlsAuthentication(this, mContext);
+        }
+
+        protected virtual Certificate CorruptCertificate(Certificate cert)
+        {
+            X509CertificateStructure[] certList = cert.GetCertificateList();
+            certList[0] = CorruptCertificateSignature(certList[0]);
+            return new Certificate(certList);
+        }
+
+        protected virtual X509CertificateStructure CorruptCertificateSignature(X509CertificateStructure cert)
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+            v.Add(cert.TbsCertificate);
+            v.Add(cert.SignatureAlgorithm);
+            v.Add(CorruptBitString(cert.Signature));
+
+            return X509CertificateStructure.GetInstance(new DerSequence(v));
+        }
+
+        protected virtual DerBitString CorruptBitString(DerBitString bs)
+        {
+            return new DerBitString(CorruptBit(bs.GetBytes()));
+        }
+
+        protected virtual byte[] CorruptBit(byte[] bs)
+        {
+            bs = Arrays.Clone(bs);
+
+            // Flip a random bit
+            int bit = mContext.SecureRandom.Next(bs.Length << 3); 
+            bs[bit >> 3] ^= (byte)(1 << (bit & 7));
+
+            return bs;
+        }
+
+        internal class MyTlsAuthentication
+            :   TlsAuthentication
+        {
+            private readonly TlsTestClientImpl mOuter;
+            private readonly TlsContext mContext;
+
+            internal MyTlsAuthentication(TlsTestClientImpl outer, TlsContext context)
+            {
+                this.mOuter = outer;
+                this.mContext = context;
+            }
+
+            public virtual void NotifyServerCertificate(Certificate serverCertificate)
+            {
+                bool isEmpty = serverCertificate == null || serverCertificate.IsEmpty;
+
+                X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+
+                // TODO Cache test resources?
+                if (isEmpty || !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server.pem"))
+                    || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-dsa.pem"))
+                    || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-ecdsa.pem"))))
+                {
+                    throw new TlsFatalAlert(AlertDescription.bad_certificate);
+                }
+
+                if (TlsTestConfig.DEBUG)
+                {
+                    Console.WriteLine("TLS client received server certificate chain of length " + chain.Length);
+                    for (int i = 0; i != chain.Length; i++)
+                    {
+                        X509CertificateStructure entry = chain[i];
+                        // TODO Create fingerprint based on certificate signature algorithm digest
+                        Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                            + entry.Subject + ")");
+                    }
+                }
+            }
+
+            public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+            {
+                if (mOuter.mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
+                    throw new InvalidOperationException();
+                if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE)
+                    return null;
+
+                byte[] certificateTypes = certificateRequest.CertificateTypes;
+                if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
+                {
+                    return null;
+                }
+
+                TlsSignerCredentials signerCredentials = TlsTestUtilities.LoadSignerCredentials(mContext,
+                    certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+                    "x509-client.pem", "x509-client-key.pem");
+
+                if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID)
+                {
+                    return signerCredentials;
+                }
+
+                return new MyTlsSignerCredentials(mOuter, signerCredentials);
+            }
+        };
+
+        internal class MyTlsSignerCredentials
+            :   TlsSignerCredentials
+        {
+            private readonly TlsTestClientImpl mOuter;
+            private readonly TlsSignerCredentials mInner;
+
+            internal MyTlsSignerCredentials(TlsTestClientImpl outer, TlsSignerCredentials inner)
+            {
+                this.mOuter = outer;
+                this.mInner = inner;
+            }
+
+            public virtual byte[] GenerateCertificateSignature(byte[] hash)
+            {
+                byte[] sig = mInner.GenerateCertificateSignature(hash);
+
+                if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_VERIFY)
+                {
+                    sig = mOuter.CorruptBit(sig);
+                }
+
+                return sig;
+            }
+
+            public virtual Certificate Certificate
+            {
+                get
+                {
+                    Certificate cert = mInner.Certificate;
+
+                    if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_CERT)
+                    {
+                        cert = mOuter.CorruptCertificate(cert);
+                    }
+
+                    return cert;
+                }
+            }
+
+            public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm
+            {
+                get { return mInner.SignatureAndHashAlgorithm; }
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs
new file mode 100644
index 000000000..0d1e7badb
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs
@@ -0,0 +1,101 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class TlsTestConfig
+    {
+        public static readonly bool DEBUG = false;
+
+        /**
+         * Client does not authenticate, ignores any certificate request
+         */
+        public const int CLIENT_AUTH_NONE = 0;
+
+        /**
+         * Client will authenticate if it receives a certificate request
+         */
+        public const int CLIENT_AUTH_VALID = 1;
+
+        /**
+         * Client will authenticate if it receives a certificate request, with an invalid certificate
+         */
+        public const int CLIENT_AUTH_INVALID_CERT = 2;
+
+        /**
+         * Client will authenticate if it receives a certificate request, with an invalid CertificateVerify signature
+         */
+        public const int CLIENT_AUTH_INVALID_VERIFY = 3;
+
+        /**
+         * Server will not request a client certificate
+         */
+        public const int SERVER_CERT_REQ_NONE = 0;
+
+        /**
+         * Server will request a client certificate but receiving one is optional
+         */
+        public const int SERVER_CERT_REQ_OPTIONAL = 1;
+
+        /**
+         * Server will request a client certificate and receiving one is mandatory
+         */
+        public const int SERVER_CERT_REQ_MANDATORY = 2;
+
+        /**
+         * Configures the client authentication behaviour of the test client. Use CLIENT_AUTH_* constants.
+         */
+        public int clientAuth = CLIENT_AUTH_VALID;
+
+        /**
+         * Configures the minimum protocol version the client will accept. If null, uses the library's default.
+         */
+        public ProtocolVersion clientMinimumVersion = null;
+
+        /**
+         * Configures the protocol version the client will offer. If null, uses the library's default.
+         */
+        public ProtocolVersion clientOfferVersion = null;
+
+        /**
+         * Configures whether the client will indicate version fallback via TLS_FALLBACK_SCSV.
+         */
+        public bool clientFallback = false;
+
+        /**
+         * Configures whether the test server will send a certificate request.
+         */
+        public int serverCertReq = SERVER_CERT_REQ_OPTIONAL;
+
+        /**
+         * Configures the maximum protocol version the server will accept. If null, uses the library's default.
+         */
+        public ProtocolVersion serverMaximumVersion = null;
+
+        /**
+         * Configures the minimum protocol version the server will accept. If null, uses the library's default.
+         */
+        public ProtocolVersion serverMinimumVersion = null;
+
+        /**
+         * Configures the connection end that a fatal alert is expected to be raised. Use ConnectionEnd.* constants.
+         */
+        public int expectFatalAlertConnectionEnd = -1;
+
+        /**
+         * Configures the type of fatal alert expected to be raised. Use AlertDescription.* constants.
+         */
+        public int expectFatalAlertDescription = -1;
+
+        public void ExpectClientFatalAlert(byte alertDescription)
+        {
+            this.expectFatalAlertConnectionEnd = ConnectionEnd.client;
+            this.expectFatalAlertDescription = alertDescription;
+        }
+
+        public void ExpectServerFatalAlert(byte alertDescription)
+        {
+            this.expectFatalAlertConnectionEnd = ConnectionEnd.server;
+            this.expectFatalAlertDescription = alertDescription;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs
new file mode 100644
index 000000000..152d5dbdc
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs
@@ -0,0 +1,194 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class TlsTestServerImpl
+        :   DefaultTlsServer
+    {
+        protected readonly TlsTestConfig mConfig;
+
+        protected int firstFatalAlertConnectionEnd = -1;
+        protected int firstFatalAlertDescription = -1;
+
+        internal TlsTestServerImpl(TlsTestConfig config)
+        {
+            this.mConfig = config;
+        }
+
+        internal int FirstFatalAlertConnectionEnd
+        {
+            get { return firstFatalAlertConnectionEnd; }
+        }
+
+        internal int FirstFatalAlertDescription
+        {
+            get { return firstFatalAlertDescription; }
+        }
+
+        protected override ProtocolVersion MaximumVersion
+        {
+	        get 
+	        { 
+                if (mConfig.serverMaximumVersion != null)
+                {
+                    return mConfig.serverMaximumVersion;
+                }
+
+                return base.MaximumVersion;
+	        }
+        }
+
+        protected override ProtocolVersion MinimumVersion
+        {
+	        get 
+	        { 
+                if (mConfig.serverMinimumVersion != null)
+                {
+                    return mConfig.serverMinimumVersion;
+                }
+
+                return base.MinimumVersion;
+	        }
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+            {
+                firstFatalAlertConnectionEnd = ConnectionEnd.server;
+                firstFatalAlertDescription = alertDescription;
+            }
+
+            if (TlsTestConfig.DEBUG)
+            {
+                TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+                output.WriteLine("TLS server raised alert: " + AlertLevel.GetText(alertLevel)
+                    + ", " + AlertDescription.GetText(alertDescription));
+                if (message != null)
+                {
+                    output.WriteLine("> " + message);
+                }
+                if (cause != null)
+                {
+                    output.WriteLine(cause);
+                }
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+            {
+                firstFatalAlertConnectionEnd = ConnectionEnd.client;
+                firstFatalAlertDescription = alertDescription;
+            }
+
+            if (TlsTestConfig.DEBUG)
+            {
+                TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+                output.WriteLine("TLS server received alert: " + AlertLevel.GetText(alertLevel)
+                    + ", " + AlertDescription.GetText(alertDescription));
+            }
+        }
+
+        public override ProtocolVersion GetServerVersion()
+        {
+            ProtocolVersion serverVersion = base.GetServerVersion();
+
+            if (TlsTestConfig.DEBUG)
+            {
+                Console.WriteLine("TLS server negotiated " + serverVersion);
+            }
+
+            return serverVersion;
+        }
+
+        public override CertificateRequest GetCertificateRequest()
+        {
+            if (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
+            {
+                return null;
+            }
+
+            byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign,
+                ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign };
+
+            IList serverSigAlgs = null;
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
+            {
+                serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
+            }
+
+            IList certificateAuthorities = new ArrayList();
+            certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject);
+
+            return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities);
+        }
+
+        public override void NotifyClientCertificate(Certificate clientCertificate)
+        {
+            bool isEmpty = (clientCertificate == null || clientCertificate.IsEmpty);
+
+            if (isEmpty != (mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE))
+            {
+                throw new InvalidOperationException();
+            }
+            if (isEmpty && (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_MANDATORY))
+            {
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+            }
+
+            X509CertificateStructure[] chain = clientCertificate.GetCertificateList();
+
+            // TODO Cache test resources?
+            if (!isEmpty && !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client.pem"))
+                || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-dsa.pem"))
+                || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-ecdsa.pem"))))
+            {
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+            }
+
+            if (TlsTestConfig.DEBUG)
+            {
+                Console.WriteLine("TLS server received client certificate chain of length " + chain.Length);
+                for (int i = 0; i != chain.Length; i++)
+                {
+                    X509CertificateStructure entry = chain[i];
+                    // TODO Create fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                        + entry.Subject + ")");
+                }
+            }
+        }
+
+        protected override TlsSignerCredentials GetDsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa,
+                "x509-server-dsa.pem", "x509-server-key-dsa.pem");
+        }
+
+        protected override TlsSignerCredentials GetECDsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.ecdsa,
+                "x509-server-ecdsa.pem", "x509-server-key-ecdsa.pem");
+        }
+
+        protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
+        {
+            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" },
+                "x509-server-key.pem");
+        }
+
+        protected override TlsSignerCredentials GetRsaSignerCredentials()
+        {
+            return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa,
+                "x509-server.pem", "x509-server-key.pem");
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs
new file mode 100644
index 000000000..dfd09d06e
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class TlsTestSuite
+    {
+        // Make the access to constants less verbose 
+        internal class C : TlsTestConfig {}
+
+        public TlsTestSuite()
+        {
+        }
+
+        public static IEnumerable Suite()
+        {
+            IList testSuite = new ArrayList();
+
+            AddFallbackTests(testSuite);
+            AddVersionTests(testSuite, ProtocolVersion.TLSv10);
+            AddVersionTests(testSuite, ProtocolVersion.TLSv11);
+            AddVersionTests(testSuite, ProtocolVersion.TLSv12);
+
+            return testSuite;
+        }
+
+        private static void AddFallbackTests(IList testSuite)
+        {
+            {
+                TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12);
+                c.clientFallback = true;
+
+                testSuite.Add(new TestCaseData(c).SetName("FallbackGood"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12);
+                c.clientOfferVersion = ProtocolVersion.TLSv11;
+                c.clientFallback = true;
+                c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback);
+
+                testSuite.Add(new TestCaseData(c).SetName("FallbackBad"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12);
+                c.clientOfferVersion = ProtocolVersion.TLSv11;
+
+                testSuite.Add(new TestCaseData(c).SetName("FallbackNone"));
+            }
+        }
+
+        private static void AddVersionTests(IList testSuite, ProtocolVersion version)
+        {
+            string prefix = version.ToString()
+                .Replace(" ", "")
+                .Replace("\\", "")
+                .Replace(".", "")
+                + "_";
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+                c.ExpectServerFatalAlert(AlertDescription.decrypt_error);
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+                c.ExpectServerFatalAlert(AlertDescription.bad_certificate);
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_NONE;
+                c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+                c.ExpectServerFatalAlert(AlertDescription.handshake_failure);
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.serverCertReq = C.SERVER_CERT_REQ_NONE;
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq"));
+            }
+
+            {
+                TlsTestConfig c = CreateTlsTestConfig(version);
+                c.clientAuth = C.CLIENT_AUTH_NONE;
+
+                testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined"));
+            }
+        }
+
+        private static TlsTestConfig CreateTlsTestConfig(ProtocolVersion version)
+        {
+            TlsTestConfig c = new TlsTestConfig();
+            c.clientMinimumVersion = ProtocolVersion.TLSv10;
+            c.clientOfferVersion = ProtocolVersion.TLSv12;
+            c.serverMaximumVersion = version;
+            c.serverMinimumVersion = ProtocolVersion.TLSv10;
+            return c;
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
index 272dfd4fd..a76858ce6 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Globalization;
 using System.IO;
 using System.Text;
@@ -89,6 +90,34 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm);
         }
 
+        internal static TlsSignerCredentials LoadSignerCredentials(TlsContext context, IList supportedSignatureAlgorithms,
+            byte signatureAlgorithm, string certResource, string keyResource)
+        {
+            /*
+             * TODO Note that this code fails to provide default value for the client supported
+             * algorithms if it wasn't sent.
+             */
+
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+            if (supportedSignatureAlgorithms != null)
+            {
+                foreach (SignatureAndHashAlgorithm alg in supportedSignatureAlgorithms)
+                {
+                    if (alg.Signature == signatureAlgorithm)
+                    {
+                        signatureAndHashAlgorithm = alg;
+                        break;
+                    }
+                }
+
+                if (signatureAndHashAlgorithm == null)
+                    return null;
+            }
+
+            return LoadSignerCredentials(context, new String[]{ certResource, "x509-ca.pem" },
+                keyResource, signatureAndHashAlgorithm);
+        }
+
         internal static Certificate LoadCertificateChain(string[] resources)
         {
             X509CertificateStructure[] chain = new X509CertificateStructure[resources.Length];
diff --git a/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs
new file mode 100644
index 000000000..b771ab7cf
--- /dev/null
+++ b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs
@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public class UnreliableDatagramTransport
+        :   DatagramTransport
+    {
+        private readonly DatagramTransport transport;
+        private readonly Random random;
+        private readonly int percentPacketLossReceiving, percentPacketLossSending;
+
+        public UnreliableDatagramTransport(DatagramTransport transport, Random random,
+            int percentPacketLossReceiving, int percentPacketLossSending)
+        {
+            if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100)
+                throw new ArgumentException("out of range", "percentPacketLossReceiving");
+            if (percentPacketLossSending < 0 || percentPacketLossSending > 100)
+                throw new ArgumentException("out of range", "percentPacketLossSending");
+
+            this.transport = transport;
+            this.random = random;
+            this.percentPacketLossReceiving = percentPacketLossReceiving;
+            this.percentPacketLossSending = percentPacketLossSending;
+        }
+
+        public virtual int GetReceiveLimit()
+        {
+            return transport.GetReceiveLimit();
+        }
+
+        public virtual int GetSendLimit()
+        {
+            return transport.GetSendLimit();
+        }
+
+        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
+        {
+            long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis;
+            for (;;)
+            {
+                int length = transport.Receive(buf, off, len, waitMillis);
+                if (length < 0 || !LostPacket(percentPacketLossReceiving))
+                {
+                    return length;
+                }
+
+                Console.WriteLine("PACKET LOSS (" + length + " byte packet not received)");
+
+                long now = DateTimeUtilities.CurrentUnixMs();
+                if (now >= endMillis)
+                {
+                    return -1;
+                }
+
+                waitMillis = (int)(endMillis - now);
+            }
+        }
+
+        public virtual void Send(byte[] buf, int off, int len)
+        {
+            if (LostPacket(percentPacketLossSending))
+            {
+                Console.WriteLine("PACKET LOSS (" + len + " byte packet not sent)");
+            }
+            else
+            {
+                transport.Send(buf, off, len);
+            }
+        }
+
+        public virtual void Close()
+        {
+            transport.Close();
+        }
+
+        private bool LostPacket(int percentPacketLoss)
+        {
+            return percentPacketLoss > 0 && random.Next(100) < percentPacketLoss;
+        }
+    }
+}
diff --git a/crypto/test/src/math/ec/test/AllTests.cs b/crypto/test/src/math/ec/test/AllTests.cs
index d4c7dc768..3e014ffd2 100644
--- a/crypto/test/src/math/ec/test/AllTests.cs
+++ b/crypto/test/src/math/ec/test/AllTests.cs
@@ -7,22 +7,21 @@ namespace Org.BouncyCastle.Math.EC.Tests
 {
     public class AllTests
     {
-        public static void Main(
-            string[] args)
+        public static void Main(string[] args)
         {
-//            junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            suite().Run(el);
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
         }
 
-        public static TestSuite suite()
+        [Suite]
+        public static TestSuite Suite
         {
-            TestSuite suite = new TestSuite("EC Math tests");
-
-            suite.Add(new ECAlgorithmsTest());
-            suite.Add(new ECPointTest());
-
-            return suite;
+            get
+            {
+                TestSuite suite = new TestSuite("EC Math tests");
+                suite.Add(new ECAlgorithmsTest());
+                suite.Add(new ECPointTest());
+                return suite;
+            }
         }
     }
 }
diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs
index 8430f437d..2a62b7740 100644
--- a/crypto/test/src/math/ec/test/ECPointTest.cs
+++ b/crypto/test/src/math/ec/test/ECPointTest.cs
@@ -483,7 +483,9 @@ namespace Org.BouncyCastle.Math.EC.Tests
             CollectionUtilities.AddRange(names, ECNamedCurveTable.Names);
             CollectionUtilities.AddRange(names, CustomNamedCurves.Names);
 
-            foreach (string name in names)
+            ISet uniqNames = new HashSet(names);
+
+            foreach (string name in uniqNames)
             {
                 X9ECParameters x9ECParameters = ECNamedCurveTable.GetByName(name);
                 if (x9ECParameters != null)
diff --git a/crypto/test/src/math/ec/test/TnafTest.cs b/crypto/test/src/math/ec/test/TnafTest.cs
index c04ae00d2..f5a58e858 100644
--- a/crypto/test/src/math/ec/test/TnafTest.cs
+++ b/crypto/test/src/math/ec/test/TnafTest.cs
@@ -40,7 +40,7 @@
 //		{
 //			X9ECParameters x9ECParameters = SecNamedCurves.GetByName(curveName);
 //
-//			F2mCurve curve = (F2mCurve)x9ECParameters.Curve;
+//			AbstractF2mCurve curve = (AbstractF2mCurve)x9ECParameters.Curve;
 //			BigInteger n = curve.N;
 //
 //			// The generator is multiplied by random b to get random q
diff --git a/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs
index 6f2b50140..40cfe3774 100644
--- a/crypto/test/src/math/test/AllTests.cs
+++ b/crypto/test/src/math/test/AllTests.cs
@@ -7,21 +7,20 @@ namespace Org.BouncyCastle.Math.Tests
 {
     public class AllTests
     {
-        public static void Main(
-			string[] args)
+        public static void Main(string[] args)
         {
-//            junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            suite().Run(el);
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
         }
 
-        public static TestSuite suite()
+        [Suite]
+        public static TestSuite Suite
         {
-			TestSuite suite = new TestSuite("Math tests");
-
-			suite.Add(new BigIntegerTest());
-
-			return suite;
+            get
+            {
+                TestSuite suite = new TestSuite("Math tests");
+                suite.Add(new BigIntegerTest());
+                return suite;
+            }
         }
     }
 }
diff --git a/crypto/test/src/ocsp/test/AllTests.cs b/crypto/test/src/ocsp/test/AllTests.cs
index 2b30e3ad4..5e919fd91 100644
--- a/crypto/test/src/ocsp/test/AllTests.cs
+++ b/crypto/test/src/ocsp/test/AllTests.cs
@@ -9,21 +9,20 @@ namespace Org.BouncyCastle.Ocsp.Tests
 {
 	public class AllTests
 	{
-		public static void Main(
-			string[] args)
-		{
-			//junit.textui.TestRunner.run(suite());
-			EventListener el = new NullListener();
-			suite().Run(el);
-		}
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
 
-		public static TestSuite suite()
-		{
-			TestSuite suite = new TestSuite("OCSP Tests");
-
-			suite.Add(new OcspTest());
-
-			return suite;
-		}
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("OCSP Tests");
+                suite.Add(new OcspTest());
+                return suite;
+            }
+        }
 	}
 }
diff --git a/crypto/test/src/openpgp/examples/test/AllTests.cs b/crypto/test/src/openpgp/examples/test/AllTests.cs
index 180d2fa80..e9a7a744d 100644
--- a/crypto/test/src/openpgp/examples/test/AllTests.cs
+++ b/crypto/test/src/openpgp/examples/test/AllTests.cs
@@ -382,22 +382,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests
 			return bRd.ReadLine();
 		}
 
-		public static void Main(
-			string[] args)
-		{
-			//junit.textui.TestRunner.run(suite());
-			EventListener el = new NullListener();
-			suite().Run(el);
-		}
-
-		public static TestSuite suite()
-		{
-			TestSuite suite = new TestSuite("OpenPGP Example Tests");
-
-			suite.Add(new AllTests());
-
-			return suite;
-		}
-
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
+
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("OpenPGP Example Tests");
+                suite.Add(new AllTests());
+                return suite;
+            }
+        }
 	}
 }
diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs
index 921208179..f843d0479 100644
--- a/crypto/test/src/openssl/test/AllTests.cs
+++ b/crypto/test/src/openssl/test/AllTests.cs
@@ -32,19 +32,24 @@ namespace Org.BouncyCastle.OpenSsl.Tests
 				return (char[]) password.Clone();
 			}
 		}
-		
-		[Suite]
-		public static TestSuite Suite
-		{
-			get
-			{
-				TestSuite suite = new TestSuite("OpenSSL Tests");
-				suite.Add(new AllTests());
-				return suite;
-			}
-		}
 
-		[Test]
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
+
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("OpenSSL Tests");
+                suite.Add(new AllTests());
+                return suite;
+            }
+        }
+
+        [Test]
 		public void TestOpenSsl()
 		{
 			Org.BouncyCastle.Utilities.Test.ITest[] tests = new Org.BouncyCastle.Utilities.Test.ITest[]{
@@ -121,13 +126,5 @@ namespace Org.BouncyCastle.OpenSsl.Tests
 
 			Assert.AreEqual(privKey, rdKey);
 		}
-
-        public static void Main(
-			string[] args)
-        {
-            //junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            Suite.Run(el);
-        }
 	}
 }
diff --git a/crypto/test/src/tsp/test/AllTests.cs b/crypto/test/src/tsp/test/AllTests.cs
index 66dc9c480..3e8b0cd5e 100644
--- a/crypto/test/src/tsp/test/AllTests.cs
+++ b/crypto/test/src/tsp/test/AllTests.cs
@@ -9,24 +9,23 @@ namespace Org.BouncyCastle.Tsp.Tests
 {
     public class AllTests
     {
-        public static void Main(
-			string[] args)
+        public static void Main(string[] args)
         {
-            //junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            suite().Run(el);
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
         }
 
-		public static TestSuite suite()
+        [Suite]
+        public static TestSuite Suite
         {
-            TestSuite suite = new TestSuite("TSP Tests");
-
-			suite.Add(new GenTimeAccuracyUnitTest());
-			suite.Add(new ParseTest());
-			suite.Add(new TimeStampTokenInfoUnitTest());
-			suite.Add(new TspTest());
-
-			return suite;
+            get
+            {
+                TestSuite suite = new TestSuite("TSP Tests");
+                suite.Add(new GenTimeAccuracyUnitTest());
+                suite.Add(new ParseTest());
+                suite.Add(new TimeStampTokenInfoUnitTest());
+                suite.Add(new TspTest());
+                return suite;
+            }
         }
     }
 }
diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs
index b44949383..c36f79304 100644
--- a/crypto/test/src/util/io/pem/test/AllTests.cs
+++ b/crypto/test/src/util/io/pem/test/AllTests.cs
@@ -19,18 +19,23 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests
 	[TestFixture]
 	public class AllTests
 	{
-		[Suite]
-		public static TestSuite Suite
-		{
-			get
-			{
-				TestSuite suite = new TestSuite("PEM Utilities Tests");
-				suite.Add(new AllTests());
-				return suite;
-			}
-		}
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
 
-		[Test]
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("PEM Utilities Tests");
+                suite.Add(new AllTests());
+                return suite;
+            }
+        }
+
+        [Test]
 		public void TestPemLength()
 		{
 			for (int i = 1; i != 60; i++)
@@ -65,13 +70,5 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests
 
 			Assert.AreEqual(sw.ToString().Length, pWrt.GetOutputSize(pemObj));
 		}
-
-		public static void Main(
-			string[] args)
-        {
-            //junit.textui.TestRunner.run(suite());
-            EventListener el = new NullListener();
-            Suite.Run(el);
-        }
 	}
 }