aboutsummaryrefslogtreecommitdiff
path: root/pki/input.h
blob: 30ce5d4afbb8f3baf686a7b40dec9d90a17cec4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BSSL_DER_INPUT_H_
#define BSSL_DER_INPUT_H_

#include <stddef.h>
#include <stdint.h>

#include <string>
#include <string_view>

#include <openssl/base.h>
#include <openssl/span.h>

namespace bssl::der {

// An opaque class that represents a fixed buffer of data of a fixed length,
// to be used as an input to other operations. An Input object does not own
// the data it references, so callers are responsible for making sure that
// the data outlives the Input object and any other associated objects.
//
// All data access for an Input should be done through the ByteReader class.
// This class and associated classes are designed with safety in mind to make it
// difficult to read memory outside of an Input. ByteReader provides a simple
// API for reading through the Input sequentially. For more complicated uses,
// multiple instances of a ByteReader for a particular Input can be created.
//
// TODO(crbug.com/boringssl/661): This class will gradually be replaced with
// bssl::Span<const uint8_t>. Avoid relying on APIs that are not part of
// bssl::Span.
class OPENSSL_EXPORT Input {
 public:
  // Creates an empty Input, one from which no data can be read.
  constexpr Input() = default;

  // Creates an Input from a span. The constructed Input is only valid as long
  // as |data| points to live memory. If constructed from, say, a
  // |std::vector<uint8_t>|, mutating the vector will invalidate the Input.
  constexpr Input(bssl::Span<const uint8_t> data) : data_(data) {}

  // Creates an Input from the given |data| and |len|.
  constexpr explicit Input(const uint8_t *data, size_t len)
      : data_(MakeConstSpan(data, len)) {}

  // Deprecated: Use StringAsBytes.
  //
  // Creates an Input from a std::string_view. The constructed Input is only
  // valid as long as |data| points to live memory. If constructed from, say, a
  // |std::string|, mutating the vector will invalidate the Input.
  explicit Input(std::string_view str)
      : data_(MakeConstSpan(reinterpret_cast<const uint8_t *>(str.data()),
                            str.size())) {}

  // The following APIs have the same semantics as in |bssl::Span|.
  constexpr Span<const uint8_t>::iterator begin() const {
    return data_.begin();
  }
  constexpr Span<const uint8_t>::iterator end() const { return data_.end(); }
  constexpr const uint8_t *data() const { return data_.data(); }
  constexpr size_t size() const { return data_.size(); }
  constexpr bool empty() const { return data_.empty(); }
  constexpr uint8_t operator[](size_t idx) const { return data_[idx]; }
  constexpr uint8_t front() const { return data_.front(); }
  constexpr uint8_t back() const { return data_.back(); }
  constexpr Input subspan(size_t pos = 0,
                          size_t len = Span<const uint8_t>::npos) const {
    return Input(data_.subspan(pos, len));
  }
  constexpr Input first(size_t len) const { return Input(data_.first(len)); }
  constexpr Input last(size_t len) const { return Input(data_.last(len)); }

  // Deprecated: use BytesAsStringView and convert to std::string.
  //
  // Returns a copy of the data represented by this object as a std::string.
  std::string AsString() const;

  // Deprecated: Use ByteAsString. 
  //
  // Returns a std::string_view pointing to the same data as the Input. The
  // resulting string_view must not outlive the data that was used to construct
  // this Input.
  std::string_view AsStringView() const { return BytesAsStringView(data_); }

  // Deprecated: This class implicitly converts to bssl::Span<const uint8_t>.
  //
  // Returns a span pointing to the same data as the Input. The resulting span
  // must not outlive the data that was used to construct this Input.
  Span<const uint8_t> AsSpan() const { return *this; }

  // Deprecated: Use size() instead.
  constexpr size_t Length() const { return size(); }

  // Deprecated: Use data() instead.
  constexpr const uint8_t *UnsafeData() const { return data(); }

 private:
  // TODO(crbug.com/770501): Replace this type with span altogether.
  Span<const uint8_t> data_;
};

// Return true if |lhs|'s data and |rhs|'s data are byte-wise equal.
OPENSSL_EXPORT bool operator==(Input lhs, Input rhs);

// Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal.
OPENSSL_EXPORT bool operator!=(Input lhs, Input rhs);

// Returns true if |lhs|'s data is lexicographically less than |rhs|'s data.
OPENSSL_EXPORT constexpr bool operator<(Input lhs, Input rhs) {
  // This is `std::lexicographical_compare`, but that's not `constexpr` until
  // C++-20.
  auto *it1 = lhs.data();
  auto *it2 = rhs.data();
  const auto *end1 = lhs.data() + lhs.size();
  const auto *end2 = rhs.data() + rhs.size();
  for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
    if (*it1 < *it2) {
      return true;
    } else if (*it2 < *it1) {
      return false;
    }
  }

  return it2 != end2;
}

// This class provides ways to read data from an Input in a bounds-checked way.
// The ByteReader is designed to read through the input sequentially. Once a
// byte has been read with a ByteReader, the caller can't go back and re-read
// that byte with the same reader. Of course, the caller can create multiple
// ByteReaders for the same input (or copy an existing ByteReader).
//
// For something simple like a single byte lookahead, the easiest way to do
// that is to copy the ByteReader and call ReadByte() on the copy - the original
// ByteReader will be unaffected and the peeked byte will be read through
// ReadByte(). For other read patterns, it can be useful to mark where one is
// in a ByteReader to be able to return to that spot.
//
// Some operations using Mark can also be done by creating a copy of the
// ByteReader. By using a Mark instead, you use less memory, but more
// importantly, you end up with an immutable object that matches the semantics
// of what is intended.
class OPENSSL_EXPORT ByteReader {
 public:
  // Creates a ByteReader to read the data represented by an Input.
  explicit ByteReader(Input in);

  // Reads a single byte from the input source, putting the byte read in
  // |*byte_p|. If a byte cannot be read from the input (because there is
  // no input left), then this method returns false.
  [[nodiscard]] bool ReadByte(uint8_t *out);

  // Reads |len| bytes from the input source, and initializes an Input to
  // point to that data. If there aren't enough bytes left in the input source,
  // then this method returns false.
  [[nodiscard]] bool ReadBytes(size_t len, Input *out);

  // Returns how many bytes are left to read.
  size_t BytesLeft() const { return data_.size(); }

  // Returns whether there is any more data to be read.
  bool HasMore();

 private:
  void Advance(size_t len);

  bssl::Span<const uint8_t> data_;
};

}  // namespace bssl::der

#endif  // BSSL_DER_INPUT_H_