未验证 提交 ab380106 编写于 作者: D David Cantú 提交者: GitHub

Add support for indefinite length arrays (#74215)

* Add support for indefinite length arrays

* Update src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseHeaderMap.cs
Co-authored-by: Ncampersau <buchholz.bastian@googlemail.com>

* Validate indefinite-length arrays length up-front for fixed-lengh arrays

* Update src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseMessage.cs
Co-authored-by: NJeremy Barton <jbarton@microsoft.com>
Co-authored-by: Ncampersau <buchholz.bastian@googlemail.com>
Co-authored-by: NJeremy Barton <jbarton@microsoft.com>
上级 3cad3d24
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
......@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
......@@ -154,10 +154,10 @@
<value>Label in Critical Headers array was incorrect.</value>
</data>
<data name="CriticalHeadersMustBeArrayOfAtLeastOne" xml:space="preserve">
<value>Critical Headers must be a definite-length CBOR array of at least one element.</value>
<value>Critical Headers must be a CBOR array of at least one element.</value>
</data>
<data name="DecodeCoseSignatureMustBeArrayOfThree" xml:space="preserve">
<value>COSE Signature must be a definite-length array of 3 elements.</value>
<value>COSE Signature must be an array of three elements.</value>
</data>
<data name="DecodeErrorWhileDecoding" xml:space="preserve">
<value>Error while decoding COSE message. {0}</value>
......@@ -168,11 +168,14 @@
<data name="DecodeMessageContainedTrailingData" xml:space="preserve">
<value>CBOR payload contained trailing data after message was complete.</value>
</data>
<data name="DecodeMultiSignArrayLengthMustBeFour" xml:space="preserve">
<value>COSE_Sign must be an array of four elements.</value>
</data>
<data name="DecodeMultiSignIncorrectTag" xml:space="preserve">
<value>Incorrect tag. Expected Sign(98) or Untagged, Actual '{0}'.</value>
</data>
<data name="DecodeSign1ArrayLengthMustBeFour" xml:space="preserve">
<value>Array length for COSE_Sign1 must be four.</value>
<value>COSE_Sign1 must be an array of four elements.</value>
</data>
<data name="DecodeSign1EncodedProtectedMapIncorrect" xml:space="preserve">
<value>Protected map was incorrect.</value>
......@@ -225,4 +228,4 @@
<data name="Sign1VerifyAlgIsRequired" xml:space="preserve">
<value>Algorithm (alg) header is required and it must be a protected header.</value>
</data>
</root>
</root>
\ No newline at end of file
......@@ -266,16 +266,18 @@ private static void ValidateInsertion(CoseHeaderLabel label, CoseHeaderValue val
reader.SkipValue();
break;
case KnownHeaders.Crit:
int length = reader.ReadStartArray().GetValueOrDefault();
if (length < 1)
{
throw new ArgumentException(SR.CriticalHeadersMustBeArrayOfAtLeastOne, nameof(value));
}
reader.ReadStartArray();
bool isEmpty = true;
for (int i = 0; i < length; i++)
while (true)
{
CborReaderState state = reader.PeekState();
if (state == CborReaderState.UnsignedInteger || state == CborReaderState.NegativeInteger)
if (state == CborReaderState.EndArray)
{
reader.ReadEndArray();
break;
}
else if (state == CborReaderState.UnsignedInteger || state == CborReaderState.NegativeInteger)
{
reader.ReadInt32();
}
......@@ -287,8 +289,13 @@ private static void ValidateInsertion(CoseHeaderLabel label, CoseHeaderValue val
{
throw new ArgumentException(SR.Format(SR.CoseHeaderMapHeaderDoesNotAcceptSpecifiedValue, label.LabelName), nameof(value));
}
isEmpty = false;
}
if (isEmpty)
{
throw new ArgumentException(SR.CriticalHeadersMustBeArrayOfAtLeastOne, nameof(value));
}
reader.SkipToParent();
break;
case KnownHeaders.ContentType:
if (initialState != CborReaderState.TextString &&
......
......@@ -128,8 +128,18 @@ private static CoseSign1Message DecodeCoseSign1Core(CborReader reader)
throw new CryptographicException(SR.Format(SR.DecodeSign1IncorrectTag, tag));
}
ReadOnlyMemory<byte> coseSignArray = reader.ReadEncodedValue();
if (reader.BytesRemaining != 0)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
}
reader = new CborReader(coseSignArray);
int? arrayLength = reader.ReadStartArray();
if (arrayLength != 4)
if (arrayLength.HasValue ? arrayLength != CoseSign1Message.Sign1ArrayLength :
HasIndefiniteLengthArrayIncorrectLength(coseSignArray, CoseSign1Message.Sign1ArrayLength))
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeSign1ArrayLengthMustBeFour));
}
......@@ -149,10 +159,7 @@ private static CoseSign1Message DecodeCoseSign1Core(CborReader reader)
byte[] signature = DecodeSignature(reader);
reader.ReadEndArray();
if (reader.BytesRemaining != 0)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
}
Debug.Assert(reader.BytesRemaining == 0);
return new CoseSign1Message(protectedHeader, unprotectedHeader, payload, signature, protectedHeaderAsBstr, tag.HasValue);
}
......@@ -207,10 +214,20 @@ private static CoseMultiSignMessage DecodeCoseMultiSignCore(CborReader reader)
throw new CryptographicException(SR.Format(SR.DecodeMultiSignIncorrectTag, tag));
}
ReadOnlyMemory<byte> coseSignArray = reader.ReadEncodedValue();
if (reader.BytesRemaining != 0)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
}
reader = new CborReader(coseSignArray);
int? arrayLength = reader.ReadStartArray();
if (arrayLength != 4)
if (arrayLength.HasValue ? arrayLength != CoseMultiSignMessage.MultiSignArrayLength :
HasIndefiniteLengthArrayIncorrectLength(coseSignArray, CoseMultiSignMessage.MultiSignArrayLength))
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeSign1ArrayLengthMustBeFour));
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMultiSignArrayLengthMustBeFour));
}
var protectedHeaders = new CoseHeaderMap();
......@@ -225,14 +242,10 @@ private static CoseMultiSignMessage DecodeCoseMultiSignCore(CborReader reader)
}
byte[]? payload = DecodePayload(reader);
List<CoseSignature> signatures = DecodeCoseSignaturesArray(reader, encodedProtectedHeaders);
List<CoseSignature> signatures = DecodeCoseSignaturesArray(reader);
reader.ReadEndArray();
if (reader.BytesRemaining != 0)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
}
Debug.Assert(reader.BytesRemaining == 0);
return new CoseMultiSignMessage(protectedHeaders, unprotectedHeaders, payload, signatures, encodedProtectedHeaders, tag.HasValue);
}
......@@ -319,46 +332,77 @@ private static byte[] DecodeSignature(CborReader reader)
return reader.ReadByteString();
}
private static List<CoseSignature> DecodeCoseSignaturesArray(CborReader reader, byte[] bodyProtected)
private static List<CoseSignature> DecodeCoseSignaturesArray(CborReader reader)
{
int? signaturesLength = reader.ReadStartArray();
List<CoseSignature> signatures = new List<CoseSignature>(signaturesLength.GetValueOrDefault());
while (reader.PeekState() == CborReaderState.StartArray)
{
CoseSignature signature = DecodeCoseSignature(reader.ReadEncodedValue());
signatures.Add(signature);
}
reader.ReadEndArray();
if (signaturesLength.GetValueOrDefault() < 1)
if (signatures.Count < 1)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.MultiSignMessageMustCarryAtLeastOneSignature));
}
List<CoseSignature> signatures = new List<CoseSignature>(signaturesLength!.Value);
return signatures;
}
for (int i = 0; i < signaturesLength; i++)
private static CoseSignature DecodeCoseSignature(ReadOnlyMemory<byte> coseSignature)
{
var reader = new CborReader(coseSignature);
int? length = reader.ReadStartArray();
if (length.HasValue ? length != CoseMultiSignMessage.CoseSignatureArrayLength :
HasIndefiniteLengthArrayIncorrectLength(coseSignature, CoseMultiSignMessage.CoseSignatureArrayLength))
{
int? length = reader.ReadStartArray();
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeCoseSignatureMustBeArrayOfThree));
}
if (length != CoseMultiSignMessage.CoseSignatureArrayLength)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeCoseSignatureMustBeArrayOfThree));
}
var protectedHeaders = new CoseHeaderMap();
DecodeProtectedBucket(reader, protectedHeaders, out byte[] signProtected);
var protectedHeaders = new CoseHeaderMap();
DecodeProtectedBucket(reader, protectedHeaders, out byte[] signProtected);
var unprotectedHeaders = new CoseHeaderMap();
DecodeUnprotectedBucket(reader, unprotectedHeaders);
var unprotectedHeaders = new CoseHeaderMap();
DecodeUnprotectedBucket(reader, unprotectedHeaders);
if (ContainDuplicateLabels(protectedHeaders, unprotectedHeaders))
{
throw new CryptographicException(SR.Sign1SignHeaderDuplicateLabels);
}
if (ContainDuplicateLabels(protectedHeaders, unprotectedHeaders))
{
throw new CryptographicException(SR.Sign1SignHeaderDuplicateLabels);
}
byte[] signatureBytes = DecodeSignature(reader);
reader.ReadEndArray();
byte[] signatureBytes = DecodeSignature(reader);
return new CoseSignature(protectedHeaders, unprotectedHeaders, signProtected, signatureBytes);
}
signatures.Add(new CoseSignature(protectedHeaders, unprotectedHeaders, bodyProtected, signProtected, signatureBytes));
private static bool HasIndefiniteLengthArrayIncorrectLength(ReadOnlyMemory<byte> encodedArray, int expectedLength)
{
var reader = new CborReader(encodedArray);
reader.ReadStartArray();
int count = 0;
reader.ReadEndArray();
while (reader.PeekState() != CborReaderState.EndArray)
{
reader.SkipValue();
count++;
if (count > expectedLength)
{
return true;
}
}
bool retVal = count != expectedLength;
reader.ReadEndArray();
Debug.Assert(reader.BytesRemaining == 0);
return signatures;
return retVal;
}
internal static void AppendToBeSigned(
......
......@@ -17,7 +17,7 @@ namespace System.Security.Cryptography.Cose
/// </summary>
public sealed class CoseMultiSignMessage : CoseMessage
{
private const int MultiSignArrayLength = 4;
internal const int MultiSignArrayLength = 4;
private const int MultiSignSizeOfCborTag = 2;
internal const int CoseSignatureArrayLength = 3;
......@@ -804,7 +804,7 @@ private void AddSignatureCore(ReadOnlySpan<byte> contentBytes, Stream? contentSt
bytesWritten = CoseHelpers.SignHash(signer, hasher, buffer);
byte[] signature = bufferSpan.Slice(0, bytesWritten).ToArray();
_signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, _protectedHeaderAsBstr, encodedSignProtected, signature));
_signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, encodedSignProtected, signature));
}
}
finally
......@@ -877,7 +877,7 @@ private async Task AddSignatureCoreAsync(Stream content, CoseSigner signer, Read
bytesWritten = CoseHelpers.SignHash(signer, hasher, buffer);
byte[] signature = buffer.AsSpan(0, bytesWritten).ToArray();
_signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, _protectedHeaderAsBstr, encodedSignProtected, signature));
_signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, encodedSignProtected, signature));
}
ArrayPool<byte>.Shared.Return(buffer, clearArray: true);
......
......@@ -15,7 +15,7 @@ namespace System.Security.Cryptography.Cose
/// </summary>
public sealed class CoseSign1Message : CoseMessage
{
private const int Sign1ArrayLength = 4;
internal const int Sign1ArrayLength = 4;
private const int Sign1SizeOfCborTag = 1;
private readonly byte[] _signature;
......
......@@ -14,7 +14,6 @@ namespace System.Security.Cryptography.Cose
/// </summary>
public sealed class CoseSignature
{
private readonly byte[] _encodedBodyProtectedHeaders;
internal readonly byte[] _encodedSignProtectedHeaders;
internal readonly byte[] _signature;
private CoseMultiSignMessage? _message;
......@@ -43,17 +42,16 @@ public sealed class CoseSignature
/// <value>A region of memory that contains the digital signature.</value>
public ReadOnlyMemory<byte> Signature => _signature;
internal CoseSignature(CoseMultiSignMessage message, CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedBodyProtectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
: this(protectedHeaders, unprotectedHeaders, encodedBodyProtectedHeaders, encodedSignProtectedHeaders, signature)
internal CoseSignature(CoseMultiSignMessage message, CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
: this(protectedHeaders, unprotectedHeaders, encodedSignProtectedHeaders, signature)
{
Message = message;
}
internal CoseSignature(CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedBodyProtectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
internal CoseSignature(CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
{
ProtectedHeaders = protectedHeaders;
UnprotectedHeaders = unprotectedHeaders;
_encodedBodyProtectedHeaders = encodedBodyProtectedHeaders;
_encodedSignProtectedHeaders = encodedSignProtectedHeaders;
_signature = signature;
}
......@@ -400,7 +398,7 @@ private async Task<bool> VerifyAsyncCore(AsymmetricAlgorithm key, Stream content
{
int bufferLength = CoseMessage.ComputeToBeSignedEncodedSize(
SigStructureContext.Signature,
_encodedBodyProtectedHeaders.Length,
Message.RawProtectedHeaders.Length,
_encodedSignProtectedHeaders.Length,
associatedData.Length,
contentLength: 0);
......@@ -408,7 +406,7 @@ private async Task<bool> VerifyAsyncCore(AsymmetricAlgorithm key, Stream content
try
{
await CoseMessage.AppendToBeSignedAsync(buffer, hasher, SigStructureContext.Signature, _encodedBodyProtectedHeaders, _encodedSignProtectedHeaders, associatedData, content, cancellationToken).ConfigureAwait(false);
await CoseMessage.AppendToBeSignedAsync(buffer, hasher, SigStructureContext.Signature, Message.RawProtectedHeaders, _encodedSignProtectedHeaders, associatedData, content, cancellationToken).ConfigureAwait(false);
return VerifyHash(key, hasher, hashAlgorithm, keyType, padding);
}
finally
......@@ -432,7 +430,7 @@ private bool VerifyCore(AsymmetricAlgorithm key, ReadOnlySpan<byte> contentBytes
{
int bufferLength = CoseMessage.ComputeToBeSignedEncodedSize(
SigStructureContext.Signature,
_encodedBodyProtectedHeaders.Length,
Message.RawProtectedHeaders.Length,
_encodedSignProtectedHeaders.Length,
associatedData.Length,
contentLength: 0);
......@@ -440,7 +438,7 @@ private bool VerifyCore(AsymmetricAlgorithm key, ReadOnlySpan<byte> contentBytes
try
{
CoseMessage.AppendToBeSigned(buffer, hasher, SigStructureContext.Signature, _encodedBodyProtectedHeaders, _encodedSignProtectedHeaders, associatedData, contentBytes, contentStream);
CoseMessage.AppendToBeSigned(buffer, hasher, SigStructureContext.Signature, Message.RawProtectedHeaders.Span, _encodedSignProtectedHeaders, associatedData, contentBytes, contentStream);
return VerifyHash(key, hasher, hashAlgorithm, keyType, padding);
}
finally
......
......@@ -295,6 +295,41 @@ public void RemoveKeyValuePair_DoesNotMatchKeyOrValue(bool changeKey)
Assert.Equal(1, map.Count);
}
[Fact]
public void SetEncodedValue_CriticalHeaders_ThrowIf_ArrayEmpty()
{
// definite length
var writer = new CborWriter();
writer.WriteStartArray(0);
writer.WriteEndArray();
Verify(writer.Encode());
// indefinite length
writer.Reset();
writer.WriteStartArray(null);
writer.WriteEndArray();
Verify(writer.Encode());
void Verify(byte[] encodedValue)
{
CoseHeaderMap map = new();
CoseHeaderValue value = CoseHeaderValue.FromEncodedValue(writer.Encode());
Assert.Throws<ArgumentException>(() => map[CoseHeaderLabel.CriticalHeaders] = value);
}
}
[Fact]
public void SetEncodedValue_CriticalHeaders_ThrowIf_IndefiniteLengthArrayMissingBreak()
{
byte[] encodedValue = GetDummyCritHeaderValue(useIndefiniteLength: true);
CoseHeaderMap map = new();
CoseHeaderValue value = CoseHeaderValue.FromEncodedValue(encodedValue.AsSpan(0, encodedValue.Length - 1));
Assert.Throws<ArgumentException>(() => map[CoseHeaderLabel.CriticalHeaders] = value);
}
public enum SetValueMethod
{
ItemSet,
......@@ -493,7 +528,11 @@ public static IEnumerable<object[]> KnownHeadersEncodedValues_TestData()
writer.WriteInt32((int)ECDsaAlgorithm.ES256);
yield return ReturnDataAndReset(KnownHeaderAlg, writer, setMethod, getMethod);
WriteDummyCritHeaderValue(writer);
WriteDummyCritHeaderValue(writer, useIndefiniteLength: false);
yield return ReturnDataAndReset(KnownHeaderCrit, writer, setMethod, getMethod);
WriteDummyCritHeaderValue(writer, useIndefiniteLength: true);
yield return ReturnDataAndReset(KnownHeaderCrit, writer, setMethod, getMethod);
writer.WriteTextString(ContentTypeDummyValue);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Formats.Cbor;
using Test.Cryptography;
......@@ -82,5 +83,66 @@ public void DecodeMultiSign_IncorrectStructure()
writer.WriteEndArray();
Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(writer.Encode()));
}
[Theory]
// COSE_Sign is an indefinite-length array
[InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
// [+COSE_Signature]
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
// COSE_Signature
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
// All of them
[InlineData("D8629F40A054546869732069732074686520636F6E74656E742E9F9F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFFFFFF")]
public void DecodeMultiSign_IndefiniteLengthArray(string hexCborPayload)
{
byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
CoseMultiSignMessage msg = CoseMessage.DecodeMultiSign(cborPayload);
ReadOnlyCollection<CoseSignature> signatures = msg.Signatures;
Assert.Equal(1, signatures.Count);
Assert.True(signatures[0].VerifyEmbedded(DefaultKey));
}
[Theory]
// COSE_Sign
[InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
// [+COSE_Signature]
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
// COSE_Signature
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
public void DecodeMultiSign_IndefiniteLengthArray_MissingBreak(string hexCborPayload)
{
byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
Assert.IsType<CborContentException>(ex.InnerException);
}
// All these payloads contain one extra element of type byte string.
[Theory]
// COSE_Sign
[InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
// [+COSE_Signature] - this structure does not have a fixed length required, but the byte string is unexpected.
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
// COSE_Signature
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
public void DecodeMultiSign_IndefiniteLengthArray_LargerByOne(string hexCborPayload)
{
byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
}
[Theory]
// COSE_Sign
[InlineData("D8629F40A054546869732069732074686520636F6E74656E742EFF")]
// [+COSE_Signature]
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E9FFF")]
// COSE_Signature
[InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A104423131FF")]
public void DecodeMultiSign_IndefiniteLengthArray_ShorterByOne(string hexCborPayload)
{
byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
Assert.Null(ex.InnerException);
}
}
}
......@@ -69,5 +69,38 @@ public void DecodeSign1_IncorrectStructure()
writer.WriteEndArray();
Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(writer.Encode()));
}
[Fact]
public void DecodeSign1_IndefiniteLengthArray()
{
byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36FF");
CoseSign1Message msg = CoseMessage.DecodeSign1(cborPayload);
Assert.True(msg.VerifyEmbedded(DefaultKey));
}
[Fact]
public void DecodeSign1_IndefiniteLengthArray_MissingBreak()
{
byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36");
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
Assert.IsType<CborContentException>(ex.InnerException);
}
[Fact]
public void DecodeSign1_IndefiniteLengthArray_LargerByOne()
{
byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB3640FF");
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
Assert.Null(ex.InnerException);
}
[Fact]
public void DecodeSign1_IndefiniteLengthArray_ShorterByOne()
{
byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742EFF");
CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
Assert.Null(ex.InnerException);
}
}
}
......@@ -541,17 +541,17 @@ internal enum CoseMessageKind
MultiSign = 98
}
internal static void WriteDummyCritHeaderValue(CborWriter writer)
internal static void WriteDummyCritHeaderValue(CborWriter writer, bool useIndefiniteLength = false)
{
writer.WriteStartArray(1);
writer.WriteStartArray(useIndefiniteLength ? null : 1);
writer.WriteInt32(42);
writer.WriteEndArray();
}
internal static byte[] GetDummyCritHeaderValue()
internal static byte[] GetDummyCritHeaderValue(bool useIndefiniteLength = false)
{
var writer = new CborWriter();
WriteDummyCritHeaderValue(writer);
WriteDummyCritHeaderValue(writer, useIndefiniteLength);
return writer.Encode();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册