1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright (C) 2018-2023 Apple Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#if ENABLE(WEB_AUTHN)
#include "CBORValue.h"
#include <stddef.h>
// Concise Binary Object Representation (CBOR) decoder as defined by
// https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical
// CBOR as defined by section 3.9.
// Supported:
// * Major types:
// * 0: Unsigned integers, up to 64-bit.
// * 2: Byte strings.
// * 3: UTF-8 strings.
// * 4: Definite-length arrays.
// * 5: Definite-length maps.
// * 7: Simple values.
//
// Requirements for canonical CBOR representation:
// - Duplicate keys for map are not allowed.
// - Keys for map must be sorted first by length and then by byte-wise
// lexical order.
//
// Known limitations and interpretations of the RFC:
// - Does not support negative integers, indefinite data streams and tagging.
// - Floating point representations and BREAK stop code in major
// type 7 are not supported.
// - Non-character codepoint are not supported for Major type 3.
// - Incomplete CBOR data items are treated as syntax errors.
// - Trailing data bytes are treated as errors.
// - Unknown additional information formats are treated as syntax errors.
// - Callers can decode CBOR values with at most 16 nested depth layer. More
// strict restrictions on nesting layer size of CBOR values can be enforced
// by setting |maxNestingLevel|.
// - Only CBOR maps with integer or string type keys are supported due to the
// cost of serialization when sorting map keys.
// - Simple values that are unassigned/reserved as per RFC 7049 are not
// supported and treated as errors.
namespace cbor {
class CBORReader {
WTF_MAKE_NONCOPYABLE(CBORReader);
public:
using Bytes = std::span<const uint8_t>;
enum class DecoderError {
CBORNoError = 0,
UnsupportedMajorType,
UnknownAdditionalInfo,
IncompleteCBORData,
IncorrectMapKeyType,
TooMuchNesting,
InvalidUTF8,
ExtraneousData,
DuplicateKey,
OutOfOrderKey,
NonMinimalCBOREncoding,
UnsupportedSimpleValue,
UnsupportedFloatingPointValue,
OutOfRangeIntegerValue,
};
// CBOR nested depth sufficient for most use cases.
static const int kCBORMaxDepth = 16;
~CBORReader();
// Reads and parses |input_data| into a CBORValue. If any one of the syntax
// formats is violated -including unknown additional info and incomplete
// CBOR data- then an empty optional is returned. Optional |errorCodeOut|
// can be provided by the caller to obtain additional information about
// decoding failures.
WEBCORE_EXPORT static std::optional<CBORValue> read(const Bytes&, DecoderError* errorCodeOut = nullptr, int maxNestingLevel = kCBORMaxDepth);
// Translates errors to human-readable error messages.
static const char* errorCodeToString(DecoderError errorCode);
private:
explicit CBORReader(const Bytes&);
std::optional<CBORValue> decodeCBOR(int maxNestingLevel);
std::optional<CBORValue> decodeValueToNegative(uint64_t value);
std::optional<CBORValue> decodeValueToUnsigned(uint64_t value);
std::optional<CBORValue> readSimpleValue(uint8_t additionalInfo, uint64_t value);
bool readVariadicLengthInteger(uint8_t additionalInfo, uint64_t* value);
std::optional<CBORValue> readBytes(uint64_t numBytes);
std::optional<CBORValue> readString(uint64_t numBytes);
std::optional<CBORValue> readCBORArray(uint64_t length, int maxNestingLevel);
std::optional<CBORValue> readCBORMap(uint64_t length, int maxNestingLevel);
bool canConsume(uint64_t bytes);
void checkExtraneousData();
bool checkDuplicateKey(const CBORValue& newKey, const CBORValue::MapValue&);
bool hasValidUTF8Format(const String&);
bool checkOutOfOrderKey(const CBORValue& newKey, const CBORValue::MapValue&);
bool checkMinimalEncoding(uint8_t additionalBytes, uint64_t uintData);
DecoderError getErrorCode();
const Bytes& m_data;
Bytes::iterator m_it;
DecoderError m_errorCode;
};
} // namespace cbor
#endif // ENABLE(WEB_AUTHN)
|