diff --git a/NuGet.config b/NuGet.config
index a24e816570c..9c82ecf3a5e 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -14,4 +14,5 @@
+
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 00a9d05e8ac..a30f8c2c7e4 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -62,10 +62,9 @@ jobs:
projectFile: scenarios.proj
channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
# - release/3.1.3xx
- - 3.1
- 3.0
- # Windows x64 Blazor 3.2 scenario benchmarks
+ # Windows x64 Blazor scenario benchmarks
- template: /eng/performance/scenarios.yml
parameters:
osName: windows
@@ -263,7 +262,6 @@ jobs:
channels: # for public jobs we want to make sure that the PRs don't break any of the supported channels
# - release/3.1.2xx
- 3.0
- - 3.1
# Windows x64 micro benchmarks
- template: /eng/performance/benchmark_jobs.yml
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index e36d757bc78..130b55920ad 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -11,9 +11,9 @@
https://github.com/dotnet/arcade
7385e2722b9fa517314aa5db1fa598a8d417b3c7
-
+
https://github.com/dotnet/installer
- b21096b25a04fa09f7b174e43335707842785395
+ e4ad1969d346798b74290f298ef4d1f4fd713535
diff --git a/eng/Versions.props b/eng/Versions.props
index 74319667505..55068e0d49d 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -7,7 +7,7 @@
- 5.0.100-rc.1.20407.13
+ 5.0.100-rc.1.20413.9
diff --git a/src/benchmarks/gc/src/exec/GCPerfSim/GCPerfSim.cs b/src/benchmarks/gc/src/exec/GCPerfSim/GCPerfSim.cs
index 6ce38c493c5..0e3b3257e18 100644
--- a/src/benchmarks/gc/src/exec/GCPerfSim/GCPerfSim.cs
+++ b/src/benchmarks/gc/src/exec/GCPerfSim/GCPerfSim.cs
@@ -1442,6 +1442,8 @@ private static Args ParseFromCommandLine(string[] args)
totalMinutesToRun = 1;
}
+ Console.WriteLine(Process.GetCurrentProcess().ProcessName + " " + Environment.CommandLine);
+
ulong livePerThread = (totalLiveBytes ?? 0) / threadCount;
ulong allocPerThread = (totalAllocBytes ?? 0) / threadCount;
if (allocPerThread != 0) Console.WriteLine("allocating {0:n0} per thread", allocPerThread);
diff --git a/src/benchmarks/micro/Categories.cs b/src/benchmarks/micro/Categories.cs
index 20bb89b175f..3e65f944496 100644
--- a/src/benchmarks/micro/Categories.cs
+++ b/src/benchmarks/micro/Categories.cs
@@ -33,6 +33,7 @@ public static class Categories
public const string Burgers = "Burgers";
public const string SciMark = "SciMark";
public const string CscBench = "CscBench";
+ public const string NoWASM = "NoWASM";
public const string JIT = "JIT";
public const string JSON = "JSON";
diff --git a/src/benchmarks/micro/MicroBenchmarks.csproj b/src/benchmarks/micro/MicroBenchmarks.csproj
index f78ffff4631..3ae2d86b386 100644
--- a/src/benchmarks/micro/MicroBenchmarks.csproj
+++ b/src/benchmarks/micro/MicroBenchmarks.csproj
@@ -22,27 +22,28 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
@@ -59,6 +60,9 @@
PreserveNewest
+
+ PreserveNewest
+
@@ -70,6 +74,7 @@
+
@@ -100,10 +105,12 @@
+
+
diff --git a/src/benchmarks/micro/Serializers/Binary_FromStream.cs b/src/benchmarks/micro/Serializers/Binary_FromStream.cs
index 4cb986307cf..d57f0cb7b25 100644
--- a/src/benchmarks/micro/Serializers/Binary_FromStream.cs
+++ b/src/benchmarks/micro/Serializers/Binary_FromStream.cs
@@ -15,6 +15,7 @@ namespace MicroBenchmarks.Serializers
[GenericTypeArguments(typeof(IndexViewModel))]
[GenericTypeArguments(typeof(MyEventsListerViewModel))]
[GenericTypeArguments(typeof(CollectionsOfPrimitives))]
+ [BenchmarkCategory(Categories.NoWASM)]
public class Binary_FromStream
{
private readonly T value;
diff --git a/src/benchmarks/micro/Serializers/Binary_ToStream.cs b/src/benchmarks/micro/Serializers/Binary_ToStream.cs
index 669e467e2c2..8fe712e748f 100644
--- a/src/benchmarks/micro/Serializers/Binary_ToStream.cs
+++ b/src/benchmarks/micro/Serializers/Binary_ToStream.cs
@@ -15,6 +15,7 @@ namespace MicroBenchmarks.Serializers
[GenericTypeArguments(typeof(IndexViewModel))]
[GenericTypeArguments(typeof(MyEventsListerViewModel))]
[GenericTypeArguments(typeof(CollectionsOfPrimitives))]
+ [BenchmarkCategory(Categories.NoWASM)]
public class Binary_ToStream
{
private readonly T value;
diff --git a/src/benchmarks/micro/libraries/System.Buffers/ArrayPoolTests.cs b/src/benchmarks/micro/libraries/System.Buffers/ArrayPoolTests.cs
index cb785dbfc20..25c8fccbec9 100644
--- a/src/benchmarks/micro/libraries/System.Buffers/ArrayPoolTests.cs
+++ b/src/benchmarks/micro/libraries/System.Buffers/ArrayPoolTests.cs
@@ -10,7 +10,7 @@
namespace System.Buffers.Tests
{
- [BenchmarkCategory(Categories.Libraries)]
+ [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)]
[GenericTypeArguments(typeof(byte))] // value type
[GenericTypeArguments(typeof(object))] // reference type
public class RentReturnArrayPoolTests
diff --git a/src/benchmarks/micro/libraries/System.Console/Perf.Console.cs b/src/benchmarks/micro/libraries/System.Console/Perf.Console.cs
index 9c4542cef0d..7fce8725089 100644
--- a/src/benchmarks/micro/libraries/System.Console/Perf.Console.cs
+++ b/src/benchmarks/micro/libraries/System.Console/Perf.Console.cs
@@ -14,7 +14,7 @@ namespace System.ConsoleTests
/// - OpenStandardInput, OpenStandardOutput, OpenStandardError
/// - ForegroundColor, BackgroundColor, ResetColor
///
- [BenchmarkCategory(Categories.Libraries)]
+ [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)]
public class Perf_Console
{
private readonly Consumer consumer = new Consumer();
diff --git a/src/benchmarks/micro/libraries/System.Drawing/Perf_Graphics_DrawBeziers.cs b/src/benchmarks/micro/libraries/System.Drawing/Perf_Graphics_DrawBeziers.cs
index eab208f92c0..475c8d6a439 100644
--- a/src/benchmarks/micro/libraries/System.Drawing/Perf_Graphics_DrawBeziers.cs
+++ b/src/benchmarks/micro/libraries/System.Drawing/Perf_Graphics_DrawBeziers.cs
@@ -8,7 +8,7 @@
namespace System.Drawing.Tests
{
- [BenchmarkCategory(Categories.Libraries)]
+ [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)]
public class Perf_Graphics_DrawBeziers
{
private Bitmap _image;
diff --git a/src/benchmarks/micro/libraries/System.Drawing/Perf_Image_Load.cs b/src/benchmarks/micro/libraries/System.Drawing/Perf_Image_Load.cs
index 9061ef5b4af..466caaf4f56 100644
--- a/src/benchmarks/micro/libraries/System.Drawing/Perf_Image_Load.cs
+++ b/src/benchmarks/micro/libraries/System.Drawing/Perf_Image_Load.cs
@@ -11,7 +11,7 @@
namespace System.Drawing.Tests
{
- [BenchmarkCategory(Categories.Libraries)]
+ [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)]
public class Perf_Image_Load
{
// this field is lazy to avoid the exception during static ctor initialization of this type (harder to catch and handle properly)
diff --git a/src/benchmarks/micro/libraries/System.Formats.Cbor/CoseKeyHelpers.cs b/src/benchmarks/micro/libraries/System.Formats.Cbor/CoseKeyHelpers.cs
new file mode 100644
index 00000000000..32e7aaf3a82
--- /dev/null
+++ b/src/benchmarks/micro/libraries/System.Formats.Cbor/CoseKeyHelpers.cs
@@ -0,0 +1,345 @@
+// 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.Diagnostics;
+using System.Security.Cryptography;
+using Test.Cryptography;
+
+// Provides a reference implementation for serializing ECDsa public keys to the COSE_Key format
+// according to https://tools.ietf.org/html/rfc8152#section-8.1
+
+namespace System.Formats.Cbor.Tests
+{
+ public class ECDsaCosePublicKey
+ {
+ public ECDsaCosePublicKey(string curveFriendlyName, string hexQx, string hexQy, string hashAlgorithmName, string hexEncodedKey)
+ {
+ Name = curveFriendlyName;
+ HashAlgorithmName = new HashAlgorithmName(hashAlgorithmName);
+ EncodedCoseKey = hexEncodedKey.HexToByteArray();
+ ECParameters = new ECParameters()
+ {
+ Curve = ECCurve.CreateFromFriendlyName(curveFriendlyName),
+ Q = new ECPoint() { X = hexQx.HexToByteArray(), Y = hexQy.HexToByteArray() },
+ };
+ }
+
+ public string Name { get; }
+ public ECParameters ECParameters { get; }
+ public HashAlgorithmName HashAlgorithmName { get; }
+ public byte[] EncodedCoseKey { get; }
+
+ public override string ToString() => Name;
+
+ public static IEnumerable CreatePublicKeys()
+ {
+ yield return new ECDsaCosePublicKey(
+ curveFriendlyName: "ECDSA_P256",
+ hexQx: "65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d",
+ hexQy: "1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c",
+ hexEncodedKey: "a501020326200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c",
+ hashAlgorithmName: "SHA256");
+
+ yield return new ECDsaCosePublicKey(
+ curveFriendlyName: "ECDSA_P384",
+ hexQx: "ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd",
+ hexQy: "24376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b",
+ hexEncodedKey: "a501020338222002215830ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd22583024376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b",
+ hashAlgorithmName: "SHA384");
+
+ yield return new ECDsaCosePublicKey(
+ curveFriendlyName: "ECDSA_P521",
+ hexQx: "00b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c",
+ hexQy: "0114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f",
+ hexEncodedKey: "a50102033823200321584200b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c2258420114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f",
+ hashAlgorithmName: "SHA512");
+ }
+ }
+
+ public static class ECDsaCosePublicKeyHelper
+ {
+ public static void WriteECParametersAsCosePublicKey(this CborWriter writer, ECParameters ecParams, HashAlgorithmName? algorithmName)
+ {
+ Debug.Assert(writer.ConformanceMode == CborConformanceMode.Ctap2Canonical && writer.ConvertIndefiniteLengthEncodings);
+
+ if (ecParams.Q.X is null || ecParams.Q.Y is null)
+ {
+ throw new ArgumentException("does not specify a public key point.", nameof(ecParams));
+ }
+
+ // run these first to perform necessary validation
+ (CoseKeyType kty, CoseCrvId crv) = MapECCurveToCoseKtyAndCrv(ecParams.Curve);
+ CoseKeyAlgorithm? alg = (algorithmName != null) ? MapHashAlgorithmNameToCoseKeyAlg(algorithmName.Value) : (CoseKeyAlgorithm?)null;
+
+ // Begin writing a CBOR object
+ writer.WriteStartMap(definiteLength: null);
+
+ // NB labels should be sorted according to CTAP2 canonical encoding rules.
+ // While the CborWriter will attempt to sort the encodings on its own,
+ // it is generally more efficient if keys are written in sorted order to begin with.
+
+ WriteCoseKeyLabel(writer, CoseKeyLabel.Kty);
+ writer.WriteInt32((int)kty);
+
+ if (alg != null)
+ {
+ WriteCoseKeyLabel(writer, CoseKeyLabel.Alg);
+ writer.WriteInt32((int)alg);
+ }
+
+ WriteCoseKeyLabel(writer, CoseKeyLabel.EcCrv);
+ writer.WriteInt32((int)crv);
+
+ WriteCoseKeyLabel(writer, CoseKeyLabel.EcX);
+ writer.WriteByteString(ecParams.Q.X);
+
+ WriteCoseKeyLabel(writer, CoseKeyLabel.EcY);
+ writer.WriteByteString(ecParams.Q.Y);
+
+ writer.WriteEndMap();
+
+ static (CoseKeyType, CoseCrvId) MapECCurveToCoseKtyAndCrv(ECCurve curve)
+ {
+ if (!curve.IsNamed)
+ {
+ throw new ArgumentException("EC COSE keys only support named curves.", nameof(curve));
+ }
+
+ if (MatchesOid(ECCurve.NamedCurves.nistP256))
+ {
+ return (CoseKeyType.EC2, CoseCrvId.P256);
+ }
+
+ if (MatchesOid(ECCurve.NamedCurves.nistP384))
+ {
+ return (CoseKeyType.EC2, CoseCrvId.P384);
+ }
+
+ if (MatchesOid(ECCurve.NamedCurves.nistP521))
+ {
+ return (CoseKeyType.EC2, CoseCrvId.P521);
+ }
+
+ throw new ArgumentException("Unrecognized named curve", curve.Oid.Value);
+
+ bool MatchesOid(ECCurve namedCurve) => curve.Oid.Value == namedCurve.Oid.Value;
+ }
+
+ static CoseKeyAlgorithm MapHashAlgorithmNameToCoseKeyAlg(HashAlgorithmName name)
+ {
+ if (MatchesName(HashAlgorithmName.SHA256))
+ {
+ return CoseKeyAlgorithm.ES256;
+ }
+
+ if (MatchesName(HashAlgorithmName.SHA384))
+ {
+ return CoseKeyAlgorithm.ES384;
+ }
+
+ if (MatchesName(HashAlgorithmName.SHA512))
+ {
+ return CoseKeyAlgorithm.ES512;
+ }
+
+ throw new ArgumentException("Unrecognized hash algorithm name.", nameof(HashAlgorithmName));
+
+ bool MatchesName(HashAlgorithmName candidate) => name.Name == candidate.Name;
+ }
+
+ static void WriteCoseKeyLabel(CborWriter writer, CoseKeyLabel label)
+ {
+ writer.WriteInt32((int)label);
+ }
+ }
+
+ public static (ECParameters, HashAlgorithmName?) ReadECParametersAsCosePublicKey(this CborReader reader)
+ {
+ Debug.Assert(reader.ConformanceMode == CborConformanceMode.Ctap2Canonical);
+
+ // CTAP2 conformance mode requires that fields are sorted by key encoding.
+ // We take advantage of this by reading keys in that order.
+ // NB1. COSE labels are not sorted according to canonical integer ordering,
+ // negative labels must always follow positive labels.
+ // NB2. Any unrecognized keys will result in the reader failing.
+ // NB3. in order to support optional fields, we need to store the latest read label.
+ CoseKeyLabel? latestReadLabel = null;
+
+ int? remainingKeys = reader.ReadStartMap();
+ Debug.Assert(remainingKeys != null); // guaranteed by CTAP2 conformance
+
+ try
+ {
+ var ecParams = new ECParameters();
+
+ ReadCoseKeyLabel(CoseKeyLabel.Kty);
+ CoseKeyType kty = (CoseKeyType)reader.ReadInt32();
+
+ HashAlgorithmName? algName = null;
+ if (TryReadCoseKeyLabel(CoseKeyLabel.Alg))
+ {
+ CoseKeyAlgorithm alg = (CoseKeyAlgorithm)reader.ReadInt32();
+ algName = MapCoseKeyAlgToHashAlgorithmName(alg);
+ }
+
+ if (TryReadCoseKeyLabel(CoseKeyLabel.KeyOps))
+ {
+ // No-op, simply tolerate potential key_ops labels
+ reader.SkipValue();
+ }
+
+ ReadCoseKeyLabel(CoseKeyLabel.EcCrv);
+ CoseCrvId crv = (CoseCrvId)reader.ReadInt32();
+
+ if (IsValidKtyCrvCombination(kty, crv))
+ {
+ ecParams.Curve = MapCoseCrvToECCurve(crv);
+ }
+ else
+ {
+ throw new CborContentException("Invalid kty/crv combination in COSE key.");
+ }
+
+ ReadCoseKeyLabel(CoseKeyLabel.EcX);
+ ecParams.Q.X = reader.ReadByteString();
+
+ ReadCoseKeyLabel(CoseKeyLabel.EcY);
+ ecParams.Q.Y = reader.ReadByteString();
+
+ if (TryReadCoseKeyLabel(CoseKeyLabel.EcD))
+ {
+ throw new CborContentException("COSE key encodes a private key.");
+ }
+
+ if (remainingKeys > 0)
+ {
+ throw new CborContentException("COSE_key contains unrecognized trailing data.");
+ }
+
+ reader.ReadEndMap();
+
+ return (ecParams, algName);
+ }
+ catch (InvalidOperationException e)
+ {
+ throw new CborContentException("Invalid COSE_key format in CBOR document", e);
+ }
+
+ static bool IsValidKtyCrvCombination(CoseKeyType kty, CoseCrvId crv)
+ {
+ return kty switch
+ {
+ CoseKeyType.EC2 => crv == CoseCrvId.P256 || crv == CoseCrvId.P384 || crv == CoseCrvId.P521,
+ CoseKeyType.OKP => crv == CoseCrvId.X255519 || crv == CoseCrvId.X448 || crv == CoseCrvId.Ed25519 || crv == CoseCrvId.Ed448,
+ _ => false,
+ };
+ }
+
+ static ECCurve MapCoseCrvToECCurve(CoseCrvId crv)
+ {
+ return crv switch
+ {
+ CoseCrvId.P256 => ECCurve.NamedCurves.nistP256,
+ CoseCrvId.P384 => ECCurve.NamedCurves.nistP384,
+ CoseCrvId.P521 => ECCurve.NamedCurves.nistP521,
+ _ => throw new CborContentException("Unrecognized COSE crv value."),
+ };
+ }
+
+ static HashAlgorithmName MapCoseKeyAlgToHashAlgorithmName(CoseKeyAlgorithm alg)
+ {
+ return alg switch
+ {
+ CoseKeyAlgorithm.ES256 => HashAlgorithmName.SHA256,
+ CoseKeyAlgorithm.ES384 => HashAlgorithmName.SHA384,
+ CoseKeyAlgorithm.ES512 => HashAlgorithmName.SHA512,
+ _ => throw new CborContentException("Unrecognized COSE alg value."),
+ };
+ }
+
+ // Handles optional labels
+ bool TryReadCoseKeyLabel(CoseKeyLabel expectedLabel)
+ {
+ // The `currentLabel` parameter can hold a label that
+ // was read when handling a previous optional field.
+ // We only need to read the next label if uninhabited.
+ if (latestReadLabel == null)
+ {
+ // check that we have not reached the end of the COSE key object
+ if (remainingKeys == 0)
+ {
+ return false;
+ }
+
+ latestReadLabel = (CoseKeyLabel)reader.ReadInt32();
+ }
+
+ if (expectedLabel != latestReadLabel.Value)
+ {
+ return false;
+ }
+
+ // read was successful, vacate the `currentLabel` parameter to advance reads.
+ latestReadLabel = null;
+ remainingKeys--;
+ return true;
+ }
+
+ // Handles required labels
+ void ReadCoseKeyLabel(CoseKeyLabel expectedLabel)
+ {
+ if (!TryReadCoseKeyLabel(expectedLabel))
+ {
+ throw new CborContentException("Unexpected COSE key label.");
+ }
+ }
+ }
+
+ private enum CoseKeyLabel : int
+ {
+ // cf. https://tools.ietf.org/html/rfc8152#section-7.1 table 3
+ Kty = 1,
+ Kid = 2,
+ Alg = 3,
+ KeyOps = 4,
+ BaseIv = 5,
+
+ // cf. https://tools.ietf.org/html/rfc8152#section-13.1.1 table 23
+ EcCrv = -1,
+ EcX = -2,
+ EcY = -3,
+ EcD = -4,
+ };
+
+ private enum CoseCrvId : int
+ {
+ // cf. https://tools.ietf.org/html/rfc8152#section-13.1 table 22
+ P256 = 1,
+ P384 = 2,
+ P521 = 3,
+ X255519 = 4,
+ X448 = 5,
+ Ed25519 = 6,
+ Ed448 = 7,
+ }
+
+ private enum CoseKeyType : int
+ {
+ // cf. https://tools.ietf.org/html/rfc8152#section-13 table 21
+ OKP = 1,
+ EC2 = 2,
+
+ Symmetric = 4,
+ Reserved = 0,
+ }
+
+ private enum CoseKeyAlgorithm : int
+ {
+ // cf. https://tools.ietf.org/html/rfc8152#section-8.1 table 5
+ ES256 = -7,
+ ES384 = -35,
+ ES512 = -36,
+ }
+ }
+}
diff --git a/src/benchmarks/micro/libraries/System.Formats.Cbor/Perf.CborReader.cs b/src/benchmarks/micro/libraries/System.Formats.Cbor/Perf.CborReader.cs
new file mode 100644
index 00000000000..8d6375fcfea
--- /dev/null
+++ b/src/benchmarks/micro/libraries/System.Formats.Cbor/Perf.CborReader.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using BenchmarkDotNet.Attributes;
+using MicroBenchmarks;
+using System.Collections.Generic;
+using Test.Cryptography;
+
+namespace System.Formats.Cbor.Tests
+{
+ [BenchmarkCategory(Categories.Libraries)]
+ public class Perf_CborReader
+ {
+ [Benchmark]
+ [ArgumentsSource(nameof(ECDSaCosePublicKeys))]
+ public void ReadCoseKey(ECDsaCosePublicKey publicKey)
+ {
+ var reader = new CborReader(publicKey.EncodedCoseKey, CborConformanceMode.Ctap2Canonical);
+ reader.ReadECParametersAsCosePublicKey();
+ }
+
+ public IEnumerable