/src/boringssl/pki/input.h
Line | Count | Source |
1 | | // Copyright 2015 The Chromium Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef BSSL_DER_INPUT_H_ |
16 | | #define BSSL_DER_INPUT_H_ |
17 | | |
18 | | #include <stddef.h> |
19 | | #include <stdint.h> |
20 | | |
21 | | #include <string> |
22 | | #include <string_view> |
23 | | |
24 | | #include <openssl/base.h> |
25 | | #include <openssl/span.h> |
26 | | |
27 | | #if __has_include(<version>) |
28 | | #include <version> |
29 | | #endif |
30 | | |
31 | | #if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L |
32 | | #include <ranges> |
33 | | BSSL_NAMESPACE_BEGIN |
34 | | namespace der { |
35 | | class OPENSSL_EXPORT Input; |
36 | | } |
37 | | BSSL_NAMESPACE_END |
38 | | |
39 | | // Mark `Input` as satisfying the `view` and `borrowed_range` concepts. This |
40 | | // should be done before the definition of `Input`, so that any inlined calls to |
41 | | // range functionality use the correct specializations. |
42 | | template <> |
43 | | inline constexpr bool std::ranges::enable_view<bssl::der::Input> = true; |
44 | | template <> |
45 | | inline constexpr bool std::ranges::enable_borrowed_range<bssl::der::Input> = |
46 | | true; |
47 | | #endif |
48 | | |
49 | | BSSL_NAMESPACE_BEGIN |
50 | | namespace der { |
51 | | |
52 | | // An opaque class that represents a fixed buffer of data of a fixed length, |
53 | | // to be used as an input to other operations. An Input object does not own |
54 | | // the data it references, so callers are responsible for making sure that |
55 | | // the data outlives the Input object and any other associated objects. |
56 | | // |
57 | | // All data access for an Input should be done through the ByteReader class. |
58 | | // This class and associated classes are designed with safety in mind to make it |
59 | | // difficult to read memory outside of an Input. ByteReader provides a simple |
60 | | // API for reading through the Input sequentially. For more complicated uses, |
61 | | // multiple instances of a ByteReader for a particular Input can be created. |
62 | | // |
63 | | // TODO(crbug.com/boringssl/661): This class will gradually be replaced with |
64 | | // bssl::Span<const uint8_t>. Avoid relying on APIs that are not part of |
65 | | // bssl::Span. |
66 | | class OPENSSL_EXPORT Input { |
67 | | public: |
68 | | // Creates an empty Input, one from which no data can be read. |
69 | 2.96M | constexpr Input() = default; |
70 | | |
71 | | // Creates an Input from a span. The constructed Input is only valid as long |
72 | | // as |data| points to live memory. If constructed from, say, a |
73 | | // |std::vector<uint8_t>|, mutating the vector will invalidate the Input. |
74 | 28.7k | constexpr Input(bssl::Span<const uint8_t> data) : data_(data) {} |
75 | | |
76 | | // Creates an Input from the given |data| and |len|. |
77 | | constexpr explicit Input(const uint8_t *data, size_t len) |
78 | 1.69M | : data_(Span(data, len)) {} |
79 | | |
80 | | // Deprecated: Use StringAsBytes. |
81 | | // |
82 | | // Creates an Input from a std::string_view. The constructed Input is only |
83 | | // valid as long as |data| points to live memory. If constructed from, say, a |
84 | | // |std::string|, mutating the vector will invalidate the Input. |
85 | 925 | explicit Input(std::string_view str) : data_(StringAsBytes(str)) {} |
86 | | |
87 | | // The following APIs have the same semantics as in |bssl::Span|. |
88 | 382 | constexpr Span<const uint8_t>::iterator begin() const { |
89 | 382 | return data_.begin(); |
90 | 382 | } |
91 | 382 | constexpr Span<const uint8_t>::iterator end() const { return data_.end(); } |
92 | 2.58M | constexpr const uint8_t *data() const { return data_.data(); } |
93 | 2.44M | constexpr size_t size() const { return data_.size(); } |
94 | 4.76k | constexpr bool empty() const { return data_.empty(); } |
95 | 1.18k | constexpr uint8_t operator[](size_t idx) const { return data_[idx]; } |
96 | 0 | constexpr uint8_t front() const { return data_.front(); } |
97 | 3.27k | constexpr uint8_t back() const { return data_.back(); } |
98 | 0 | constexpr Input subspan(size_t pos, size_t len) const { |
99 | 0 | return Input(data_.subspan(pos, len)); |
100 | 0 | } |
101 | 188 | constexpr Input subspan(size_t pos) const { |
102 | 188 | return Input(data_.subspan(pos)); |
103 | 188 | } |
104 | 188 | constexpr Input first(size_t len) const { return Input(data_.first(len)); } |
105 | 0 | constexpr Input last(size_t len) const { return Input(data_.last(len)); } |
106 | | |
107 | | private: |
108 | | // TODO(crbug.com/770501): Replace this type with span altogether. |
109 | | Span<const uint8_t> data_; |
110 | | }; |
111 | | |
112 | | // Return true if |lhs|'s data and |rhs|'s data are byte-wise equal. |
113 | | OPENSSL_EXPORT bool operator==(Input lhs, Input rhs); |
114 | | |
115 | | // Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal. |
116 | | OPENSSL_EXPORT bool operator!=(Input lhs, Input rhs); |
117 | | |
118 | | // Returns true if |lhs|'s data is lexicographically less than |rhs|'s data. |
119 | 242k | OPENSSL_EXPORT constexpr bool operator<(Input lhs, Input rhs) { |
120 | | // This is `std::lexicographical_compare`, but that's not `constexpr` until |
121 | | // C++-20. |
122 | 242k | auto *it1 = lhs.data(); |
123 | 242k | auto *it2 = rhs.data(); |
124 | 242k | const auto *end1 = lhs.data() + lhs.size(); |
125 | 242k | const auto *end2 = rhs.data() + rhs.size(); |
126 | 687k | for (; it1 != end1 && it2 != end2; ++it1, ++it2) { |
127 | 659k | if (*it1 < *it2) { |
128 | 143k | return true; |
129 | 515k | } else if (*it2 < *it1) { |
130 | 71.2k | return false; |
131 | 71.2k | } |
132 | 659k | } |
133 | | |
134 | 27.6k | return it2 != end2; |
135 | 242k | } |
136 | | |
137 | | // This class provides ways to read data from an Input in a bounds-checked way. |
138 | | // The ByteReader is designed to read through the input sequentially. Once a |
139 | | // byte has been read with a ByteReader, the caller can't go back and re-read |
140 | | // that byte with the same reader. Of course, the caller can create multiple |
141 | | // ByteReaders for the same input (or copy an existing ByteReader). |
142 | | // |
143 | | // For something simple like a single byte lookahead, the easiest way to do |
144 | | // that is to copy the ByteReader and call ReadByte() on the copy - the original |
145 | | // ByteReader will be unaffected and the peeked byte will be read through |
146 | | // ReadByte(). For other read patterns, it can be useful to mark where one is |
147 | | // in a ByteReader to be able to return to that spot. |
148 | | // |
149 | | // Some operations using Mark can also be done by creating a copy of the |
150 | | // ByteReader. By using a Mark instead, you use less memory, but more |
151 | | // importantly, you end up with an immutable object that matches the semantics |
152 | | // of what is intended. |
153 | | class OPENSSL_EXPORT ByteReader { |
154 | | public: |
155 | | // Creates a ByteReader to read the data represented by an Input. |
156 | | explicit ByteReader(Input in); |
157 | | |
158 | | // Reads a single byte from the input source, putting the byte read in |
159 | | // |*byte_p|. If a byte cannot be read from the input (because there is |
160 | | // no input left), then this method returns false. |
161 | | [[nodiscard]] bool ReadByte(uint8_t *out); |
162 | | |
163 | | // Reads |len| bytes from the input source, and initializes an Input to |
164 | | // point to that data. If there aren't enough bytes left in the input source, |
165 | | // then this method returns false. |
166 | | [[nodiscard]] bool ReadBytes(size_t len, Input *out); |
167 | | |
168 | | // Returns how many bytes are left to read. |
169 | 3.28k | size_t BytesLeft() const { return data_.size(); } |
170 | | |
171 | | // Returns whether there is any more data to be read. |
172 | | bool HasMore(); |
173 | | |
174 | | private: |
175 | | void Advance(size_t len); |
176 | | |
177 | | bssl::Span<const uint8_t> data_; |
178 | | }; |
179 | | |
180 | | } // namespace der |
181 | | BSSL_NAMESPACE_END |
182 | | |
183 | | #endif // BSSL_DER_INPUT_H_ |