Skip to content

Commit

Permalink
Add Prehash digest for safer raw signers
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdettman committed Jan 29, 2024
1 parent e253567 commit 5ad15ee
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 7 deletions.
69 changes: 69 additions & 0 deletions crypto/src/crypto/digests/Prehash.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
9 changes: 6 additions & 3 deletions crypto/src/crypto/signers/PssSigner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,22 @@ public class PssSigner

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(
Expand Down
3 changes: 1 addition & 2 deletions crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
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
Expand Down
3 changes: 1 addition & 2 deletions crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ public override bool VerifyRawSignature(DigitallySigned digitallySigned, byte[]
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);
Expand Down
58 changes: 58 additions & 0 deletions crypto/src/util/io/LimitedBuffer.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

0 comments on commit 5ad15ee

Please sign in to comment.