blob: e0dff1ffb4bd250544f363b41a722b54fec02df3 [file] [log] [blame]
Bob Beckbc97b7a2023-04-18 08:35:15 -06001// 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 "fillins/openssl_util.h"
9#include <stddef.h>
10#include <stdint.h>
11
12#include <string>
Bob Beck2e119172023-08-14 11:06:38 -060013#include <string_view>
14
Bob Beckbc97b7a2023-04-18 08:35:15 -060015
16#include <openssl/span.h>
17
Bob Beckbc97b7a2023-04-18 08:35:15 -060018namespace bssl::der {
19
20// An opaque class that represents a fixed buffer of data of a fixed length,
21// to be used as an input to other operations. An Input object does not own
22// the data it references, so callers are responsible for making sure that
23// the data outlives the Input object and any other associated objects.
24//
25// All data access for an Input should be done through the ByteReader class.
26// This class and associated classes are designed with safety in mind to make it
27// difficult to read memory outside of an Input. ByteReader provides a simple
28// API for reading through the Input sequentially. For more complicated uses,
29// multiple instances of a ByteReader for a particular Input can be created.
30class OPENSSL_EXPORT Input {
31 public:
32 // Creates an empty Input, one from which no data can be read.
33 constexpr Input() = default;
34
Bob Beck2e119172023-08-14 11:06:38 -060035 // Creates an Input from a span. The constructed Input is only valid as long
36 // as |data| points to live memory. If constructed from, say, a
37 // |std::vector<uint8_t>|, mutating the vector will invalidate the Input.
38 constexpr explicit Input(bssl::Span<const uint8_t> data) : data_(data) {}
Bob Beckbc97b7a2023-04-18 08:35:15 -060039
40 // Creates an Input from the given |data| and |len|.
41 constexpr explicit Input(const uint8_t* data, size_t len)
Bob Beck2e119172023-08-14 11:06:38 -060042 : data_(bssl::MakeConstSpan(data, len)) {}
Bob Beckbc97b7a2023-04-18 08:35:15 -060043
Bob Beck2e119172023-08-14 11:06:38 -060044 // Creates an Input from a std::string_view. The constructed Input is only
45 // valid as long as |data| points to live memory. If constructed from, say, a
46 // |std::string|, mutating the vector will invalidate the Input.
47 explicit Input(std::string_view str)
48 : data_(bssl::MakeConstSpan(reinterpret_cast<const uint8_t*>(str.data()),
49 str.size())) {}
Bob Beckbc97b7a2023-04-18 08:35:15 -060050
51 // Returns the length in bytes of an Input's data.
Bob Beck2e119172023-08-14 11:06:38 -060052 constexpr size_t Length() const { return data_.size(); }
Bob Beckbc97b7a2023-04-18 08:35:15 -060053
54 // Returns a pointer to the Input's data. This method is marked as "unsafe"
55 // because access to the Input's data should be done through ByteReader
56 // instead. This method should only be used where using a ByteReader truly
57 // is not an option.
Bob Beck2e119172023-08-14 11:06:38 -060058 constexpr const uint8_t* UnsafeData() const { return data_.data(); }
Bob Beckbc97b7a2023-04-18 08:35:15 -060059
60 // Returns a copy of the data represented by this object as a std::string.
61 std::string AsString() const;
62
63 // Returns a std::string_view pointing to the same data as the Input. The
64 // resulting string_view must not outlive the data that was used to construct
65 // this Input.
66 std::string_view AsStringView() const;
67
Bob Beck2e119172023-08-14 11:06:38 -060068 // Returns a span pointing to the same data as the Input. The resulting span
69 // must not outlive the data that was used to construct this Input.
Bob Beckbc97b7a2023-04-18 08:35:15 -060070 bssl::Span<const uint8_t> AsSpan() const;
71
72 private:
Bob Beck2e119172023-08-14 11:06:38 -060073 // TODO(crbug.com/770501): Replace this type with span altogether.
74 bssl::Span<const uint8_t> data_;
Bob Beckbc97b7a2023-04-18 08:35:15 -060075};
76
77// Return true if |lhs|'s data and |rhs|'s data are byte-wise equal.
78OPENSSL_EXPORT bool operator==(const Input& lhs, const Input& rhs);
79
80// Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal.
81OPENSSL_EXPORT bool operator!=(const Input& lhs, const Input& rhs);
82
83// Returns true if |lhs|'s data is lexicographically less than |rhs|'s data.
84OPENSSL_EXPORT constexpr bool operator<(const Input& lhs,
85 const Input& rhs) {
86 // This is `std::lexicographical_compare`, but that's not `constexpr` until
87 // C++-20.
88 auto* it1 = lhs.UnsafeData();
89 auto* it2 = rhs.UnsafeData();
90 const auto* end1 = lhs.UnsafeData() + lhs.Length();
91 const auto* end2 = rhs.UnsafeData() + rhs.Length();
92 for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
93 if (*it1 < *it2) {
94 return true;
95 } else if (*it2 < *it1) {
96 return false;
97 }
98 }
99
100 return it2 != end2;
101}
102
103// This class provides ways to read data from an Input in a bounds-checked way.
104// The ByteReader is designed to read through the input sequentially. Once a
105// byte has been read with a ByteReader, the caller can't go back and re-read
106// that byte with the same reader. Of course, the caller can create multiple
107// ByteReaders for the same input (or copy an existing ByteReader).
108//
109// For something simple like a single byte lookahead, the easiest way to do
110// that is to copy the ByteReader and call ReadByte() on the copy - the original
111// ByteReader will be unaffected and the peeked byte will be read through
112// ReadByte(). For other read patterns, it can be useful to mark where one is
113// in a ByteReader to be able to return to that spot.
114//
115// Some operations using Mark can also be done by creating a copy of the
116// ByteReader. By using a Mark instead, you use less memory, but more
117// importantly, you end up with an immutable object that matches the semantics
118// of what is intended.
119class OPENSSL_EXPORT ByteReader {
120 public:
121 // Creates a ByteReader to read the data represented by an Input.
122 explicit ByteReader(const Input& in);
123
124 // Reads a single byte from the input source, putting the byte read in
125 // |*byte_p|. If a byte cannot be read from the input (because there is
126 // no input left), then this method returns false.
127 [[nodiscard]] bool ReadByte(uint8_t* out);
128
129 // Reads |len| bytes from the input source, and initializes an Input to
130 // point to that data. If there aren't enough bytes left in the input source,
131 // then this method returns false.
132 [[nodiscard]] bool ReadBytes(size_t len, Input* out);
133
134 // Returns how many bytes are left to read.
135 size_t BytesLeft() const { return len_; }
136
137 // Returns whether there is any more data to be read.
138 bool HasMore();
139
140 private:
141 void Advance(size_t len);
142
143 const uint8_t* data_;
144 size_t len_;
145};
146
147} // namespace bssl::der
148
149#endif // BSSL_DER_INPUT_H_