Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@
<data name="Sign1UnsupportedKey" xml:space="preserve">
<value>Unsupported key '{0}'.</value>
</data>
<data name="Sign1VerifyAlgDoesNotMatchKeyAlgorithm" xml:space="preserve">
<value>COSE algorithm '{0}' does not match the algorithm '{1}' of the specified key.</value>
</data>
<data name="Sign1VerifyAlgHeaderWasIncorrect" xml:space="preserve">
<value>Algorithm header CBOR type was incorrect, expected int or tstr.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -771,18 +771,7 @@ public bool VerifyDetached(CoseKey key, Stream detachedContent, ReadOnlySpan<byt
private bool VerifyCore(CoseKey key, ReadOnlySpan<byte> contentBytes, Stream? contentStream, ReadOnlySpan<byte> associatedData)
{
Debug.Assert(contentStream == null || contentBytes.Length == 0);
ReadOnlyMemory<byte> encodedAlg = CoseHelpers.GetCoseAlgorithmFromProtectedHeaders(ProtectedHeaders);
Comment thread
vcsjones marked this conversation as resolved.

CoseAlgorithm? nullableAlg = CoseHelpers.DecodeCoseAlgorithmHeader(encodedAlg);
if (nullableAlg == null)
{
throw new CryptographicException(SR.Sign1VerifyAlgHeaderWasIncorrect);
}

if (nullableAlg.Value != key.Algorithm)
{
throw new CryptographicException(SR.Format(SR.Sign1UnknownCoseAlgorithm, nullableAlg));
}
ValidateAlgorithm(key);

using (ToBeSignedBuilder toBeSignedBuilder = key.CreateToBeSignedBuilder())
{
Expand Down Expand Up @@ -932,6 +921,7 @@ public Task<bool> VerifyDetachedAsync(CoseKey key, Stream detachedContent, ReadO
throw new InvalidOperationException(SR.ContentWasEmbedded);
}

ValidateAlgorithm(key);
return VerifyAsyncCore(key, detachedContent, associatedData, cancellationToken);
}

Expand Down Expand Up @@ -1048,5 +1038,15 @@ private CoseAlgorithm GetCoseAlgorithmFromProtectedHeaders()

return nullableAlg.Value;
}

private void ValidateAlgorithm(CoseKey key)
{
CoseAlgorithm algorithm = GetCoseAlgorithmFromProtectedHeaders();

if (algorithm != key.Algorithm)
{
throw new CryptographicException(SR.Format(SR.Sign1VerifyAlgDoesNotMatchKeyAlgorithm, algorithm, key.Algorithm));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ public Task<bool> VerifyDetachedAsync(CoseKey key, Stream detachedContent, ReadO
throw new InvalidOperationException(SR.ContentWasEmbedded);
}

ValidateAlgorithm(key);
return VerifyAsyncCore(key, detachedContent, associatedData, cancellationToken);
}

Expand Down Expand Up @@ -644,6 +645,8 @@ private async Task<bool> VerifyAsyncCore(CoseKey key, Stream content, ReadOnlyMe

private bool VerifyCore(CoseKey key, ReadOnlySpan<byte> contentBytes, Stream? contentStream, ReadOnlySpan<byte> associatedData)
{
ValidateAlgorithm(key);

using (ToBeSignedBuilder toBeSignedBuilder = key.CreateToBeSignedBuilder())
{
int bufferLength = CoseMessage.ComputeToBeSignedEncodedSize(
Expand Down Expand Up @@ -685,5 +688,15 @@ private CoseAlgorithm GetCoseAlgorithmFromProtectedHeaders()

return nullableAlg.Value;
}

private void ValidateAlgorithm(CoseKey key)
{
CoseAlgorithm algorithm = GetCoseAlgorithmFromProtectedHeaders();

if (algorithm != key.Algorithm)
{
throw new CryptographicException(SR.Format(SR.Sign1VerifyAlgDoesNotMatchKeyAlgorithm, algorithm, key.Algorithm));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using Test.Cryptography;
using Xunit;
using static System.Security.Cryptography.Cose.Tests.CoseTestHelpers;

Expand Down Expand Up @@ -63,6 +64,49 @@ public async Task VerifyAsyncWithUnreadableStream()
using Stream unseekableStream = GetTestStream(s_sampleContent, StreamKind.Unreadable);
await Assert.ThrowsAsync<ArgumentException>("detachedContent", () => msg.Signatures[0].VerifyDetachedAsync(DefaultKey, unseekableStream));
}

[Fact]
public async Task VerifyWithCoseKeyThrowsForMismatchedAlgorithmHeader()
{
CoseSigner signer = GetCoseSigner(DefaultKey, DefaultHash);
signer.ProtectedHeaders.Add(new CoseHeaderLabel(42), 42);
string encodedMessage = CoseMultiSignMessage.SignDetached(s_sampleContent, signer).ByteArrayToHex();
encodedMessage = ReplaceFirst(encodedMessage, "47A20126182A182A", "44A1013822");

CoseMultiSignMessage message = CoseMessage.DecodeMultiSign(ByteUtils.HexToByteArray(encodedMessage));
CoseSignature signature = Assert.Single(message.Signatures);
CoseKey key = new CoseKey(DefaultKey, DefaultHash);
using Stream syncStream = GetTestStream(s_sampleContent);
using Stream asyncStream = GetTestStream(s_sampleContent);

CryptographicException syncException = Assert.Throws<CryptographicException>(
() => signature.VerifyDetached(key, syncStream));
CryptographicException asyncException = await Assert.ThrowsAsync<CryptographicException>(
() => signature.VerifyDetachedAsync(key, asyncStream));

Assert.Contains(nameof(CoseAlgorithm.ES384), syncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES256), syncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES384), asyncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES256), asyncException.Message);
}

[Fact]
public async Task VerifyWithCoseKeyThrowsForMissingAlgorithmHeader()
{
CoseSigner signer = GetCoseSigner(DefaultKey, DefaultHash);
signer.ProtectedHeaders.Add(new CoseHeaderLabel(42), 42);
string encodedMessage = CoseMultiSignMessage.SignDetached(s_sampleContent, signer).ByteArrayToHex();
encodedMessage = ReplaceFirst(encodedMessage, "47A20126182A182A", "45A1182A182A");

CoseMultiSignMessage message = CoseMessage.DecodeMultiSign(ByteUtils.HexToByteArray(encodedMessage));
CoseSignature signature = Assert.Single(message.Signatures);
CoseKey key = new CoseKey(DefaultKey, DefaultHash);
using Stream syncStream = GetTestStream(s_sampleContent);
using Stream asyncStream = GetTestStream(s_sampleContent);

Assert.Throws<CryptographicException>(() => signature.VerifyDetached(key, syncStream));
await Assert.ThrowsAsync<CryptographicException>(() => signature.VerifyDetachedAsync(key, asyncStream));
}
}

public class CoseMultiSignMessageTests_VerifyStream_Sync : CoseMultiSignMessageTests_VerifyStream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.IO;
using System.Threading.Tasks;
using Test.Cryptography;
using Xunit;
using static System.Security.Cryptography.Cose.Tests.CoseTestHelpers;

Expand Down Expand Up @@ -59,6 +60,47 @@ public async Task VerifyAsyncWithUnreadableStream()
using Stream unseekableStream = GetTestStream(s_sampleContent, StreamKind.Unreadable);
await Assert.ThrowsAsync<ArgumentException>("detachedContent", () => msg.VerifyDetachedAsync(DefaultKey, unseekableStream));
}

[Fact]
public async Task VerifyWithCoseKeyThrowsForMismatchedAlgorithmHeader()
{
CoseSigner signer = GetCoseSigner(DefaultKey, DefaultHash);
signer.ProtectedHeaders.Add(new CoseHeaderLabel(42), 42);
string encodedMessage = CoseSign1Message.SignDetached(s_sampleContent, signer).ByteArrayToHex();
encodedMessage = ReplaceFirst(encodedMessage, "47A20126182A182A", "44A1013822");

CoseSign1Message message = CoseMessage.DecodeSign1(ByteUtils.HexToByteArray(encodedMessage));
CoseKey key = new CoseKey(DefaultKey, DefaultHash);
using Stream syncStream = GetTestStream(s_sampleContent);
using Stream asyncStream = GetTestStream(s_sampleContent);

CryptographicException syncException = Assert.Throws<CryptographicException>(
() => message.VerifyDetached(key, syncStream));
CryptographicException asyncException = await Assert.ThrowsAsync<CryptographicException>(
() => message.VerifyDetachedAsync(key, asyncStream));

Assert.Contains(nameof(CoseAlgorithm.ES384), syncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES256), syncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES384), asyncException.Message);
Assert.Contains(nameof(CoseAlgorithm.ES256), asyncException.Message);
}

[Fact]
public async Task VerifyWithCoseKeyThrowsForMissingAlgorithmHeader()
{
CoseSigner signer = GetCoseSigner(DefaultKey, DefaultHash);
signer.ProtectedHeaders.Add(new CoseHeaderLabel(42), 42);
string encodedMessage = CoseSign1Message.SignDetached(s_sampleContent, signer).ByteArrayToHex();
encodedMessage = ReplaceFirst(encodedMessage, "47A20126182A182A", "45A1182A182A");

CoseSign1Message message = CoseMessage.DecodeSign1(ByteUtils.HexToByteArray(encodedMessage));
CoseKey key = new CoseKey(DefaultKey, DefaultHash);
using Stream syncStream = GetTestStream(s_sampleContent);
using Stream asyncStream = GetTestStream(s_sampleContent);

Assert.Throws<CryptographicException>(() => message.VerifyDetached(key, syncStream));
await Assert.ThrowsAsync<CryptographicException>(() => message.VerifyDetachedAsync(key, asyncStream));
}
}

public class CoseSign1MessageTests_VerifyStream_Sync : CoseSign1MessageTests_VerifyStream
Expand Down
Loading