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