xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/input.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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