diff options
-rw-r--r-- | crypto/src/cms/SignerInformation.cs | 24 | ||||
-rw-r--r-- | crypto/src/crypto/digests/NullDigest.cs | 24 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs | 3 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/X448PrivateKeyParameters.cs | 3 | ||||
-rw-r--r-- | crypto/src/crypto/signers/Ed25519Signer.cs | 11 | ||||
-rw-r--r-- | crypto/src/crypto/signers/Ed25519ctxSigner.cs | 11 | ||||
-rw-r--r-- | crypto/src/crypto/signers/Ed25519phSigner.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/signers/Ed448Signer.cs | 11 | ||||
-rw-r--r-- | crypto/src/crypto/signers/Ed448phSigner.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsProtocol.cs | 29 | ||||
-rw-r--r-- | crypto/src/math/ec/rfc7748/X25519.cs | 8 | ||||
-rw-r--r-- | crypto/src/math/ec/rfc7748/X448.cs | 8 | ||||
-rw-r--r-- | crypto/src/util/Arrays.cs | 10 | ||||
-rw-r--r-- | crypto/src/util/io/Streams.cs | 25 |
14 files changed, 130 insertions, 45 deletions
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs index dad128263..39ecfa6d3 100644 --- a/crypto/src/cms/SignerInformation.cs +++ b/crypto/src/cms/SignerInformation.cs @@ -84,6 +84,30 @@ namespace Org.BouncyCastle.Cms this.digestCalculator = digestCalculator; } + /** + * Protected constructor. In some cases clients have their own idea about how to encode + * the signed attributes and calculate the signature. This constructor is to allow developers + * to deal with that by extending off the class and overridng methods like getSignedAttributes(). + * + * @param baseInfo the SignerInformation to base this one on. + */ + protected SignerInformation(SignerInformation baseInfo) + { + this.info = baseInfo.info; + this.contentType = baseInfo.contentType; + this.isCounterSignature = baseInfo.IsCounterSignature; + this.sid = baseInfo.SignerID; + this.digestAlgorithm = info.DigestAlgorithm; + this.signedAttributeSet = info.AuthenticatedAttributes; + this.unsignedAttributeSet = info.UnauthenticatedAttributes; + this.encryptionAlgorithm = info.DigestEncryptionAlgorithm; + this.signature = info.EncryptedDigest.GetOctets(); + this.content = baseInfo.content; + this.resultDigest = baseInfo.resultDigest; + this.signedAttributeTable = baseInfo.signedAttributeTable; + this.unsignedAttributeTable = baseInfo.unsignedAttributeTable; + } + public bool IsCounterSignature { get { return isCounterSignature; } diff --git a/crypto/src/crypto/digests/NullDigest.cs b/crypto/src/crypto/digests/NullDigest.cs index e598cb145..76b69afbf 100644 --- a/crypto/src/crypto/digests/NullDigest.cs +++ b/crypto/src/crypto/digests/NullDigest.cs @@ -1,6 +1,8 @@ using System; using System.IO; +using Org.BouncyCastle.Utilities.IO; + namespace Org.BouncyCastle.Crypto.Digests { public class NullDigest : IDigest @@ -20,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Digests public int GetDigestSize() { - return (int) bOut.Length; + return (int)bOut.Length; } public void Update(byte b) @@ -33,15 +35,19 @@ namespace Org.BouncyCastle.Crypto.Digests bOut.Write(inBytes, inOff, len); } - public int DoFinal(byte[] outBytes, int outOff) + public int DoFinal(byte[] outBytes, int outOff) { - byte[] res = bOut.ToArray(); - res.CopyTo(outBytes, outOff); - Reset(); - return res.Length; - } - - public void Reset() + try + { + return Streams.WriteBufTo(bOut, outBytes, outOff); + } + finally + { + Reset(); + } + } + + public void Reset() { bOut.SetLength(0); } diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs index c25ab9364..fb49a02b3 100644 --- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs @@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters { byte[] encoded = new byte[X25519.PointSize]; publicKey.Encode(encoded, 0); - X25519.ScalarMult(data, 0, encoded, 0, buf, off); + if (!X25519.CalculateAgreement(data, 0, encoded, 0, buf, off)) + throw new InvalidOperationException("X25519 agreement failed"); } } } diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs index 291eac10f..d17aa7947 100644 --- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs @@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters { byte[] encoded = new byte[X448.PointSize]; publicKey.Encode(encoded, 0); - X448.ScalarMult(data, 0, encoded, 0, buf, off); + if (!X448.CalculateAgreement(data, 0, encoded, 0, buf, off)) + throw new InvalidOperationException("X448 agreement failed"); } } } diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs index 904450ed1..1b3142c7b 100644 --- a/crypto/src/crypto/signers/Ed25519Signer.cs +++ b/crypto/src/crypto/signers/Ed25519Signer.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Signers { @@ -58,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual byte[] GenerateSignature() { - if (!forSigning) + if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed25519Signer not initialised for signature generation."); return buffer.GenerateSignature(privateKey, publicKey); @@ -66,7 +67,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual bool VerifySignature(byte[] signature) { - if (forSigning) + if (forSigning || null == publicKey) throw new InvalidOperationException("Ed25519Signer not initialised for verification"); return buffer.VerifySignature(publicKey, signature); @@ -114,12 +115,12 @@ namespace Org.BouncyCastle.Crypto.Signers [MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { + long count = Position; #if PORTABLE this.Position = 0L; - - // TODO Clear using Write method + Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs index e9c2eca44..965453011 100644 --- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs +++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Signers { @@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual byte[] GenerateSignature() { - if (!forSigning) + if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation."); return buffer.GenerateSignature(privateKey, publicKey, context); @@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual bool VerifySignature(byte[] signature) { - if (forSigning) + if (forSigning || null == publicKey) throw new InvalidOperationException("Ed25519ctxSigner not initialised for verification"); return buffer.VerifySignature(publicKey, context, signature); @@ -116,12 +117,12 @@ namespace Org.BouncyCastle.Crypto.Signers [MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { + long count = Position; #if PORTABLE this.Position = 0L; - - // TODO Clear using Write method + Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs index 0d3de96f3..3318f6438 100644 --- a/crypto/src/crypto/signers/Ed25519phSigner.cs +++ b/crypto/src/crypto/signers/Ed25519phSigner.cs @@ -60,7 +60,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual byte[] GenerateSignature() { - if (!forSigning) + if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed25519phSigner not initialised for signature generation."); byte[] msg = new byte[Ed25519.PrehashSize]; @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual bool VerifySignature(byte[] signature) { - if (forSigning) + if (forSigning || null == publicKey) throw new InvalidOperationException("Ed25519phSigner not initialised for verification"); byte[] pk = publicKey.GetEncoded(); diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs index c01d84b4d..d18f956a8 100644 --- a/crypto/src/crypto/signers/Ed448Signer.cs +++ b/crypto/src/crypto/signers/Ed448Signer.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Signers { @@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual byte[] GenerateSignature() { - if (!forSigning) + if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed448Signer not initialised for signature generation."); return buffer.GenerateSignature(privateKey, publicKey, context); @@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual bool VerifySignature(byte[] signature) { - if (forSigning) + if (forSigning || null == publicKey) throw new InvalidOperationException("Ed448Signer not initialised for verification"); return buffer.VerifySignature(publicKey, context, signature); @@ -116,12 +117,12 @@ namespace Org.BouncyCastle.Crypto.Signers [MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { + long count = Position; #if PORTABLE this.Position = 0L; - - // TODO Clear using Write method + Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs index 50d0a0154..b86d0855c 100644 --- a/crypto/src/crypto/signers/Ed448phSigner.cs +++ b/crypto/src/crypto/signers/Ed448phSigner.cs @@ -60,7 +60,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual byte[] GenerateSignature() { - if (!forSigning) + if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed448phSigner not initialised for signature generation."); byte[] msg = new byte[Ed448.PrehashSize]; @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers public virtual bool VerifySignature(byte[] signature) { - if (forSigning) + if (forSigning || null == publicKey) throw new InvalidOperationException("Ed448phSigner not initialised for verification"); byte[] pk = publicKey.GetEncoded(); diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 72151d414..bbb76d53c 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -391,31 +391,30 @@ namespace Org.BouncyCastle.Crypto.Tls if (queue.Available < totalLength) break; - CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished); - /* * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages * starting at client hello up to, but not including, this finished message. * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes. */ - switch (type) - { - case HandshakeType.hello_request: - break; - case HandshakeType.finished: - default: + if (HandshakeType.hello_request != type) { - TlsContext ctx = Context; - if (type == HandshakeType.finished - && this.mExpectedVerifyData == null - && ctx.SecurityParameters.MasterSecret != null) + if (HandshakeType.finished == type) { - this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); + CheckReceivedChangeCipherSpec(true); + + TlsContext ctx = Context; + if (this.mExpectedVerifyData == null + && ctx.SecurityParameters.MasterSecret != null) + { + this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); + } + } + else + { + CheckReceivedChangeCipherSpec(mConnectionState == CS_END); } queue.CopyTo(mRecordStream.HandshakeHashUpdater, totalLength); - break; - } } queue.RemoveData(4); diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs index d63cc5a3e..6b6acdecd 100644 --- a/crypto/src/math/ec/rfc7748/X25519.cs +++ b/crypto/src/math/ec/rfc7748/X25519.cs @@ -2,6 +2,8 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using Org.BouncyCastle.Utilities; + namespace Org.BouncyCastle.Math.EC.Rfc7748 { public abstract class X25519 @@ -21,6 +23,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 private static int[] precompBase = null; + public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) + { + ScalarMult(k, kOff, u, uOff, r, rOff); + return !Arrays.AreAllZeroes(r, rOff, PointSize); + } + private static uint Decode32(byte[] bs, int off) { uint n = bs[off]; diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs index aac603b08..b93cb24c5 100644 --- a/crypto/src/math/ec/rfc7748/X448.cs +++ b/crypto/src/math/ec/rfc7748/X448.cs @@ -2,6 +2,8 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using Org.BouncyCastle.Utilities; + namespace Org.BouncyCastle.Math.EC.Rfc7748 { public abstract class X448 @@ -24,6 +26,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 private static uint[] precompBase = null; + public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) + { + ScalarMult(k, kOff, u, uOff, r, rOff); + return !Arrays.AreAllZeroes(r, rOff, PointSize); + } + private static uint Decode32(byte[] bs, int off) { uint n = bs[off]; diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index 3df908240..a9a574dbf 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -11,6 +11,16 @@ namespace Org.BouncyCastle.Utilities public static readonly byte[] EmptyBytes = new byte[0]; public static readonly int[] EmptyInts = new int[0]; + public static bool AreAllZeroes(byte[] buf, int off, int len) + { + uint bits = 0; + for (int i = 0; i < len; ++i) + { + bits |= buf[off + i]; + } + return bits == 0; + } + public static bool AreEqual( bool[] a, bool[] b) diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs index cc7fa924c..503a1b4f1 100644 --- a/crypto/src/util/io/Streams.cs +++ b/crypto/src/util/io/Streams.cs @@ -96,5 +96,30 @@ namespace Org.BouncyCastle.Utilities.IO { buf.WriteTo(output); } + + /// <exception cref="IOException"></exception> + public static int WriteBufTo(MemoryStream buf, byte[] output, int offset) + { +#if PORTABLE + byte[] bytes = buf.ToArray(); + bytes.CopyTo(output, offset); + return bytes.Length; +#else + int size = (int)buf.Length; + buf.WriteTo(new MemoryStream(output, offset, size, true)); + return size; +#endif + } + + public static void WriteZeroes(Stream outStr, long count) + { + byte[] zeroes = new byte[BufferSize]; + while (count > BufferSize) + { + outStr.Write(zeroes, 0, BufferSize); + count -= BufferSize; + } + outStr.Write(zeroes, 0, (int)count); + } } } |