diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp index 158eebd7f0..e68d28109f 100644 --- a/Source/Core/Core/IOS/ES/Formats.cpp +++ b/Source/Core/Core/IOS/ES/Formats.cpp @@ -59,6 +59,106 @@ bool Content::IsShared() const return (type & 0x8000) != 0; } +SignedBlobReader::SignedBlobReader(const std::vector& bytes) : m_bytes(bytes) +{ +} + +SignedBlobReader::SignedBlobReader(std::vector&& bytes) : m_bytes(std::move(bytes)) +{ +} + +const std::vector& SignedBlobReader::GetBytes() const +{ + return m_bytes; +} + +void SignedBlobReader::SetBytes(const std::vector& bytes) +{ + m_bytes = bytes; +} + +void SignedBlobReader::SetBytes(std::vector&& bytes) +{ + m_bytes = std::move(bytes); +} + +bool SignedBlobReader::IsSignatureValid() const +{ + // Too small for the certificate type. + if (m_bytes.size() < sizeof(Cert::type)) + return false; + + // Too small to contain the whole signature data. + const size_t signature_size = GetSignatureSize(); + if (signature_size == 0 || m_bytes.size() < signature_size) + return false; + + return true; +} + +SignatureType SignedBlobReader::GetSignatureType() const +{ + return static_cast(Common::swap32(m_bytes.data())); +} + +std::vector SignedBlobReader::GetSignatureData() const +{ + switch (GetSignatureType()) + { + case SignatureType::RSA4096: + { + const auto signature_begin = m_bytes.begin() + offsetof(SignatureRSA4096, sig); + return std::vector(signature_begin, signature_begin + sizeof(SignatureRSA4096::sig)); + } + case SignatureType::RSA2048: + { + const auto signature_begin = m_bytes.begin() + offsetof(SignatureRSA2048, sig); + return std::vector(signature_begin, signature_begin + sizeof(SignatureRSA2048::sig)); + } + default: + return {}; + } +} + +size_t SignedBlobReader::GetSignatureSize() const +{ + switch (GetSignatureType()) + { + case SignatureType::RSA4096: + return sizeof(SignatureRSA4096); + case SignatureType::RSA2048: + return sizeof(SignatureRSA2048); + default: + return 0; + } +} + +std::string SignedBlobReader::GetIssuer() const +{ + switch (GetSignatureType()) + { + case SignatureType::RSA4096: + { + const char* issuer = + reinterpret_cast(m_bytes.data() + offsetof(SignatureRSA4096, issuer)); + return std::string(issuer, strnlen(issuer, sizeof(SignatureRSA4096::issuer))); + } + case SignatureType::RSA2048: + { + const char* issuer = + reinterpret_cast(m_bytes.data() + offsetof(SignatureRSA2048, issuer)); + return std::string(issuer, strnlen(issuer, sizeof(SignatureRSA2048::issuer))); + } + default: + return ""; + } +} + +void SignedBlobReader::DoState(PointerWrap& p) +{ + p.Do(m_bytes); +} + bool IsValidTMDSize(size_t size) { return size <= 0x49e4; diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h index 178fc643fa..83666f726c 100644 --- a/Source/Core/Core/IOS/ES/Formats.h +++ b/Source/Core/Core/IOS/ES/Formats.h @@ -140,6 +140,33 @@ struct Ticket static_assert(sizeof(Ticket) == 0x2A4, "Ticket has the wrong size"); #pragma pack(pop) +class SignedBlobReader +{ +public: + SignedBlobReader() = default; + explicit SignedBlobReader(const std::vector& bytes); + explicit SignedBlobReader(std::vector&& bytes); + + const std::vector& GetBytes() const; + void SetBytes(const std::vector& bytes); + void SetBytes(std::vector&& bytes); + + // Only checks whether the signature data could be parsed. The signature is not verified. + bool IsSignatureValid() const; + + SignatureType GetSignatureType() const; + std::vector GetSignatureData() const; + size_t GetSignatureSize() const; + // Returns the whole issuer chain. + // Example: Root-CA00000001 if the blob was signed by CA00000001, which is signed by the Root. + std::string GetIssuer() const; + + void DoState(PointerWrap& p); + +protected: + std::vector m_bytes; +}; + bool IsValidTMDSize(size_t size); class TMDReader final