From c17b6d0d44a0eb5e270585abafd689138d15c751 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 24 Feb 2020 20:14:29 -0800 Subject: [PATCH] util: add uuid --- .../include/stratosphere/util.hpp | 1 + .../stratosphere/util/util_uuid_api.hpp | 28 +++++ .../source/util/util_uuid_api.cpp | 111 ++++++++++++++++++ libraries/libvapours/include/vapours/util.hpp | 9 +- .../include/vapours/util/util_endian.hpp | 1 + .../include/vapours/util/util_uuid.hpp | 41 +++++++ 6 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/util/util_uuid_api.hpp create mode 100644 libraries/libstratosphere/source/util/util_uuid_api.cpp create mode 100644 libraries/libvapours/include/vapours/util/util_uuid.hpp diff --git a/libraries/libstratosphere/include/stratosphere/util.hpp b/libraries/libstratosphere/include/stratosphere/util.hpp index 2c4f3bd3b..db47d867f 100644 --- a/libraries/libstratosphere/include/stratosphere/util.hpp +++ b/libraries/libstratosphere/include/stratosphere/util.hpp @@ -16,5 +16,6 @@ #pragma once +#include "util/util_uuid_api.hpp" #include "util/util_compression.hpp" #include "util/util_ini.hpp" diff --git a/libraries/libstratosphere/include/stratosphere/util/util_uuid_api.hpp b/libraries/libstratosphere/include/stratosphere/util/util_uuid_api.hpp new file mode 100644 index 000000000..4782a558d --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/util/util_uuid_api.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#pragma once +#include + +namespace ams::util { + + /* Nintendo provides UUID generation following RFC 4122. */ + /* By default, UUIDs are generated as version 4 (random). */ + + Uuid GenerateUuid(); + Uuid GenerateUuidVersion5(const void *sha1_hash); + +} \ No newline at end of file diff --git a/libraries/libstratosphere/source/util/util_uuid_api.cpp b/libraries/libstratosphere/source/util/util_uuid_api.cpp new file mode 100644 index 000000000..b7f031959 --- /dev/null +++ b/libraries/libstratosphere/source/util/util_uuid_api.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include + +namespace ams::util { + + namespace { + + struct UuidImpl { + util::BitPack32 data[4]; + + using TimeLow = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + + using TimeMid = util::BitPack32::Field<0, BITSIZEOF(u16), u16>; + using TimeHighAndVersion = util::BitPack32::Field; + using Version = util::BitPack32::Field; + + static_assert(TimeHighAndVersion::Next == Version::Next); + + using ClockSeqHiAndReserved = util::BitPack32::Field<0, BITSIZEOF(u8), u8>; + using Reserved = util::BitPack32::Field<6, 2, u8>; + using ClockSeqLow = util::BitPack32::Field; + using NodeLow = util::BitPack32::Field; + + static_assert(ClockSeqHiAndReserved::Next == Reserved::Next); + + using NodeHigh = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + + + inline Uuid Convert() const { + /* Convert the fields from native endian to big endian. */ + util::BitPack32 converted[4] = {util::BitPack32(0), util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}; + + converted[0].Set(util::ConvertToBigEndian(this->data[0].Get())); + + converted[1].Set(util::ConvertToBigEndian(this->data[1].Get())); + converted[1].Set(util::ConvertToBigEndian(this->data[1].Get())); + + + converted[2].Set(util::ConvertToBigEndian(this->data[2].Get())); + converted[2].Set(util::ConvertToBigEndian(this->data[2].Get())); + + u64 node_lo = static_cast(this->data[2].Get()); + u64 node_hi = static_cast(this->data[3].Get()); + u64 node = util::ConvertToBigEndian48(static_cast((node_hi << BITSIZEOF(u16)) | (node_lo))); + + constexpr u64 NodeLoMask = (UINT64_C(1) << BITSIZEOF(u16)) - 1u; + constexpr u64 NodeHiMask = (UINT64_C(1) << BITSIZEOF(u32)) - 1u; + + converted[2].Set(static_cast(node & NodeLoMask)); + converted[3].Set(static_cast((node >> BITSIZEOF(u16)) & NodeHiMask)); + + Uuid uuid; + std::memcpy(uuid.data, converted, sizeof(uuid.data)); + return uuid; + } + }; + static_assert(sizeof(UuidImpl) == sizeof(Uuid)); + + ALWAYS_INLINE Uuid GenerateUuidVersion4() { + constexpr u16 Version = 0x4; + constexpr u8 Reserved = 0x1; + + /* Generate a random uuid. */ + UuidImpl uuid = {util::BitPack32(0), util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}; + os::GenerateRandomBytes(uuid.data, sizeof(uuid.data)); + + /* Set version and reserved. */ + uuid.data[1].Set(Version); + uuid.data[2].Set(Reserved); + + /* Return the uuid. */ + return uuid.Convert(); + } + + } + + Uuid GenerateUuid() { + return GenerateUuidVersion4(); + } + + Uuid GenerateUuidVersion5(const void *sha1_hash) { + constexpr u16 Version = 0x5; + constexpr u8 Reserved = 0x1; + + /* Generate a uuid from a SHA1 hash. */ + UuidImpl uuid = {util::BitPack32(0), util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}; + std::memcpy(uuid.data, sha1_hash, sizeof(uuid.data)); + + /* Set version and reserved. */ + uuid.data[1].Set(Version); + uuid.data[2].Set(Reserved); + + /* Return the uuid. */ + return uuid.Convert(); + } + +} diff --git a/libraries/libvapours/include/vapours/util.hpp b/libraries/libvapours/include/vapours/util.hpp index e3018fa6e..b1d000fea 100644 --- a/libraries/libvapours/include/vapours/util.hpp +++ b/libraries/libvapours/include/vapours/util.hpp @@ -21,13 +21,14 @@ #include #include #include -#include -#include -#include #include #include +#include +#include +#include #include +#include #include #include #include -#include +#include diff --git a/libraries/libvapours/include/vapours/util/util_endian.hpp b/libraries/libvapours/include/vapours/util/util_endian.hpp index 7f7e11bee..fcf294baf 100644 --- a/libraries/libvapours/include/vapours/util/util_endian.hpp +++ b/libraries/libvapours/include/vapours/util/util_endian.hpp @@ -65,6 +65,7 @@ namespace ams::util { ((u & (ByteMask << 0)) << 8); } else if constexpr (std::is_same::value) { + AMS_UNUSED(ByteMask); return u; } else { static_assert(!std::is_same::value); diff --git a/libraries/libvapours/include/vapours/util/util_uuid.hpp b/libraries/libvapours/include/vapours/util/util_uuid.hpp new file mode 100644 index 000000000..c7ce3ef74 --- /dev/null +++ b/libraries/libvapours/include/vapours/util/util_uuid.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#pragma once +#include +#include + +namespace ams::util { + + struct Uuid { + static constexpr size_t Size = 0x10; + + u8 data[Size]; + + bool operator==(const Uuid &rhs) const { + return std::memcmp(this->data, rhs.data, Size) == 0; + } + + bool operator!=(const Uuid &rhs) const { + return !(*this == rhs); + } + + u8 operator[](size_t i) const { + return this->data[i]; + } + }; + +}