blob: 7fbf3359e25839ebb6a23bfd80ba6ede42d19af0 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright (C) 2018 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 = Vector<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 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:
CBORReader(Bytes::const_iterator, const Bytes::const_iterator);
Optional<CBORValue> decodeCBOR(int maxNestingLevel);
Optional<CBORValue> decodeValueToNegative(uint64_t value);
Optional<CBORValue> decodeValueToUnsigned(uint64_t value);
Optional<CBORValue> readSimpleValue(uint8_t additionalInfo, uint64_t value);
bool readVariadicLengthInteger(uint8_t additionalInfo, uint64_t* value);
Optional<CBORValue> readBytes(uint64_t numBytes);
Optional<CBORValue> readString(uint64_t numBytes);
Optional<CBORValue> readCBORArray(uint64_t length, int maxNestingLevel);
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();
Bytes::const_iterator m_it;
const Bytes::const_iterator m_end;
DecoderError m_errorCode;
};
} // namespace cbor
#endif // ENABLE(WEB_AUTHN)