1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BSSL_DER_INPUT_H_ 6 #define BSSL_DER_INPUT_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <string> 12 #include <string_view> 13 14 #include <openssl/base.h> 15 #include <openssl/span.h> 16 17 namespace bssl::der { 18 19 // An opaque class that represents a fixed buffer of data of a fixed length, 20 // to be used as an input to other operations. An Input object does not own 21 // the data it references, so callers are responsible for making sure that 22 // the data outlives the Input object and any other associated objects. 23 // 24 // All data access for an Input should be done through the ByteReader class. 25 // This class and associated classes are designed with safety in mind to make it 26 // difficult to read memory outside of an Input. ByteReader provides a simple 27 // API for reading through the Input sequentially. For more complicated uses, 28 // multiple instances of a ByteReader for a particular Input can be created. 29 // 30 // TODO(crbug.com/boringssl/661): This class will gradually be replaced with 31 // bssl::Span<const uint8_t>. Avoid relying on APIs that are not part of 32 // bssl::Span. 33 class OPENSSL_EXPORT Input { 34 public: 35 // Creates an empty Input, one from which no data can be read. 36 constexpr Input() = default; 37 38 // Creates an Input from a span. The constructed Input is only valid as long 39 // as |data| points to live memory. If constructed from, say, a 40 // |std::vector<uint8_t>|, mutating the vector will invalidate the Input. Input(bssl::Span<const uint8_t> data)41 constexpr Input(bssl::Span<const uint8_t> data) : data_(data) {} 42 43 // Creates an Input from the given |data| and |len|. Input(const uint8_t * data,size_t len)44 constexpr explicit Input(const uint8_t *data, size_t len) 45 : data_(MakeConstSpan(data, len)) {} 46 47 // Deprecated: Use StringAsBytes. 48 // 49 // Creates an Input from a std::string_view. The constructed Input is only 50 // valid as long as |data| points to live memory. If constructed from, say, a 51 // |std::string|, mutating the vector will invalidate the Input. Input(std::string_view str)52 explicit Input(std::string_view str) 53 : data_(MakeConstSpan(reinterpret_cast<const uint8_t *>(str.data()), 54 str.size())) {} 55 56 // The following APIs have the same semantics as in |bssl::Span|. begin()57 constexpr Span<const uint8_t>::iterator begin() const { 58 return data_.begin(); 59 } end()60 constexpr Span<const uint8_t>::iterator end() const { return data_.end(); } data()61 constexpr const uint8_t *data() const { return data_.data(); } size()62 constexpr size_t size() const { return data_.size(); } empty()63 constexpr bool empty() const { return data_.empty(); } 64 constexpr uint8_t operator[](size_t idx) const { return data_[idx]; } front()65 constexpr uint8_t front() const { return data_.front(); } back()66 constexpr uint8_t back() const { return data_.back(); } 67 constexpr Input subspan(size_t pos = 0, 68 size_t len = Span<const uint8_t>::npos) const { 69 return Input(data_.subspan(pos, len)); 70 } first(size_t len)71 constexpr Input first(size_t len) const { return Input(data_.first(len)); } last(size_t len)72 constexpr Input last(size_t len) const { return Input(data_.last(len)); } 73 74 // Deprecated: use BytesAsStringView and convert to std::string. 75 // 76 // Returns a copy of the data represented by this object as a std::string. 77 std::string AsString() const; 78 79 // Deprecated: Use ByteAsString. 80 // 81 // Returns a std::string_view pointing to the same data as the Input. The 82 // resulting string_view must not outlive the data that was used to construct 83 // this Input. AsStringView()84 std::string_view AsStringView() const { return BytesAsStringView(data_); } 85 86 // Deprecated: This class implicitly converts to bssl::Span<const uint8_t>. 87 // 88 // Returns a span pointing to the same data as the Input. The resulting span 89 // must not outlive the data that was used to construct this Input. AsSpan()90 Span<const uint8_t> AsSpan() const { return *this; } 91 92 // Deprecated: Use size() instead. Length()93 constexpr size_t Length() const { return size(); } 94 95 // Deprecated: Use data() instead. UnsafeData()96 constexpr const uint8_t *UnsafeData() const { return data(); } 97 98 private: 99 // TODO(crbug.com/770501): Replace this type with span altogether. 100 Span<const uint8_t> data_; 101 }; 102 103 // Return true if |lhs|'s data and |rhs|'s data are byte-wise equal. 104 OPENSSL_EXPORT bool operator==(Input lhs, Input rhs); 105 106 // Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal. 107 OPENSSL_EXPORT bool operator!=(Input lhs, Input rhs); 108 109 // Returns true if |lhs|'s data is lexicographically less than |rhs|'s data. 110 OPENSSL_EXPORT constexpr bool operator<(Input lhs, Input rhs) { 111 // This is `std::lexicographical_compare`, but that's not `constexpr` until 112 // C++-20. 113 auto *it1 = lhs.data(); 114 auto *it2 = rhs.data(); 115 const auto *end1 = lhs.data() + lhs.size(); 116 const auto *end2 = rhs.data() + rhs.size(); 117 for (; it1 != end1 && it2 != end2; ++it1, ++it2) { 118 if (*it1 < *it2) { 119 return true; 120 } else if (*it2 < *it1) { 121 return false; 122 } 123 } 124 125 return it2 != end2; 126 } 127 128 // This class provides ways to read data from an Input in a bounds-checked way. 129 // The ByteReader is designed to read through the input sequentially. Once a 130 // byte has been read with a ByteReader, the caller can't go back and re-read 131 // that byte with the same reader. Of course, the caller can create multiple 132 // ByteReaders for the same input (or copy an existing ByteReader). 133 // 134 // For something simple like a single byte lookahead, the easiest way to do 135 // that is to copy the ByteReader and call ReadByte() on the copy - the original 136 // ByteReader will be unaffected and the peeked byte will be read through 137 // ReadByte(). For other read patterns, it can be useful to mark where one is 138 // in a ByteReader to be able to return to that spot. 139 // 140 // Some operations using Mark can also be done by creating a copy of the 141 // ByteReader. By using a Mark instead, you use less memory, but more 142 // importantly, you end up with an immutable object that matches the semantics 143 // of what is intended. 144 class OPENSSL_EXPORT ByteReader { 145 public: 146 // Creates a ByteReader to read the data represented by an Input. 147 explicit ByteReader(Input in); 148 149 // Reads a single byte from the input source, putting the byte read in 150 // |*byte_p|. If a byte cannot be read from the input (because there is 151 // no input left), then this method returns false. 152 [[nodiscard]] bool ReadByte(uint8_t *out); 153 154 // Reads |len| bytes from the input source, and initializes an Input to 155 // point to that data. If there aren't enough bytes left in the input source, 156 // then this method returns false. 157 [[nodiscard]] bool ReadBytes(size_t len, Input *out); 158 159 // Returns how many bytes are left to read. BytesLeft()160 size_t BytesLeft() const { return data_.size(); } 161 162 // Returns whether there is any more data to be read. 163 bool HasMore(); 164 165 private: 166 void Advance(size_t len); 167 168 bssl::Span<const uint8_t> data_; 169 }; 170 171 } // namespace bssl::der 172 173 #endif // BSSL_DER_INPUT_H_ 174