From e29f6e383fb95d32710ef22d99e771428c8994a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 10 Jun 2017 19:10:55 +0200 Subject: [PATCH] IOS/ESFormats: Add CertReader --- Source/Core/Core/IOS/ES/Formats.cpp | 67 +++++++++++++++++++++++++++++ Source/Core/Core/IOS/ES/Formats.h | 20 +++++++++ 2 files changed, 87 insertions(+) diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp index e33b339089..377d36eb28 100644 --- a/Source/Core/Core/IOS/ES/Formats.cpp +++ b/Source/Core/Core/IOS/ES/Formats.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -614,5 +615,71 @@ u32 UIDSys::GetOrInsertUIDForTitle(const u64 title_id) return uid; } + +CertReader::CertReader(std::vector&& bytes) : SignedBlobReader(std::move(bytes)) +{ + if (!IsSignatureValid()) + return; + + switch (GetSignatureType()) + { + case SignatureType::RSA4096: + if (m_bytes.size() < sizeof(CertRSA4096)) + return; + m_bytes.resize(sizeof(CertRSA4096)); + break; + + case SignatureType::RSA2048: + if (m_bytes.size() < sizeof(CertRSA2048)) + return; + m_bytes.resize(sizeof(CertRSA2048)); + break; + + default: + return; + } + + m_is_valid = true; +} + +bool CertReader::IsValid() const +{ + return m_is_valid; +} + +u32 CertReader::GetId() const +{ + const size_t offset = GetSignatureSize() + offsetof(CertHeader, id); + return Common::swap32(m_bytes.data() + offset); +} + +std::string CertReader::GetName() const +{ + const char* name = reinterpret_cast(m_bytes.data() + GetSignatureSize() + + offsetof(CertHeader, name)); + return std::string(name, strnlen(name, sizeof(CertHeader::name))); +} + +PublicKeyType CertReader::GetPublicKeyType() const +{ + const size_t offset = GetSignatureSize() + offsetof(CertHeader, public_key_type); + return static_cast(Common::swap32(m_bytes.data() + offset)); +} + +std::vector CertReader::GetPublicKey() const +{ + static const std::map> type_to_key_info = {{ + {SignatureType::RSA4096, + {offsetof(CertRSA4096, public_key), + sizeof(CertRSA4096::public_key) + sizeof(CertRSA4096::exponent)}}, + {SignatureType::RSA2048, + {offsetof(CertRSA2048, public_key), + sizeof(CertRSA2048::public_key) + sizeof(CertRSA2048::exponent)}}, + }}; + + const auto info = type_to_key_info.at(GetSignatureType()); + const auto key_begin = m_bytes.begin() + info.first; + return std::vector(key_begin, key_begin + info.second); +} } // namespace ES } // namespace IOS diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h index a3adbf7493..3606b12f49 100644 --- a/Source/Core/Core/IOS/ES/Formats.h +++ b/Source/Core/Core/IOS/ES/Formats.h @@ -16,6 +16,7 @@ #include "Common/CommonTypes.h" #include "Common/NandPaths.h" +#include "Core/IOS/Device.h" #include "Core/IOS/IOSC.h" #include "DiscIO/Enums.h" @@ -264,5 +265,24 @@ private: std::string m_file_path; std::map m_entries; }; + +class CertReader final : public SignedBlobReader +{ +public: + explicit CertReader(std::vector&& bytes); + + bool IsValid() const; + + u32 GetId() const; + // Returns the certificate name. Examples: XS00000003, CA00000001 + std::string GetName() const; + PublicKeyType GetPublicKeyType() const; + // Returns the public key bytes + any other data associated with it. + // For RSA public keys, this includes 4 bytes for the exponent at the end. + std::vector GetPublicKey() const; + +private: + bool m_is_valid = false; +}; } // namespace ES } // namespace IOS