// 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> // A basic Concise Binary Object Representation (CBOR) encoder as defined by // https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies // canonical, well-formed CBOR values but does not guarantee their validity // (see https://tools.ietf.org/html/rfc7049#section-3.2). // Supported: // * Major types: // * 0: Unsigned integers, up to INT64_MAX. // * 1: Negative integers, to INT64_MIN. // * 2: Byte strings. // * 3: UTF-8 strings. // * 4: Arrays, with the number of elements known at the start. // * 5: Maps, with the number of elements known at the start // of the container. // * 7: Simple values. // // Unsupported: // * Floating-point numbers. // * Indefinite-length encodings. // * Parsing. // // Requirements for canonical CBOR as suggested by RFC 7049 are: // 1) All major data types for the CBOR values must be as short as possible. // * Unsigned integer between 0 to 23 must be expressed in same byte as // the major type. // * 24 to 255 must be expressed only with an additional uint8_t. // * 256 to 65535 must be expressed only with an additional uint16_t. // * 65536 to 4294967295 must be expressed only with an additional // uint32_t. * The rules for expression of length in major types // 2 to 5 follow the above rule for integers. // 2) Keys in every map must be sorted (first by major type, then by key // length, then by value in byte-wise lexical order). // 3) Indefinite length items must be converted to definite length items. // 4) All maps must not have duplicate keys. // // Current implementation of CBORWriter encoder meets all the requirements of // canonical CBOR. namespace cbor { class CBORWriter { WTF_MAKE_NONCOPYABLE(CBORWriter); public: // Default that should be sufficiently large for most use cases. static constexpr size_t kDefaultMaxNestingDepth = 16; ~CBORWriter(); // Returns the CBOR byte string representation of |node|, unless its nesting // depth is greater than |max_nesting_depth|, in which case an empty optional // value is returned. The nesting depth of |node| is defined as the number of // arrays/maps that has to be traversed to reach the most nested CBORValue // contained in |node|. Primitive values and empty containers have nesting // depths of 0. WEBCORE_EXPORT static Optional<Vector<uint8_t>> write(const CBORValue&, size_t maxNestingLevel = kDefaultMaxNestingDepth); private: explicit CBORWriter(Vector<uint8_t>*); // Called recursively to build the CBOR bytestring. When completed, // |m_encodedCBOR| will contain the CBOR. bool encodeCBOR(const CBORValue&, int maxNestingLevel); // Encodes the type and size of the data being added. void startItem(CBORValue::Type, uint64_t size); // Encodes the additional information for the data. void setAdditionalInformation(uint8_t); // Encodes an unsigned integer value. This is used to both write // unsigned integers and to encode the lengths of other major types. void setUint(uint64_t value); // Get the number of bytes needed to store the unsigned integer. size_t getNumUintBytes(uint64_t value); // Holds the encoded CBOR data. Vector<uint8_t>* m_encodedCBOR; }; } // namespace cbor #endif // ENABLE(WEB_AUTHN)