diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2024-01-29 17:32:32 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2024-01-29 17:32:32 +0700 |
commit | 5ad15eeceb4678bce4fccc158312e89076ad2952 (patch) | |
tree | a235570743f236cc567502199f4a19a61ba32191 | |
parent | Add contributor entry (diff) | |
download | BouncyCastle.NET-ed25519-5ad15eeceb4678bce4fccc158312e89076ad2952.tar.xz |
Add Prehash digest for safer raw signers
-rw-r--r-- | crypto/src/crypto/digests/Prehash.cs | 69 | ||||
-rw-r--r-- | crypto/src/crypto/signers/PssSigner.cs | 9 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs | 3 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs | 3 | ||||
-rw-r--r-- | crypto/src/util/io/LimitedBuffer.cs | 58 |
5 files changed, 135 insertions, 7 deletions
diff --git a/crypto/src/crypto/digests/Prehash.cs b/crypto/src/crypto/digests/Prehash.cs new file mode 100644 index 000000000..ae7b2ad89 --- /dev/null +++ b/crypto/src/crypto/digests/Prehash.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Digests +{ + public sealed class Prehash + : IDigest + { + public static Prehash ForDigest(IDigest digest) => new Prehash(digest); + + private readonly string m_algorithmName; + private readonly LimitedBuffer m_buf; + + private Prehash(IDigest digest) + { + m_algorithmName = digest.AlgorithmName; + m_buf = new LimitedBuffer(digest.GetDigestSize()); + } + + public string AlgorithmName => m_algorithmName; + + public int GetByteLength() => throw new NotSupportedException(); + + public int GetDigestSize() => m_buf.Limit; + + public void Update(byte input) => m_buf.WriteByte(input); + + public void BlockUpdate(byte[] input, int inOff, int inLen) => m_buf.Write(input, inOff, inLen); + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void BlockUpdate(ReadOnlySpan<byte> input) => m_buf.Write(input); +#endif + + public int DoFinal(byte[] output, int outOff) + { + try + { + if (GetDigestSize() != m_buf.Count) + throw new InvalidOperationException("Incorrect prehash size"); + + return m_buf.CopyTo(output, outOff); + } + finally + { + Reset(); + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int DoFinal(Span<byte> output) + { + try + { + if (GetDigestSize() != m_buf.Count) + throw new InvalidOperationException("Incorrect prehash size"); + + return m_buf.CopyTo(output); + } + finally + { + Reset(); + } + } +#endif + + public void Reset() => m_buf.Reset(); + } +} diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index 2e4c37772..7c2fcd071 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -35,19 +35,22 @@ namespace Org.BouncyCastle.Crypto.Signers public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest digest) { - return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), null, TrailerImplicit); + return new PssSigner(cipher, Prehash.ForDigest(digest), digest, digest, digest.GetDigestSize(), null, + TrailerImplicit); } public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest, int saltLen, byte trailer) { - return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, null, trailer); + return new PssSigner(cipher, Prehash.ForDigest(contentDigest), contentDigest, mgfDigest, saltLen, null, + trailer); } public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest, byte[] salt, byte trailer) { - return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, salt.Length, salt, trailer); + return new PssSigner(cipher, Prehash.ForDigest(contentDigest), contentDigest, mgfDigest, salt.Length, salt, + trailer); } public PssSigner( diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs b/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs index 1b33573f6..5d8892f1f 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs @@ -30,8 +30,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(m_signatureScheme); IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); - PssSigner signer = PssSigner.CreateRawSigner(new RsaBlindedEngine(), digest, digest, digest.GetDigestSize(), - PssSigner.TrailerImplicit); + PssSigner signer = PssSigner.CreateRawSigner(new RsaBlindedEngine(), digest); signer.Init(true, new ParametersWithRandom(m_privateKey, m_crypto.SecureRandom)); signer.BlockUpdate(hash, 0, hash.Length); try diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs b/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs index 18c2082aa..da6c5b11e 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs @@ -31,8 +31,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(m_signatureScheme); IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); - PssSigner verifier = PssSigner.CreateRawSigner(new RsaEngine(), digest, digest, digest.GetDigestSize(), - PssSigner.TrailerImplicit); + PssSigner verifier = PssSigner.CreateRawSigner(new RsaEngine(), digest); verifier.Init(false, m_publicKey); verifier.BlockUpdate(hash, 0, hash.Length); return verifier.VerifySignature(digitallySigned.Signature); diff --git a/crypto/src/util/io/LimitedBuffer.cs b/crypto/src/util/io/LimitedBuffer.cs new file mode 100644 index 000000000..07c9969ad --- /dev/null +++ b/crypto/src/util/io/LimitedBuffer.cs @@ -0,0 +1,58 @@ +using System; + +namespace Org.BouncyCastle.Utilities.IO +{ + public sealed class LimitedBuffer + : BaseOutputStream + { + private readonly byte[] m_buf; + private int m_count; + + public LimitedBuffer(int limit) + { + m_buf = new byte[limit]; + m_count = 0; + } + + public int CopyTo(byte[] buffer, int offset) + { + Array.Copy(m_buf, 0, buffer, offset, m_count); + return m_count; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int CopyTo(Span<byte> buffer) + { + m_buf.AsSpan(0, m_count).CopyTo(buffer); + return m_count; + } +#endif + + public int Count => m_count; + + public int Limit => m_buf.Length; + + public void Reset() + { + m_count = 0; + } + + public override void Write(byte[] buffer, int offset, int count) + { + Array.Copy(buffer, offset, m_buf, m_count, count); + m_count += count; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + buffer.CopyTo(m_buf.AsSpan(m_count)); + } +#endif + + public override void WriteByte(byte value) + { + m_buf[m_count++] = value; + } + } +} |