diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/prov/tpm/info.txt | 1 | ||||
-rw-r--r-- | src/lib/prov/tpm/uuid.h | 106 | ||||
-rw-r--r-- | src/lib/utils/uuid/info.txt | 8 | ||||
-rw-r--r-- | src/lib/utils/uuid/uuid.cpp | 82 | ||||
-rw-r--r-- | src/lib/utils/uuid/uuid.h | 66 | ||||
-rw-r--r-- | src/tests/test_utils.cpp | 73 |
6 files changed, 230 insertions, 106 deletions
diff --git a/src/lib/prov/tpm/info.txt b/src/lib/prov/tpm/info.txt index 8ec00ba86..3993efc53 100644 --- a/src/lib/prov/tpm/info.txt +++ b/src/lib/prov/tpm/info.txt @@ -9,6 +9,7 @@ all -> tspi </libs> <requires> +uuid hash_id rsa rng diff --git a/src/lib/prov/tpm/uuid.h b/src/lib/prov/tpm/uuid.h deleted file mode 100644 index 2c89d45b4..000000000 --- a/src/lib/prov/tpm/uuid.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -* UUID type -* (C) 2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_UUID_H_ -#define BOTAN_UUID_H_ - -#include <botan/secmem.h> -#include <botan/hex.h> -#include <sstream> - -namespace Botan { - -// TODO: move to util? -class UUID final - { - public: - // Represents an unassigned UUID object - UUID() : m_uuid(0) {} - - UUID(RandomNumberGenerator& rng) - { - m_uuid.resize(16); - rng.randomize(m_uuid.data(), m_uuid.size()); - - // Mark as a random UUID (RFC 4122 sec 4.4) - m_uuid[6] = 0x40 | (m_uuid[6] & 0x0F); - - // Set two reserved bits - m_uuid[8] = 0xC0 | (m_uuid[8] & 0x3F); - } - - UUID(const std::vector<uint8_t>& blob) - { - if(blob.size() != 16) - { - throw Invalid_Argument("Bad UUID blob " + hex_encode(blob)); - } - - m_uuid = blob; - } - - UUID(const std::string& uuid_str) - { - if(uuid_str.size() != 36 || - uuid_str[8] != '-' || - uuid_str[14] != '-' || - uuid_str[19] != '-' || - uuid_str[24] != '-') - { - throw Invalid_Argument("Bad UUID '" + uuid_str + "'"); - } - - std::string just_hex; - for(size_t i = 0; i != uuid_str.size(); ++i) - { - char c = uuid_str[i]; - - if(c == '-') - continue; - - just_hex += c; - } - - m_uuid = hex_decode(just_hex); - - if(m_uuid.size() != 16) - { - throw Invalid_Argument("Bad UUID '" + uuid_str + "'"); - } - } - - - std::string to_string() const - { - std::string h = hex_encode(m_uuid); - - h.insert(8, "-"); - h.insert(14, "-"); - h.insert(19, "-"); - h.insert(24, "-"); - - return h; - } - - const std::vector<uint8_t>& binary_value() const { return m_uuid; } - - bool operator==(const UUID& other) const - { - return m_uuid == other.m_uuid; - } - - bool operator!=(const UUID& other) const { return !(*this == other); } - - bool is_valid() const { return m_uuid.size() == 16; } - - private: - std::vector<uint8_t> m_uuid; - }; - -} - -#endif diff --git a/src/lib/utils/uuid/info.txt b/src/lib/utils/uuid/info.txt new file mode 100644 index 000000000..b078146e8 --- /dev/null +++ b/src/lib/utils/uuid/info.txt @@ -0,0 +1,8 @@ +<defines> +UUID -> 20180930 +</defines> + +<requires> +rng +hex +</requires> diff --git a/src/lib/utils/uuid/uuid.cpp b/src/lib/utils/uuid/uuid.cpp new file mode 100644 index 000000000..c81cae665 --- /dev/null +++ b/src/lib/utils/uuid/uuid.cpp @@ -0,0 +1,82 @@ +/* +* UUID type +* (C) 2015,2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/uuid.h> +#include <botan/rng.h> +#include <botan/hex.h> +#include <sstream> + +namespace Botan { + +UUID::UUID(RandomNumberGenerator& rng) + { + m_uuid.resize(16); + rng.randomize(m_uuid.data(), m_uuid.size()); + + // Mark as a random v4 UUID (RFC 4122 sec 4.4) + m_uuid[6] = 0x40 | (m_uuid[6] & 0x0F); + + // Set reserved bits + m_uuid[8] = 0x80 | (m_uuid[8] & 0x3F); + } + +UUID::UUID(const std::vector<uint8_t>& blob) + { + if(blob.size() != 16) + { + throw Invalid_Argument("Bad UUID blob " + hex_encode(blob)); + } + + m_uuid = blob; + } + +UUID::UUID(const std::string& uuid_str) + { + if(uuid_str.size() != 36 || + uuid_str[8] != '-' || + uuid_str[13] != '-' || + uuid_str[18] != '-' || + uuid_str[23] != '-') + { + throw Invalid_Argument("Bad UUID '" + uuid_str + "'"); + } + + std::string just_hex; + for(size_t i = 0; i != uuid_str.size(); ++i) + { + char c = uuid_str[i]; + + if(c == '-') + continue; + + just_hex += c; + } + + m_uuid = hex_decode(just_hex); + + if(m_uuid.size() != 16) + { + throw Invalid_Argument("Bad UUID '" + uuid_str + "'"); + } + } + +std::string UUID::to_string() const + { + if(is_valid() == false) + throw Invalid_State("UUID object is empty cannot convert to string"); + + std::string h = hex_encode(m_uuid); + + h.insert(8, "-"); + h.insert(13, "-"); + h.insert(18, "-"); + h.insert(23, "-"); + + return h; + } + +} diff --git a/src/lib/utils/uuid/uuid.h b/src/lib/utils/uuid/uuid.h new file mode 100644 index 000000000..9d02fc2cd --- /dev/null +++ b/src/lib/utils/uuid/uuid.h @@ -0,0 +1,66 @@ +/* +* UUID type +* (C) 2015,2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_UUID_H_ +#define BOTAN_UUID_H_ + +#include <botan/types.h> +#include <vector> + +namespace Botan { + +class RandomNumberGenerator; + +class BOTAN_UNSTABLE_API UUID final + { + public: + /** + * Create an uninitialized UUID object + */ + UUID() : m_uuid() {} + + /** + * Create a random UUID + */ + UUID(RandomNumberGenerator& rng); + + /** + * Load a UUID from a 16 byte vector + */ + UUID(const std::vector<uint8_t>& blob); + + UUID& operator=(const UUID& other) = default; + UUID(const UUID& other) = default; + + /** + * Decode a UUID string + */ + UUID(const std::string& uuid_str); + + /** + * Convert the UUID to a string + */ + std::string to_string() const; + + const std::vector<uint8_t>& binary_value() const { return m_uuid; } + + bool operator==(const UUID& other) const + { + return m_uuid == other.m_uuid; + } + + bool operator!=(const UUID& other) const { return !(*this == other); } + + bool is_valid() const { return m_uuid.size() == 16; } + + private: + std::vector<uint8_t> m_uuid; + }; + +} + +#endif diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp index 2202a8f96..933f8b1e4 100644 --- a/src/tests/test_utils.cpp +++ b/src/tests/test_utils.cpp @@ -31,6 +31,10 @@ #include <botan/internal/poly_dbl.h> #endif +#if defined(BOTAN_HAS_UUID) + #include <botan/uuid.h> +#endif + namespace Botan_Tests { namespace { @@ -799,6 +803,75 @@ class CPUID_Tests final : public Test BOTAN_REGISTER_TEST("cpuid", CPUID_Tests); +#if defined(BOTAN_HAS_UUID) + +class UUID_Tests : public Test + { + public: + std::vector<Test::Result> run() override + { + Test::Result result("UUID"); + + const Botan::UUID empty_uuid; + const Botan::UUID random_uuid1(Test::rng()); + const Botan::UUID random_uuid2(Test::rng()); + const Botan::UUID loaded_uuid(std::vector<uint8_t>(16, 4)); + + result.test_throws("Cannot load wrong number of bytes", []() { Botan::UUID u(std::vector<uint8_t>(15)); }); + + result.test_eq("Empty UUID is empty", empty_uuid.is_valid(), false); + result.confirm("Empty UUID equals self", empty_uuid == empty_uuid); + + result.test_throws("Empty UUID cannot become a string", [&]() { empty_uuid.to_string(); }); + + result.test_eq("Random UUID not empty", random_uuid1.is_valid(), true); + result.test_eq("Random UUID not empty", random_uuid2.is_valid(), true); + + result.confirm("Random UUIDs are distinct", random_uuid1 != random_uuid2); + result.confirm("Random UUIDs not equal to empty", random_uuid1 != empty_uuid); + + const std::string uuid4_str = loaded_uuid.to_string(); + result.test_eq("String matches expected", uuid4_str, "04040404-0404-0404-0404-040404040404"); + + const std::string uuid_r1_str = random_uuid1.to_string(); + result.confirm("UUID from string matches", Botan::UUID(uuid_r1_str) == random_uuid1); + + class AllSame_RNG : public Botan::RandomNumberGenerator + { + public: + AllSame_RNG(uint8_t b) : m_val(b) {} + + void randomize(uint8_t out[], size_t len) override + { + std::memset(out, m_val, len); + } + + std::string name() const override { return "zeros"; } + bool accepts_input() const override { return false; } + void add_entropy(const uint8_t[], size_t) override {} + void clear() override {} + bool is_seeded() const override { return true; } + private: + uint8_t m_val; + }; + + AllSame_RNG zeros(0x00); + const Botan::UUID zero_uuid(zeros); + result.test_eq("Zero UUID matches expected", zero_uuid.to_string(), "00000000-0000-4000-8000-000000000000"); + + AllSame_RNG ones(0xFF); + const Botan::UUID ones_uuid(ones); + result.test_eq("Ones UUID matches expected", ones_uuid.to_string(), "FFFFFFFF-FFFF-4FFF-BFFF-FFFFFFFFFFFF"); + + return {result}; + } + + }; + +BOTAN_REGISTER_TEST("uuid", UUID_Tests); + +#endif + } } |