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