1#ifndef SOURCEMETA_CORE_CRYPTO_SECURE_H_
2#define SOURCEMETA_CORE_CRYPTO_SECURE_H_
4#ifndef SOURCEMETA_CORE_CRYPTO_EXPORT
5#include <sourcemeta/core/crypto_export.h>
16namespace sourcemeta::core {
32inline auto secure_zero(
void *
const data,
const std::size_t size)
noexcept
34 if (data ==
nullptr) {
38 auto *pointer{
static_cast<volatile unsigned char *
>(data)};
39 for (std::size_t index{0}; index < size; index += 1) {
110 using value_type = T;
116 template <typename Other>
120 [[nodiscard]]
auto allocate(
const std::size_t count) -> T * {
121 if (count > std::numeric_limits<std::size_t>::max() /
sizeof(T)) {
122 throw std::bad_array_new_length{};
125 return static_cast<T *
>(
126 ::operator
new(count *
sizeof(T), std::align_val_t{
alignof(T)}));
130 auto deallocate(T *
const pointer,
const std::size_t count)
noexcept ->
void {
132 ::operator
delete(pointer, std::align_val_t{
alignof(T)});
136 template <
typename Other>
142 template <
typename Other>
165 using size_type = std::vector<char, SecureAllocator<char>>::size_type;
172 : buffer_(value.begin(), value.end()) {}
180 : buffer_(count, value) {}
183 [[nodiscard]]
auto size() const noexcept -> size_type {
184 return this->buffer_.size();
188 [[nodiscard]]
auto empty() const noexcept ->
bool {
189 return this->buffer_.empty();
198 [[nodiscard]]
auto capacity() const noexcept -> size_type {
199 return this->buffer_.capacity();
204 auto resize(
const size_type count,
const char value) ->
void {
205 this->buffer_.resize(count, value);
209 auto push_back(
const char value) ->
void { this->buffer_.push_back(value); }
212 auto append(
const std::string_view value) ->
void {
218 const char *
const first{this->buffer_.data()};
219 const std::less<const char *> before{};
220 if (!this->buffer_.empty() && !before(value.data(), first) &&
221 before(value.data(), first + this->buffer_.size())) {
222 const std::vector<char, SecureAllocator<char>> copy(value.begin(),
224 this->buffer_.insert(this->buffer_.end(), copy.begin(), copy.end());
226 this->buffer_.insert(this->buffer_.end(), value.begin(), value.end());
231 auto append(
const size_type count,
const char value) ->
void {
232 this->buffer_.insert(this->buffer_.end(), count, value);
236 [[nodiscard]]
auto operator[](
const size_type index)
noexcept ->
char & {
237 return this->buffer_[index];
241 [[nodiscard]]
auto operator[](
const size_type index)
const noexcept ->
char {
242 return this->buffer_[index];
246 [[nodiscard]]
auto front() const noexcept ->
char {
247 return this->buffer_.front();
251 [[nodiscard]]
auto back() const noexcept ->
char {
252 return this->buffer_.back();
256 [[nodiscard]]
operator std::string_view() const noexcept {
259 if (this->buffer_.empty()) {
263 return {this->buffer_.data(), this->buffer_.size()};
267 [[nodiscard]]
auto data() const noexcept -> const
char * {
268 return this->buffer_.data();
272 [[nodiscard]]
auto operator==(
const std::string_view other)
const noexcept
274 return std::string_view{*
this} == other;
278 std::vector<char, SecureAllocator<char>> buffer_;
SecureString(const char *const data, const size_type length)
Construct from a pointer and a length.
Definition crypto_secure.h:175
auto deallocate(T *const pointer, const std::size_t count) noexcept -> void
Wipe and release the storage of the given number of objects.
Definition crypto_secure.h:130
auto capacity() const noexcept -> size_type
The number of bytes that can be held before growing the storage.
Definition crypto_secure.h:198
auto size() const noexcept -> size_type
The number of bytes held.
Definition crypto_secure.h:183
auto push_back(const char value) -> void
Append a single byte.
Definition crypto_secure.h:209
auto empty() const noexcept -> bool
Whether no bytes are held.
Definition crypto_secure.h:188
auto reserve(const size_type capacity) -> void
Reserve storage for at least the given number of bytes.
Definition crypto_secure.h:193
SecureString(const size_type count, const char value)
Construct a run of a repeated byte.
Definition crypto_secure.h:179
auto allocate(const std::size_t count) -> T *
Allocate storage for the given number of objects.
Definition crypto_secure.h:120
auto resize(const size_type count, const char value) -> void
Definition crypto_secure.h:204
auto data() const noexcept -> const char *
A pointer to the held bytes, valid until the next mutation.
Definition crypto_secure.h:267
auto back() const noexcept -> char
The last byte.
Definition crypto_secure.h:251
auto append(const std::string_view value) -> void
Append a view of bytes.
Definition crypto_secure.h:212
SecureAllocator() noexcept=default
Construct an allocator, which holds no state of its own.
auto append(const size_type count, const char value) -> void
Append a run of a repeated byte.
Definition crypto_secure.h:231
std::string & target
The captured string, whose storage is wiped at scope exit.
Definition crypto_secure.h:91
SecureString()=default
Construct an empty string.
auto front() const noexcept -> char
The first byte.
Definition crypto_secure.h:246
SecureString(const std::string_view value)
Construct from a view of bytes.
Definition crypto_secure.h:171
SecureStringScope(std::string &value) noexcept
Capture the string to wipe when leaving the current scope.
Definition crypto_secure.h:84
auto secure_zero(void *const data, const std::size_t size) noexcept -> void
Definition crypto_secure.h:32