Skip to content

Commit 5ad15ee

Browse files
committed
Add Prehash digest for safer raw signers
1 parent e253567 commit 5ad15ee

File tree

5 files changed

+135
-7
lines changed

5 files changed

+135
-7
lines changed

crypto/src/crypto/digests/Prehash.cs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System;
2+
3+
using Org.BouncyCastle.Utilities.IO;
4+
5+
namespace Org.BouncyCastle.Crypto.Digests
6+
{
7+
public sealed class Prehash
8+
: IDigest
9+
{
10+
public static Prehash ForDigest(IDigest digest) => new Prehash(digest);
11+
12+
private readonly string m_algorithmName;
13+
private readonly LimitedBuffer m_buf;
14+
15+
private Prehash(IDigest digest)
16+
{
17+
m_algorithmName = digest.AlgorithmName;
18+
m_buf = new LimitedBuffer(digest.GetDigestSize());
19+
}
20+
21+
public string AlgorithmName => m_algorithmName;
22+
23+
public int GetByteLength() => throw new NotSupportedException();
24+
25+
public int GetDigestSize() => m_buf.Limit;
26+
27+
public void Update(byte input) => m_buf.WriteByte(input);
28+
29+
public void BlockUpdate(byte[] input, int inOff, int inLen) => m_buf.Write(input, inOff, inLen);
30+
31+
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
32+
public void BlockUpdate(ReadOnlySpan<byte> input) => m_buf.Write(input);
33+
#endif
34+
35+
public int DoFinal(byte[] output, int outOff)
36+
{
37+
try
38+
{
39+
if (GetDigestSize() != m_buf.Count)
40+
throw new InvalidOperationException("Incorrect prehash size");
41+
42+
return m_buf.CopyTo(output, outOff);
43+
}
44+
finally
45+
{
46+
Reset();
47+
}
48+
}
49+
50+
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
51+
public int DoFinal(Span<byte> output)
52+
{
53+
try
54+
{
55+
if (GetDigestSize() != m_buf.Count)
56+
throw new InvalidOperationException("Incorrect prehash size");
57+
58+
return m_buf.CopyTo(output);
59+
}
60+
finally
61+
{
62+
Reset();
63+
}
64+
}
65+
#endif
66+
67+
public void Reset() => m_buf.Reset();
68+
}
69+
}

crypto/src/crypto/signers/PssSigner.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,22 @@ public class PssSigner
3535

3636
public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest digest)
3737
{
38-
return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), null, TrailerImplicit);
38+
return new PssSigner(cipher, Prehash.ForDigest(digest), digest, digest, digest.GetDigestSize(), null,
39+
TrailerImplicit);
3940
}
4041

4142
public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest,
4243
int saltLen, byte trailer)
4344
{
44-
return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, null, trailer);
45+
return new PssSigner(cipher, Prehash.ForDigest(contentDigest), contentDigest, mgfDigest, saltLen, null,
46+
trailer);
4547
}
4648

4749
public static PssSigner CreateRawSigner(IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest,
4850
byte[] salt, byte trailer)
4951
{
50-
return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, salt.Length, salt, trailer);
52+
return new PssSigner(cipher, Prehash.ForDigest(contentDigest), contentDigest, mgfDigest, salt.Length, salt,
53+
trailer);
5154
}
5255

5356
public PssSigner(

crypto/src/tls/crypto/impl/bc/BcTlsRsaPssSigner.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
3030
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(m_signatureScheme);
3131
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
3232

33-
PssSigner signer = PssSigner.CreateRawSigner(new RsaBlindedEngine(), digest, digest, digest.GetDigestSize(),
34-
PssSigner.TrailerImplicit);
33+
PssSigner signer = PssSigner.CreateRawSigner(new RsaBlindedEngine(), digest);
3534
signer.Init(true, new ParametersWithRandom(m_privateKey, m_crypto.SecureRandom));
3635
signer.BlockUpdate(hash, 0, hash.Length);
3736
try

crypto/src/tls/crypto/impl/bc/BcTlsRsaPssVerifier.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ public override bool VerifyRawSignature(DigitallySigned digitallySigned, byte[]
3131
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(m_signatureScheme);
3232
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
3333

34-
PssSigner verifier = PssSigner.CreateRawSigner(new RsaEngine(), digest, digest, digest.GetDigestSize(),
35-
PssSigner.TrailerImplicit);
34+
PssSigner verifier = PssSigner.CreateRawSigner(new RsaEngine(), digest);
3635
verifier.Init(false, m_publicKey);
3736
verifier.BlockUpdate(hash, 0, hash.Length);
3837
return verifier.VerifySignature(digitallySigned.Signature);

crypto/src/util/io/LimitedBuffer.cs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
3+
namespace Org.BouncyCastle.Utilities.IO
4+
{
5+
public sealed class LimitedBuffer
6+
: BaseOutputStream
7+
{
8+
private readonly byte[] m_buf;
9+
private int m_count;
10+
11+
public LimitedBuffer(int limit)
12+
{
13+
m_buf = new byte[limit];
14+
m_count = 0;
15+
}
16+
17+
public int CopyTo(byte[] buffer, int offset)
18+
{
19+
Array.Copy(m_buf, 0, buffer, offset, m_count);
20+
return m_count;
21+
}
22+
23+
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
24+
public int CopyTo(Span<byte> buffer)
25+
{
26+
m_buf.AsSpan(0, m_count).CopyTo(buffer);
27+
return m_count;
28+
}
29+
#endif
30+
31+
public int Count => m_count;
32+
33+
public int Limit => m_buf.Length;
34+
35+
public void Reset()
36+
{
37+
m_count = 0;
38+
}
39+
40+
public override void Write(byte[] buffer, int offset, int count)
41+
{
42+
Array.Copy(buffer, offset, m_buf, m_count, count);
43+
m_count += count;
44+
}
45+
46+
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
47+
public override void Write(ReadOnlySpan<byte> buffer)
48+
{
49+
buffer.CopyTo(m_buf.AsSpan(m_count));
50+
}
51+
#endif
52+
53+
public override void WriteByte(byte value)
54+
{
55+
m_buf[m_count++] = value;
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)