diff --git a/crypto/NBuild.build b/crypto/NBuild.build
index 89c557702..dd63df279 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.2"/>
+ <property name="version" value="1.8.3"/>
<property name="name" value="BouncyCastle.Crypto"/>
<property name="OPTIONAL_STRONG_NAME" value="" />
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 9f4705f00..72e97516f 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,7 +294,17 @@ 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="mozTocId85317"></a>Release 1.8.3, TBD</h4>
+ <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Saturday August 11, 2018</h4>
+
+ <h5>IMPORTANT</h5>
+ <ul>
+ <li>
+ In this release, the TLS library has moved to a whitelisting approach for client-side validation of server-presented
+ Diffie-Hellman (DH) parameters. In the default configuration, if a ciphersuite using ephemeral DH is selected by the
+ server, the client will abort the handshake if the proposed DH group is not one of those specified in RFC 3526 or RFC 7919,
+ or if the DH prime is < 2048 bits. The client therefore no longer offers DH ciphersuites by default.
+ </li>
+ </ul>
<h5>Additional Features and Functionality</h5>
<ul>
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 7cd8de821..b6dfb3963 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -4869,6 +4869,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\tls\DefaultTlsDHVerifier.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\tls\DefaultTlsEncryptionCredentials.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -5084,11 +5089,6 @@
BuildAction = "Compile"
/>
<File
- RelPath = "src\crypto\tls\ServerDHParams.cs"
- SubType = "Code"
- BuildAction = "Compile"
- />
- <File
RelPath = "src\crypto\tls\ServerSrpParams.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -5249,6 +5249,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\tls\TlsDHVerifier.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\tls\TlsDsaSigner.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/asn1/cmp/PollRepContent.cs b/crypto/src/asn1/cmp/PollRepContent.cs
index f8bb098a2..ff75d7d6d 100644
--- a/crypto/src/asn1/cmp/PollRepContent.cs
+++ b/crypto/src/asn1/cmp/PollRepContent.cs
@@ -33,6 +33,25 @@ namespace Org.BouncyCastle.Asn1.Cmp
throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
}
+ public PollRepContent(
+ DerInteger certReqId,
+ DerInteger checkAfter)
+ {
+ this.certReqId = certReqId;
+ this.checkAfter = checkAfter;
+ this.reason = null;
+ }
+
+ public PollRepContent(
+ DerInteger certReqId,
+ DerInteger checkAfter,
+ PkiFreeText reason)
+ {
+ this.certReqId = certReqId;
+ this.checkAfter = checkAfter;
+ this.reason = reason;
+ }
+
public virtual DerInteger CertReqID
{
get { return certReqId; }
diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index f63ed874e..5aa5f92ab 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -513,15 +513,19 @@ namespace Org.BouncyCastle.Cms
if (_certs.Count != 0)
{
- certificates = CmsUtilities.CreateBerSetFromList(_certs);
+ certificates = UseDerForCerts
+ ? CmsUtilities.CreateDerSetFromList(_certs)
+ : CmsUtilities.CreateBerSetFromList(_certs);
}
Asn1Set certrevlist = null;
if (_crls.Count != 0)
{
- certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
- }
+ certrevlist = UseDerForCrls
+ ? CmsUtilities.CreateDerSetFromList(_crls)
+ : CmsUtilities.CreateBerSetFromList(_crls);
+ }
Asn1OctetString octs = null;
if (encapsulate)
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 55fde90df..1c8fac22b 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -836,16 +836,20 @@ namespace Org.BouncyCastle.Cms
outer._digests.Clear(); // clear the current preserved digest state
- if (outer._certs.Count > 0)
- {
- Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
+ if (outer._certs.Count > 0)
+ {
+ Asn1Set certs = outer.UseDerForCerts
+ ? CmsUtilities.CreateDerSetFromList(outer._certs)
+ : CmsUtilities.CreateBerSetFromList(outer._certs);
WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
}
- if (outer._crls.Count > 0)
- {
- Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
+ if (outer._crls.Count > 0)
+ {
+ Asn1Set crls = outer.UseDerForCrls
+ ? CmsUtilities.CreateDerSetFromList(outer._crls)
+ : CmsUtilities.CreateBerSetFromList(outer._crls);
WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
}
diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs
index eec2e875b..249d70499 100644
--- a/crypto/src/cms/CMSSignedGenerator.cs
+++ b/crypto/src/cms/CMSSignedGenerator.cs
@@ -147,6 +147,8 @@ namespace Org.BouncyCastle.Cms
internal IList _crls = Platform.CreateArrayList();
internal IList _signers = Platform.CreateArrayList();
internal IDictionary _digests = Platform.CreateHashtable();
+ internal bool _useDerForCerts = false;
+ internal bool _useDerForCrls = false;
protected readonly SecureRandom rand;
@@ -251,6 +253,18 @@ namespace Org.BouncyCastle.Cms
return Platform.CreateHashtable(_digests);
}
+ public bool UseDerForCerts
+ {
+ get { return _useDerForCerts; }
+ set { this._useDerForCerts = value; }
+ }
+
+ public bool UseDerForCrls
+ {
+ get { return _useDerForCrls; }
+ set { this._useDerForCrls = value; }
+ }
+
internal virtual void AddSignerCallback(
SignerInformation si)
{
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index 287876f12..92001589c 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -212,10 +212,17 @@ namespace Org.BouncyCastle.Crypto.Encodings
// on encryption, we need to make sure our decrypted block comes back
// the same size.
//
+ bool wrongData = (block.Length < (2 * defHash.Length) + 1);
- Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
-
- bool shortData = (block.Length < (2 * defHash.Length) + 1);
+ if (data.Length <= block.Length)
+ {
+ Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
+ }
+ else
+ {
+ Array.Copy(data, 0, block, 0, block.Length);
+ wrongData = true;
+ }
//
// unmask the seed.
@@ -269,7 +276,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
start++;
- if (defHashWrong | shortData | dataStartWrong)
+ if (defHashWrong | wrongData | dataStartWrong)
{
Arrays.Fill(block, 0);
throw new InvalidCipherTextException("data wrong");
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index e023c1d18..373ba0cee 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -325,7 +325,8 @@ namespace Org.BouncyCastle.Crypto.Operators
/// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
/// signature algorithm details.
/// </summary>
- public class Asn1SignatureFactory: ISignatureFactory
+ public class Asn1SignatureFactory
+ : ISignatureFactory
{
private readonly AlgorithmIdentifier algID;
private readonly string algorithm;
@@ -337,7 +338,8 @@ namespace Org.BouncyCastle.Crypto.Operators
/// </summary>
/// <param name="algorithm">The name of the signature algorithm to use.</param>
/// <param name="privateKey">The private key to be used in the signing operation.</param>
- public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
+ public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey)
+ : this(algorithm, privateKey, null)
{
}
@@ -347,14 +349,21 @@ namespace Org.BouncyCastle.Crypto.Operators
/// <param name="algorithm">The name of the signature algorithm to use.</param>
/// <param name="privateKey">The private key to be used in the signing operation.</param>
/// <param name="random">The source of randomness to be used in signature calculation.</param>
- public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
+ public Asn1SignatureFactory(string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
{
- DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+ if (algorithm == null)
+ throw new ArgumentNullException("algorithm");
+ if (privateKey == null)
+ throw new ArgumentNullException("privateKey");
+ if (!privateKey.IsPrivate)
+ throw new ArgumentException("Key for signing must be private", "privateKey");
+
+ DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm);
this.algorithm = algorithm;
this.privateKey = privateKey;
this.random = random;
- this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+ this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm);
}
public Object AlgorithmDetails
@@ -365,16 +374,12 @@ namespace Org.BouncyCastle.Crypto.Operators
public IStreamCalculator CreateCalculator()
{
ISigner sig = SignerUtilities.GetSigner(algorithm);
-
+ ICipherParameters cp = privateKey;
if (random != null)
{
- sig.Init(true, new ParametersWithRandom(privateKey, random));
+ cp = new ParametersWithRandom(cp, random);
}
- else
- {
- sig.Init(true, privateKey);
- }
-
+ sig.Init(true, cp);
return new SigCalculator(sig);
}
@@ -437,7 +442,8 @@ namespace Org.BouncyCastle.Crypto.Operators
/// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
/// signature algorithm details.
/// </summary>
- public class Asn1VerifierFactory: IVerifierFactory
+ public class Asn1VerifierFactory
+ : IVerifierFactory
{
private readonly AlgorithmIdentifier algID;
private readonly AsymmetricKeyParameter publicKey;
@@ -447,15 +453,22 @@ namespace Org.BouncyCastle.Crypto.Operators
/// </summary>
/// <param name="algorithm">The name of the signature algorithm to use.</param>
/// <param name="publicKey">The public key to be used in the verification operation.</param>
- public Asn1VerifierFactory (String algorithm, AsymmetricKeyParameter publicKey)
+ public Asn1VerifierFactory(string algorithm, AsymmetricKeyParameter publicKey)
{
- DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+ if (algorithm == null)
+ throw new ArgumentNullException("algorithm");
+ if (publicKey == null)
+ throw new ArgumentNullException("publicKey");
+ if (publicKey.IsPrivate)
+ throw new ArgumentException("Key for verifying must be public", "publicKey");
+
+ DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm);
this.publicKey = publicKey;
- this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+ this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm);
}
- public Asn1VerifierFactory (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
+ public Asn1VerifierFactory(AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
{
this.publicKey = publicKey;
this.algID = algorithm;
@@ -540,7 +553,7 @@ namespace Org.BouncyCastle.Crypto.Operators
public IVerifierFactory CreateVerifierFactory(Object algorithmDetails)
{
- return new Asn1VerifierFactory ((AlgorithmIdentifier)algorithmDetails, publicKey);
+ return new Asn1VerifierFactory((AlgorithmIdentifier)algorithmDetails, publicKey);
}
/// <summary>
diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs
index 32a86e503..64d29863b 100644
--- a/crypto/src/crypto/tls/DefaultTlsClient.cs
+++ b/crypto/src/crypto/tls/DefaultTlsClient.cs
@@ -14,14 +14,22 @@ namespace Org.BouncyCastle.Crypto.Tls
public abstract class DefaultTlsClient
: AbstractTlsClient
{
+ protected TlsDHVerifier mDHVerifier;
+
public DefaultTlsClient()
- : base()
+ : this(new DefaultTlsCipherFactory())
{
}
public DefaultTlsClient(TlsCipherFactory cipherFactory)
- : base(cipherFactory)
+ : this(cipherFactory, new DefaultTlsDHVerifier())
+ {
+ }
+
+ public DefaultTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier)
+ : base(cipherFactory)
{
+ this.mDHVerifier = dhVerifier;
}
public override int[] GetCipherSuites()
@@ -34,12 +42,6 @@ namespace Org.BouncyCastle.Crypto.Tls
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
@@ -85,12 +87,12 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
{
- return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+ return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
}
protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
{
- return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+ return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
}
protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
new file mode 100644
index 000000000..ae26d04c3
--- /dev/null
+++ b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class DefaultTlsDHVerifier
+ : TlsDHVerifier
+ {
+ public static readonly int DefaultMinimumPrimeBits = 2048;
+
+ protected static readonly IList DefaultGroups = Platform.CreateArrayList();
+
+ private static void AddDefaultGroup(DHParameters dhParameters)
+ {
+ DefaultGroups.Add(dhParameters);
+ }
+
+ static DefaultTlsDHVerifier()
+ {
+ AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe2048);
+ AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe3072);
+ AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe4096);
+ AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe6144);
+ AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe8192);
+
+ AddDefaultGroup(DHStandardGroups.rfc3526_1536);
+ AddDefaultGroup(DHStandardGroups.rfc3526_2048);
+ AddDefaultGroup(DHStandardGroups.rfc3526_3072);
+ AddDefaultGroup(DHStandardGroups.rfc3526_4096);
+ AddDefaultGroup(DHStandardGroups.rfc3526_6144);
+ AddDefaultGroup(DHStandardGroups.rfc3526_8192);
+ }
+
+ // IList is (DHParameters)
+ protected readonly IList mGroups;
+ protected readonly int mMinimumPrimeBits;
+
+ /// <summary>Accept various standard DH groups with 'P' at least <c>DefaultMinimumPrimeBits</c> bits.</summary>
+ public DefaultTlsDHVerifier()
+ : this(DefaultMinimumPrimeBits)
+ {
+ }
+
+ /// <summary>Accept various standard DH groups with 'P' at least the specified number of bits.</summary>
+ public DefaultTlsDHVerifier(int minimumPrimeBits)
+ : this(DefaultGroups, minimumPrimeBits)
+ {
+ }
+
+ /// <summary>Accept a custom set of group parameters, subject to a minimum bitlength for 'P'.</summary>
+ /// <param name="groups">An <c>IList</c> of acceptable <c>DHParameters</c>.</param>
+ /// <param name="minimumPrimeBits">The minimum acceptable bitlength of the 'P' parameter.</param>
+ public DefaultTlsDHVerifier(IList groups, int minimumPrimeBits)
+ {
+ this.mGroups = groups;
+ this.mMinimumPrimeBits = minimumPrimeBits;
+ }
+
+ public virtual bool Accept(DHParameters dhParameters)
+ {
+ return CheckMinimumPrimeBits(dhParameters) && CheckGroup(dhParameters);
+ }
+
+ public virtual int MinimumPrimeBits
+ {
+ get { return mMinimumPrimeBits; }
+ }
+
+ protected virtual bool AreGroupsEqual(DHParameters a, DHParameters b)
+ {
+ return a == b || (AreParametersEqual(a.P, b.P) && AreParametersEqual(a.G, b.G));
+ }
+
+ protected virtual bool AreParametersEqual(BigInteger a, BigInteger b)
+ {
+ return a == b || a.Equals(b);
+ }
+
+ protected virtual bool CheckGroup(DHParameters dhParameters)
+ {
+ foreach (DHParameters group in mGroups)
+ {
+ if (AreGroupsEqual(dhParameters, group))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected virtual bool CheckMinimumPrimeBits(DHParameters dhParameters)
+ {
+ return dhParameters.P.BitLength >= MinimumPrimeBits;
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs
index 97eaa079d..90f357687 100644
--- a/crypto/src/crypto/tls/DefaultTlsServer.cs
+++ b/crypto/src/crypto/tls/DefaultTlsServer.cs
@@ -138,12 +138,12 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
{
- return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+ return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
}
protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
{
- return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+ return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
}
protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 2ef80dcfd..d5fa43543 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -6,16 +6,23 @@ namespace Org.BouncyCastle.Crypto.Tls
public class PskTlsClient
: AbstractTlsClient
{
+ protected TlsDHVerifier mDHVerifier;
protected TlsPskIdentity mPskIdentity;
public PskTlsClient(TlsPskIdentity pskIdentity)
- : this(new DefaultTlsCipherFactory(), pskIdentity)
+ : this(new DefaultTlsCipherFactory(), pskIdentity)
{
}
public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
- : base(cipherFactory)
+ : this(cipherFactory, new DefaultTlsDHVerifier(), pskIdentity)
{
+ }
+
+ public PskTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity)
+ : base(cipherFactory)
+ {
+ this.mDHVerifier = dhVerifier;
this.mPskIdentity = pskIdentity;
}
@@ -25,8 +32,6 @@ namespace Org.BouncyCastle.Crypto.Tls
{
CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA
};
}
@@ -63,8 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
{
- return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves,
- mClientECPointFormats, mServerECPointFormats);
+ return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mDHVerifier, null,
+ mNamedCurves, mClientECPointFormats, mServerECPointFormats);
}
}
}
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
index b0fb67c04..a3778420d 100644
--- a/crypto/src/crypto/tls/PskTlsServer.cs
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -87,7 +87,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
{
return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager,
- GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
+ null, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
}
}
}
diff --git a/crypto/src/crypto/tls/ServerDHParams.cs b/crypto/src/crypto/tls/ServerDHParams.cs
deleted file mode 100644
index b09262771..000000000
--- a/crypto/src/crypto/tls/ServerDHParams.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
- public class ServerDHParams
- {
- protected readonly DHPublicKeyParameters mPublicKey;
-
- public ServerDHParams(DHPublicKeyParameters publicKey)
- {
- if (publicKey == null)
- throw new ArgumentNullException("publicKey");
-
- this.mPublicKey = publicKey;
- }
-
- public virtual DHPublicKeyParameters PublicKey
- {
- get { return mPublicKey; }
- }
-
- /**
- * Encode this {@link ServerDHParams} to a {@link Stream}.
- *
- * @param output
- * the {@link Stream} to encode to.
- * @throws IOException
- */
- public virtual void Encode(Stream output)
- {
- DHParameters dhParameters = mPublicKey.Parameters;
- BigInteger Ys = mPublicKey.Y;
-
- TlsDHUtilities.WriteDHParameter(dhParameters.P, output);
- TlsDHUtilities.WriteDHParameter(dhParameters.G, output);
- TlsDHUtilities.WriteDHParameter(Ys, output);
- }
-
- /**
- * Parse a {@link ServerDHParams} from a {@link Stream}.
- *
- * @param input
- * the {@link Stream} to parse from.
- * @return a {@link ServerDHParams} object.
- * @throws IOException
- */
- public static ServerDHParams Parse(Stream input)
- {
- BigInteger p = TlsDHUtilities.ReadDHParameter(input);
- BigInteger g = TlsDHUtilities.ReadDHParameter(input);
- BigInteger Ys = TlsDHUtilities.ReadDHParameter(input);
-
- return new ServerDHParams(
- TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g))));
- }
- }
-}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index d179068bb..59d52265b 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Tls
@@ -14,6 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls
: AbstractTlsKeyExchange
{
protected TlsSigner mTlsSigner;
+ protected TlsDHVerifier mDHVerifier;
protected DHParameters mDHParameters;
protected AsymmetricKeyParameter mServerPublicKey;
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected DHPrivateKeyParameters mDHAgreePrivateKey;
protected DHPublicKeyParameters mDHAgreePublicKey;
- public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+ public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
: base(keyExchange, supportedSignatureAlgorithms)
{
switch (keyExchange)
@@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tls
throw new InvalidOperationException("unsupported key exchange algorithm");
}
+ this.mDHVerifier = dhVerifier;
this.mDHParameters = dhParameters;
}
@@ -84,8 +85,8 @@ namespace Org.BouncyCastle.Crypto.Tls
{
try
{
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
- this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+ this.mDHAgreePublicKey = (DHPublicKeyParameters)this.mServerPublicKey;
+ this.mDHParameters = mDHAgreePublicKey.Parameters;
}
catch (InvalidCastException e)
{
@@ -143,10 +144,8 @@ namespace Org.BouncyCastle.Crypto.Tls
// DH_anon is handled here, DHE_* in a subclass
- ServerDHParams dhParams = ServerDHParams.Parse(input);
-
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
- this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+ this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+ this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
}
public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
@@ -223,9 +222,7 @@ namespace Org.BouncyCastle.Crypto.Tls
return;
}
- BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+ this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
}
public override byte[] GeneratePremasterSecret()
@@ -242,18 +239,5 @@ namespace Org.BouncyCastle.Crypto.Tls
throw new TlsFatalAlert(AlertDescription.internal_error);
}
-
- protected virtual int MinimumPrimeBits
- {
- get { return 1024; }
- }
-
- protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
- {
- if (parameters.P.BitLength < MinimumPrimeBits)
- throw new TlsFatalAlert(AlertDescription.insufficient_security);
-
- return TlsDHUtilities.ValidateDHParameters(parameters);
- }
}
}
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 6df61cbed..9567ee062 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -417,46 +417,43 @@ namespace Org.BouncyCastle.Crypto.Tls
AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams);
DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public;
- new ServerDHParams(dhPublic).Encode(output);
+ WriteDHParameters(dhParams, output);
+ WriteDHParameter(dhPublic.Y, output);
return (DHPrivateKeyParameters)kp.Private;
}
- public static DHParameters ValidateDHParameters(DHParameters parameters)
+ public static BigInteger ReadDHParameter(Stream input)
{
- BigInteger p = parameters.P;
- BigInteger g = parameters.G;
-
- if (!p.IsProbablePrime(2))
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-
-
- return parameters;
+ return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
}
- public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+ public static DHParameters ReadDHParameters(Stream input)
{
- DHParameters parameters = ValidateDHParameters(key.Parameters);
-
- BigInteger Y = key.Y;
- if (Y.CompareTo(Two) < 0 || Y.CompareTo(parameters.P.Subtract(Two)) > 0)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ BigInteger p = ReadDHParameter(input);
+ BigInteger g = ReadDHParameter(input);
- // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
-
- return key;
+ return new DHParameters(p, g);
}
- public static BigInteger ReadDHParameter(Stream input)
+ public static DHParameters ReceiveDHParameters(TlsDHVerifier dhVerifier, Stream input)
{
- return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
+ DHParameters dhParameters = ReadDHParameters(input);
+ if (!dhVerifier.Accept(dhParameters))
+ throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+ return dhParameters;
}
public static void WriteDHParameter(BigInteger x, Stream output)
{
TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output);
}
+
+ public static void WriteDHParameters(DHParameters dhParameters, Stream output)
+ {
+ WriteDHParameter(dhParameters.P, output);
+ WriteDHParameter(dhParameters.G, output);
+ }
}
}
diff --git a/crypto/src/crypto/tls/TlsDHVerifier.cs b/crypto/src/crypto/tls/TlsDHVerifier.cs
new file mode 100644
index 000000000..867403c3c
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsDHVerifier.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /// <summary>An interface for verifying that Diffie-Hellman parameters are acceptable.</summary>
+ public interface TlsDHVerifier
+ {
+ /// <summary>Verify that the given <c>DHParameters</c> are acceptable.</summary>
+ /// <param name="dhParameters">The <c>DHParameters</c> to verify.</param>
+ /// <returns>true if (and only if) the specified parameters are acceptable.</returns>
+ bool Accept(DHParameters dhParameters);
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index cdd629247..402c74720 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -3,7 +3,6 @@ using System.Collections;
using System.IO;
using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;
@@ -14,8 +13,8 @@ namespace Org.BouncyCastle.Crypto.Tls
{
protected TlsSignerCredentials mServerCredentials = null;
- public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
- : base(keyExchange, supportedSignatureAlgorithms, dhParameters)
+ public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
+ : base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters)
{
}
@@ -69,7 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls
SignerInputBuffer buf = new SignerInputBuffer();
Stream teeIn = new TeeInputStream(input, buf);
- ServerDHParams dhParams = ServerDHParams.Parse(teeIn);
+ this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, teeIn);
+ this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(teeIn), mDHParameters);
DigitallySigned signed_params = ParseSignature(input);
@@ -77,9 +77,6 @@ namespace Org.BouncyCastle.Crypto.Tls
buf.UpdateSigner(signer);
if (!signer.VerifySignature(signed_params.Signature))
throw new TlsFatalAlert(AlertDescription.decrypt_error);
-
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
- this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
}
protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index 0af7f7a69..36ef09e85 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
@@ -18,6 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected TlsPskIdentity mPskIdentity;
protected TlsPskIdentityManager mPskIdentityManager;
+ protected TlsDHVerifier mDHVerifier;
protected DHParameters mDHParameters;
protected int[] mNamedCurves;
protected byte[] mClientECPointFormats, mServerECPointFormats;
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected byte[] mPremasterSecret;
public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
- TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
+ TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves,
byte[] clientECPointFormats, byte[] serverECPointFormats)
: base(keyExchange, supportedSignatureAlgorithms)
{
@@ -54,6 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mPskIdentity = pskIdentity;
this.mPskIdentityManager = pskIdentityManager;
+ this.mDHVerifier = dhVerifier;
this.mDHParameters = dhParameters;
this.mNamedCurves = namedCurves;
this.mClientECPointFormats = clientECPointFormats;
@@ -162,10 +163,8 @@ namespace Org.BouncyCastle.Crypto.Tls
if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
- ServerDHParams serverDHParams = ServerDHParams.Parse(input);
-
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey);
- this.mDHParameters = mDHAgreePublicKey.Parameters;
+ this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+ this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
@@ -240,9 +239,7 @@ namespace Org.BouncyCastle.Crypto.Tls
if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
- BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+ this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 24dc9b1cc..34bda3815 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -210,71 +210,73 @@ namespace Org.BouncyCastle.Pkcs
/// <param name="publicKey">Public Key to be included in cert reqest.</param>
/// <param name="attributes">ASN1Set of Attributes.</param>
/// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
- [Obsolete("Use constructor with an ISignatureFactory")]
public Pkcs10CertificationRequest(
string signatureAlgorithm,
X509Name subject,
AsymmetricKeyParameter publicKey,
Asn1Set attributes,
AsymmetricKeyParameter signingKey)
+ : this(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes)
{
- if (signatureAlgorithm == null)
- throw new ArgumentNullException("signatureAlgorithm");
- if (subject == null)
- throw new ArgumentNullException("subject");
- if (publicKey == null)
- throw new ArgumentNullException("publicKey");
- if (publicKey.IsPrivate)
- throw new ArgumentException("expected public key", "publicKey");
- if (!signingKey.IsPrivate)
- throw new ArgumentException("key for signing must be private", "signingKey");
-
- init(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes, signingKey);
}
/// <summary>
/// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
/// </summary>
- ///<param name="signatureCalculatorFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
+ ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
/// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
/// <param name="publicKey">Public Key to be included in cert reqest.</param>
/// <param name="attributes">ASN1Set of Attributes.</param>
- /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+ /// <param name="signingKey">Ignored.</param>
+ [Obsolete("Use constructor without 'signingKey' parameter (ignored here)")]
public Pkcs10CertificationRequest(
- ISignatureFactory signatureCalculatorFactory,
+ ISignatureFactory signatureFactory,
X509Name subject,
AsymmetricKeyParameter publicKey,
Asn1Set attributes,
AsymmetricKeyParameter signingKey)
+ : this(signatureFactory, subject, publicKey, attributes)
{
- if (signatureCalculatorFactory == null)
- throw new ArgumentNullException("signatureCalculator");
+ }
+
+ /// <summary>
+ /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+ /// </summary>
+ ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
+ /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+ /// <param name="publicKey">Public Key to be included in cert reqest.</param>
+ /// <param name="attributes">ASN1Set of Attributes.</param>
+ public Pkcs10CertificationRequest(
+ ISignatureFactory signatureFactory,
+ X509Name subject,
+ AsymmetricKeyParameter publicKey,
+ Asn1Set attributes)
+ {
+ if (signatureFactory == null)
+ throw new ArgumentNullException("signatureFactory");
if (subject == null)
throw new ArgumentNullException("subject");
if (publicKey == null)
throw new ArgumentNullException("publicKey");
if (publicKey.IsPrivate)
throw new ArgumentException("expected public key", "publicKey");
- if (!signingKey.IsPrivate)
- throw new ArgumentException("key for signing must be private", "signingKey");
- init(signatureCalculatorFactory, subject, publicKey, attributes, signingKey);
+ Init(signatureFactory, subject, publicKey, attributes);
}
- private void init(
- ISignatureFactory signatureCalculator,
+ private void Init(
+ ISignatureFactory signatureFactory,
X509Name subject,
AsymmetricKeyParameter publicKey,
- Asn1Set attributes,
- AsymmetricKeyParameter signingKey)
+ Asn1Set attributes)
{
- this.sigAlgId = (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails;
+ this.sigAlgId = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
- IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+ IStreamCalculator streamCalculator = signatureFactory.CreateCalculator();
byte[] reqInfoData = reqInfo.GetDerEncoded();
diff --git a/crypto/src/x509/store/X509CertStoreSelector.cs b/crypto/src/x509/store/X509CertStoreSelector.cs
index 3874edf1d..f92a4ac03 100644
--- a/crypto/src/x509/store/X509CertStoreSelector.cs
+++ b/crypto/src/x509/store/X509CertStoreSelector.cs
@@ -21,6 +21,7 @@ namespace Org.BouncyCastle.X509.Store
private X509Certificate certificate;
private DateTimeObject certificateValid;
private ISet extendedKeyUsage;
+ private bool ignoreX509NameOrdering;
private X509Name issuer;
private bool[] keyUsage;
private ISet policy;
@@ -43,6 +44,7 @@ namespace Org.BouncyCastle.X509.Store
this.certificate = o.Certificate;
this.certificateValid = o.CertificateValid;
this.extendedKeyUsage = o.ExtendedKeyUsage;
+ this.ignoreX509NameOrdering = o.IgnoreX509NameOrdering;
this.issuer = o.Issuer;
this.keyUsage = o.KeyUsage;
this.policy = o.Policy;
@@ -95,6 +97,12 @@ namespace Org.BouncyCastle.X509.Store
set { extendedKeyUsage = CopySet(value); }
}
+ public bool IgnoreX509NameOrdering
+ {
+ get { return ignoreX509NameOrdering; }
+ set { this.ignoreX509NameOrdering = value; }
+ }
+
public X509Name Issuer
{
get { return issuer; }
@@ -140,7 +148,8 @@ namespace Org.BouncyCastle.X509.Store
set { subject = value; }
}
- public string SubjectAsString
+ [Obsolete("Avoid working with X509Name objects in string form")]
+ public string SubjectAsString
{
get { return subject != null ? subject.ToString() : null; }
}
@@ -212,7 +221,7 @@ namespace Org.BouncyCastle.X509.Store
}
}
- if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
+ if (issuer != null && !issuer.Equivalent(c.IssuerDN, !ignoreX509NameOrdering))
return false;
if (keyUsage != null)
@@ -277,7 +286,7 @@ namespace Org.BouncyCastle.X509.Store
if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
return false;
- if (subject != null && !subject.Equivalent(c.SubjectDN, true))
+ if (subject != null && !subject.Equivalent(c.SubjectDN, !ignoreX509NameOrdering))
return false;
if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs
index 39af21137..781e92ba5 100644
--- a/crypto/test/src/crypto/test/OAEPTest.cs
+++ b/crypto/test/src/crypto/test/OAEPTest.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
@@ -780,8 +781,10 @@ namespace Org.BouncyCastle.Crypto.Tests
OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
+ TestForHighByteError("invalidCiphertextOaepTest 1024", 1024);
+
//
- // OAEP - public encrypt, private decrypt differring hashes
+ // OAEP - public encrypt, private decrypt, differing hashes
//
IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), new byte[10]);
@@ -822,8 +825,78 @@ namespace Org.BouncyCastle.Crypto.Tests
}
}
- public static void MainOld(
- string[] args)
+ private void TestForHighByteError(string label, int keySizeBits)
+ {
+ // draw a key of the size asked
+ BigInteger e = BigInteger.One.ShiftLeft(16).Add(BigInteger.One);
+
+ IAsymmetricCipherKeyPairGenerator kpGen = new RsaKeyPairGenerator();
+
+ kpGen.Init(new RsaKeyGenerationParameters(e, new SecureRandom(), keySizeBits, 100));
+
+ AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+ IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine());
+
+ // obtain a known good ciphertext
+ cipher.Init(true, new ParametersWithRandom(kp.Public, new VecRand(seed)));
+ byte[] m = { 42 };
+ byte[] c = cipher.ProcessBlock(m, 0, m.Length);
+ int keySizeBytes = (keySizeBits + 7) / 8;
+ if (c.Length != keySizeBytes)
+ {
+ Fail(label + " failed ciphertext size");
+ }
+
+ BigInteger n = ((RsaPrivateCrtKeyParameters)kp.Private).Modulus;
+
+ // decipher
+ cipher.Init(false, kp.Private);
+ byte[] r = cipher.ProcessBlock(c, 0, keySizeBytes);
+ if (r.Length != 1 || r[0] != 42)
+ {
+ Fail(label + " failed first decryption of test message");
+ }
+
+ // decipher again
+ r = cipher.ProcessBlock(c, 0, keySizeBytes);
+ if (r.Length != 1 || r[0] != 42)
+ {
+ Fail(label + " failed second decryption of test message");
+ }
+
+ // check hapazard incorrect ciphertexts
+ for (int i = keySizeBytes * 8; --i >= 0; )
+ {
+ c[i / 8] ^= (byte)(1 << (i & 7));
+ bool ko = true;
+ try
+ {
+ BigInteger cV = new BigInteger(1, c);
+
+ // don't pass in c if it will be rejected trivially
+ if (cV.CompareTo(n) < 0)
+ {
+ r = cipher.ProcessBlock(c, 0, keySizeBytes);
+ }
+ else
+ {
+ ko = false; // size errors are picked up at start
+ }
+ }
+ catch (InvalidCipherTextException)
+ {
+ ko = false;
+ }
+ if (ko)
+ {
+ Fail(label + " invalid ciphertext caused no exception");
+ }
+ c[i / 8] ^= (byte)(1 << (i & 7));
+ }
+ }
+
+ public static void MainOld(string[] args)
{
RunTest(new OaepTest());
}
|