| File: Passkeys\Ctap2CborReader.cs | Web Access |
| Project: src\aspnetcore\src\Identity\Core\src\Microsoft.AspNetCore.Identity.csproj (Microsoft.AspNetCore.Identity) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Formats.Cbor; namespace Microsoft.AspNetCore.Identity; /// <summary> /// A variation of <see cref="CborReader"/> that is used to read COSE keys in a CTAP2 canonical CBOR encoding form. /// </summary> internal sealed class Ctap2CborReader : CborReader { private int _remainingKeys; private int? _lastReadLabel; public static Ctap2CborReader Create(ReadOnlyMemory<byte> data) { var reader = new Ctap2CborReader(data); if (reader.ReadStartMap() is not { } keyCount) { throw new CborContentException("CTAP2 canonical CBOR encoding form requires there to be a definite number of keys."); } reader._remainingKeys = keyCount; return reader; } private Ctap2CborReader(ReadOnlyMemory<byte> data) : base(data, CborConformanceMode.Ctap2Canonical) { } public bool TryReadCoseKeyLabel(int expectedLabel) { // The 'expectedLabel' 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 (_lastReadLabel is null) { // Check that we have not reached the end of the COSE key object. if (_remainingKeys == 0) { return false; } _lastReadLabel = ReadInt32(); } if (expectedLabel != _lastReadLabel.Value) { return false; } // Read was successful - vacate '_lastReadLabel' to advance reads. _lastReadLabel = null; _remainingKeys--; return true; } public void ReadCoseKeyLabel(int expectedLabel) { if (!TryReadCoseKeyLabel(expectedLabel)) { throw new CborContentException("Unexpected COSE key label"); } } }