From 0c4942439b5cb0b59d2e723ade34a46ea932ff28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <>
Date: Tue, 2 Jan 2024 16:21:51 -0500
Subject: [PATCH] move secure_vector to its own file

---
 include/opendht/crypto.h               |  88 -------------------
 include/opendht/crypto/secure_vector.h | 114 +++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 88 deletions(-)
 create mode 100644 include/opendht/crypto/secure_vector.h

diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index e72082ea..6e8ff7a9 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -670,94 +670,6 @@ private:
     gnutls_x509_trust_list_t trust {nullptr};
 };
 
-template <class T>
-class OPENDHT_PUBLIC secure_vector
-{
-public:
-    secure_vector() {}
-    secure_vector(secure_vector<T> const&) = default;
-    secure_vector(secure_vector<T> &&) = default;
-    explicit secure_vector(unsigned size): data_(size) {}
-    explicit secure_vector(unsigned size, T _item): data_(size, _item) {}
-    explicit secure_vector(const std::vector<T>& c): data_(c) {}
-    secure_vector(std::vector<T>&& c): data_(std::move(c)) {}
-    ~secure_vector() { clean(); }
-
-    static secure_vector<T> getRandom(size_t size) {
-        secure_vector<T> ret(size);
-        std::random_device rdev;
-#ifdef _WIN32
-        std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint8_t>::max() };
-#else
-        std::uniform_int_distribution<uint8_t> rand_byte;
-#endif
-        std::generate_n((uint8_t*)ret.data_.data(), ret.size()*sizeof(T), std::bind(rand_byte, std::ref(rdev)));
-        return ret;
-    }
-    secure_vector<T>& operator=(const secure_vector<T>& c) {
-        if (&c == this)
-            return *this;
-        clean();
-        data_ = c.data_;
-        return *this;
-    }
-    secure_vector<T>& operator=(secure_vector<T>&& c) {
-        if (&c == this)
-            return *this;
-        clean();
-        data_ = std::move(c.data_);
-        return *this;
-    }
-    secure_vector<T>& operator=(std::vector<T>&& c) {
-        clean();
-        data_ = std::move(c);
-        return *this;
-    }
-    std::vector<T>& writable() { clean(); return data_; }
-    const std::vector<T>& makeInsecure() const { return data_; }
-    const uint8_t* data() const { return data_.data(); }
-
-    void clean() {
-        clean(data_.begin(), data_.end());
-    }
-
-    void clear() { clean(); data_.clear(); }
-
-    size_t size() const { return data_.size(); }
-    bool empty() const { return data_.empty(); }
-
-    void swap(secure_vector<T>& other) { data_.swap(other.data_); }
-    void resize(size_t s) {
-        if (s == data_.size()) return;
-        if (s < data_.size()) {
-            //shrink
-            clean(data_.begin()+s, data_.end());
-            data_.resize(s);
-        } else {
-            //grow
-            auto data = std::move(data_); // move protected data
-            clear();
-            data_.resize(s);
-            std::copy(data.begin(), data.end(), data_.begin());
-            clean(data.begin(), data.end());
-        }
-    }
-
-private:
-    /**
-     * Securely wipe memory
-     */
-    static void clean(const typename std::vector<T>::iterator& i, const typename std::vector<T>::iterator& j) {
-        volatile uint8_t* b = reinterpret_cast<uint8_t*>(&*i);
-        volatile uint8_t* e = reinterpret_cast<uint8_t*>(&*j);
-        std::fill(b, e, 0);
-    }
-
-    std::vector<T> data_;
-};
-
-using SecureBlob = secure_vector<uint8_t>;
-
 /**
  * Generate an RSA key pair (4096 bits) and a certificate.
  * @param name the name used in the generated certificate
diff --git a/include/opendht/crypto/secure_vector.h b/include/opendht/crypto/secure_vector.h
new file mode 100644
index 00000000..1dfb5036
--- /dev/null
+++ b/include/opendht/crypto/secure_vector.h
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (C) 2014-2023 Savoir-faire Linux Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <vector>
+#include <random>
+
+namespace dht {
+namespace crypto {
+
+template <class T>
+class secure_vector
+{
+public:
+    secure_vector() {}
+    secure_vector(secure_vector<T> const&) = default;
+    secure_vector(secure_vector<T> &&) = default;
+    explicit secure_vector(unsigned size): data_(size) {}
+    explicit secure_vector(unsigned size, T _item): data_(size, _item) {}
+    explicit secure_vector(const std::vector<T>& c): data_(c) {}
+    secure_vector(std::vector<T>&& c): data_(std::move(c)) {}
+    ~secure_vector() { clean(); }
+
+    static secure_vector<T> getRandom(size_t size) {
+        secure_vector<T> ret(size);
+        std::random_device rdev;
+#ifdef _WIN32
+        std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint8_t>::max() };
+#else
+        std::uniform_int_distribution<uint8_t> rand_byte;
+#endif
+        std::generate_n((uint8_t*)ret.data_.data(), ret.size()*sizeof(T), std::bind(rand_byte, std::ref(rdev)));
+        return ret;
+    }
+    secure_vector<T>& operator=(const secure_vector<T>& c) {
+        if (&c == this)
+            return *this;
+        clean();
+        data_ = c.data_;
+        return *this;
+    }
+    secure_vector<T>& operator=(secure_vector<T>&& c) {
+        if (&c == this)
+            return *this;
+        clean();
+        data_ = std::move(c.data_);
+        return *this;
+    }
+    secure_vector<T>& operator=(std::vector<T>&& c) {
+        clean();
+        data_ = std::move(c);
+        return *this;
+    }
+    std::vector<T>& writable() { clean(); return data_; }
+    const std::vector<T>& makeInsecure() const { return data_; }
+    const uint8_t* data() const { return data_.data(); }
+
+    void clean() {
+        clean(data_.begin(), data_.end());
+    }
+
+    void clear() { clean(); data_.clear(); }
+
+    size_t size() const { return data_.size(); }
+    bool empty() const { return data_.empty(); }
+
+    void swap(secure_vector<T>& other) { data_.swap(other.data_); }
+    void resize(size_t s) {
+        if (s == data_.size()) return;
+        if (s < data_.size()) {
+            //shrink
+            clean(data_.begin()+s, data_.end());
+            data_.resize(s);
+        } else {
+            //grow
+            auto data = std::move(data_); // move protected data
+            clear();
+            data_.resize(s);
+            std::copy(data.begin(), data.end(), data_.begin());
+            clean(data.begin(), data.end());
+        }
+    }
+
+private:
+    /**
+     * Securely wipe memory
+     */
+    static void clean(const typename std::vector<T>::iterator& i, const typename std::vector<T>::iterator& j) {
+        volatile uint8_t* b = reinterpret_cast<uint8_t*>(&*i);
+        volatile uint8_t* e = reinterpret_cast<uint8_t*>(&*j);
+        std::fill(b, e, 0);
+    }
+
+    std::vector<T> data_;
+};
+
+using SecureBlob = secure_vector<uint8_t>;
+
+}
+}
-- 
GitLab