diff --git a/lib/libes/include/es/CertificateBody.h b/lib/libes/include/es/CertificateBody.h index 37c3e48..20cbbe9 100644 --- a/lib/libes/include/es/CertificateBody.h +++ b/lib/libes/include/es/CertificateBody.h @@ -1,13 +1,12 @@ #pragma once #include -#include -#include +#include #include namespace es { class CertificateBody - : public fnd::ISerialiseableBinary + : public fnd::ISerialisable { public: CertificateBody(); @@ -17,12 +16,12 @@ namespace es bool operator==(const CertificateBody& other) const; bool operator!=(const CertificateBody& other) const; - void importBinary(const byte_t* src, size_t size); - void exportBinary(); - - const byte_t* getBytes() const; - size_t getSize() const; + // export/import binary + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; + // variables void clear(); const std::string& getIssuer() const; @@ -50,7 +49,7 @@ namespace es const std::string kModuleName = "CERTIFICATE_BODY"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables std::string mIssuer; @@ -61,9 +60,5 @@ namespace es crypto::rsa::sRsa4096Key mRsa4096PublicKey; crypto::rsa::sRsa2048Key mRsa2048PublicKey; crypto::ecdsa::sEcdsa240Point mEcdsa240PublicKey; - - // helpers - bool isEqual(const CertificateBody& other) const; - void copyFrom(const CertificateBody& other); }; } \ No newline at end of file diff --git a/lib/libes/include/es/SectionHeader_V2.h b/lib/libes/include/es/SectionHeader_V2.h index a69c7e1..35b1083 100644 --- a/lib/libes/include/es/SectionHeader_V2.h +++ b/lib/libes/include/es/SectionHeader_V2.h @@ -1,30 +1,25 @@ #pragma once #include -#include -#include +#include #include namespace es { class SectionHeader_V2 : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: SectionHeader_V2(); SectionHeader_V2(const SectionHeader_V2& other); - SectionHeader_V2(const byte_t* bytes, size_t len); + void operator=(const SectionHeader_V2& other); bool operator==(const SectionHeader_V2& other) const; bool operator!=(const SectionHeader_V2& other) const; - void operator=(const SectionHeader_V2& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - virtual void exportBinary(); - virtual void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; // variables virtual void clear(); @@ -48,7 +43,7 @@ namespace es const std::string kModuleName = "SECTION_HEADER_V2"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables uint32_t mSectionOffset; @@ -56,11 +51,6 @@ namespace es uint32_t mSectionSize; uint16_t mRecordNum; ticket::SectionType mSectionType; - - // helpers - bool isEqual(const SectionHeader_V2& other) const; - void copyFrom(const SectionHeader_V2& other); - }; } diff --git a/lib/libes/include/es/SignatureBlock.h b/lib/libes/include/es/SignatureBlock.h index dcd5acb..46d5c98 100644 --- a/lib/libes/include/es/SignatureBlock.h +++ b/lib/libes/include/es/SignatureBlock.h @@ -1,13 +1,12 @@ #pragma once #include -#include -#include +#include #include namespace es { class SignatureBlock - : public fnd::ISerialiseableBinary + : public fnd::ISerialisable { public: SignatureBlock(); @@ -17,12 +16,12 @@ namespace es bool operator==(const SignatureBlock& other) const; bool operator!=(const SignatureBlock& other) const; - void importBinary(const byte_t* src, size_t size); - void exportBinary(); - - const byte_t* getBytes() const; - size_t getSize() const; + // export/import binary + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; + // variables void clear(); es::sign::SignType getSignType() const; @@ -31,23 +30,19 @@ namespace es bool isLittleEndian() const; void setLittleEndian(bool isLE); - const fnd::MemoryBlob& getSignature() const; - void setSignature(const fnd::MemoryBlob& signature); + const fnd::Vec& getSignature() const; + void setSignature(const fnd::Vec& signature); private: const std::string kModuleName = "SIGNATURE_BLOCK"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables es::sign::SignType mSignType; bool mIsLittleEndian; - fnd::MemoryBlob mSignature; - - // helpers - bool isEqual(const SignatureBlock& other) const; - void copyFrom(const SignatureBlock& other); + fnd::Vec mSignature; }; } \ No newline at end of file diff --git a/lib/libes/include/es/SignedData.h b/lib/libes/include/es/SignedData.h index 6f4a7e1..366b350 100644 --- a/lib/libes/include/es/SignedData.h +++ b/lib/libes/include/es/SignedData.h @@ -1,113 +1,137 @@ #pragma once #include -#include -#include +#include #include namespace es { template class SignedData - : public fnd::ISerialiseableBinary + : public fnd::ISerialisable { public: - SignedData() - { - clear(); - } - SignedData(const SignedData& other) - { - copyFrom(other); - } + SignedData(); + SignedData(const SignedData& other); - void operator=(const SignedData& other) - { - copyFrom(other); - } - bool operator==(const SignedData& other) const - { - return isEqual(other); - } - bool operator!=(const SignedData& other) const - { - return !(*this == other); - } + void operator=(const SignedData& other); + bool operator==(const SignedData& other) const; + bool operator!=(const SignedData& other) const; - void importBinary(const byte_t* src, size_t size) - { - mSignature.importBinary(src, size); - mBody.importBinary(src + mSignature.getSize(), size - mSignature.getSize()); + // export/import + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; - mBinaryBlob.alloc(mSignature.getSize() + mBody.getSize()); - memcpy(mBinaryBlob.getBytes(), src, mBinaryBlob.getSize()); - } + // variables + void clear(); - void exportBinary() - { - mSignature.exportBinary(); - mBody.exportBinary(); + const es::SignatureBlock& getSignature() const; + void setSignature(const SignatureBlock& signature); - mBinaryBlob.alloc(mSignature.getSize() + mBody.getSize()); - - memcpy(mBinaryBlob.getBytes(), mSignature.getBytes(), mSignature.getSize()); - memcpy(mBinaryBlob.getBytes() + mSignature.getSize(), mBody.getBytes(), mBody.getSize()); - } - - const byte_t* getBytes() const - { - return mBinaryBlob.getBytes(); - } - size_t getSize() const - { - return mBinaryBlob.getSize(); - } - - void clear() - { - mBinaryBlob.clear(); - mSignature.clear(); - mBody.clear(); - } - - const es::SignatureBlock& getSignature() const - { - return mSignature; - } - void setSignature(const SignatureBlock& signature) - { - mSignature = signature; - } - - const T& getBody() const - { - return mBody; - } - void setBody(const T& body) - { - mBody = body; - } + const T& getBody() const; + void setBody(const T& body); private: const std::string kModuleName = "SIGNED_DATA"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables SignatureBlock mSignature; T mBody; - - // helpers - bool isEqual(const SignedData& other) const - { - return (mSignature == other.mSignature) \ - && (mBody == other.mBody); - } - void copyFrom(const SignedData& other) - { - mBinaryBlob = other.mBinaryBlob; - mSignature = other.mSignature; - mBody = other.mBody; - } }; + + template + inline SignedData::SignedData() + { + clear(); + } + + template + inline SignedData::SignedData(const SignedData& other) + { + *this = other; + } + + template + inline void SignedData::operator=(const SignedData& other) + { + mRawBinary = other.mRawBinary; + mSignature = other.mSignature; + mBody = other.mBody; + } + + template + inline bool SignedData::operator==(const SignedData& other) const + { + return (mSignature == other.mSignature) \ + && (mBody == other.mBody); + } + + template + inline bool SignedData::operator!=(const SignedData& other) const + { + return !(*this == other); + } + + template + inline void SignedData::toBytes() + { + mSignature.toBytes(); + mBody.toBytes(); + + mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); + + memcpy(mRawBinary.data(), mSignature.getBytes().data(), mSignature.getBytes().size()); + memcpy(mRawBinary.data() + mSignature.getBytes().size(), mBody.getBytes().data(), mBody.getBytes().size()); + } + + template + inline void SignedData::fromBytes(const byte_t* src, size_t size) + { + mSignature.fromBytes(src, size); + mBody.fromBytes(src + mSignature.getBytes().size(), size - mSignature.getBytes().size()); + + mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); + memcpy(mRawBinary.data(), src, mRawBinary.size()); + } + + template + inline const fnd::Vec& SignedData::getBytes() const + { + return mRawBinary; + } + + template + inline void SignedData::clear() + { + mRawBinary.clear(); + mSignature.clear(); + mBody.clear(); + } + + template + inline const es::SignatureBlock& SignedData::getSignature() const + { + return mSignature; + } + + template + inline void SignedData::setSignature(const SignatureBlock& signature) + { + mSignature = signature; + } + + template + inline const T& SignedData::getBody() const + { + return mBody; + } + + template + inline void SignedData::setBody(const T& body) + { + mBody = body; + } } diff --git a/lib/libes/include/es/TicketBody_V2.h b/lib/libes/include/es/TicketBody_V2.h index 8a93dc8..6b0be01 100644 --- a/lib/libes/include/es/TicketBody_V2.h +++ b/lib/libes/include/es/TicketBody_V2.h @@ -1,33 +1,28 @@ #pragma once #include -#include -#include +#include #include namespace es { class TicketBody_V2 : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: TicketBody_V2(); TicketBody_V2(const TicketBody_V2& other); - TicketBody_V2(const byte_t* bytes, size_t len); + void operator=(const TicketBody_V2& other); bool operator==(const TicketBody_V2& other) const; bool operator!=(const TicketBody_V2& other) const; - void operator=(const TicketBody_V2& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - virtual void exportBinary(); - virtual void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables - virtual void clear(); + void clear(); const std::string& getIssuer() const; void setIssuer(const std::string& issuer); @@ -87,7 +82,7 @@ namespace es const std::string kModuleName = "TICKET_BODY_V2"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables std::string mIssuer; @@ -108,10 +103,6 @@ namespace es uint32_t mSectHeaderOffset; uint16_t mSectNum; uint16_t mSectEntrySize; - - // helpers - bool isEqual(const TicketBody_V2& other) const; - void copyFrom(const TicketBody_V2& other); }; } diff --git a/lib/libes/source/CertificateBody.cpp b/lib/libes/source/CertificateBody.cpp index 6dca809..11bec02 100644 --- a/lib/libes/source/CertificateBody.cpp +++ b/lib/libes/source/CertificateBody.cpp @@ -7,17 +7,30 @@ es::CertificateBody::CertificateBody() es::CertificateBody::CertificateBody(const CertificateBody& other) { - copyFrom(other); + *this = other; } void es::CertificateBody::operator=(const CertificateBody& other) { - copyFrom(other); + mRawBinary = other.mRawBinary; + mIssuer = other.mIssuer; + mSubject = other.mSubject; + mCertId = other.mCertId; + mPublicKeyType = other.mPublicKeyType; + mRsa4096PublicKey = other.mRsa4096PublicKey; + mRsa2048PublicKey = other.mRsa2048PublicKey; + mEcdsa240PublicKey = other.mEcdsa240PublicKey; } bool es::CertificateBody::operator==(const CertificateBody& other) const { - return isEqual(other); + return (mIssuer == other.mIssuer) \ + && (mSubject == other.mSubject) \ + && (mCertId == other.mCertId) \ + && (mPublicKeyType == other.mPublicKeyType) \ + && (mRsa4096PublicKey == other.mRsa4096PublicKey) \ + && (mRsa2048PublicKey == other.mRsa2048PublicKey) \ + && (mEcdsa240PublicKey == other.mEcdsa240PublicKey); } bool es::CertificateBody::operator!=(const CertificateBody& other) const @@ -25,7 +38,55 @@ bool es::CertificateBody::operator!=(const CertificateBody& other) const return !(*this == other); } -void es::CertificateBody::importBinary(const byte_t* src, size_t size) +void es::CertificateBody::toBytes() +{ + // get public key size + size_t pubkeySize = 0; + switch (mPublicKeyType) + { + case (cert::RSA4096): + pubkeySize = sizeof(sRsa4096PublicKeyBlock); + break; + case (cert::RSA2048): + pubkeySize = sizeof(sRsa2048PublicKeyBlock); + break; + case (cert::ECDSA240): + pubkeySize = sizeof(sEcdsa240PublicKeyBlock); + break; + default: + throw fnd::Exception(kModuleName, "Unknown public key type"); + } + + mRawBinary.alloc(sizeof(sCertificateHeader) + pubkeySize); + sCertificateHeader* hdr = (sCertificateHeader*)mRawBinary.data(); + + // copy header vars + strncpy(hdr->issuer, mIssuer.c_str(), cert::kIssuerSize); + hdr->key_type = mPublicKeyType; + strncpy(hdr->subject, mSubject.c_str(), cert::kSubjectSize); + hdr->cert_id = mCertId; + + // copy public key + if (mPublicKeyType == cert::RSA4096) + { + sRsa4096PublicKeyBlock* pubkey = (sRsa4096PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); + memcpy(pubkey->modulus, mRsa4096PublicKey.modulus, sizeof(mRsa4096PublicKey.modulus)); + memcpy(pubkey->public_exponent, mRsa4096PublicKey.public_exponent, sizeof(mRsa4096PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::RSA2048) + { + sRsa2048PublicKeyBlock* pubkey = (sRsa2048PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); + memcpy(pubkey->modulus, mRsa2048PublicKey.modulus, sizeof(mRsa2048PublicKey.modulus)); + memcpy(pubkey->public_exponent, mRsa2048PublicKey.public_exponent, sizeof(mRsa2048PublicKey.public_exponent)); + } + else if (mPublicKeyType == cert::ECDSA240) + { + sEcdsa240PublicKeyBlock* pubkey = (sEcdsa240PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); + pubkey->public_key = mEcdsa240PublicKey; + } +} + +void es::CertificateBody::fromBytes(const byte_t* src, size_t size) { clear(); @@ -61,11 +122,11 @@ void es::CertificateBody::importBinary(const byte_t* src, size_t size) } // save raw binary - mBinaryBlob.alloc((sizeof(sCertificateHeader) + pubkeySize)); - memcpy(mBinaryBlob.getBytes(), src, mBinaryBlob.getSize()); + mRawBinary.alloc((sizeof(sCertificateHeader) + pubkeySize)); + memcpy(mRawBinary.data(), src, mRawBinary.size()); // save hdr variables - hdr = (const sCertificateHeader*)mBinaryBlob.getBytes(); + hdr = (const sCertificateHeader*)mRawBinary.data(); if (hdr->issuer[0] != 0) mIssuer = std::string(hdr->issuer, cert::kIssuerSize); @@ -77,80 +138,28 @@ void es::CertificateBody::importBinary(const byte_t* src, size_t size) // save public key if (mPublicKeyType == cert::RSA4096) { - const sRsa4096PublicKeyBlock* pubkey = (const sRsa4096PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + const sRsa4096PublicKeyBlock* pubkey = (const sRsa4096PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); memcpy(mRsa4096PublicKey.modulus, pubkey->modulus, sizeof(mRsa4096PublicKey.modulus)); memcpy(mRsa4096PublicKey.public_exponent, pubkey->public_exponent, sizeof(mRsa4096PublicKey.public_exponent)); } else if (mPublicKeyType == cert::RSA2048) { - const sRsa2048PublicKeyBlock* pubkey = (const sRsa2048PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + const sRsa2048PublicKeyBlock* pubkey = (const sRsa2048PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); memcpy(mRsa2048PublicKey.modulus, pubkey->modulus, sizeof(mRsa2048PublicKey.modulus)); memcpy(mRsa2048PublicKey.public_exponent, pubkey->public_exponent, sizeof(mRsa2048PublicKey.public_exponent)); } else if (mPublicKeyType == cert::ECDSA240) { - const sEcdsa240PublicKeyBlock* pubkey = (const sEcdsa240PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); + const sEcdsa240PublicKeyBlock* pubkey = (const sEcdsa240PublicKeyBlock*)(mRawBinary.data() + sizeof(sCertificateHeader)); mEcdsa240PublicKey = pubkey->public_key; } } -void es::CertificateBody::exportBinary() +const fnd::Vec& es::CertificateBody::getBytes() const { - // get public key size - size_t pubkeySize = 0; - switch (mPublicKeyType) - { - case (cert::RSA4096): - pubkeySize = sizeof(sRsa4096PublicKeyBlock); - break; - case (cert::RSA2048): - pubkeySize = sizeof(sRsa2048PublicKeyBlock); - break; - case (cert::ECDSA240): - pubkeySize = sizeof(sEcdsa240PublicKeyBlock); - break; - default: - throw fnd::Exception(kModuleName, "Unknown public key type"); - } - - mBinaryBlob.alloc(sizeof(sCertificateHeader) + pubkeySize); - sCertificateHeader* hdr = (sCertificateHeader*)mBinaryBlob.getBytes(); - - // copy header vars - strncpy(hdr->issuer, mIssuer.c_str(), cert::kIssuerSize); - hdr->key_type = mPublicKeyType; - strncpy(hdr->subject, mSubject.c_str(), cert::kSubjectSize); - hdr->cert_id = mCertId; - - // copy public key - if (mPublicKeyType == cert::RSA4096) - { - sRsa4096PublicKeyBlock* pubkey = (sRsa4096PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); - memcpy(pubkey->modulus, mRsa4096PublicKey.modulus, sizeof(mRsa4096PublicKey.modulus)); - memcpy(pubkey->public_exponent, mRsa4096PublicKey.public_exponent, sizeof(mRsa4096PublicKey.public_exponent)); - } - else if (mPublicKeyType == cert::RSA2048) - { - sRsa2048PublicKeyBlock* pubkey = (sRsa2048PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); - memcpy(pubkey->modulus, mRsa2048PublicKey.modulus, sizeof(mRsa2048PublicKey.modulus)); - memcpy(pubkey->public_exponent, mRsa2048PublicKey.public_exponent, sizeof(mRsa2048PublicKey.public_exponent)); - } - else if (mPublicKeyType == cert::ECDSA240) - { - sEcdsa240PublicKeyBlock* pubkey = (sEcdsa240PublicKeyBlock*)(mBinaryBlob.getBytes() + sizeof(sCertificateHeader)); - pubkey->public_key = mEcdsa240PublicKey; - } + return mRawBinary; } -const byte_t* es::CertificateBody::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t es::CertificateBody::getSize() const -{ - return mBinaryBlob.getSize(); -} void es::CertificateBody::clear() { @@ -242,28 +251,4 @@ const crypto::ecdsa::sEcdsa240Point& es::CertificateBody::getEcdsa240PublicKey() void es::CertificateBody::setEcdsa240PublicKey(const crypto::ecdsa::sEcdsa240Point& key) { mEcdsa240PublicKey = key; -} - -bool es::CertificateBody::isEqual(const CertificateBody& other) const -{ - return (mIssuer == other.mIssuer) \ - && (mSubject == other.mSubject) \ - && (mCertId == other.mCertId) \ - && (mPublicKeyType == other.mPublicKeyType) \ - && (mRsa4096PublicKey == other.mRsa4096PublicKey) \ - && (mRsa2048PublicKey == other.mRsa2048PublicKey) \ - && (mEcdsa240PublicKey == other.mEcdsa240PublicKey); - -} - -void es::CertificateBody::copyFrom(const CertificateBody& other) -{ - mBinaryBlob = other.mBinaryBlob; - mIssuer = other.mIssuer; - mSubject = other.mSubject; - mCertId = other.mCertId; - mPublicKeyType = other.mPublicKeyType; - mRsa4096PublicKey = other.mRsa4096PublicKey; - mRsa2048PublicKey = other.mRsa2048PublicKey; - mEcdsa240PublicKey = other.mEcdsa240PublicKey; -} +} \ No newline at end of file diff --git a/lib/libes/source/SectionHeader_V2.cpp b/lib/libes/source/SectionHeader_V2.cpp index 4470e3f..2fd18ac 100644 --- a/lib/libes/source/SectionHeader_V2.cpp +++ b/lib/libes/source/SectionHeader_V2.cpp @@ -7,89 +7,18 @@ es::SectionHeader_V2::SectionHeader_V2() es::SectionHeader_V2::SectionHeader_V2(const SectionHeader_V2 & other) { - copyFrom(other); -} - -es::SectionHeader_V2::SectionHeader_V2(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool es::SectionHeader_V2::operator==(const SectionHeader_V2 & other) const -{ - return isEqual(other); -} - -bool es::SectionHeader_V2::operator!=(const SectionHeader_V2 & other) const -{ - return !isEqual(other); + *this = other; } void es::SectionHeader_V2::operator=(const SectionHeader_V2 & other) { - copyFrom(other); -} - -const byte_t * es::SectionHeader_V2::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t es::SectionHeader_V2::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void es::SectionHeader_V2::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sSectionHeader_v2)); - sSectionHeader_v2* hdr = (sSectionHeader_v2*)mBinaryBlob.getBytes(); - - hdr->section_offset = (mSectionOffset); - hdr->record_size = (mRecordSize); - hdr->section_size = (mSectionSize); - hdr->record_num = (mRecordNum); - hdr->section_type = (mSectionType); -} - -void es::SectionHeader_V2::importBinary(const byte_t * bytes, size_t len) -{ - if (len < sizeof(sSectionHeader_v2)) + if (other.getBytes().size()) { - throw fnd::Exception(kModuleName, "Binary too small"); - } - - clear(); - - mBinaryBlob.alloc(sizeof(sSectionHeader_v2)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - sSectionHeader_v2* hdr = (sSectionHeader_v2*)mBinaryBlob.getBytes(); - - mSectionOffset = hdr->section_offset.get(); - mRecordSize = hdr->record_size.get(); - mSectionSize = hdr->section_size.get(); - mRecordNum = hdr->record_num.get(); - mSectionType = (ticket::SectionType)hdr->section_type.get(); -} - -bool es::SectionHeader_V2::isEqual(const SectionHeader_V2 & other) const -{ - return (mSectionOffset == other.mSectionOffset) \ - && (mRecordSize == other.mRecordSize) \ - && (mSectionSize == other.mSectionSize) \ - && (mRecordNum == other.mRecordNum) \ - && (mSectionType == other.mSectionType); -} - -void es::SectionHeader_V2::copyFrom(const SectionHeader_V2 & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); + fromBytes(other.getBytes().data(), other.getBytes().size()); } else { - mBinaryBlob.clear(); + mRawBinary.clear(); mSectionOffset = other.mSectionOffset; mRecordSize = other.mRecordSize; mSectionSize = other.mSectionSize; @@ -98,9 +27,60 @@ void es::SectionHeader_V2::copyFrom(const SectionHeader_V2 & other) } } +bool es::SectionHeader_V2::operator==(const SectionHeader_V2 & other) const +{ + return (mSectionOffset == other.mSectionOffset) \ + && (mRecordSize == other.mRecordSize) \ + && (mSectionSize == other.mSectionSize) \ + && (mRecordNum == other.mRecordNum) \ + && (mSectionType == other.mSectionType); +} + +bool es::SectionHeader_V2::operator!=(const SectionHeader_V2 & other) const +{ + return !(*this ==other); +} + +void es::SectionHeader_V2::toBytes() +{ + mRawBinary.alloc(sizeof(sSectionHeader_v2)); + sSectionHeader_v2* hdr = (sSectionHeader_v2*)mRawBinary.data(); + + hdr->section_offset = (mSectionOffset); + hdr->record_size = (mRecordSize); + hdr->section_size = (mSectionSize); + hdr->record_num = (mRecordNum); + hdr->section_type = (mSectionType); +} + +void es::SectionHeader_V2::fromBytes(const byte_t * bytes, size_t len) +{ + if (len < sizeof(sSectionHeader_v2)) + { + throw fnd::Exception(kModuleName, "Binary too small"); + } + + clear(); + + mRawBinary.alloc(sizeof(sSectionHeader_v2)); + memcpy(mRawBinary.data(), bytes, mRawBinary.size()); + sSectionHeader_v2* hdr = (sSectionHeader_v2*)mRawBinary.data(); + + mSectionOffset = hdr->section_offset.get(); + mRecordSize = hdr->record_size.get(); + mSectionSize = hdr->section_size.get(); + mRecordNum = hdr->record_num.get(); + mSectionType = (ticket::SectionType)hdr->section_type.get(); +} + +const fnd::Vec& es::SectionHeader_V2::getBytes() const +{ + return mRawBinary; +} + void es::SectionHeader_V2::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mSectionOffset = 0; mRecordSize = 0; mSectionSize = 0; diff --git a/lib/libes/source/SignatureBlock.cpp b/lib/libes/source/SignatureBlock.cpp index d79ba96..4aa591d 100644 --- a/lib/libes/source/SignatureBlock.cpp +++ b/lib/libes/source/SignatureBlock.cpp @@ -7,17 +7,22 @@ es::SignatureBlock::SignatureBlock() es::SignatureBlock::SignatureBlock(const SignatureBlock& other) { - copyFrom(other); + *this = other; } void es::SignatureBlock::operator=(const SignatureBlock& other) { - copyFrom(other); + mRawBinary = other.mRawBinary; + mSignType = other.mSignType; + mIsLittleEndian = other.mIsLittleEndian; + mSignature = other.mSignature; } bool es::SignatureBlock::operator==(const SignatureBlock& other) const { - return isEqual(other); + return (mSignType == other.mSignType) \ + && (mIsLittleEndian == other.mIsLittleEndian) \ + && (mSignature == other.mSignature); } bool es::SignatureBlock::operator!=(const SignatureBlock& other) const @@ -25,7 +30,45 @@ bool es::SignatureBlock::operator!=(const SignatureBlock& other) const return !(*this == other); } -void es::SignatureBlock::importBinary(const byte_t* src, size_t size) +void es::SignatureBlock::toBytes() +{ + size_t totalSize = 0; + size_t sigSize = 0; + + switch (mSignType) + { + case (sign::SIGN_RSA4096_SHA1): + case (sign::SIGN_RSA4096_SHA256): + totalSize = sizeof(sRsa4096SignBlock); + sigSize = crypto::rsa::kRsa4096Size; + break; + case (sign::SIGN_RSA2048_SHA1): + case (sign::SIGN_RSA2048_SHA256): + totalSize = sizeof(sRsa2048SignBlock); + sigSize = crypto::rsa::kRsa2048Size; + break; + case (sign::SIGN_ECDSA240_SHA1): + case (sign::SIGN_ECDSA240_SHA256): + totalSize = sizeof(sEcdsa240SignBlock); + sigSize = sign::kEcdsaSigSize; + break; + default: + throw fnd::Exception(kModuleName, "Unknown signature type"); + } + + if (mSignature.size() != sigSize) + throw fnd::Exception(kModuleName, "Signature size is incorrect"); + + // commit to binary + mRawBinary.alloc(totalSize); + if (mIsLittleEndian) + *(le_uint32_t*)(mRawBinary.data()) = mSignType; + else + *(be_uint32_t*)(mRawBinary.data()) = mSignType; + memcpy(mRawBinary.data() + 4, mSignature.data(), sigSize); +} + +void es::SignatureBlock::fromBytes(const byte_t* src, size_t size) { clear(); @@ -87,65 +130,22 @@ void es::SignatureBlock::importBinary(const byte_t* src, size_t size) throw fnd::Exception(kModuleName, "Certificate too small"); } - mBinaryBlob.alloc(totalSize); - memcpy(mBinaryBlob.getBytes(), src, totalSize); + mRawBinary.alloc(totalSize); + memcpy(mRawBinary.data(), src, totalSize); mSignType = (sign::SignType)signType; mSignature.alloc(sigSize); - memcpy(mSignature.getBytes(), mBinaryBlob.getBytes() + 4, sigSize); + memcpy(mSignature.data(), mRawBinary.data() + 4, sigSize); } -void es::SignatureBlock::exportBinary() +const fnd::Vec& es::SignatureBlock::getBytes() const { - size_t totalSize = 0; - size_t sigSize = 0; - - switch (mSignType) - { - case (sign::SIGN_RSA4096_SHA1): - case (sign::SIGN_RSA4096_SHA256): - totalSize = sizeof(sRsa4096SignBlock); - sigSize = crypto::rsa::kRsa4096Size; - break; - case (sign::SIGN_RSA2048_SHA1): - case (sign::SIGN_RSA2048_SHA256): - totalSize = sizeof(sRsa2048SignBlock); - sigSize = crypto::rsa::kRsa2048Size; - break; - case (sign::SIGN_ECDSA240_SHA1): - case (sign::SIGN_ECDSA240_SHA256): - totalSize = sizeof(sEcdsa240SignBlock); - sigSize = sign::kEcdsaSigSize; - break; - default: - throw fnd::Exception(kModuleName, "Unknown signature type"); - } - - if (mSignature.getSize() != sigSize) - throw fnd::Exception(kModuleName, "Signature size is incorrect"); - - // commit to binary - mBinaryBlob.alloc(totalSize); - if (mIsLittleEndian) - *(le_uint32_t*)(mBinaryBlob.getBytes()) = mSignType; - else - *(be_uint32_t*)(mBinaryBlob.getBytes()) = mSignType; - memcpy(mBinaryBlob.getBytes() + 4, mSignature.getBytes(), sigSize); -} - -const byte_t* es::SignatureBlock::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t es::SignatureBlock::getSize() const -{ - return mBinaryBlob.getSize(); + return mRawBinary; } void es::SignatureBlock::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mSignType = sign::SIGN_RSA4096_SHA1; mIsLittleEndian = false; mSignature.clear(); @@ -171,27 +171,12 @@ void es::SignatureBlock::setLittleEndian(bool isLE) mIsLittleEndian = isLE; } -const fnd::MemoryBlob& es::SignatureBlock::getSignature() const +const fnd::Vec& es::SignatureBlock::getSignature() const { return mSignature; } -void es::SignatureBlock::setSignature(const fnd::MemoryBlob& signature) +void es::SignatureBlock::setSignature(const fnd::Vec& signature) { mSignature = signature; } - -bool es::SignatureBlock::isEqual(const SignatureBlock& other) const -{ - return (mSignType == other.mSignType) \ - && (mIsLittleEndian == other.mIsLittleEndian) \ - && (mSignature == other.mSignature); -} - -void es::SignatureBlock::copyFrom(const SignatureBlock& other) -{ - mBinaryBlob = other.mBinaryBlob; - mSignType = other.mSignType; - mIsLittleEndian = other.mIsLittleEndian; - mSignature = other.mSignature; -} diff --git a/lib/libes/source/TicketBody_V2.cpp b/lib/libes/source/TicketBody_V2.cpp index a9da7f2..a9bd29c 100644 --- a/lib/libes/source/TicketBody_V2.cpp +++ b/lib/libes/source/TicketBody_V2.cpp @@ -9,43 +9,68 @@ es::TicketBody_V2::TicketBody_V2() es::TicketBody_V2::TicketBody_V2(const TicketBody_V2 & other) { - copyFrom(other); -} - -es::TicketBody_V2::TicketBody_V2(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool es::TicketBody_V2::operator==(const TicketBody_V2 & other) const -{ - return isEqual(other); -} - -bool es::TicketBody_V2::operator!=(const TicketBody_V2 & other) const -{ - return !isEqual(other); + *this = other; } void es::TicketBody_V2::operator=(const TicketBody_V2 & other) { - copyFrom(other); + if (other.getBytes().size()) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + mIssuer = other.mIssuer; + memcpy(mEncTitleKey, other.mEncTitleKey, ticket::kEncTitleKeySize); + mEncType = other.mEncType; + mTicketVersion = other.mTicketVersion; + mLicenseType = other.mLicenseType; + mPreInstall = other.mPreInstall; + mSharedTitle = other.mSharedTitle; + mAllowAllContent = other.mAllowAllContent; + memcpy(mReservedRegion, other.mReservedRegion, ticket::kReservedRegionSize); + mTicketId = other.mTicketId; + mDeviceId = other.mDeviceId; + memcpy(mRightsId, other.mRightsId, ticket::kRightsIdSize); + mAccountId = other.mAccountId; + mSectTotalSize = other.mSectTotalSize; + mSectHeaderOffset = other.mSectHeaderOffset; + mSectNum = other.mSectNum; + mSectEntrySize = other.mSectEntrySize; + } } -const byte_t * es::TicketBody_V2::getBytes() const +bool es::TicketBody_V2::operator==(const TicketBody_V2 & other) const { - return mBinaryBlob.getBytes(); + return (mIssuer == other.mIssuer) \ + && (memcmp(mEncTitleKey, other.mEncTitleKey, ticket::kEncTitleKeySize) == 0) \ + && (mEncType == other.mEncType) \ + && (mTicketVersion == other.mTicketVersion) \ + && (mLicenseType == other.mLicenseType) \ + && (mPreInstall == other.mPreInstall) \ + && (mSharedTitle == other.mSharedTitle) \ + && (mAllowAllContent == other.mAllowAllContent) \ + && (memcmp(mReservedRegion, other.mReservedRegion, ticket::kReservedRegionSize) == 0) \ + && (mTicketId == other.mTicketId) \ + && (mDeviceId == other.mDeviceId) \ + && (memcmp(mRightsId, other.mRightsId, ticket::kRightsIdSize) == 0) \ + && (mAccountId == other.mAccountId) \ + && (mSectTotalSize == other.mSectTotalSize) \ + && (mSectHeaderOffset == other.mSectHeaderOffset) \ + && (mSectNum == other.mSectNum) \ + && (mSectEntrySize == other.mSectEntrySize); } -size_t es::TicketBody_V2::getSize() const +bool es::TicketBody_V2::operator!=(const TicketBody_V2 & other) const { - return mBinaryBlob.getSize(); + return !(*this == other); } -void es::TicketBody_V2::exportBinary() +void es::TicketBody_V2::toBytes() { - mBinaryBlob.alloc(sizeof(sTicketBody_v2)); - sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sTicketBody_v2)); + sTicketBody_v2* body = (sTicketBody_v2*)mRawBinary.data(); body->format_version = (ticket::kFormatVersion); @@ -69,7 +94,7 @@ void es::TicketBody_V2::exportBinary() body->sect_entry_size = (mSectEntrySize); } -void es::TicketBody_V2::importBinary(const byte_t * bytes, size_t len) +void es::TicketBody_V2::fromBytes(const byte_t * bytes, size_t len) { if (len < sizeof(sTicketBody_v2)) { @@ -78,9 +103,9 @@ void es::TicketBody_V2::importBinary(const byte_t * bytes, size_t len) clear(); - mBinaryBlob.alloc(sizeof(sTicketBody_v2)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sTicketBody_v2)); + memcpy(mRawBinary.data(), bytes, mRawBinary.size()); + sTicketBody_v2* body = (sTicketBody_v2*)mRawBinary.data(); if (body->format_version != ticket::kFormatVersion) { @@ -106,9 +131,14 @@ void es::TicketBody_V2::importBinary(const byte_t * bytes, size_t len) mSectEntrySize = body->sect_entry_size.get(); } +const fnd::Vec& es::TicketBody_V2::getBytes() const +{ + return mRawBinary; +} + void es::TicketBody_V2::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mIssuer.clear(); memset(mEncTitleKey, 0, ticket::kEncTitleKeySize); mEncType = ticket::AES128_CBC; @@ -151,7 +181,7 @@ const byte_t * es::TicketBody_V2::getEncTitleKey() const void es::TicketBody_V2::setEncTitleKey(const byte_t * data, size_t len) { memset(mEncTitleKey, 0, ticket::kEncTitleKeySize); - memcpy(mEncTitleKey, data, MIN(len, ticket::kEncTitleKeySize)); + memcpy(mEncTitleKey, data, _MIN(len, ticket::kEncTitleKeySize)); } es::ticket::TitleKeyEncType es::TicketBody_V2::getTitleKeyEncType() const @@ -232,7 +262,7 @@ const byte_t * es::TicketBody_V2::getReservedRegion() const void es::TicketBody_V2::setReservedRegion(const byte_t * data, size_t len) { memset(mReservedRegion, 0, ticket::kReservedRegionSize); - memcpy(mReservedRegion, data, MIN(len, ticket::kReservedRegionSize)); + memcpy(mReservedRegion, data, _MIN(len, ticket::kReservedRegionSize)); } uint64_t es::TicketBody_V2::getTicketId() const @@ -313,54 +343,4 @@ uint16_t es::TicketBody_V2::getSectionEntrySize() const void es::TicketBody_V2::setSectionEntrySize(uint16_t size) { mSectEntrySize = size; -} - -bool es::TicketBody_V2::isEqual(const TicketBody_V2 & other) const -{ - return (mIssuer == other.mIssuer) \ - && (memcmp(mEncTitleKey, other.mEncTitleKey, ticket::kEncTitleKeySize) == 0) \ - && (mEncType == other.mEncType) \ - && (mTicketVersion == other.mTicketVersion) \ - && (mLicenseType == other.mLicenseType) \ - && (mPreInstall == other.mPreInstall) \ - && (mSharedTitle == other.mSharedTitle) \ - && (mAllowAllContent == other.mAllowAllContent) \ - && (memcmp(mReservedRegion, other.mReservedRegion, ticket::kReservedRegionSize) == 0) \ - && (mTicketId == other.mTicketId) \ - && (mDeviceId == other.mDeviceId) \ - && (memcmp(mRightsId, other.mRightsId, ticket::kRightsIdSize) == 0) \ - && (mAccountId == other.mAccountId) \ - && (mSectTotalSize == other.mSectTotalSize) \ - && (mSectHeaderOffset == other.mSectHeaderOffset) \ - && (mSectNum == other.mSectNum) \ - && (mSectEntrySize == other.mSectEntrySize); -} - -void es::TicketBody_V2::copyFrom(const TicketBody_V2 & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - clear(); - mIssuer = other.mIssuer; - memcpy(mEncTitleKey, other.mEncTitleKey, ticket::kEncTitleKeySize); - mEncType = other.mEncType; - mTicketVersion = other.mTicketVersion; - mLicenseType = other.mLicenseType; - mPreInstall = other.mPreInstall; - mSharedTitle = other.mSharedTitle; - mAllowAllContent = other.mAllowAllContent; - memcpy(mReservedRegion, other.mReservedRegion, ticket::kReservedRegionSize); - mTicketId = other.mTicketId; - mDeviceId = other.mDeviceId; - memcpy(mRightsId, other.mRightsId, ticket::kRightsIdSize); - mAccountId = other.mAccountId; - mSectTotalSize = other.mSectTotalSize; - mSectHeaderOffset = other.mSectHeaderOffset; - mSectNum = other.mSectNum; - mSectEntrySize = other.mSectEntrySize; - } } \ No newline at end of file diff --git a/lib/libfnd/fnd.vcxproj b/lib/libfnd/fnd.vcxproj index 90edb79..703f93b 100644 --- a/lib/libfnd/fnd.vcxproj +++ b/lib/libfnd/fnd.vcxproj @@ -119,6 +119,9 @@ true + + + @@ -126,27 +129,23 @@ - + - + - - - - diff --git a/lib/libfnd/fnd.vcxproj.filters b/lib/libfnd/fnd.vcxproj.filters index 36b0ec3..5becb28 100644 --- a/lib/libfnd/fnd.vcxproj.filters +++ b/lib/libfnd/fnd.vcxproj.filters @@ -15,22 +15,40 @@ + + + + + Header Files + Header Files + + Header Files + Header Files + + Header Files + Header Files - + Header Files Header Files - + + Header Files + + + Header Files + + Header Files @@ -39,22 +57,7 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - + Header Files @@ -65,23 +68,17 @@ Source Files - - Source Files - - - Source Files - - - Source Files - Source Files Source Files - - - + + Source Files + + + Source Files + \ No newline at end of file diff --git a/lib/libfnd/include/fnd/ISerialisable.h b/lib/libfnd/include/fnd/ISerialisable.h new file mode 100644 index 0000000..a484ea0 --- /dev/null +++ b/lib/libfnd/include/fnd/ISerialisable.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include + +namespace fnd +{ + class ISerialisable + { + public: + // serialise + virtual void toBytes() = 0; + // deserialise + virtual void fromBytes(const byte_t* data, size_t len) = 0; + + // get byte vector + virtual const fnd::Vec& getBytes() const = 0; + + // clear data + virtual void clear() = 0; + }; +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/ISerialiseableBinary.h b/lib/libfnd/include/fnd/ISerialiseableBinary.h deleted file mode 100644 index 5928c81..0000000 --- a/lib/libfnd/include/fnd/ISerialiseableBinary.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include - -namespace fnd -{ - class ISerialiseableBinary - { - public: - virtual const byte_t* getBytes() const = 0; - virtual size_t getSize() const = 0; - - virtual void exportBinary() = 0; - virtual void importBinary(const byte_t* bytes, size_t len) = 0; - - virtual void clear() = 0; - }; -} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/List.h b/lib/libfnd/include/fnd/List.h index b4dd398..d15d8ba 100644 --- a/lib/libfnd/include/fnd/List.h +++ b/lib/libfnd/include/fnd/List.h @@ -1,6 +1,7 @@ #pragma once #include #include +//#include namespace fnd { @@ -8,130 +9,159 @@ namespace fnd class List { public: - List() : - mElements() - { - } + // constructors + List(); + List(const List& other); - List(const T* elements, size_t num) : - mElements(num) - { - initList(elements, num); - } + // copy operator + void operator=(const List& other); - // assignment operator - const List& operator=(const List& other) - { - mElements.clear(); - for (size_t i = 0; i < other.getSize(); i++) - { - mElements.push_back(other[i]); - } + // equivalence operators + bool operator==(const List& other) const; + bool operator!=(const List& other) const; - return *this; - } + // back relative insertion + void addElement(const T& element); + + // element access + const T& operator[](size_t index) const; + T& operator[](size_t index); + const T& atBack() const; + T& atBack(); - // comparision operator - bool operator==(const List& other) const - { - if (other.getSize() != this->getSize()) - { - return false; - } + // element num + size_t size() const; - for (size_t i = 0; i < this->getSize(); i++) - { - if (getElement(i) != other[i]) - { - return false; - } - } + // clear List + void clear(); - return true; - } - - bool operator!=(const List& other) const - { - return !operator==(other); - } - - // access operators - const T& getElement(size_t index) const - { - return mElements[index]; - } - T& getElement(size_t index) - { - if (index == mElements.size()) mElements.push_back(T()); - return mElements[index]; - } - - const T& operator[](size_t index) const { return getElement(index); } - T& operator[](size_t index) { return getElement(index); } - const T& atBack() const { return getElement(getSize() - 1); } - T& atBack() { return getElement(getSize() - 1); } - - // functions - void addElement(const T& element) { mElements.push_back(element); } - size_t getIndexOf(const T& key) const - { - for (size_t i = 0; i < getSize(); i++) - { - if (getElement(i) == key) return i; - } - - throw Exception("LIST", "Element does not exist"); - } - bool hasElement(const T& key) const - { - try - { - getIndexOf(key); - } catch (const Exception&) - { - return false; - } - - return true; - } - - // special - template - size_t getIndexOf(const X& key) const - { - for (size_t i = 0; i < getSize(); i++) - { - if (getElement(i) == key) return i; - } - - throw Exception("LIST", "Element does not exist"); - } - template - bool hasElement(const X& key) const - { - try - { - getIndexOf(key); - } catch (const Exception&) - { - return false; - } - - return true; - } - size_t getSize() const { return mElements.size(); } - void clear() { mElements.clear(); } + // element access by key + template + bool hasElement(const K& key) const; + template + const T& getElement(const K& key) const; + template + T& getElement(const K& key); + private: - std::vector mElements; + std::vector m_Vec; + }; - void initList(T* elements, size_t num) + template + inline List::List() : + m_Vec() + { + } + + template + inline List::List(const List& other) : + List() + { + *this = other; + } + + template + inline void List::operator=(const List& other) + { + m_Vec = other.m_Vec; + } + + template + inline bool List::operator==(const List& other) const + { + return m_Vec == other.m_Vec; + } + + template + inline bool List::operator!=(const List& other) const + { + return !(*this == other); + } + + template + inline void List::addElement(const T & element) + { + m_Vec.push_back(element); + } + + template + inline const T & List::operator[](size_t index) const + { + return m_Vec[index]; + } + + template + inline T & List::operator[](size_t index) + { + return m_Vec[index]; + } + + template + inline const T & List::atBack() const + { + return m_Vec.back(); + } + + template + inline T & List::atBack() + { + return m_Vec.back(); + } + + template + inline size_t List::size() const + { + return m_Vec.size(); + } + + template + inline void List::clear() + { + m_Vec.clear(); + } + + template + template + inline bool List::hasElement(const K & key) const + { + for (size_t i = 0; i < m_Vec.size(); i++) { - mElements.clear(); - for (size_t i = 0; i < num; i++) + if (m_Vec[i] == key) { - mElements.push_back(elements[i]); + return true; } } - }; -} + return false; + } + + template + template + inline const T & List::getElement(const K & key) const + { + for (size_t i = 0; i < m_Vec.size(); i++) + { + if (m_Vec[i] == key) + { + return m_Vec[i]; + } + } + + throw fnd::Exception("getElement(): element does not exist"); + } + + template + template + inline T & List::getElement(const K & key) + { + for (size_t i = 0; i < m_Vec.size(); i++) + { + if (m_Vec[i] == key) + { + return m_Vec[i]; + } + } + + throw fnd::Exception("getElement(): element does not exist"); + } +} diff --git a/lib/libfnd/include/fnd/MemoryBlob.h b/lib/libfnd/include/fnd/MemoryBlob.h deleted file mode 100644 index 465f257..0000000 --- a/lib/libfnd/include/fnd/MemoryBlob.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace fnd -{ - class MemoryBlob - { - public: - MemoryBlob(); - MemoryBlob(const byte_t* bytes, size_t len); - - bool operator==(const MemoryBlob& other) const; - bool operator!=(const MemoryBlob& other) const; - void operator=(const MemoryBlob& other); - - void alloc(size_t size); - void extend(size_t new_size); - void clear(); - - inline byte_t& operator[](size_t index) { return mData[index]; } - inline const byte_t& operator[](size_t index) const { return mData[index]; } - - inline byte_t* getBytes() { return mData.data(); } - inline const byte_t* getBytes() const { return mData.data(); } - inline size_t getSize() const { return mVisableSize; } - private: - const std::string kModuleName = "MEMORY_BLOB"; - static const size_t kAllocBlockSize = 0x1000; - - std::vector mData; - size_t mSize; - size_t mVisableSize; - - void allocateMemory(size_t size); - void clearMemory(); - }; -} diff --git a/lib/libfnd/include/fnd/Vec.h b/lib/libfnd/include/fnd/Vec.h new file mode 100644 index 0000000..6cc2ed3 --- /dev/null +++ b/lib/libfnd/include/fnd/Vec.h @@ -0,0 +1,198 @@ +#pragma once +#include + +namespace fnd +{ + template + class Vec + { + public: + // constructors + Vec(); + Vec(const Vec& other); + Vec(const T* array, size_t num); + ~Vec(); + + // copy operator + void operator=(const Vec& other); + + // equivalence operators + bool operator==(const Vec& other) const; + bool operator!=(const Vec& other) const; + + // element access + const T& operator[](size_t index) const; + T& operator[](size_t index); + + // raw access + const T* data() const; + T* data(); + + // element num + size_t size() const; + + // allocate vector + void alloc(size_t new_size); + + // resize vector + void resize(size_t new_size); + + // clear vector + void clear(); + private: + T* m_Vec; + size_t m_Size; + + void copyFrom(const T * array, size_t num); + }; + + template + inline Vec::Vec() : + m_Vec(nullptr), + m_Size(0) + {} + + template + inline Vec::Vec(const Vec& other) : + Vec() + { + copyFrom(other.data(), other.size()); + } + + template + inline Vec::Vec(const T * array, size_t num) : + Vec() + { + copyFrom(array, num); + } + + template + inline Vec::~Vec() + { + clear(); + } + + template + inline void Vec::operator=(const Vec& other) + { + copyFrom(other.data(), other.size()); + } + + template + inline bool Vec::operator==(const Vec& other) const + { + bool isEqual = true; + + if (m_Size == other.m_Size) + { + for (size_t i = 0; i < m_Size && isEqual; i++) + { + if (m_Vec[i] != other.m_Vec[i]) + { + isEqual = false; + } + } + } + else + { + isEqual = false; + } + + return isEqual; + } + + template + inline bool Vec::operator!=(const Vec& other) const + { + return !(*this == other); + } + + template + inline const T & Vec::operator[](size_t index) const + { + return m_Vec[index]; + } + + template + inline T & Vec::operator[](size_t index) + { + return m_Vec[index]; + } + + template + inline const T * Vec::data() const + { + return m_Vec; + } + + template + inline T * Vec::data() + { + return m_Vec; + } + + template + inline size_t Vec::size() const + { + return m_Size; + } + + template + inline void Vec::alloc(size_t new_size) + { + clear(); + m_Vec = new T[new_size]; + if (m_Vec == nullptr) + { + fnd::Exception("Vec", "Failed to allocate memory for vector"); + } + m_Size = new_size; + } + + template + inline void Vec::resize(size_t new_size) + { + if (m_Vec != nullptr) + { + T* new_vec = new T[new_size]; + if (new_vec == nullptr) + { + fnd::Exception("Vec", "Failed to allocate memory for vector"); + } + + for (size_t i = 0; i < _MIN(m_Size, new_size); i++) + { + new_vec[i] = m_Vec[i]; + } + delete[] m_Vec; + m_Vec = new_vec; + m_Size = new_size; + } + else + { + alloc(new_size); + } + } + + template + inline void Vec::clear() + { + if (m_Vec != nullptr) + { + delete[] m_Vec; + } + m_Vec = nullptr; + m_Size = 0; + } + + template + inline void Vec::copyFrom(const T * array, size_t num) + { + clear(); + alloc(num); + for (size_t i = 0; i < m_Size; i++) + { + m_Vec[i] = array[i]; + } + } +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/io.h b/lib/libfnd/include/fnd/io.h index 58aa895..291a79b 100644 --- a/lib/libfnd/include/fnd/io.h +++ b/lib/libfnd/include/fnd/io.h @@ -1,6 +1,5 @@ #pragma once #include -#include namespace fnd { @@ -13,10 +12,6 @@ namespace fnd #endif size_t getFileSize(const std::string& path); - void readFile(const std::string& path, MemoryBlob& blob); - void readFile(const std::string& path, size_t offset, size_t len, MemoryBlob& blob); - void writeFile(const std::string& path, const MemoryBlob& blob); - void writeFile(const std::string& path, const byte_t* data, size_t len); void makeDirectory(const std::string& path); void getEnvironVar(std::string& var, const std::string& key); void appendToPath(std::string& base, const std::string& add); diff --git a/lib/libfnd/include/fnd/types.h b/lib/libfnd/include/fnd/types.h index 2eeb08a..81cac74 100644 --- a/lib/libfnd/include/fnd/types.h +++ b/lib/libfnd/include/fnd/types.h @@ -6,8 +6,8 @@ typedef uint8_t byte_t; -#define MIN(x,y) ((x) <= (y)? (x) : (y)) -#define MAX(x,y) ((x) >= (y)? (x) : (y)) +#define _MIN(x,y) ((x) <= (y)? (x) : (y)) +#define _MAX(x,y) ((x) >= (y)? (x) : (y)) static inline uint64_t align(uint64_t size, uint64_t align) { diff --git a/lib/libfnd/source/MemoryBlob.cpp b/lib/libfnd/source/MemoryBlob.cpp deleted file mode 100644 index 2456972..0000000 --- a/lib/libfnd/source/MemoryBlob.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include - -using namespace fnd; - -MemoryBlob::MemoryBlob() : - mData(), - mSize(0), - mVisableSize(0) -{ - -} - -fnd::MemoryBlob::MemoryBlob(const byte_t * bytes, size_t len) : - mData(), - mSize(0), - mVisableSize(0) -{ - alloc(len); - memcpy(getBytes(), bytes, getSize()); -} - -bool fnd::MemoryBlob::operator==(const MemoryBlob & other) const -{ - bool isEqual = true; - - if (this->getSize() == other.getSize()) - { - isEqual = memcmp(this->getBytes(), other.getBytes(), this->getSize()) == 0; - } - else - { - isEqual = false; - } - - - return isEqual; -} - -bool fnd::MemoryBlob::operator!=(const MemoryBlob & other) const -{ - return !operator==(other); -} - -void fnd::MemoryBlob::operator=(const MemoryBlob & other) -{ - alloc(other.getSize()); - memcpy(getBytes(), other.getBytes(), getSize()); -} - -void MemoryBlob::alloc(size_t size) -{ - if (size > mSize) - { - allocateMemory(size); - } - else - { - mVisableSize = size; - clearMemory(); - } -} - -void MemoryBlob::extend(size_t new_size) -{ - try { - mData.resize(new_size); - } - catch (...) { - throw fnd::Exception(kModuleName, "extend() failed to allocate memory"); - } -} - -void fnd::MemoryBlob::clear() -{ - mVisableSize = 0; -} - -void MemoryBlob::allocateMemory(size_t size) -{ - mSize = (size_t)align(size, kAllocBlockSize); - mVisableSize = size; - extend(mSize); - clearMemory(); -} - -void MemoryBlob::clearMemory() -{ - memset(mData.data(), 0, mSize); -} diff --git a/lib/libfnd/source/SimpleTextOutput.cpp b/lib/libfnd/source/SimpleTextOutput.cpp index e1efc77..7dbc17d 100644 --- a/lib/libfnd/source/SimpleTextOutput.cpp +++ b/lib/libfnd/source/SimpleTextOutput.cpp @@ -6,7 +6,7 @@ void fnd::SimpleTextOutput::hxdStyleDump(const byte_t* data, size_t len, size_t // iterate over blocks for (size_t i = 0; i < (len / row_len); i++) { - printf("%08" PRIx64 " | ", i*row_len); + printf("%08" PRIx64 " | ", (uint64_t)(i * row_len)); // for block i print each byte for (size_t j = 0; j < row_len; j++) { @@ -26,7 +26,7 @@ void fnd::SimpleTextOutput::hxdStyleDump(const byte_t* data, size_t len, size_t if ((len % row_len) > 0) { size_t i = (len / row_len); - printf("%08" PRIx64 " | ", i * row_len); + printf("%08" PRIx64 " | ", (uint64_t)(i * row_len)); // for block i print each byte for (size_t j = 0; j < row_len; j++) { diff --git a/lib/libfnd/source/io.cpp b/lib/libfnd/source/io.cpp index 9bb966b..1c1d5dd 100644 --- a/lib/libfnd/source/io.cpp +++ b/lib/libfnd/source/io.cpp @@ -11,9 +11,6 @@ using namespace fnd; -static const std::string kModuleName = "IO"; -static const size_t kBlockSize = 0x100000; - size_t io::getFileSize(const std::string& path) { std::ifstream f; @@ -25,112 +22,6 @@ size_t io::getFileSize(const std::string& path) return static_cast(f.tellg() - begin_pos); } -void io::readFile(const std::string& path, MemoryBlob & blob) -{ - fnd::SimpleFile file; - try - { - file.open(path, file.Read); - } - catch (const fnd::Exception&) - { - throw fnd::Exception(kModuleName, "Failed to open \"" + path + "\": does not exist"); - } - - size_t filesz, filepos; - filesz = file.size(); - - - try { - blob.alloc(filesz); - } - catch (const fnd::Exception& e) - { - throw fnd::Exception(kModuleName, "Failed to allocate memory for file: " + std::string(e.what())); - } - - for (filepos = 0; filesz > kBlockSize; filesz -= kBlockSize, filepos += kBlockSize) - { - file.read(blob.getBytes() + filepos, kBlockSize); - } - - if (filesz) - { - file.read(blob.getBytes() + filepos, filesz); - } -} - -void fnd::io::readFile(const std::string& path, size_t offset, size_t len, MemoryBlob& blob) -{ - fnd::SimpleFile file; - try - { - file.open(path, file.Read); - } catch (const fnd::Exception&) - { - throw fnd::Exception(kModuleName, "Failed to open \"" + path + "\": does not exist"); - } - - size_t filesz, filepos; - filesz = file.size(); - file.seek(offset); - - if (filesz < len || filesz < offset || filesz < (offset + len)) - { - throw Exception(kModuleName, "Failed to open \"" + path + "\": file to small"); - } - - try - { - blob.alloc(filesz); - } catch (const fnd::Exception& e) - { - throw fnd::Exception(kModuleName, "Failed to allocate memory for file: " + std::string(e.what())); - } - - for (filepos = 0; filesz > kBlockSize; filesz -= kBlockSize, filepos += kBlockSize) - { - file.read(blob.getBytes() + filepos, kBlockSize); - } - - if (filesz) - { - file.read(blob.getBytes() + filepos, filesz); - } -} - -void io::writeFile(const std::string& path, const MemoryBlob & blob) -{ - writeFile(path, blob.getBytes(), blob.getSize()); -} - -void io::writeFile(const std::string & path, const byte_t * data, size_t len) -{ - fnd::SimpleFile file; - try - { - file.open(path, file.Create); - } catch (const fnd::Exception&) - { - throw fnd::Exception(kModuleName, "Failed to open \"" + path + "\": does not exist"); - } - - size_t filesz, filepos; - - filesz = len; - - - for (filepos = 0; filesz > kBlockSize; filesz -= kBlockSize, filepos += kBlockSize) - { - file.write(data + filepos, kBlockSize); - } - - if (filesz) - { - file.write(data + filepos, filesz); - } -} - void io::makeDirectory(const std::string& path) { #ifdef _WIN32 diff --git a/lib/libnx-hb/include/nx/AssetHeader.h b/lib/libnx-hb/include/nx/AssetHeader.h index 17da642..61deecb 100644 --- a/lib/libnx-hb/include/nx/AssetHeader.h +++ b/lib/libnx-hb/include/nx/AssetHeader.h @@ -1,13 +1,12 @@ #pragma once #include -#include #include -#include +#include namespace nx { class AssetHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sSection @@ -29,25 +28,21 @@ namespace nx bool operator!=(const sSection& other) const { - return !(*this == other); + return !operator==(other); } }; AssetHeader(); AssetHeader(const AssetHeader& other); - AssetHeader(const byte_t* bytes, size_t len); + void operator=(const AssetHeader& other); bool operator==(const AssetHeader& other) const; bool operator!=(const AssetHeader& other) const; - void operator=(const AssetHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -64,16 +59,12 @@ namespace nx const std::string kModuleName = "NRO_ASSET_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data sSection mIconInfo; sSection mNacpInfo; sSection mRomfsInfo; - - // helpers - bool isEqual(const AssetHeader& other) const; - void copyFrom(const AssetHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx-hb/include/nx/aset.h b/lib/libnx-hb/include/nx/aset.h index 58701bc..9e821cb 100644 --- a/lib/libnx-hb/include/nx/aset.h +++ b/lib/libnx-hb/include/nx/aset.h @@ -6,7 +6,7 @@ namespace nx { namespace aset { - static const uint32_t kAssetSig = _MAKE_STRUCT_SIGNATURE("ASET"); + static const uint32_t kAssetStructMagic = _MAKE_STRUCT_MAGIC_U32("ASET"); static const uint32_t kDefaultAssetFormatVersion = 0; } @@ -20,7 +20,7 @@ namespace nx struct sAssetHeader { - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t format_version; sAssetSection icon; sAssetSection nacp; diff --git a/lib/libnx-hb/include/nx/nro-hb.h b/lib/libnx-hb/include/nx/nro-hb.h index 7c13988..5e5bd05 100644 --- a/lib/libnx-hb/include/nx/nro-hb.h +++ b/lib/libnx-hb/include/nx/nro-hb.h @@ -6,6 +6,6 @@ namespace nx { namespace nro { - static const uint64_t kNroHomebrewSig = _MAKE_STRUCT_SIGNATURE_U64("HOMEBREW"); + static const uint64_t kNroHomebrewStructMagic = _MAKE_STRUCT_MAGIC_U64("HOMEBREW"); } } \ No newline at end of file diff --git a/lib/libnx-hb/source/AssetHeader.cpp b/lib/libnx-hb/source/AssetHeader.cpp index 3d61036..0f8eebb 100644 --- a/lib/libnx-hb/source/AssetHeader.cpp +++ b/lib/libnx-hb/source/AssetHeader.cpp @@ -7,17 +7,22 @@ nx::AssetHeader::AssetHeader() nx::AssetHeader::AssetHeader(const AssetHeader& other) { - copyFrom(other); + *this = other; } -nx::AssetHeader::AssetHeader(const byte_t* bytes, size_t len) +void nx::AssetHeader::operator=(const AssetHeader& other) { - importBinary(bytes, len); + mRawBinary = other.mRawBinary; + mIconInfo = other.mIconInfo; + mNacpInfo = other.mNacpInfo; + mRomfsInfo = other.mRomfsInfo; } bool nx::AssetHeader::operator==(const AssetHeader& other) const { - return isEqual(other); + return (mIconInfo == other.mIconInfo) \ + && (mNacpInfo == other.mNacpInfo) \ + && (mRomfsInfo == other.mRomfsInfo); } bool nx::AssetHeader::operator!=(const AssetHeader& other) const @@ -25,28 +30,13 @@ bool nx::AssetHeader::operator!=(const AssetHeader& other) const return !(*this == other); } -void nx::AssetHeader::operator=(const AssetHeader& other) +void nx::AssetHeader::toBytes() { - copyFrom(other); -} - -const byte_t* nx::AssetHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::AssetHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::AssetHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sAssetHeader)); - nx::sAssetHeader* hdr = (nx::sAssetHeader*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sAssetHeader)); + nx::sAssetHeader* hdr = (nx::sAssetHeader*)mRawBinary.data(); // set header identifers - hdr->signature = aset::kAssetSig; + hdr->st_magic = aset::kAssetStructMagic; hdr->format_version = aset::kDefaultAssetFormatVersion; // set icon section @@ -62,7 +52,7 @@ void nx::AssetHeader::exportBinary() hdr->romfs.size = mRomfsInfo.size; } -void nx::AssetHeader::importBinary(const byte_t* bytes, size_t len) +void nx::AssetHeader::fromBytes(const byte_t* bytes, size_t len) { // check input data size if (len < sizeof(sAssetHeader)) @@ -74,14 +64,14 @@ void nx::AssetHeader::importBinary(const byte_t* bytes, size_t len) clear(); // allocate internal local binary copy - mBinaryBlob.alloc(sizeof(sAssetHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(sizeof(sAssetHeader)); + memcpy(mRawBinary.data(), bytes, mRawBinary.size()); // get sAssetHeader ptr - const nx::sAssetHeader* hdr = (const nx::sAssetHeader*)mBinaryBlob.getBytes(); + const nx::sAssetHeader* hdr = (const nx::sAssetHeader*)mRawBinary.data(); // check NRO signature - if (hdr->signature.get() != aset::kAssetSig) + if (hdr->st_magic.get() != aset::kAssetStructMagic) { throw fnd::Exception(kModuleName, "ASET header corrupt (unrecognised header signature)"); } @@ -100,9 +90,14 @@ void nx::AssetHeader::importBinary(const byte_t* bytes, size_t len) mRomfsInfo.size = hdr->romfs.size.get(); } +const fnd::Vec& nx::AssetHeader::getBytes() const +{ + return mRawBinary; +} + void nx::AssetHeader::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); memset(&mIconInfo, 0, sizeof(mIconInfo)); memset(&mNacpInfo, 0, sizeof(mNacpInfo)); memset(&mRomfsInfo, 0, sizeof(mRomfsInfo)); @@ -136,18 +131,4 @@ const nx::AssetHeader::sSection& nx::AssetHeader::getRomfsInfo() const void nx::AssetHeader::setRomfsInfo(const sSection& info) { mRomfsInfo = info; -} - -bool nx::AssetHeader::isEqual(const AssetHeader& other) const -{ - return (mIconInfo == other.mIconInfo) \ - && (mNacpInfo == other.mNacpInfo) \ - && (mRomfsInfo == other.mRomfsInfo); -} - -void nx::AssetHeader::copyFrom(const AssetHeader& other) -{ - mIconInfo = other.mIconInfo; - mNacpInfo = other.mNacpInfo; - mRomfsInfo = other.mRomfsInfo; } \ No newline at end of file diff --git a/lib/libnx/include/nx/AccessControlInfoBinary.h b/lib/libnx/include/nx/AccessControlInfoBinary.h new file mode 100644 index 0000000..f16cc20 --- /dev/null +++ b/lib/libnx/include/nx/AccessControlInfoBinary.h @@ -0,0 +1,53 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +namespace nx +{ + class AccessControlInfoBinary : public fnd::ISerialisable + { + public: + AccessControlInfoBinary(); + AccessControlInfoBinary(const AccessControlInfoBinary& other); + + void operator=(const AccessControlInfoBinary& other); + bool operator==(const AccessControlInfoBinary& other) const; + bool operator!=(const AccessControlInfoBinary& other) const; + + // export/import binary + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getProgramId() const; + void setProgramId(uint64_t program_id); + + const nx::FileSystemAccessControlBinary& getFileSystemAccessControl() const; + void setFileSystemAccessControl(const FileSystemAccessControlBinary& fac); + + const nx::ServiceAccessControlBinary& getServiceAccessControl() const; + void setServiceAccessControl(const ServiceAccessControlBinary& sac); + + const nx::KernelCapabilityBinary& getKernelCapabilities() const; + void setKernelCapabilities(const KernelCapabilityBinary& kc); + private: + const std::string kModuleName = "ACCESS_CONTROL_INFO_BINARY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + uint64_t mProgramId; + nx::FileSystemAccessControlBinary mFileSystemAccessControl; + nx::ServiceAccessControlBinary mServiceAccessControl; + nx::KernelCapabilityBinary mKernelCapabilities; + }; +} \ No newline at end of file diff --git a/lib/libnx/include/nx/AccessControlInfoDescBinary.h b/lib/libnx/include/nx/AccessControlInfoDescBinary.h new file mode 100644 index 0000000..53519a8 --- /dev/null +++ b/lib/libnx/include/nx/AccessControlInfoDescBinary.h @@ -0,0 +1,88 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nx +{ + class AccessControlInfoDescBinary : public fnd::ISerialisable + { + public: + struct sProgramIdRestrict + { + uint64_t min; + uint64_t max; + + void operator=(const sProgramIdRestrict& other) + { + min = other.min; + max = other.max; + } + + bool operator==(const sProgramIdRestrict& other) const + { + return (min == other.min) \ + && (max == other.max); + } + + bool operator!=(const sProgramIdRestrict& other) const + { + return !(*this == other); + } + }; + + AccessControlInfoDescBinary(); + AccessControlInfoDescBinary(const AccessControlInfoDescBinary& other); + + void operator=(const AccessControlInfoDescBinary& other); + bool operator==(const AccessControlInfoDescBinary& other) const; + bool operator!=(const AccessControlInfoDescBinary& other) const; + + // export/import binary + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + void generateSignature(const crypto::rsa::sRsa2048Key& key); + void validateSignature(const crypto::rsa::sRsa2048Key& key) const; + + // variables + void clear(); + + const crypto::rsa::sRsa2048Key& getNcaHeaderSignature2Key() const; + void setNcaHeaderSignature2Key(const crypto::rsa::sRsa2048Key& key); + + const fnd::List& getFlagList() const; + void setFlagList(const fnd::List& flags); + + const sProgramIdRestrict& getProgramIdRestrict() const; + void setProgramIdRestrict(const sProgramIdRestrict& pid_restrict); + + const nx::FileSystemAccessControlBinary& getFileSystemAccessControl() const; + void setFileSystemAccessControl(const FileSystemAccessControlBinary& fac); + + const nx::ServiceAccessControlBinary& getServiceAccessControl() const; + void setServiceAccessControl(const ServiceAccessControlBinary& sac); + + const nx::KernelCapabilityBinary& getKernelCapabilities() const; + void setKernelCapabilities(const KernelCapabilityBinary& kc); + private: + const std::string kModuleName = "ACCESS_CONTROL_INFO_DESC_BINARY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + crypto::rsa::sRsa2048Key mNcaHeaderSignature2Key; + fnd::List mFlags; + sProgramIdRestrict mProgramIdRestrict; + nx::FileSystemAccessControlBinary mFileSystemAccessControl; + nx::ServiceAccessControlBinary mServiceAccessControl; + nx::KernelCapabilityBinary mKernelCapabilities; + }; +} \ No newline at end of file diff --git a/lib/libnx/include/nx/AciBinary.h b/lib/libnx/include/nx/AciBinary.h deleted file mode 100644 index c32e01c..0000000 --- a/lib/libnx/include/nx/AciBinary.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace nx -{ - class AciBinary : - public AciHeader - { - public: - AciBinary(); - AciBinary(const AciBinary& other); - AciBinary(const byte_t* bytes, size_t len); - - bool operator==(const AciBinary& other) const; - bool operator!=(const AciBinary& other) const; - void operator=(const AciBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - virtual void exportBinary(); - virtual void importBinary(const byte_t* bytes, size_t len); - - // variables - virtual void clear(); - - const FacBinary& getFac() const; - void setFac(const FacBinary& fac); - - const SacBinary& getSac() const; - void setSac(const SacBinary& sac); - - const KcBinary& getKc() const; - void setKc(const KcBinary& kc); - - private: - const std::string kModuleName = "ACI_BINARY"; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - FacBinary mFac; - SacBinary mSac; - KcBinary mKc; - - bool isEqual(const AciBinary& other) const; - void copyFrom(const AciBinary& other); - }; -} - diff --git a/lib/libnx/include/nx/AciHeader.h b/lib/libnx/include/nx/AciHeader.h deleted file mode 100644 index 71734d0..0000000 --- a/lib/libnx/include/nx/AciHeader.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nx -{ - class AciHeader : - public fnd::ISerialiseableBinary - { - public: - enum AciType - { - TYPE_ACI0, // for Access Control Info - TYPE_ACID // for Access Control Info Desc - }; - - struct sSection - { - size_t offset; - size_t size; - - void operator=(const sSection& other) - { - offset = other.offset; - size = other.size; - } - - bool operator==(const sSection& other) const - { - return (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sSection& other) const - { - return !operator==(other); - } - }; - - AciHeader(); - AciHeader(const AciHeader& other); - AciHeader(const byte_t* bytes, size_t len); - - bool operator==(const AciHeader& other) const; - bool operator!=(const AciHeader& other) const; - void operator=(const AciHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - virtual void exportBinary(); - virtual void importBinary(const byte_t* bytes, size_t len); - - // variables - virtual void clear(); - size_t getAciSize() const; - - // ACI0 only - uint64_t getProgramId() const; - void setProgramId(uint64_t program_id); - - // ACID only - size_t getAcidSize() const; - //void setAcidSize(size_t size); - uint64_t getProgramIdMin() const; - void setProgramIdMin(uint64_t program_id); - uint64_t getProgramIdMax() const; - void setProgramIdMax(uint64_t program_id); - - // ACID & ACI0 - void setHeaderOffset(size_t offset); - AciType getAciType() const; - void setAciType(AciType type); - bool isProduction() const; - void setIsProduction(bool isProduction); - bool isUnqualifiedApproval() const; - void setIsUnqualifiedApproval(bool isUnqualifiedApproval); - const sSection& getFacPos() const; - void setFacSize(size_t size); - const sSection& getSacPos() const; - void setSacSize(size_t size); - const sSection& getKcPos() const; - void setKcSize(size_t size); - - private: - const std::string kModuleName = "ACI_HEADER"; - - // raw data - fnd::MemoryBlob mBinaryBlob; - - // ACI variables - uint64_t mProgramId; - - // ACID variables - size_t mAcidSize; - uint64_t mProgramIdMin; - uint64_t mProgramIdMax; - - // ACI(D) variables - size_t mHeaderOffset; - AciType mType; - bool mIsProduction; - bool mIsUnqualifiedApproval; - sSection mFac, mSac, mKc; - - void calculateSectionOffsets(); - bool isEqual(const AciHeader& other) const; - void copyFrom(const AciHeader& other); - }; -} - diff --git a/lib/libnx/include/nx/AcidBinary.h b/lib/libnx/include/nx/AcidBinary.h deleted file mode 100644 index c00b1d7..0000000 --- a/lib/libnx/include/nx/AcidBinary.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace nx -{ - class AcidBinary : - public AciBinary - { - public: - AcidBinary(); - AcidBinary(const AcidBinary& other); - AcidBinary(const byte_t* bytes, size_t len); - - bool operator==(const AcidBinary& other) const; - bool operator!=(const AcidBinary& other) const; - void operator=(const AcidBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - virtual void exportBinary(); - void signBinary(const crypto::rsa::sRsa2048Key& key); - virtual void importBinary(const byte_t* bytes, size_t len); - void verifyBinary(const crypto::rsa::sRsa2048Key& key) const; - - // variables - virtual void clear(); - - const crypto::rsa::sRsa2048Key& getNcaHeader2RsaKey() const; - void setNcaHeader2RsaKey(const crypto::rsa::sRsa2048Key& key); - - private: - const std::string kModuleName = "ACID_BINARY"; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - crypto::rsa::sRsa2048Key mEmbeddedPublicKey; - - bool isEqual(const AcidBinary& other) const; - void copyFrom(const AcidBinary& other); - }; -} - diff --git a/lib/libnx/include/nx/ApplicationControlPropertyBinary.h b/lib/libnx/include/nx/ApplicationControlPropertyBinary.h index a5aed57..ed5a96d 100644 --- a/lib/libnx/include/nx/ApplicationControlPropertyBinary.h +++ b/lib/libnx/include/nx/ApplicationControlPropertyBinary.h @@ -1,15 +1,14 @@ #pragma once #include #include -#include +#include #include -#include #include namespace nx { class ApplicationControlPropertyBinary : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sTitle @@ -86,19 +85,15 @@ namespace nx ApplicationControlPropertyBinary(); ApplicationControlPropertyBinary(const ApplicationControlPropertyBinary& other); - ApplicationControlPropertyBinary(const byte_t* bytes, size_t len); + void operator=(const ApplicationControlPropertyBinary& other); bool operator==(const ApplicationControlPropertyBinary& other) const; bool operator!=(const ApplicationControlPropertyBinary& other) const; - void operator=(const ApplicationControlPropertyBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -222,7 +217,7 @@ namespace nx const std::string kModuleName = "APPLICATION_CONTROL_PROPERTY"; // raw data - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables fnd::List mTitle; @@ -263,8 +258,5 @@ namespace nx nacp::PlayLogQueryCapability mPlayLogQueryCapability; nacp::RepairFlag mRepairFlag; byte_t mProgramIndex; - - bool isEqual(const ApplicationControlPropertyBinary& other) const; - void copyFrom(const ApplicationControlPropertyBinary& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/ContentMetaBinary.h b/lib/libnx/include/nx/ContentMetaBinary.h index 6bf2ddb..59eee5d 100644 --- a/lib/libnx/include/nx/ContentMetaBinary.h +++ b/lib/libnx/include/nx/ContentMetaBinary.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include @@ -8,7 +8,7 @@ namespace nx { class ContentMetaBinary : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct ContentInfo @@ -18,13 +18,12 @@ namespace nx size_t size; cnmt::ContentType type; - ContentInfo& operator=(const ContentInfo& other) + void operator=(const ContentInfo& other) { hash = other.hash; memcpy(nca_id, other.nca_id, cnmt::kContentIdLen); size = other.size; type = other.type; - return *this; } bool operator==(const ContentInfo& other) const @@ -48,13 +47,12 @@ namespace nx cnmt::ContentMetaType type; byte_t attributes; - ContentMetaInfo& operator=(const ContentMetaInfo& other) + void operator=(const ContentMetaInfo& other) { id = other.id; version = other.version; type = other.type; attributes = other.attributes; - return *this; } bool operator==(const ContentMetaInfo& other) const @@ -76,11 +74,10 @@ namespace nx uint64_t patch_id; uint32_t required_system_version; - ApplicationMetaExtendedHeader& operator=(const ApplicationMetaExtendedHeader& other) + void operator=(const ApplicationMetaExtendedHeader& other) { patch_id = other.patch_id; required_system_version = other.required_system_version; - return *this; } bool operator==(const ApplicationMetaExtendedHeader& other) const @@ -100,11 +97,10 @@ namespace nx uint64_t application_id; uint32_t required_system_version; - PatchMetaExtendedHeader& operator=(const PatchMetaExtendedHeader& other) + void operator=(const PatchMetaExtendedHeader& other) { application_id = other.application_id; required_system_version = other.required_system_version; - return *this; } bool operator==(const PatchMetaExtendedHeader& other) const @@ -124,11 +120,10 @@ namespace nx uint64_t application_id; uint32_t required_system_version; - AddOnContentMetaExtendedHeader& operator=(const AddOnContentMetaExtendedHeader& other) + void operator=(const AddOnContentMetaExtendedHeader& other) { application_id = other.application_id; required_system_version = other.required_system_version; - return *this; } bool operator==(const AddOnContentMetaExtendedHeader& other) const @@ -147,10 +142,9 @@ namespace nx { uint64_t application_id; - DeltaMetaExtendedHeader& operator=(const DeltaMetaExtendedHeader& other) + void operator=(const DeltaMetaExtendedHeader& other) { application_id = other.application_id; - return *this; } bool operator==(const DeltaMetaExtendedHeader& other) const @@ -166,15 +160,15 @@ namespace nx ContentMetaBinary(); ContentMetaBinary(const ContentMetaBinary& other); - ContentMetaBinary(const byte_t* bytes, size_t len); - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; + void operator=(const ContentMetaBinary& other); + bool operator==(const ContentMetaBinary& other) const; + bool operator!=(const ContentMetaBinary& other) const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -212,8 +206,8 @@ namespace nx const fnd::List& getContentMetaInfo() const; void setContentMetaInfo(const fnd::List& info); - const fnd::MemoryBlob& getExtendedData() const; - void setExtendedData(const fnd::MemoryBlob& data); + const fnd::Vec& getExtendedData() const; + void setExtendedData(const fnd::Vec& data); const nx::sDigest& getDigest() const; void setDigest(const nx::sDigest& digest); @@ -223,7 +217,7 @@ namespace nx const std::string kModuleName = "CONTENT_META_BINARY"; // binary blob - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables uint64_t mTitleId; @@ -231,7 +225,7 @@ namespace nx cnmt::ContentMetaType mType; byte_t mAttributes; uint32_t mRequiredDownloadSystemVersion; - fnd::MemoryBlob mExtendedHeader; + fnd::Vec mExtendedHeader; ApplicationMetaExtendedHeader mApplicationMetaExtendedHeader; PatchMetaExtendedHeader mPatchMetaExtendedHeader; @@ -240,7 +234,7 @@ namespace nx fnd::List mContentInfo; fnd::List mContentMetaInfo; - fnd::MemoryBlob mExtendedData; + fnd::Vec mExtendedData; nx::sDigest mDigest; inline size_t getExtendedHeaderOffset() const { return sizeof(sContentMetaHeader); } @@ -253,8 +247,5 @@ namespace nx bool validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const; size_t getExtendedDataSize(cnmt::ContentMetaType type, const byte_t* data) const; void validateBinary(const byte_t* bytes, size_t len) const; - - bool isEqual(const ContentMetaBinary& other) const; - void copyFrom(const ContentMetaBinary& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/FacBinary.h b/lib/libnx/include/nx/FacBinary.h deleted file mode 100644 index 619617c..0000000 --- a/lib/libnx/include/nx/FacBinary.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include - - -namespace nx -{ - class FacBinary : - public FacHeader - { - public: - FacBinary(); - FacBinary(const FacBinary& other); - FacBinary(const byte_t* bytes, size_t len); - - bool operator==(const FacBinary& other) const; - bool operator!=(const FacBinary& other) const; - void operator=(const FacBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); - - // variables - void clear(); - - const fnd::List& getContentOwnerIdList() const; - void setContentOwnerIdList(const fnd::List& list); - - const fnd::List& getSaveDataOwnerIdList() const; - void setSaveDataOwnerIdList(const fnd::List& list); - - private: - const std::string kModuleName = "FAC_BINARY"; - static const uint32_t kFacFormatVersion = 1; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - fnd::List mContentOwnerIdList; - fnd::List mSaveDataOwnerIdList; - - bool isEqual(const FacBinary& other) const; - void copyFrom(const FacBinary& other); - }; -} - diff --git a/lib/libnx/include/nx/FacHeader.h b/lib/libnx/include/nx/FacHeader.h deleted file mode 100644 index 672c451..0000000 --- a/lib/libnx/include/nx/FacHeader.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace nx -{ - class FacHeader : - public fnd::ISerialiseableBinary - { - public: - enum FsAccessFlag - { - FSA_APPLICATION_INFO, - FSA_BOOT_MODE_CONTROL, - FSA_CALIBRATION, - FSA_SYSTEM_SAVE_DATA, - FSA_GAME_CARD, - FSA_SAVE_DATA_BACKUP, - FSA_SAVE_DATA_MANAGEMENT, - FSA_BIS_ALL_RAW, - FSA_GAME_CARD_RAW, - FSA_GAME_CARD_PRIVATE, - FSA_SET_TIME, - FSA_CONTENT_MANAGER, - FSA_IMAGE_MANAGER, - FSA_CREATE_SAVE_DATA, - FSA_SYSTEM_SAVE_DATA_MANAGEMENT, - FSA_BIS_FILE_SYSTEM, - FSA_SYSTEM_UPDATE, - FSA_SAVE_DATA_META, - FSA_DEVICE_SAVE_CONTROL, - FSA_SETTINGS_CONTROL, - FSA_DEBUG = 62, - FSA_FULL_PERMISSION = 63, - }; - - FacHeader(); - FacHeader(const FacHeader& other); - FacHeader(const byte_t* bytes, size_t len); - - bool operator==(const FacHeader& other) const; - bool operator!=(const FacHeader& other) const; - void operator=(const FacHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); - - // variables - void clear(); - size_t getFacSize() const; - - uint32_t getFormatVersion() const; - void setFormatVersion(uint32_t version); - - const fnd::List& getFsaRightsList() const; - void setFsaRightsList(const fnd::List& list); - - size_t getContentOwnerIdOffset() const; - size_t getContentOwnerIdSize() const; - void setContentOwnerIdSize(size_t size); - - size_t getSaveDataOwnerIdOffset() const; - size_t getSaveDataOwnerIdSize() const; - void setSaveDataOwnerIdSize(size_t size); - - private: - const std::string kModuleName = "FAC_HEADER"; - static const uint32_t kFacFormatVersion = 1; - -#pragma pack (push, 1) - struct sFacHeader - { - le_uint32_t version; // default 1 - le_uint64_t fac_flags; - struct sFacSection - { - le_uint32_t start; - le_uint32_t end; - } content_owner_ids, save_data_owner_ids; // the data for these follow later in binary. start/end relative to base of FacData instance - }; -#pragma pack (pop) - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - uint32_t mVersion; - fnd::List mFsaRights; - struct sSection - { - size_t offset; - size_t size; - } mContentOwnerIdPos, mSaveDataOwnerIdPos; - - void calculateOffsets(); - bool isEqual(const FacHeader& other) const; - void copyFrom(const FacHeader& other); - }; -} - diff --git a/lib/libnx/include/nx/FileSystemAccessControlBinary.h b/lib/libnx/include/nx/FileSystemAccessControlBinary.h new file mode 100644 index 0000000..3a822bc --- /dev/null +++ b/lib/libnx/include/nx/FileSystemAccessControlBinary.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include +#include +#include + + +namespace nx +{ + class FileSystemAccessControlBinary : public fnd::ISerialisable + { + public: + FileSystemAccessControlBinary(); + FileSystemAccessControlBinary(const FileSystemAccessControlBinary& other); + + void operator=(const FileSystemAccessControlBinary& other); + bool operator==(const FileSystemAccessControlBinary& other) const; + bool operator!=(const FileSystemAccessControlBinary& other) const; + + // export/import binary + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint32_t getFormatVersion() const; + void setFormatVersion(uint32_t version); + + const fnd::List& getFsaRightsList() const; + void setFsaRightsList(const fnd::List& list); + + const fnd::List& getContentOwnerIdList() const; + void setContentOwnerIdList(const fnd::List& list); + + const fnd::List& getSaveDataOwnerIdList() const; + void setSaveDataOwnerIdList(const fnd::List& list); + private: + const std::string kModuleName = "FILE_SYSTEM_ACCESS_CONTROL_BINARY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + uint32_t mVersion; + fnd::List mFsaRights; + fnd::List mContentOwnerIdList; + fnd::List mSaveDataOwnerIdList; + }; +} \ No newline at end of file diff --git a/lib/libnx/include/nx/HandleTableSizeEntry.h b/lib/libnx/include/nx/HandleTableSizeEntry.h index 7f19964..18c92e8 100644 --- a/lib/libnx/include/nx/HandleTableSizeEntry.h +++ b/lib/libnx/include/nx/HandleTableSizeEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,23 +9,27 @@ namespace nx { public: HandleTableSizeEntry(); - HandleTableSizeEntry(const KernelCapability& kernel_cap); + HandleTableSizeEntry(const KernelCapabilityEntry& kernel_cap); HandleTableSizeEntry(uint16_t size); + void operator=(const HandleTableSizeEntry& other); + bool operator==(const HandleTableSizeEntry& other) const; + bool operator!=(const HandleTableSizeEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint16_t getHandleTableSize() const; void setHandleTableSize(uint16_t size); private: const std::string kModuleName = "HANDLE_TABLE_SIZE_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_HANDLE_TABLE_SIZE; + static const kc::KernelCapId kCapId = kc::KC_HANDLE_TABLE_SIZE; static const uint16_t kValBits = 10; static const uint16_t kMaxHandleTableSize = BIT(kValBits) - 1; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint16_t mHandleTableSize; inline void updateCapField() diff --git a/lib/libnx/include/nx/HandleTableSizeHandler.h b/lib/libnx/include/nx/HandleTableSizeHandler.h index 8beb3de..3094df8 100644 --- a/lib/libnx/include/nx/HandleTableSizeHandler.h +++ b/lib/libnx/include/nx/HandleTableSizeHandler.h @@ -10,13 +10,13 @@ namespace nx public: HandleTableSizeHandler(); + void operator=(const HandleTableSizeHandler& other); bool operator==(const HandleTableSizeHandler& other) const; bool operator!=(const HandleTableSizeHandler& other) const; - void operator=(const HandleTableSizeHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -30,9 +30,6 @@ namespace nx bool mIsSet; HandleTableSizeEntry mEntry; - - void copyFrom(const HandleTableSizeHandler& other); - bool isEqual(const HandleTableSizeHandler& other) const; }; } diff --git a/lib/libnx/include/nx/HierarchicalIntegrityHeader.h b/lib/libnx/include/nx/HierarchicalIntegrityHeader.h index ddcb5f9..b0d0945 100644 --- a/lib/libnx/include/nx/HierarchicalIntegrityHeader.h +++ b/lib/libnx/include/nx/HierarchicalIntegrityHeader.h @@ -1,13 +1,13 @@ #pragma once #include -#include +#include #include -#include +#include namespace nx { class HierarchicalIntegrityHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sLayer @@ -36,19 +36,15 @@ namespace nx HierarchicalIntegrityHeader(); HierarchicalIntegrityHeader(const HierarchicalIntegrityHeader& other); - HierarchicalIntegrityHeader(const byte_t* bytes, size_t len); + void operator=(const HierarchicalIntegrityHeader& other); bool operator==(const HierarchicalIntegrityHeader& other) const; bool operator!=(const HierarchicalIntegrityHeader& other) const; - void operator=(const HierarchicalIntegrityHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -62,14 +58,11 @@ namespace nx const std::string kModuleName = "HIERARCHICAL_INTEGRITY_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data fnd::List mLayerInfo; fnd::List mMasterHashList; - - bool isEqual(const HierarchicalIntegrityHeader& other) const; - void copyFrom(const HierarchicalIntegrityHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/HierarchicalSha256Header.h b/lib/libnx/include/nx/HierarchicalSha256Header.h index f5568e8..4082916 100644 --- a/lib/libnx/include/nx/HierarchicalSha256Header.h +++ b/lib/libnx/include/nx/HierarchicalSha256Header.h @@ -1,13 +1,12 @@ #pragma once #include -#include +#include #include -#include namespace nx { class HierarchicalSha256Header : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sLayer @@ -34,19 +33,15 @@ namespace nx HierarchicalSha256Header(); HierarchicalSha256Header(const HierarchicalSha256Header& other); - HierarchicalSha256Header(const byte_t* bytes, size_t len); + void operator=(const HierarchicalSha256Header& other); bool operator==(const HierarchicalSha256Header& other) const; bool operator!=(const HierarchicalSha256Header& other) const; - void operator=(const HierarchicalSha256Header& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -63,15 +58,12 @@ namespace nx const std::string kModuleName = "HIERARCHICAL_SHA256_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data crypto::sha::sSha256Hash mMasterHash; size_t mHashBlockSize; fnd::List mLayerInfo; - - bool isEqual(const HierarchicalSha256Header& other) const; - void copyFrom(const HierarchicalSha256Header& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/IKernelCapabilityHandler.h b/lib/libnx/include/nx/IKernelCapabilityHandler.h index 40e2c57..ad117c4 100644 --- a/lib/libnx/include/nx/IKernelCapabilityHandler.h +++ b/lib/libnx/include/nx/IKernelCapabilityHandler.h @@ -1,15 +1,15 @@ #pragma once #include #include -#include +#include namespace nx { class IKernelCapabilityHandler { public: - virtual void importKernelCapabilityList(const fnd::List& caps) = 0; - virtual void exportKernelCapabilityList(fnd::List& caps) const = 0; + virtual void importKernelCapabilityList(const fnd::List& caps) = 0; + virtual void exportKernelCapabilityList(fnd::List& caps) const = 0; virtual void clear() = 0; virtual bool isSet() const = 0; }; diff --git a/lib/libnx/include/nx/InteruptEntry.h b/lib/libnx/include/nx/InteruptEntry.h index 9602228..7633281 100644 --- a/lib/libnx/include/nx/InteruptEntry.h +++ b/lib/libnx/include/nx/InteruptEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -13,12 +13,16 @@ namespace nx static const uint32_t kInteruptNum = 2; InteruptEntry(); - InteruptEntry(const KernelCapability& kernel_cap); + InteruptEntry(const KernelCapabilityEntry& kernel_cap); InteruptEntry(uint32_t interupt0, uint32_t interupt1); + void operator=(const InteruptEntry& other); + bool operator==(const InteruptEntry& other) const; + bool operator!=(const InteruptEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint32_t operator[](size_t index) const; @@ -28,9 +32,9 @@ namespace nx private: const std::string kModuleName = "INTERUPT_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_INTERUPTS; + static const kc::KernelCapId kCapId = kc::KC_ENABLE_INTERUPTS; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint32_t mInterupt[kInteruptNum]; inline void updateCapField() diff --git a/lib/libnx/include/nx/InteruptHandler.h b/lib/libnx/include/nx/InteruptHandler.h index 19af059..529886f 100644 --- a/lib/libnx/include/nx/InteruptHandler.h +++ b/lib/libnx/include/nx/InteruptHandler.h @@ -10,13 +10,13 @@ namespace nx public: InteruptHandler(); + void operator=(const InteruptHandler& other); bool operator==(const InteruptHandler& other) const; bool operator!=(const InteruptHandler& other) const; - void operator=(const InteruptHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -29,9 +29,6 @@ namespace nx bool mIsSet; fnd::List mInterupts; - - void copyFrom(const InteruptHandler& other); - bool isEqual(const InteruptHandler& other) const; }; } diff --git a/lib/libnx/include/nx/KernelCapability.h b/lib/libnx/include/nx/KernelCapability.h deleted file mode 100644 index af35353..0000000 --- a/lib/libnx/include/nx/KernelCapability.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include - -namespace nx -{ - class KernelCapability - { - public: - enum KernelCapId - { - KC_INVALID = 0, - KC_THREAD_INFO = 3, - KC_ENABLE_SYSTEM_CALLS = 4, - KC_MEMORY_MAP = 6, - KC_IO_MEMORY_MAP = 7, - KC_ENABLE_INTERUPTS = 11, - KC_MISC_PARAMS = 13, - KC_KERNEL_VERSION = 14, - KC_HANDLE_TABLE_SIZE = 15, - KC_MISC_FLAGS = 16 - }; - - KernelCapability(); - KernelCapability(KernelCapId type); - KernelCapability(KernelCapId type, uint32_t field); - - const KernelCapability& operator=(const KernelCapability& other); - bool operator==(const KernelCapability& other) const; - bool operator!=(const KernelCapability& other) const; - - uint32_t getCap() const; - void setCap(uint32_t cap); - - KernelCapId getType() const; - void setType(KernelCapId type); - - uint32_t getField() const; - void setField(uint32_t field); - - private: - KernelCapId mType; - uint32_t mField; - - inline uint32_t getFieldShift() const { return mType + 1; } - inline uint32_t getFieldMask() const { return BIT(31 - mType) - 1; } - inline uint32_t getCapMask() const { return BIT(mType) - 1; } - inline KernelCapId getCapId(uint32_t cap) const - { - KernelCapId id = KC_INVALID; - for (byte_t tmp = 0; tmp < 31; tmp++) - { - if (((cap >> tmp) & 1) == 0) - { - id = (KernelCapId)tmp; - break; - } - } - return id; - } - }; -} - diff --git a/lib/libnx/include/nx/KcBinary.h b/lib/libnx/include/nx/KernelCapabilityBinary.h similarity index 70% rename from lib/libnx/include/nx/KcBinary.h rename to lib/libnx/include/nx/KernelCapabilityBinary.h index ca2ad3a..d5369a3 100644 --- a/lib/libnx/include/nx/KcBinary.h +++ b/lib/libnx/include/nx/KernelCapabilityBinary.h @@ -1,9 +1,8 @@ #pragma once #include #include -#include +#include #include -#include #include #include #include @@ -15,25 +14,21 @@ namespace nx { - class KcBinary : - public fnd::ISerialiseableBinary + class KernelCapabilityBinary : + public fnd::ISerialisable { public: - KcBinary(); - KcBinary(const KcBinary& other); - KcBinary(const byte_t* bytes, size_t len); + KernelCapabilityBinary(); + KernelCapabilityBinary(const KernelCapabilityBinary& other); - bool operator==(const KcBinary& other) const; - bool operator!=(const KcBinary& other) const; - void operator=(const KcBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; + void operator=(const KernelCapabilityBinary& other); + bool operator==(const KernelCapabilityBinary& other) const; + bool operator!=(const KernelCapabilityBinary& other) const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + virtual const fnd::Vec& getBytes() const; // variables (consider further abstraction?) void clear(); @@ -65,7 +60,7 @@ namespace nx const std::string kModuleName = "KC_BINARY"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables ThreadInfoHandler mThreadInfo; @@ -76,11 +71,6 @@ namespace nx KernelVersionHandler mKernelVersion; HandleTableSizeHandler mHandleTableSize; MiscFlagsHandler mMiscFlags; - - - void clearVariables(); - bool isEqual(const KcBinary& other) const; - void copyFrom(const KcBinary& other); }; } diff --git a/lib/libnx/include/nx/KernelCapabilityEntry.h b/lib/libnx/include/nx/KernelCapabilityEntry.h new file mode 100644 index 0000000..9be2761 --- /dev/null +++ b/lib/libnx/include/nx/KernelCapabilityEntry.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include + +namespace nx +{ + class KernelCapabilityEntry + { + public: + + KernelCapabilityEntry(); + KernelCapabilityEntry(kc::KernelCapId type); + KernelCapabilityEntry(kc::KernelCapId type, uint32_t field); + + void operator=(const KernelCapabilityEntry& other); + bool operator==(const KernelCapabilityEntry& other) const; + bool operator!=(const KernelCapabilityEntry& other) const; + + uint32_t getCap() const; + void setCap(uint32_t cap); + + kc::KernelCapId getType() const; + void setType(kc::KernelCapId type); + + uint32_t getField() const; + void setField(uint32_t field); + + private: + kc::KernelCapId mType; + uint32_t mField; + + inline uint32_t getFieldShift() const { return mType + 1; } + inline uint32_t getFieldMask() const { return BIT(31 - mType) - 1; } + inline uint32_t getCapMask() const { return BIT(mType) - 1; } + inline kc::KernelCapId getCapId(uint32_t cap) const + { + kc::KernelCapId id = kc::KC_INVALID; + for (byte_t tmp = 0; tmp < 31; tmp++) + { + if (((cap >> tmp) & 1) == 0) + { + id = (kc::KernelCapId)tmp; + break; + } + } + return id; + } + }; +} + diff --git a/lib/libnx/include/nx/KernelVersionEntry.h b/lib/libnx/include/nx/KernelVersionEntry.h index b01597e..d0b339b 100644 --- a/lib/libnx/include/nx/KernelVersionEntry.h +++ b/lib/libnx/include/nx/KernelVersionEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,12 +9,16 @@ namespace nx { public: KernelVersionEntry(); - KernelVersionEntry(const KernelCapability& kernel_cap); + KernelVersionEntry(const KernelCapabilityEntry& kernel_cap); KernelVersionEntry(uint16_t major, uint8_t minor); + void operator=(const KernelVersionEntry& other); + bool operator==(const KernelVersionEntry& other) const; + bool operator!=(const KernelVersionEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint16_t getVerMajor() const; @@ -23,13 +27,13 @@ namespace nx void setVerMinor(uint8_t minor); private: const std::string kModuleName = "KERNEL_VERSION_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_KERNEL_VERSION; + static const kc::KernelCapId kCapId = kc::KC_KERNEL_VERSION; static const uint32_t kVerMajorBits = 13; static const uint32_t kVerMajorMax = BIT(kVerMajorBits) - 1; static const uint32_t kVerMinorBits = 4; static const uint32_t kVerMinorMax = BIT(kVerMinorBits) - 1; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint16_t mVerMajor; uint8_t mVerMinor; diff --git a/lib/libnx/include/nx/KernelVersionHandler.h b/lib/libnx/include/nx/KernelVersionHandler.h index 003c060..be9cc2e 100644 --- a/lib/libnx/include/nx/KernelVersionHandler.h +++ b/lib/libnx/include/nx/KernelVersionHandler.h @@ -10,13 +10,13 @@ namespace nx public: KernelVersionHandler(); + void operator=(const KernelVersionHandler& other); bool operator==(const KernelVersionHandler& other) const; bool operator!=(const KernelVersionHandler& other) const; - void operator=(const KernelVersionHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -32,9 +32,6 @@ namespace nx bool mIsSet; KernelVersionEntry mEntry; - - void copyFrom(const KernelVersionHandler& other); - bool isEqual(const KernelVersionHandler& other) const; }; } diff --git a/lib/libnx/include/nx/MemoryMappingHandler.h b/lib/libnx/include/nx/MemoryMappingHandler.h index 49f055b..9b5e0d4 100644 --- a/lib/libnx/include/nx/MemoryMappingHandler.h +++ b/lib/libnx/include/nx/MemoryMappingHandler.h @@ -52,13 +52,13 @@ namespace nx MemoryMappingHandler(); + void operator=(const MemoryMappingHandler& other); bool operator==(const MemoryMappingHandler& other) const; bool operator!=(const MemoryMappingHandler& other) const; - void operator=(const MemoryMappingHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -73,9 +73,6 @@ namespace nx bool mIsSet; fnd::List mMemRange; fnd::List mMemPage; - - void copyFrom(const MemoryMappingHandler& other); - bool isEqual(const MemoryMappingHandler& other) const; }; } diff --git a/lib/libnx/include/nx/MemoryPageEntry.h b/lib/libnx/include/nx/MemoryPageEntry.h index 6beb9d6..9fc4536 100644 --- a/lib/libnx/include/nx/MemoryPageEntry.h +++ b/lib/libnx/include/nx/MemoryPageEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,13 +9,17 @@ namespace nx { public: MemoryPageEntry(); - MemoryPageEntry(const KernelCapability& kernel_cap); + MemoryPageEntry(const KernelCapabilityEntry& kernel_cap); MemoryPageEntry(uint32_t page); MemoryPageEntry(uint32_t page, bool flag); + void operator=(const MemoryPageEntry& other); + bool operator==(const MemoryPageEntry& other) const; + bool operator!=(const MemoryPageEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint32_t getPage() const; @@ -30,7 +34,7 @@ namespace nx static const uint32_t kPageBits = 24; static const uint32_t kMaxPage = BIT(kPageBits) - 1; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint32_t mPage; bool mFlag; bool mUseFlag; @@ -41,7 +45,7 @@ namespace nx field |= (uint32_t)(mPage & kMaxPage) << 0; field |= (uint32_t)(mFlag) << kPageBits; mCap.setField(field); - mCap.setType(mUseFlag ? KernelCapability::KC_MEMORY_MAP : KernelCapability::KC_IO_MEMORY_MAP); + mCap.setType(mUseFlag ? kc::KC_MEMORY_MAP : kc::KC_IO_MEMORY_MAP); } inline void processCapField() @@ -49,7 +53,7 @@ namespace nx uint32_t field = mCap.getField(); mPage = (field >> 0) & kMaxPage; mFlag = (field >> kPageBits); - mUseFlag = mCap.getType() == KernelCapability::KC_MEMORY_MAP; + mUseFlag = mCap.getType() == kc::KC_MEMORY_MAP; } }; diff --git a/lib/libnx/include/nx/MiscFlagsEntry.h b/lib/libnx/include/nx/MiscFlagsEntry.h index 813b7c7..34167e0 100644 --- a/lib/libnx/include/nx/MiscFlagsEntry.h +++ b/lib/libnx/include/nx/MiscFlagsEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,23 +9,27 @@ namespace nx { public: MiscFlagsEntry(); - MiscFlagsEntry(const KernelCapability& kernel_cap); + MiscFlagsEntry(const KernelCapabilityEntry& kernel_cap); MiscFlagsEntry(uint32_t flags); + void operator=(const MiscFlagsEntry& other); + bool operator==(const MiscFlagsEntry& other) const; + bool operator!=(const MiscFlagsEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint32_t getFlags() const; void setFlags(uint32_t flags); private: const std::string kModuleName = "MISC_FLAG_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_MISC_FLAGS; + static const kc::KernelCapId kCapId = kc::KC_MISC_FLAGS; static const uint32_t kValueBits = 15; static const uint32_t kMaxVal = BIT(kValueBits)-1; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint32_t mFlags; inline void updateCapField() diff --git a/lib/libnx/include/nx/MiscFlagsHandler.h b/lib/libnx/include/nx/MiscFlagsHandler.h index 124ce45..41d3bf9 100644 --- a/lib/libnx/include/nx/MiscFlagsHandler.h +++ b/lib/libnx/include/nx/MiscFlagsHandler.h @@ -30,13 +30,13 @@ namespace nx MiscFlagsHandler(); + void operator=(const MiscFlagsHandler& other); bool operator==(const MiscFlagsHandler& other) const; bool operator!=(const MiscFlagsHandler& other) const; - void operator=(const MiscFlagsHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -50,9 +50,6 @@ namespace nx bool mIsSet; fnd::List mFlags; - - void copyFrom(const MiscFlagsHandler& other); - bool isEqual(const MiscFlagsHandler& other) const; }; } diff --git a/lib/libnx/include/nx/MiscParamsEntry.h b/lib/libnx/include/nx/MiscParamsEntry.h index 9db0f17..04b5cc0 100644 --- a/lib/libnx/include/nx/MiscParamsEntry.h +++ b/lib/libnx/include/nx/MiscParamsEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,23 +9,27 @@ namespace nx { public: MiscParamsEntry(); - MiscParamsEntry(const KernelCapability& kernel_cap); + MiscParamsEntry(const KernelCapabilityEntry& kernel_cap); MiscParamsEntry(byte_t program_type); + void operator=(const MiscParamsEntry& other); + bool operator==(const MiscParamsEntry& other) const; + bool operator!=(const MiscParamsEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables byte_t getProgramType() const; void setProgramType(byte_t type); private: const std::string kModuleName = "MISC_PARAMS_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_MISC_PARAMS; + static const kc::KernelCapId kCapId = kc::KC_MISC_PARAMS; static const byte_t kValBits = 3; static const byte_t kMaxProgramType = BIT(kValBits)-1; - KernelCapability mCap; + KernelCapabilityEntry mCap; byte_t mProgramType; inline void updateCapField() diff --git a/lib/libnx/include/nx/MiscParamsHandler.h b/lib/libnx/include/nx/MiscParamsHandler.h index bf84cb6..b88b522 100644 --- a/lib/libnx/include/nx/MiscParamsHandler.h +++ b/lib/libnx/include/nx/MiscParamsHandler.h @@ -10,13 +10,13 @@ namespace nx public: MiscParamsHandler(); + void operator=(const MiscParamsHandler& other); bool operator==(const MiscParamsHandler& other) const; bool operator!=(const MiscParamsHandler& other) const; - void operator=(const MiscParamsHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -30,9 +30,6 @@ namespace nx bool mIsSet; MiscParamsEntry mEntry; - - void copyFrom(const MiscParamsHandler& other); - bool isEqual(const MiscParamsHandler& other) const; }; } diff --git a/lib/libnx/include/nx/NcaHeader.h b/lib/libnx/include/nx/NcaHeader.h index 3b417d4..6a2f1fe 100644 --- a/lib/libnx/include/nx/NcaHeader.h +++ b/lib/libnx/include/nx/NcaHeader.h @@ -1,13 +1,12 @@ #pragma once #include -#include +#include #include -#include namespace nx { class NcaHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: enum FormatVersion @@ -49,19 +48,18 @@ namespace nx NcaHeader(); NcaHeader(const NcaHeader& other); - NcaHeader(const byte_t* bytes, size_t len); + void operator=(const NcaHeader& other); bool operator==(const NcaHeader& other) const; bool operator!=(const NcaHeader& other) const; - void operator=(const NcaHeader& other); // to be used after export - const byte_t* getBytes() const; size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -95,7 +93,7 @@ namespace nx const std::string kModuleName = "NCA_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data FormatVersion mFormatVersion; @@ -113,8 +111,6 @@ namespace nx uint64_t blockNumToSize(uint32_t block_num) const; uint32_t sizeToBlockNum(uint64_t real_size) const; - bool isEqual(const NcaHeader& other) const; - void copyFrom(const NcaHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/NpdmBinary.h b/lib/libnx/include/nx/NpdmBinary.h index e6aaa35..c64f2d8 100644 --- a/lib/libnx/include/nx/NpdmBinary.h +++ b/lib/libnx/include/nx/NpdmBinary.h @@ -1,54 +1,79 @@ #pragma once #include -#include #include -#include -#include -#include +#include +#include +#include +#include namespace nx { class NpdmBinary : - public NpdmHeader + public fnd::ISerialisable { public: NpdmBinary(); NpdmBinary(const NpdmBinary& other); - NpdmBinary(const byte_t* bytes, size_t len); + void operator=(const NpdmBinary& other); bool operator==(const NpdmBinary& other) const; bool operator!=(const NpdmBinary& other) const; - void operator=(const NpdmBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); - const AciBinary& getAci() const; - void setAci(const AciBinary& aci); + npdm::InstructionType getInstructionType() const; + void setInstructionType(npdm::InstructionType type); - const AcidBinary& getAcid() const; - void setAcid(const AcidBinary& acid); + npdm::ProcAddrSpaceType getProcAddressSpaceType() const; + void setProcAddressSpaceType(npdm::ProcAddrSpaceType type); + + byte_t getMainThreadPriority() const; + void setMainThreadPriority(byte_t priority); + + byte_t getMainThreadCpuId() const; + void setMainThreadCpuId(byte_t cpu_id); + + uint32_t getVersion() const; + void setVersion(uint32_t version); + + uint32_t getMainThreadStackSize() const; + void setMainThreadStackSize(uint32_t size); + + const std::string& getName() const; + void setName(const std::string& name); + + const std::string& getProductCode() const; + void setProductCode(const std::string& product_code); + + const AccessControlInfoBinary& getAci() const; + void setAci(const AccessControlInfoBinary& aci); + + const AccessControlInfoDescBinary& getAcid() const; + void setAcid(const AccessControlInfoDescBinary& acid); private: const std::string kModuleName = "NPDM_BINARY"; // raw binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables - AciBinary mAci; - AcidBinary mAcid; - - bool isEqual(const NpdmBinary& other) const; - void copyFrom(const NpdmBinary& other); + npdm::InstructionType mInstructionType; + npdm::ProcAddrSpaceType mProcAddressSpaceType; + byte_t mMainThreadPriority; + byte_t mMainThreadCpuId; + uint32_t mVersion; + uint32_t mMainThreadStackSize; + std::string mName; + std::string mProductCode; + AccessControlInfoBinary mAci; + AccessControlInfoDescBinary mAcid; }; } diff --git a/lib/libnx/include/nx/NpdmHeader.h b/lib/libnx/include/nx/NpdmHeader.h deleted file mode 100644 index 7054bee..0000000 --- a/lib/libnx/include/nx/NpdmHeader.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nx -{ - class NpdmHeader : - public fnd::ISerialiseableBinary - { - public: - struct sSection - { - size_t offset; - size_t size; - - void operator=(const sSection& other) - { - offset = other.offset; - size = other.size; - } - - bool operator==(const sSection& other) const - { - return (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sSection& other) const - { - return !operator==(other); - } - }; - - NpdmHeader(); - NpdmHeader(const NpdmHeader& other); - NpdmHeader(const byte_t* bytes, size_t len); - - bool operator==(const NpdmHeader& other) const; - bool operator!=(const NpdmHeader& other) const; - void operator=(const NpdmHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); - - // variables - void clear(); - size_t getNpdmSize() const; - - npdm::InstructionType getInstructionType() const; - void setInstructionType(npdm::InstructionType type); - - npdm::ProcAddrSpaceType getProcAddressSpaceType() const; - void setProcAddressSpaceType(npdm::ProcAddrSpaceType type); - - byte_t getMainThreadPriority() const; - void setMainThreadPriority(byte_t priority); - - byte_t getMainThreadCpuId() const; - void setMainThreadCpuId(byte_t cpu_id); - - uint32_t getVersion() const; - void setVersion(uint32_t version); - - uint32_t getMainThreadStackSize() const; - void setMainThreadStackSize(uint32_t size); - - const std::string& getName() const; - void setName(const std::string& name); - - const std::string& getProductCode() const; - void setProductCode(const std::string& product_code); - - const sSection& getAciPos() const; - void setAciSize(size_t size); - - const sSection& getAcidPos() const; - void setAcidSize(size_t size); - private: - const std::string kModuleName = "NPDM_HEADER"; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - npdm::InstructionType mInstructionType; - npdm::ProcAddrSpaceType mProcAddressSpaceType; - byte_t mMainThreadPriority; - byte_t mMainThreadCpuId; - uint32_t mVersion; - uint32_t mMainThreadStackSize; - std::string mName; - std::string mProductCode; - sSection mAciPos; - sSection mAcidPos; - - void calculateOffsets(); - bool isEqual(const NpdmHeader& other) const; - void copyFrom(const NpdmHeader& other); - }; -} - diff --git a/lib/libnx/include/nx/NroHeader.h b/lib/libnx/include/nx/NroHeader.h index f259e5d..cb1dc95 100644 --- a/lib/libnx/include/nx/NroHeader.h +++ b/lib/libnx/include/nx/NroHeader.h @@ -1,13 +1,12 @@ #pragma once #include -#include +#include #include -#include namespace nx { class NroHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sRoCrt @@ -75,19 +74,15 @@ namespace nx NroHeader(); NroHeader(const NroHeader& other); - NroHeader(const byte_t* bytes, size_t len); + void operator=(const NroHeader& other); bool operator==(const NroHeader& other) const; bool operator!=(const NroHeader& other) const; - void operator=(const NroHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -125,7 +120,7 @@ namespace nx const std::string kModuleName = "NRO_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data sRoCrt mRoCrt; @@ -138,10 +133,6 @@ namespace nx sSection mRoEmbeddedInfo; sSection mRoDynStrInfo; sSection mRoDynSymInfo; - - // helpers - bool isEqual(const NroHeader& other) const; - void copyFrom(const NroHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/NsoHeader.h b/lib/libnx/include/nx/NsoHeader.h index 37cca28..cd65fde 100644 --- a/lib/libnx/include/nx/NsoHeader.h +++ b/lib/libnx/include/nx/NsoHeader.h @@ -1,13 +1,12 @@ #pragma once #include -#include +#include #include -#include namespace nx { class NsoHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: struct sModuleId @@ -87,19 +86,15 @@ namespace nx NsoHeader(); NsoHeader(const NsoHeader& other); - NsoHeader(const byte_t* bytes, size_t len); + void operator=(const NsoHeader& other); bool operator==(const NsoHeader& other) const; bool operator!=(const NsoHeader& other) const; - void operator=(const NsoHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -134,7 +129,7 @@ namespace nx const std::string kModuleName = "NSO_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data sModuleId mModuleId; @@ -146,10 +141,6 @@ namespace nx sLayout mRoEmbeddedInfo; sLayout mRoDynStrInfo; sLayout mRoDynSymInfo; - - // helpers - bool isEqual(const NsoHeader& other) const; - void copyFrom(const NsoHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/PfsHeader.h b/lib/libnx/include/nx/PfsHeader.h index c3a76a1..2c5ed37 100644 --- a/lib/libnx/include/nx/PfsHeader.h +++ b/lib/libnx/include/nx/PfsHeader.h @@ -1,16 +1,15 @@ #pragma once #include #include -#include +#include #include -#include #include namespace nx { class PfsHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: enum FsType @@ -64,24 +63,22 @@ namespace nx PfsHeader(); PfsHeader(const PfsHeader& other); - PfsHeader(const byte_t* bytes, size_t len); + void operator=(const PfsHeader& other); bool operator==(const PfsHeader& other) const; bool operator!=(const PfsHeader& other) const; - void operator=(const PfsHeader& other); // to be used after export - const byte_t* getBytes() const; size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); - FsType getFsType() const; void setFsType(FsType type); const fnd::List& getFileList() const; @@ -92,7 +89,7 @@ namespace nx const std::string kModuleName = "PFS_HEADER"; // binary blob - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // variables FsType mFsType; @@ -100,8 +97,6 @@ namespace nx size_t getFileEntrySize(FsType fs_type); void calculateOffsets(size_t data_offset); - bool isEqual(const PfsHeader& other) const; - void copyFrom(const PfsHeader& other); }; } diff --git a/lib/libnx/include/nx/SacBinary.h b/lib/libnx/include/nx/SacBinary.h deleted file mode 100644 index 8e8fcd8..0000000 --- a/lib/libnx/include/nx/SacBinary.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace nx -{ - class SacBinary : - public fnd::ISerialiseableBinary - { - public: - SacBinary(); - SacBinary(const SacBinary& other); - SacBinary(const byte_t* bytes, size_t len); - - bool operator==(const SacBinary& other) const; - bool operator!=(const SacBinary& other) const; - void operator=(const SacBinary& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); - - // variables - void clear(); - const fnd::List& getServiceList() const; - void addService(const SacEntry& service); - private: - const std::string kModuleName = "SAC_BINARY"; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - fnd::List mServices; - - bool isEqual(const SacBinary& other) const; - void copyFrom(const SacBinary& other); - }; - -} diff --git a/lib/libnx/include/nx/SacEntry.h b/lib/libnx/include/nx/SacEntry.h deleted file mode 100644 index c6d4117..0000000 --- a/lib/libnx/include/nx/SacEntry.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace nx -{ - class SacEntry : - public fnd::ISerialiseableBinary - { - public: - SacEntry(); - SacEntry(const std::string& name, bool isServer); - SacEntry(const SacEntry& other); - - bool operator==(const SacEntry& other) const; - bool operator!=(const SacEntry& other) const; - void operator=(const SacEntry& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; - - // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); - - // variables - void clear(); - bool isServer() const; - void setIsServer(bool isServer); - const std::string& getName() const; - void setName(const std::string& name); - private: - const std::string kModuleName = "SAC_ENTRY"; - static const size_t kMaxServiceNameLen = 8; - - enum SacEntryFlag - { - SAC_IS_SERVER = BIT(7), - SAC_NAME_LEN_MASK = BIT(7) - 1 - }; - - // raw binary - fnd::MemoryBlob mBinaryBlob; - - // variables - bool mIsServer; - std::string mName; - - bool isEqual(const SacEntry& other) const; - void copyFrom(const SacEntry& other); - }; -} \ No newline at end of file diff --git a/lib/libnx/include/nx/ServiceAccessControlBinary.h b/lib/libnx/include/nx/ServiceAccessControlBinary.h new file mode 100644 index 0000000..3066e5f --- /dev/null +++ b/lib/libnx/include/nx/ServiceAccessControlBinary.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace nx +{ + class ServiceAccessControlBinary : + public fnd::ISerialisable + { + public: + ServiceAccessControlBinary(); + ServiceAccessControlBinary(const ServiceAccessControlBinary& other); + + void operator=(const ServiceAccessControlBinary& other); + bool operator==(const ServiceAccessControlBinary& other) const; + bool operator!=(const ServiceAccessControlBinary& other) const; + + // export/import binary + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + const fnd::List& getServiceList() const; + void addService(const ServiceAccessControlEntry& service); + private: + const std::string kModuleName = "SERVICE_ACCESS_CONTROL_BINARY"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + fnd::List mServices; + }; + +} diff --git a/lib/libnx/include/nx/ServiceAccessControlEntry.h b/lib/libnx/include/nx/ServiceAccessControlEntry.h new file mode 100644 index 0000000..71a6587 --- /dev/null +++ b/lib/libnx/include/nx/ServiceAccessControlEntry.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include +#include + +namespace nx +{ + class ServiceAccessControlEntry : + public fnd::ISerialisable + { + public: + ServiceAccessControlEntry(); + ServiceAccessControlEntry(const std::string& name, bool isServer); + ServiceAccessControlEntry(const ServiceAccessControlEntry& other); + + void operator=(const ServiceAccessControlEntry& other); + bool operator==(const ServiceAccessControlEntry& other) const; + bool operator!=(const ServiceAccessControlEntry& other) const; + + // export/import binary + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + bool isServer() const; + void setIsServer(bool isServer); + const std::string& getName() const; + void setName(const std::string& name); + private: + const std::string kModuleName = "SERVICE_ACCESS_CONTROL_ENTRY"; + static const size_t kMaxServiceNameLen = 8; + + enum ServiceAccessControlEntryFlag + { + SAC_IS_SERVER = _BIT(7), + SAC_NAME_LEN_MASK = _BIT(7) - 1 + }; + + // raw binary + fnd::Vec mRawBinary; + + // variables + bool mIsServer; + std::string mName; + + bool isEqual(const ServiceAccessControlEntry& other) const; + void copyFrom(const ServiceAccessControlEntry& other); + }; +} \ No newline at end of file diff --git a/lib/libnx/include/nx/SystemCallEntry.h b/lib/libnx/include/nx/SystemCallEntry.h index 52863c1..1a1ca64 100644 --- a/lib/libnx/include/nx/SystemCallEntry.h +++ b/lib/libnx/include/nx/SystemCallEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,12 +9,16 @@ namespace nx { public: SystemCallEntry(); - SystemCallEntry(const KernelCapability& kernel_cap); + SystemCallEntry(const KernelCapabilityEntry& kernel_cap); SystemCallEntry(uint32_t upper_bits, uint32_t lower_bits); + void operator=(const SystemCallEntry& other); + bool operator==(const SystemCallEntry& other) const; + bool operator!=(const SystemCallEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint32_t getSystemCallUpperBits() const; @@ -24,13 +28,13 @@ namespace nx private: const std::string kModuleName = "SYSTEM_CALL_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_ENABLE_SYSTEM_CALLS; + static const kc::KernelCapId kCapId = kc::KC_ENABLE_SYSTEM_CALLS; static const uint32_t kSysCallUpperBits = 3; static const uint32_t kSysCallLowerBits = 24; static const uint32_t kSysCallUpperMax = BIT(kSysCallUpperBits) - 1; static const uint32_t kSysCallLowerMax = BIT(kSysCallLowerBits) - 1; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint32_t mSystemCallUpper; uint32_t mSystemCallLower; diff --git a/lib/libnx/include/nx/SystemCallHandler.h b/lib/libnx/include/nx/SystemCallHandler.h index ead489d..35ac45a 100644 --- a/lib/libnx/include/nx/SystemCallHandler.h +++ b/lib/libnx/include/nx/SystemCallHandler.h @@ -11,13 +11,13 @@ namespace nx SystemCallHandler(); + void operator=(const SystemCallHandler& other); bool operator==(const SystemCallHandler& other) const; bool operator!=(const SystemCallHandler& other) const; - void operator=(const SystemCallHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -31,9 +31,6 @@ namespace nx bool mIsSet; fnd::List mSystemCalls; - - void copyFrom(const SystemCallHandler& other); - bool isEqual(const SystemCallHandler& other) const; }; } diff --git a/lib/libnx/include/nx/ThreadInfoEntry.h b/lib/libnx/include/nx/ThreadInfoEntry.h index 879e59f..ff0e062 100644 --- a/lib/libnx/include/nx/ThreadInfoEntry.h +++ b/lib/libnx/include/nx/ThreadInfoEntry.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace nx { @@ -9,12 +9,16 @@ namespace nx { public: ThreadInfoEntry(); - ThreadInfoEntry(const KernelCapability& kernel_cap); + ThreadInfoEntry(const KernelCapabilityEntry& kernel_cap); ThreadInfoEntry(uint8_t min_priority, uint8_t max_priority, uint8_t min_cpu_id, uint8_t max_cpu_id); + void operator=(const ThreadInfoEntry& other); + bool operator==(const ThreadInfoEntry& other) const; + bool operator!=(const ThreadInfoEntry& other) const; + // kernel capability - const KernelCapability& getKernelCapability() const; - void setKernelCapability(const KernelCapability& kernel_cap); + const KernelCapabilityEntry& getKernelCapability() const; + void setKernelCapability(const KernelCapabilityEntry& kernel_cap); // variables uint8_t getMinPriority() const; @@ -28,13 +32,13 @@ namespace nx private: const std::string kModuleName = "THREAD_INFO_ENTRY"; - static const KernelCapability::KernelCapId kCapId = KernelCapability::KC_THREAD_INFO; + static const kc::KernelCapId kCapId = kc::KC_THREAD_INFO; static const uint8_t kValBits = 6; static const uint8_t kMaxVal = BIT(kValBits)-1; static const uint8_t kDefaultPriority = 6; static const uint8_t kDefaultCpuId = 8; - KernelCapability mCap; + KernelCapabilityEntry mCap; uint8_t mMinPriority; uint8_t mMaxPriority; uint8_t mMinCpuId; diff --git a/lib/libnx/include/nx/ThreadInfoHandler.h b/lib/libnx/include/nx/ThreadInfoHandler.h index d2bd516..d2fd01c 100644 --- a/lib/libnx/include/nx/ThreadInfoHandler.h +++ b/lib/libnx/include/nx/ThreadInfoHandler.h @@ -10,13 +10,13 @@ namespace nx public: ThreadInfoHandler(); + void operator=(const ThreadInfoHandler& other); bool operator==(const ThreadInfoHandler& other) const; bool operator!=(const ThreadInfoHandler& other) const; - void operator=(const ThreadInfoHandler& other); // kernel capabilty list in/out - void importKernelCapabilityList(const fnd::List& caps); - void exportKernelCapabilityList(fnd::List& caps) const; + void importKernelCapabilityList(const fnd::List& caps); + void exportKernelCapabilityList(fnd::List& caps) const; void clear(); bool isSet() const; @@ -36,9 +36,6 @@ namespace nx bool mIsSet; ThreadInfoEntry mEntry; - - void copyFrom(const ThreadInfoHandler& other); - bool isEqual(const ThreadInfoHandler& other) const; }; } diff --git a/lib/libnx/include/nx/XciHeader.h b/lib/libnx/include/nx/XciHeader.h index f469f12..bbbf2cd 100644 --- a/lib/libnx/include/nx/XciHeader.h +++ b/lib/libnx/include/nx/XciHeader.h @@ -1,30 +1,25 @@ #pragma once #include -#include +#include #include -#include namespace nx { class XciHeader : - public fnd::ISerialiseableBinary + public fnd::ISerialisable { public: XciHeader(); XciHeader(const XciHeader& other); - XciHeader(const byte_t* bytes, size_t len); + void operator=(const XciHeader& other); bool operator==(const XciHeader& other) const; bool operator!=(const XciHeader& other) const; - void operator=(const XciHeader& other); - - // to be used after export - const byte_t* getBytes() const; - size_t getSize() const; // export/import binary - void exportBinary(); - void importBinary(const byte_t* bytes, size_t len); + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; // variables void clear(); @@ -92,7 +87,7 @@ namespace nx const std::string kModuleName = "XCI_HEADER"; // binary - fnd::MemoryBlob mBinaryBlob; + fnd::Vec mRawBinary; // data uint32_t mRomAreaStartPage; @@ -125,10 +120,6 @@ namespace nx uint32_t mUppVersion; byte_t mUppHash[8]; uint64_t mUppId; - - // helpers - bool isEqual(const XciHeader& other) const; - void copyFrom(const XciHeader& other); }; } \ No newline at end of file diff --git a/lib/libnx/include/nx/aci.h b/lib/libnx/include/nx/aci.h index a5bf705..b2755e5 100644 --- a/lib/libnx/include/nx/aci.h +++ b/lib/libnx/include/nx/aci.h @@ -1,46 +1,53 @@ #pragma once -#include #include -#include -#include -#include +#include #include namespace nx { namespace aci { - static const uint32_t kAciStructSig = _MAKE_STRUCT_SIGNATURE("ACI0"); - static const uint32_t kAciDescStructSig = _MAKE_STRUCT_SIGNATURE("ACID"); - static const size_t kAciAlignSize = 0x10; + static const uint32_t kAciStructMagic = _MAKE_STRUCT_MAGIC_U32("ACI0"); + static const uint32_t kAciDescStructMagic = _MAKE_STRUCT_MAGIC_U32("ACID"); + static const size_t kSectionAlignSize = 0x10; - enum Flags + enum Flag { FLAG_PRODUCTION, FLAG_UNQUALIFIED_APPROVAL }; } #pragma pack(push,1) + struct sAciSection + { + le_uint32_t offset; + le_uint32_t size; + }; + struct sAciHeader { - le_uint32_t signature; - le_uint32_t size; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning) - byte_t reserved_0[4]; - le_uint32_t flags; // set in ACID only - union uProgramIdInfo - { - struct sRestrictProgramId - { - le_uint64_t min; - le_uint64_t max; - } program_id_restrict; - le_uint64_t program_id; - } program_id_info; - struct sAciSection - { - le_uint32_t offset; // aligned by 0x10 from the last one - le_uint32_t size; - } fac, sac, kc; + le_uint32_t st_magic; + byte_t reserved_00[0xC]; + le_uint64_t program_id; + byte_t reserved_01[0x8]; + sAciSection fac; + sAciSection sac; + sAciSection kc; + }; + + struct sAciDescHeader + { + byte_t signature[crypto::rsa::kRsa2048Size]; + byte_t nca_rsa_signature2_modulus[crypto::rsa::kRsa2048Size]; + le_uint32_t st_magic; + le_uint32_t signed_size; + byte_t reserved_00[0x4]; + le_uint32_t flags; + le_uint64_t program_id_min; + le_uint64_t program_id_max; + sAciSection fac; + sAciSection sac; + sAciSection kc; }; #pragma pack(pop) } \ No newline at end of file diff --git a/lib/libnx/include/nx/cnmt.h b/lib/libnx/include/nx/cnmt.h index 8912a89..10d972c 100644 --- a/lib/libnx/include/nx/cnmt.h +++ b/lib/libnx/include/nx/cnmt.h @@ -1,9 +1,6 @@ #pragma once -#include #include -#include #include -#include namespace nx { diff --git a/lib/libnx/include/nx/fac.h b/lib/libnx/include/nx/fac.h new file mode 100644 index 0000000..886c930 --- /dev/null +++ b/lib/libnx/include/nx/fac.h @@ -0,0 +1,50 @@ +#pragma once +#include + +namespace nx +{ + namespace fac + { + static const uint32_t kFacFormatVersion = 1; + static const size_t kSectionAlignSize = 4; + + enum FsAccessFlag + { + FSA_APPLICATION_INFO, + FSA_BOOT_MODE_CONTROL, + FSA_CALIBRATION, + FSA_SYSTEM_SAVE_DATA, + FSA_GAME_CARD, + FSA_SAVE_DATA_BACKUP, + FSA_SAVE_DATA_MANAGEMENT, + FSA_BIS_ALL_RAW, + FSA_GAME_CARD_RAW, + FSA_GAME_CARD_PRIVATE, + FSA_SET_TIME, + FSA_CONTENT_MANAGER, + FSA_IMAGE_MANAGER, + FSA_CREATE_SAVE_DATA, + FSA_SYSTEM_SAVE_DATA_MANAGEMENT, + FSA_BIS_FILE_SYSTEM, + FSA_SYSTEM_UPDATE, + FSA_SAVE_DATA_META, + FSA_DEVICE_SAVE_CONTROL, + FSA_SETTINGS_CONTROL, + FSA_DEBUG = 62, + FSA_FULL_PERMISSION = 63, + }; + } + +#pragma pack(push,1) + struct sFacHeader + { + le_uint32_t version; // default 1 + le_uint64_t fac_flags; + struct sFacSection + { + le_uint32_t start; + le_uint32_t end; + } content_owner_ids, save_data_owner_ids; // the data for these follow later in binary. start/end relative to base of FacData instance + }; +#pragma pack(pop) +} \ No newline at end of file diff --git a/lib/libnx/include/nx/hierarchicalintegrity.h b/lib/libnx/include/nx/hierarchicalintegrity.h index 3e23eb3..4c16d0d 100644 --- a/lib/libnx/include/nx/hierarchicalintegrity.h +++ b/lib/libnx/include/nx/hierarchicalintegrity.h @@ -1,16 +1,12 @@ #pragma once -#include #include -#include -#include #include namespace nx { - // Also known to the public as IVFC namespace hierarchicalintegrity { - static const uint32_t kStructSig = _MAKE_STRUCT_SIGNATURE("IVFC"); + static const uint32_t kStructMagic = _MAKE_STRUCT_MAGIC_U32("IVFC"); static const uint32_t kRomfsTypeId = 0x20000; static const size_t kDefaultLayerNum = 6; static const size_t kHeaderAlignLen = 0x20; @@ -19,7 +15,7 @@ namespace nx #pragma pack(push,1) struct sHierarchicalIntegrityHeader { - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t type_id; le_uint32_t master_hash_size; le_uint32_t layer_num; diff --git a/lib/libnx/include/nx/hierarchicalsha256.h b/lib/libnx/include/nx/hierarchicalsha256.h index a620826..5b78c66 100644 --- a/lib/libnx/include/nx/hierarchicalsha256.h +++ b/lib/libnx/include/nx/hierarchicalsha256.h @@ -1,8 +1,6 @@ #pragma once -#include #include #include -#include namespace nx { diff --git a/lib/libnx/include/nx/kc.h b/lib/libnx/include/nx/kc.h new file mode 100644 index 0000000..192c6de --- /dev/null +++ b/lib/libnx/include/nx/kc.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include + +namespace nx +{ + namespace kc + { + enum KernelCapId + { + KC_INVALID = 0, + KC_THREAD_INFO = 3, + KC_ENABLE_SYSTEM_CALLS = 4, + KC_MEMORY_MAP = 6, + KC_IO_MEMORY_MAP = 7, + KC_ENABLE_INTERUPTS = 11, + KC_MISC_PARAMS = 13, + KC_KERNEL_VERSION = 14, + KC_HANDLE_TABLE_SIZE = 15, + KC_MISC_FLAGS = 16 + }; + } +} \ No newline at end of file diff --git a/lib/libnx/include/nx/macro.h b/lib/libnx/include/nx/macro.h index 4ef53e8..6e1431f 100644 --- a/lib/libnx/include/nx/macro.h +++ b/lib/libnx/include/nx/macro.h @@ -1,5 +1,5 @@ #pragma once #include -#define _MAKE_STRUCT_SIGNATURE(x) ((uint32_t)(x[3]) << 24 | (uint32_t)(x[2]) << 16 | (uint32_t)(x[1]) << 8 | (uint32_t)(x[0])) -#define _MAKE_STRUCT_SIGNATURE_U64(x) ((uint64_t)(x[7]) << 56 | (uint64_t)(x[6]) << 48 | (uint64_t)(x[5]) << 40 | (uint64_t)(x[4]) << 32 | (uint64_t)(x[3]) << 24 | (uint64_t)(x[2]) << 16 | (uint64_t)(x[1]) << 8 | (uint64_t)(x[0])) +#define _MAKE_STRUCT_MAGIC_U32(x) ((uint32_t)(x[3]) << 24 | (uint32_t)(x[2]) << 16 | (uint32_t)(x[1]) << 8 | (uint32_t)(x[0])) +#define _MAKE_STRUCT_MAGIC_U64(x) ((uint64_t)(x[7]) << 56 | (uint64_t)(x[6]) << 48 | (uint64_t)(x[5]) << 40 | (uint64_t)(x[4]) << 32 | (uint64_t)(x[3]) << 24 | (uint64_t)(x[2]) << 16 | (uint64_t)(x[1]) << 8 | (uint64_t)(x[0])) diff --git a/lib/libnx/include/nx/nacp.h b/lib/libnx/include/nx/nacp.h index 7eddd79..c319395 100644 --- a/lib/libnx/include/nx/nacp.h +++ b/lib/libnx/include/nx/nacp.h @@ -1,12 +1,22 @@ #pragma once -#include #include -#include namespace nx { namespace nacp { + static const size_t kNameLength = 0x200; + static const size_t kPublisherLength = 0x100; + static const size_t kMaxLanguageCount = 16; + static const size_t kIsbnLength = 37; + static const size_t kRatingAgeCount = 32; + static const size_t kDisplayVersionLength = 16; + static const size_t kApplicationErrorCodeCategoryLength = 8; + static const size_t kLocalCommunicationIdCount = 8; + static const size_t kBcatPassphraseLength = 65; + static const size_t kPlayLogQueryableApplicationIdCount = 16; + static const int8_t kUnusedAgeRating = -1; + enum AocRegistrationType { AOC_AllOnLaunch, @@ -144,18 +154,6 @@ namespace nx VCAP_Manual, VCAP_Enable }; - - static const size_t kNameLength = 0x200; - static const size_t kPublisherLength = 0x100; - static const size_t kMaxLanguageCount = 16; - static const size_t kIsbnLength = 37; - static const size_t kRatingAgeCount = 32; - static const size_t kDisplayVersionLength = 16; - static const size_t kApplicationErrorCodeCategoryLength = 8; - static const size_t kLocalCommunicationIdCount = 8; - static const size_t kBcatPassphraseLength = 65; - static const size_t kPlayLogQueryableApplicationIdCount = 16; - static const int8_t kUnusedAgeRating = -1; } diff --git a/lib/libnx/include/nx/nca.h b/lib/libnx/include/nx/nca.h index e9764dc..e49e4a4 100644 --- a/lib/libnx/include/nx/nca.h +++ b/lib/libnx/include/nx/nca.h @@ -1,18 +1,16 @@ #pragma once -#include #include #include #include #include -#include #include namespace nx { namespace nca { - static const uint32_t kNca2Sig = _MAKE_STRUCT_SIGNATURE("NCA2"); - static const uint32_t kNca3Sig = _MAKE_STRUCT_SIGNATURE("NCA3"); + static const uint32_t kNca2StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA2"); + static const uint32_t kNca3StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA3"); static const size_t kSectorSize = 0x200; static const size_t kPartitionNum = 4; static const size_t kHeaderSectorNum = 6; @@ -89,7 +87,7 @@ namespace nx #pragma pack(push,1) struct sNcaHeader { - le_uint32_t signature; + le_uint32_t st_magic; byte_t distribution_type; byte_t content_type; byte_t key_generation; diff --git a/lib/libnx/include/nx/npdm.h b/lib/libnx/include/nx/npdm.h index 2551929..b508ba8 100644 --- a/lib/libnx/include/nx/npdm.h +++ b/lib/libnx/include/nx/npdm.h @@ -1,20 +1,16 @@ #pragma once -#include #include -#include -#include -#include #include namespace nx { namespace npdm { - static const uint32_t kNpdmStructSig = _MAKE_STRUCT_SIGNATURE("META"); + static const uint32_t kNpdmStructMagic = _MAKE_STRUCT_MAGIC_U32("META"); static const size_t kNameMaxLen = 0x10; static const size_t kProductCodeMaxLen = 0x10; - static const uint32_t kMaxPriority = BIT(6) -1 ; - static const size_t kNpdmAlignSize = 0x10; + static const uint32_t kMaxPriority = BIT(6) - 1; + static const size_t kSectionAlignSize = 0x10; static const uint32_t kDefaultMainThreadStackSize = 4096; enum InstructionType @@ -34,7 +30,7 @@ namespace nx struct sNpdmHeader { - le_uint32_t signature; + le_uint32_t st_magic; byte_t reserved_0[8]; byte_t flags; byte_t reserved_1; diff --git a/lib/libnx/include/nx/nro.h b/lib/libnx/include/nx/nro.h index ff378c8..c145e64 100644 --- a/lib/libnx/include/nx/nro.h +++ b/lib/libnx/include/nx/nro.h @@ -1,15 +1,12 @@ #pragma once #include -#include #include namespace nx { namespace nro { - static const uint32_t kNroSig = _MAKE_STRUCT_SIGNATURE("NRO0"); - - + static const uint32_t kNroStructMagic = _MAKE_STRUCT_MAGIC_U32("NRO0"); static const uint32_t kDefaultFormatVersion = 0; static const size_t kRoCrtSize = 8; static const size_t kModuleIdSize = 32; @@ -26,7 +23,7 @@ namespace nx { byte_t ro_crt[nro::kRoCrtSize]; byte_t reserved_0[8]; - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t format_version; le_uint32_t size; le_uint32_t flags; diff --git a/lib/libnx/include/nx/nrr.h b/lib/libnx/include/nx/nrr.h index a11498e..3931ad1 100644 --- a/lib/libnx/include/nx/nrr.h +++ b/lib/libnx/include/nx/nrr.h @@ -7,7 +7,7 @@ namespace nx { namespace nrr { - static const uint32_t kNrrSig = _MAKE_STRUCT_SIGNATURE("NRR0"); + static const uint32_t kNrrStructMagic = _MAKE_STRUCT_MAGIC_U32("NRR0"); } #pragma pack(push,1) @@ -21,7 +21,7 @@ namespace nx struct sNrrHeader { - le_uint32_t signature; + le_uint32_t st_magic; byte_t reserved_0[28]; sNrrCertificate certificate; byte_t nrr_body_signature[crypto::rsa::kRsa2048Size]; diff --git a/lib/libnx/include/nx/nso.h b/lib/libnx/include/nx/nso.h index 8af09e1..d40c925 100644 --- a/lib/libnx/include/nx/nso.h +++ b/lib/libnx/include/nx/nso.h @@ -7,7 +7,9 @@ namespace nx { namespace nso { - static const uint32_t kNsoSig = _MAKE_STRUCT_SIGNATURE("NSO0"); + static const uint32_t kNsoStructMagic = _MAKE_STRUCT_MAGIC_U32("NSO0"); + static const uint32_t kDefaultFormatVersion = 0; + static const size_t kModuleIdSize = 32; enum HeaderFlags { @@ -18,9 +20,6 @@ namespace nx FLAG_RO_HASH, FLAG_DATA_HASH }; - - static const uint32_t kDefaultFormatVersion = 0; - static const size_t kModuleIdSize = 32; } #pragma pack(push,1) @@ -39,7 +38,7 @@ namespace nx struct sNsoHeader { - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t format_version; byte_t reserved_1[4]; le_uint32_t flags; diff --git a/lib/libnx/include/nx/pfs.h b/lib/libnx/include/nx/pfs.h index f00d7f9..9b1fde1 100644 --- a/lib/libnx/include/nx/pfs.h +++ b/lib/libnx/include/nx/pfs.h @@ -1,22 +1,20 @@ -#include #include #include -#include #include namespace nx { namespace pfs { - static const uint32_t kPfsSig = _MAKE_STRUCT_SIGNATURE("PFS0"); - static const uint32_t kHashedPfsSig = _MAKE_STRUCT_SIGNATURE("HFS0"); + static const uint32_t kPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("PFS0"); + static const uint32_t kHashedPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("HFS0"); static const size_t kHeaderAlign = 64; } #pragma pack(push,1) struct sPfsHeader { - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t file_num; le_uint32_t name_table_size; byte_t padding[4]; diff --git a/lib/libnx/include/nx/romfs.h b/lib/libnx/include/nx/romfs.h index 62fe0ec..1756425 100644 --- a/lib/libnx/include/nx/romfs.h +++ b/lib/libnx/include/nx/romfs.h @@ -1,14 +1,13 @@ #pragma once -#include #include -#include -#include -#include namespace nx { namespace romfs { + static const uint64_t kRomfsHeaderAlign = 0x200; + static const uint32_t kInvalidAddr = 0xffffffff; + enum HeaderSectionIndex { DIR_HASHMAP_TABLE, @@ -17,9 +16,6 @@ namespace nx FILE_NODE_TABLE, SECTION_NUM }; - - static const uint64_t kRomfsHeaderAlign = 0x200; - static const uint32_t kInvalidAddr = 0xffffffff; } #pragma pack(push,1) diff --git a/lib/libnx/include/nx/xci.h b/lib/libnx/include/nx/xci.h index 5a0a875..b7b0797 100644 --- a/lib/libnx/include/nx/xci.h +++ b/lib/libnx/include/nx/xci.h @@ -1,28 +1,28 @@ #pragma once -#include #include #include #include #include #include -#include #include namespace nx { namespace xci { - static const uint32_t kXciSig = _MAKE_STRUCT_SIGNATURE("HEAD"); + static const uint32_t kXciStructMagic = _MAKE_STRUCT_MAGIC_U32("HEAD"); static const uint32_t kHeaderEncOffset = 0x90; static const uint32_t kHeaderEncSize = 0x70; static const uint32_t kPageSize = 0x200; static const uint32_t kUppHashLen = 8; + /* static const uint32_t kCardKeyAreaPageCount = 8; static const uint32_t kCardHeaderPageCount = 1; static const uint32_t kReservedAreaPageCount = 55; static const uint32_t kCertAreaStartPageAddress = kCardHeaderPageCount + kReservedAreaPageCount + kCardKeyAreaPageCount; static const uint32_t kCertAreaPageCount = 64; static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount; + */ const std::string kUpdatePartitionStr = "update"; const std::string kLogoPartitionStr = "logo"; @@ -68,7 +68,7 @@ namespace nx #pragma pack(push,1) struct sXciHeader { - le_uint32_t signature; + le_uint32_t st_magic; le_uint32_t rom_area_start_page; le_uint32_t backup_area_start_page; byte_t key_flag; diff --git a/lib/libnx/nx.vcxproj b/lib/libnx/nx.vcxproj index c8becaa..9d72230 100644 --- a/lib/libnx/nx.vcxproj +++ b/lib/libnx/nx.vcxproj @@ -19,29 +19,32 @@ + + + + + - - - - - + + + - - - + + + @@ -53,22 +56,20 @@ + - - - - - + + @@ -78,26 +79,21 @@ - - - - - - + + - - + - - + + @@ -109,12 +105,11 @@ - - - + + diff --git a/lib/libnx/nx.vcxproj.filters b/lib/libnx/nx.vcxproj.filters index 065a177..5147ede 100644 --- a/lib/libnx/nx.vcxproj.filters +++ b/lib/libnx/nx.vcxproj.filters @@ -15,19 +15,40 @@ - + + + + Header Files - + Header Files - + Header Files - + Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files @@ -36,6 +57,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + Header Files @@ -45,10 +78,13 @@ Header Files - + Header Files - + + Header Files + + Header Files @@ -57,6 +93,9 @@ Header Files + + Header Files + Header Files @@ -75,25 +114,52 @@ Header Files - + Header Files - + Header Files Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files Header Files - + Header Files - + + Header Files + + Header Files @@ -108,108 +174,36 @@ Header Files - - Header Files - - - Header Files - Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - Header Files Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - + Source Files - - Source Files - - + Source Files Source Files + + Source Files + + + Source Files + Source Files - - Source Files - - + Source Files @@ -230,10 +224,10 @@ Source Files - + Source Files - + Source Files @@ -269,9 +263,6 @@ Source Files - - Source Files - Source Files @@ -281,10 +272,10 @@ Source Files - + Source Files - + Source Files @@ -305,11 +296,5 @@ Source Files - - Source Files - - - Source Files - \ No newline at end of file diff --git a/lib/libnx/source/AccessControlInfoBinary.cpp b/lib/libnx/source/AccessControlInfoBinary.cpp new file mode 100644 index 0000000..0abad1a --- /dev/null +++ b/lib/libnx/source/AccessControlInfoBinary.cpp @@ -0,0 +1,172 @@ +#include + +nx::AccessControlInfoBinary::AccessControlInfoBinary() +{ + clear(); +} + +nx::AccessControlInfoBinary::AccessControlInfoBinary(const AccessControlInfoBinary & other) +{ + *this = other; +} + +void nx::AccessControlInfoBinary::operator=(const AccessControlInfoBinary & other) +{ + mRawBinary = other.mRawBinary; + mProgramId = other.mProgramId; + mFileSystemAccessControl = other.mFileSystemAccessControl; + mServiceAccessControl = other.mServiceAccessControl; + mKernelCapabilities = other.mKernelCapabilities; +} + +bool nx::AccessControlInfoBinary::operator==(const AccessControlInfoBinary & other) const +{ + return (mProgramId == other.mProgramId) \ + && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ + && (mServiceAccessControl == other.mServiceAccessControl) \ + && (mKernelCapabilities == other.mKernelCapabilities); +} + +bool nx::AccessControlInfoBinary::operator!=(const AccessControlInfoBinary & other) const +{ + return !(*this == other); +} + +void nx::AccessControlInfoBinary::toBytes() +{ + if (mFileSystemAccessControl.getBytes().size() == 0) + mFileSystemAccessControl.toBytes(); + + if (mServiceAccessControl.getBytes().size() == 0) + mServiceAccessControl.toBytes(); + + if (mKernelCapabilities.getBytes().size() == 0) + mKernelCapabilities.toBytes(); + + // determine section layout + struct sLayout { + uint32_t offset, size; + } fac, sac, kc; + + fac.offset = align(sizeof(sAciHeader), aci::kSectionAlignSize); + fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); + sac.offset = align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); + kc.offset = align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); + + // get total size + size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); + + mRawBinary.alloc(total_size); + sAciHeader* hdr = (sAciHeader*)mRawBinary.data(); + + // set type + hdr->st_magic = aci::kAciStructMagic; + + // set program id + hdr->program_id = mProgramId; + + // set offset/size + hdr->fac.offset = fac.offset; + hdr->fac.size = fac.size; + hdr->sac.offset = sac.offset; + hdr->sac.size = sac.size; + hdr->kc.offset = kc.offset; + hdr->kc.size = kc.size; +} + +void nx::AccessControlInfoBinary::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sAciHeader)) + { + throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sAciHeader hdr; + memcpy((void*)&hdr, data, sizeof(sAciHeader)); + + // check magic + if (hdr.st_magic.get() != aci::kAciStructMagic) + { + throw fnd::Exception(kModuleName, "AccessControlInfo header corrupt"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); + } + + // allocate memory for header + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + mProgramId = hdr.program_id.get(); + mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); + mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); + mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); +} + +const fnd::Vec& nx::AccessControlInfoBinary::getBytes() const +{ + return mRawBinary; +} + +void nx::AccessControlInfoBinary::clear() +{ + mRawBinary.clear(); + mProgramId = 0; + mFileSystemAccessControl.clear(); + mServiceAccessControl.clear(); + mKernelCapabilities.clear(); +} + +uint64_t nx::AccessControlInfoBinary::getProgramId() const +{ + return mProgramId; +} + +void nx::AccessControlInfoBinary::setProgramId(uint64_t program_id) +{ + mProgramId = program_id; +} + +const nx::FileSystemAccessControlBinary& nx::AccessControlInfoBinary::getFileSystemAccessControl() const +{ + return mFileSystemAccessControl; +} + +void nx::AccessControlInfoBinary::setFileSystemAccessControl(const nx::FileSystemAccessControlBinary& fac) +{ + mFileSystemAccessControl = fac; +} + +const nx::ServiceAccessControlBinary& nx::AccessControlInfoBinary::getServiceAccessControl() const +{ + return mServiceAccessControl; +} + +void nx::AccessControlInfoBinary::setServiceAccessControl(const nx::ServiceAccessControlBinary& sac) +{ + mServiceAccessControl = sac; +} + +const nx::KernelCapabilityBinary& nx::AccessControlInfoBinary::getKernelCapabilities() const +{ + return mKernelCapabilities; +} + +void nx::AccessControlInfoBinary::setKernelCapabilities(const nx::KernelCapabilityBinary& kc) +{ + mKernelCapabilities = kc; +} \ No newline at end of file diff --git a/lib/libnx/source/AccessControlInfoDescBinary.cpp b/lib/libnx/source/AccessControlInfoDescBinary.cpp new file mode 100644 index 0000000..122d89c --- /dev/null +++ b/lib/libnx/source/AccessControlInfoDescBinary.cpp @@ -0,0 +1,250 @@ +#include + +nx::AccessControlInfoDescBinary::AccessControlInfoDescBinary() +{ + clear(); +} + +nx::AccessControlInfoDescBinary::AccessControlInfoDescBinary(const AccessControlInfoDescBinary & other) +{ + *this = other; +} + +void nx::AccessControlInfoDescBinary::operator=(const AccessControlInfoDescBinary & other) +{ + mRawBinary = other.mRawBinary; + mNcaHeaderSignature2Key = other.mNcaHeaderSignature2Key; + mFlags = other.mFlags; + mProgramIdRestrict = other.mProgramIdRestrict; + mFileSystemAccessControl = other.mFileSystemAccessControl; + mServiceAccessControl = other.mServiceAccessControl; + mKernelCapabilities = other.mKernelCapabilities; +} + +bool nx::AccessControlInfoDescBinary::operator==(const AccessControlInfoDescBinary & other) const +{ + return (mNcaHeaderSignature2Key == other.mNcaHeaderSignature2Key) \ + && (mFlags == other.mFlags) \ + && (mProgramIdRestrict == other.mProgramIdRestrict) \ + && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ + && (mServiceAccessControl == other.mServiceAccessControl) \ + && (mKernelCapabilities == other.mKernelCapabilities); +} + +bool nx::AccessControlInfoDescBinary::operator!=(const AccessControlInfoDescBinary & other) const +{ + return !(*this == other); +} + +void nx::AccessControlInfoDescBinary::toBytes() +{ + if (mFileSystemAccessControl.getBytes().size() == 0) + mFileSystemAccessControl.toBytes(); + + if (mServiceAccessControl.getBytes().size() == 0) + mServiceAccessControl.toBytes(); + + if (mKernelCapabilities.getBytes().size() == 0) + mKernelCapabilities.toBytes(); + + // determine section layout + struct sLayout { + uint32_t offset, size; + } fac, sac, kc; + + fac.offset = align(sizeof(sAciDescHeader), aci::kSectionAlignSize); + fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); + sac.offset = align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); + kc.offset = align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); + + // get total size + size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); + + mRawBinary.alloc(total_size); + sAciDescHeader* hdr = (sAciDescHeader*)mRawBinary.data(); + + // set rsa modulus + memcpy(hdr->nca_rsa_signature2_modulus, mNcaHeaderSignature2Key.modulus, crypto::rsa::kRsa2048Size); + + // set type + hdr->st_magic = aci::kAciDescStructMagic; + + // set "acid size" + hdr->signed_size = total_size - crypto::rsa::kRsa2048Size; + + // set flags + uint32_t flags = 0; + for (size_t i = 0; i < mFlags.size(); i++) + flags |= _BIT(mFlags[i]); + hdr->flags = flags; + + // set program id restrict settings + hdr->program_id_min = mProgramIdRestrict.min; + hdr->program_id_max = mProgramIdRestrict.max; + + // set offset/size + hdr->fac.offset = fac.offset; + hdr->fac.size = fac.size; + hdr->sac.offset = sac.offset; + hdr->sac.size = sac.size; + hdr->kc.offset = kc.offset; + hdr->kc.size = kc.size; +} + +void nx::AccessControlInfoDescBinary::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sAciDescHeader)) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sAciDescHeader hdr; + memcpy((void*)&hdr, data, sizeof(sAciDescHeader)); + + // check magic + if (hdr.st_magic.get() != aci::kAciDescStructMagic) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc header corrupt"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); + } + + // allocate memory for header + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + memcpy(mNcaHeaderSignature2Key.modulus, hdr.nca_rsa_signature2_modulus, crypto::rsa::kRsa2048Size); + + for (size_t i = 0; i < 32; i++) + { + if (_HAS_BIT(hdr.flags.get(), i)) + mFlags.addElement((aci::Flag)i); + } + + mProgramIdRestrict.min = hdr.program_id_min.get(); + mProgramIdRestrict.max = hdr.program_id_max.get(); + + mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); + mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); + mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); +} + +const fnd::Vec& nx::AccessControlInfoDescBinary::getBytes() const +{ + return mRawBinary; +} + +void nx::AccessControlInfoDescBinary::generateSignature(const crypto::rsa::sRsa2048Key& key) +{ + if (mRawBinary.size() == 0) + toBytes(); + + byte_t hash[crypto::sha::kSha256HashLen]; + crypto::sha::Sha256(mRawBinary.data() + crypto::rsa::kRsa2048Size, mRawBinary.size() - crypto::rsa::kRsa2048Size, hash); + + if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) + { + throw fnd::Exception(kModuleName, "Failed to sign Access Control Info Desc"); + } +} + +void nx::AccessControlInfoDescBinary::validateSignature(const crypto::rsa::sRsa2048Key& key) const +{ + if (mRawBinary.size() == 0) + throw fnd::Exception(kModuleName, "No Access Control Info Desc binary exists to verify"); + + byte_t hash[crypto::sha::kSha256HashLen]; + crypto::sha::Sha256(mRawBinary.data() + crypto::rsa::kRsa2048Size, mRawBinary.size() - crypto::rsa::kRsa2048Size, hash); + + if (crypto::rsa::pss::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) + { + throw fnd::Exception(kModuleName, "Failed to verify Access Control Info Desc"); + } +} + +void nx::AccessControlInfoDescBinary::clear() +{ + mRawBinary.clear(); + memset((void*)&mNcaHeaderSignature2Key, 0, sizeof(mNcaHeaderSignature2Key)); + mFlags.clear(); + mProgramIdRestrict.min = 0; + mProgramIdRestrict.max = 0; + mFileSystemAccessControl.clear(); + mServiceAccessControl.clear(); + mKernelCapabilities.clear(); +} + +const crypto::rsa::sRsa2048Key& nx::AccessControlInfoDescBinary::getNcaHeaderSignature2Key() const +{ + return mNcaHeaderSignature2Key; +} + +void nx::AccessControlInfoDescBinary::setNcaHeaderSignature2Key(const crypto::rsa::sRsa2048Key& key) +{ + mNcaHeaderSignature2Key = key; +} + +const fnd::List& nx::AccessControlInfoDescBinary::getFlagList() const +{ + return mFlags; +} + +void nx::AccessControlInfoDescBinary::setFlagList(const fnd::List& flags) +{ + mFlags = flags; +} + +const nx::AccessControlInfoDescBinary::sProgramIdRestrict& nx::AccessControlInfoDescBinary::getProgramIdRestrict() const +{ + return mProgramIdRestrict; +} + +void nx::AccessControlInfoDescBinary::setProgramIdRestrict(const sProgramIdRestrict& pid_restrict) +{ + mProgramIdRestrict = pid_restrict; +} + +const nx::FileSystemAccessControlBinary& nx::AccessControlInfoDescBinary::getFileSystemAccessControl() const +{ + return mFileSystemAccessControl; +} + +void nx::AccessControlInfoDescBinary::setFileSystemAccessControl(const nx::FileSystemAccessControlBinary& fac) +{ + mFileSystemAccessControl = fac; +} + +const nx::ServiceAccessControlBinary& nx::AccessControlInfoDescBinary::getServiceAccessControl() const +{ + return mServiceAccessControl; +} + +void nx::AccessControlInfoDescBinary::setServiceAccessControl(const nx::ServiceAccessControlBinary& sac) +{ + mServiceAccessControl = sac; +} + +const nx::KernelCapabilityBinary& nx::AccessControlInfoDescBinary::getKernelCapabilities() const +{ + return mKernelCapabilities; +} + +void nx::AccessControlInfoDescBinary::setKernelCapabilities(const nx::KernelCapabilityBinary& kc) +{ + mKernelCapabilities = kc; +} \ No newline at end of file diff --git a/lib/libnx/source/AciBinary.cpp b/lib/libnx/source/AciBinary.cpp deleted file mode 100644 index e6c3376..0000000 --- a/lib/libnx/source/AciBinary.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include - - - -nx::AciBinary::AciBinary() -{ - clear(); -} - -nx::AciBinary::AciBinary(const AciBinary & other) -{ - copyFrom(other); -} - -nx::AciBinary::AciBinary(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::AciBinary::operator==(const AciBinary & other) const -{ - return isEqual(other); -} - -bool nx::AciBinary::operator!=(const AciBinary & other) const -{ - return !isEqual(other); -} - -void nx::AciBinary::operator=(const AciBinary & other) -{ - copyFrom(other); -} - -const byte_t * nx::AciBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::AciBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::AciBinary::exportBinary() -{ - // export components - mFac.exportBinary(); - mSac.exportBinary(); - mKc.exportBinary(); - - // set sizes - setFacSize(mFac.getSize()); - setSacSize(mSac.getSize()); - setKcSize(mKc.getSize()); - - // export header - AciHeader::exportBinary(); - - // allocate binary - mBinaryBlob.alloc(getAciSize()); - - // copy header - memcpy(mBinaryBlob.getBytes(), AciHeader::getBytes(), AciHeader::getSize()); - - // copy components - memcpy(mBinaryBlob.getBytes() + getFacPos().offset, mFac.getBytes(), mFac.getSize()); - memcpy(mBinaryBlob.getBytes() + getSacPos().offset, mSac.getBytes(), mSac.getSize()); - memcpy(mBinaryBlob.getBytes() + getKcPos().offset, mKc.getBytes(), mKc.getSize()); -} - -void nx::AciBinary::importBinary(const byte_t * bytes, size_t len) -{ - AciHeader::importBinary(bytes, len); - - if (getAciSize() > len) - { - throw fnd::Exception(kModuleName, "ACI binary too small"); - } - - mBinaryBlob.alloc(getAciSize()); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - - if (getFacPos().size > 0) - { - mFac.importBinary(mBinaryBlob.getBytes() + getFacPos().offset, getFacPos().size); - } - if (getSacPos().size > 0) - { - mSac.importBinary(mBinaryBlob.getBytes() + getSacPos().offset, getSacPos().size); - } - if (getKcPos().size > 0) - { - mKc.importBinary(mBinaryBlob.getBytes() + getKcPos().offset, getKcPos().size); - } - -} - -void nx::AciBinary::clear() -{ - AciHeader::clear(); - mFac.clear(); - mSac.clear(); - mKc.clear(); -} - -const nx::FacBinary & nx::AciBinary::getFac() const -{ - return mFac; -} - -void nx::AciBinary::setFac(const FacBinary & fac) -{ - mFac = fac; -} - -const nx::SacBinary & nx::AciBinary::getSac() const -{ - return mSac; -} - -void nx::AciBinary::setSac(const SacBinary & sac) -{ - mSac = sac; -} - -const nx::KcBinary & nx::AciBinary::getKc() const -{ - return mKc; -} - -void nx::AciBinary::setKc(const KcBinary & kc) -{ - mKc = kc; -} - -bool nx::AciBinary::isEqual(const AciBinary & other) const -{ - return (AciHeader::operator==(other)) \ - && (mFac == other.mFac) \ - && (mSac == other.mSac) \ - && (mKc == other.mKc); -} - -void nx::AciBinary::copyFrom(const AciBinary & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - AciHeader::operator=(other); - mFac = other.mFac; - mSac = other.mSac; - mKc = other.mKc; - } -} diff --git a/lib/libnx/source/AciHeader.cpp b/lib/libnx/source/AciHeader.cpp deleted file mode 100644 index 9bbcc00..0000000 --- a/lib/libnx/source/AciHeader.cpp +++ /dev/null @@ -1,324 +0,0 @@ -#include - -using namespace nx; - -void AciHeader::calculateSectionOffsets() -{ - mFac.offset = align(mHeaderOffset, aci::kAciAlignSize) + align(sizeof(sAciHeader), aci::kAciAlignSize); - mSac.offset = mFac.offset + align(mFac.size, aci::kAciAlignSize); - mKc.offset = mSac.offset + align(mSac.size, aci::kAciAlignSize); -} - -bool AciHeader::isEqual(const AciHeader & other) const -{ - return (mHeaderOffset == other.mHeaderOffset) \ - && (mType == other.mType) \ - && (mIsProduction == other.mIsProduction) \ - && (mIsUnqualifiedApproval == other.mIsUnqualifiedApproval) \ - && (mAcidSize == other.mAcidSize) \ - && (mProgramIdMin == other.mProgramIdMin) \ - && (mProgramIdMax == other.mProgramIdMax) \ - && (mProgramId == other.mProgramId) \ - && (mFac == other.mFac) \ - && (mSac == other.mSac) \ - && (mKc == other.mKc); -} - -void AciHeader::copyFrom(const AciHeader & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mHeaderOffset = other.mHeaderOffset; - mType = other.mType; - mIsProduction = other.mIsProduction; - mIsUnqualifiedApproval = other.mIsUnqualifiedApproval; - mAcidSize = other.mAcidSize; - mProgramIdMin = other.mProgramIdMin; - mProgramIdMax = other.mProgramIdMax; - mProgramId = other.mProgramId; - mFac = other.mFac; - mSac = other.mSac; - mKc = other.mKc; - } -} - -AciHeader::AciHeader() -{ - clear(); -} - -AciHeader::AciHeader(const AciHeader & other) -{ - importBinary(other.getBytes(), other.getSize()); -} - -AciHeader::AciHeader(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool AciHeader::operator==(const AciHeader & other) const -{ - return isEqual(other); -} - -bool AciHeader::operator!=(const AciHeader & other) const -{ - return !isEqual(other); -} - -void AciHeader::operator=(const AciHeader & other) -{ - this->importBinary(other.getBytes(), other.getSize()); -} - -const byte_t * AciHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t AciHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void AciHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sAciHeader)); - sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes(); - - // set type - switch (mType) - { - case (TYPE_ACI0): - hdr->signature = aci::kAciStructSig; - break; - case (TYPE_ACID): - hdr->signature = aci::kAciDescStructSig; - break; - default: - throw fnd::Exception(kModuleName, "Unexpected ACI type"); - } - - // set offset/size - calculateSectionOffsets(); - hdr->fac.offset = (uint32_t)mFac.offset; - hdr->fac.size = (uint32_t)mFac.size; - hdr->sac.offset = (uint32_t)mSac.offset; - hdr->sac.size = (uint32_t)mSac.size; - hdr->kc.offset = (uint32_t)mKc.offset; - hdr->kc.size = (uint32_t)mKc.size; - - uint32_t flags = 0; - if (mIsProduction) - flags |= _BIT(aci::FLAG_PRODUCTION); - if (mIsUnqualifiedApproval) - flags |= _BIT(aci::FLAG_UNQUALIFIED_APPROVAL); - - hdr->flags = flags; - - if (mType == TYPE_ACI0) - { - // set program - hdr->program_id_info.program_id = mProgramId; - } - else if (mType == TYPE_ACID) - { - mAcidSize = getAciSize(); - hdr->size = (uint32_t)mAcidSize; - hdr->program_id_info.program_id_restrict.min = mProgramIdMin; - hdr->program_id_info.program_id_restrict.max = mProgramIdMax; - } -} - -void AciHeader::importBinary(const byte_t * bytes, size_t len) -{ - if (len < sizeof(sAciHeader)) - { - throw fnd::Exception(kModuleName, "ACI header too small"); - } - - clear(); - - mBinaryBlob.alloc(sizeof(sAciHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader)); - - sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes(); - - switch (hdr->signature.get()) - { - case (aci::kAciStructSig): - mType = TYPE_ACI0; - break; - case (aci::kAciDescStructSig): - mType = TYPE_ACID; - break; - default: - throw fnd::Exception(kModuleName, "ACI header corrupt"); - } - - - if (mType == TYPE_ACI0) - { - mProgramId = hdr->program_id_info.program_id.get(); - mIsProduction = false; - mIsUnqualifiedApproval = false; - mAcidSize = 0; - mProgramIdMin = 0; - mProgramIdMax = 0; - } - else if (mType == TYPE_ACID) - { - mProgramId = 0; - mIsProduction = _HAS_BIT(hdr->flags.get(), aci::FLAG_PRODUCTION); - mIsUnqualifiedApproval = _HAS_BIT(hdr->flags.get(), aci::FLAG_UNQUALIFIED_APPROVAL); - mAcidSize = hdr->size.get(); - mProgramIdMin = hdr->program_id_info.program_id_restrict.min.get(); - mProgramIdMax = hdr->program_id_info.program_id_restrict.max.get(); - } - - // the header offset is the MIN(sac.offset, fac.offset, kc.offset) - sizeof(sHeader) - mHeaderOffset = MAX(MIN(hdr->sac.offset.get(), MIN(hdr->fac.offset.get(), hdr->kc.offset.get())), align(sizeof(sAciHeader), aci::kAciAlignSize)) - align(sizeof(sAciHeader), aci::kAciAlignSize); - - mFac.offset = hdr->fac.offset.get() - mHeaderOffset; - mFac.size = hdr->fac.size.get(); - mSac.offset = hdr->sac.offset.get() - mHeaderOffset; - mSac.size = hdr->sac.size.get(); - mKc.offset = hdr->kc.offset.get() - mHeaderOffset; - mKc.size = hdr->kc.size.get(); -} - -void nx::AciHeader::clear() -{ - mBinaryBlob.clear(); - mHeaderOffset = 0; - mType = TYPE_ACI0; - mProgramId = 0; - mProgramIdMin = 0; - mProgramIdMax = 0; - mAcidSize = 0; - mIsProduction = false; - mIsUnqualifiedApproval = false; - mFac.offset = 0; - mFac.size = 0; - mSac.offset = 0; - mSac.size = 0; - mKc.offset = 0; - mKc.size = 0; -} - -size_t nx::AciHeader::getAciSize() const -{ - return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader)); -} - -size_t nx::AciHeader::getAcidSize() const -{ - return mAcidSize; -} - -/* -void nx::AciHeader::setAcidSize(size_t size) -{ - mAcidSize = size; -} -*/ - -uint64_t nx::AciHeader::getProgramIdMin() const -{ - return mProgramIdMin; -} - -void nx::AciHeader::setProgramIdMin(uint64_t program_id) -{ - mProgramIdMin = program_id; -} - -uint64_t nx::AciHeader::getProgramIdMax() const -{ - return mProgramIdMax; -} - -void nx::AciHeader::setProgramIdMax(uint64_t program_id) -{ - mProgramIdMax = program_id; -} - -void nx::AciHeader::setHeaderOffset(size_t offset) -{ - mHeaderOffset = offset; -} - -AciHeader::AciType AciHeader::getAciType() const -{ - return mType; -} - -void AciHeader::setAciType(AciType type) -{ - mType = type; -} - -bool nx::AciHeader::isProduction() const -{ - return mIsProduction; -} - -void nx::AciHeader::setIsProduction(bool isProduction) -{ - mIsProduction = isProduction; -} - -bool nx::AciHeader::isUnqualifiedApproval() const -{ - return mIsUnqualifiedApproval; -} - -void nx::AciHeader::setIsUnqualifiedApproval(bool isUnqualifiedApproval) -{ - mIsUnqualifiedApproval = isUnqualifiedApproval; -} - -uint64_t AciHeader::getProgramId() const -{ - return mProgramId; -} - -void AciHeader::setProgramId(uint64_t program_id) -{ - mProgramId = program_id; -} - -const AciHeader::sSection & AciHeader::getFacPos() const -{ - return mFac; -} - -void AciHeader::setFacSize(size_t size) -{ - mFac.size = size; -} - -const AciHeader::sSection & AciHeader::getSacPos() const -{ - return mSac; -} - -void AciHeader::setSacSize(size_t size) -{ - mSac.size = size; -} - -const AciHeader::sSection & AciHeader::getKcPos() const -{ - return mKc; -} - -void AciHeader::setKcSize(size_t size) -{ - mKc.size = size; -} diff --git a/lib/libnx/source/AcidBinary.cpp b/lib/libnx/source/AcidBinary.cpp deleted file mode 100644 index c1017a2..0000000 --- a/lib/libnx/source/AcidBinary.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include - - - -nx::AcidBinary::AcidBinary() -{ - clear(); -} - -nx::AcidBinary::AcidBinary(const AcidBinary & other) -{ - copyFrom(other); -} - -nx::AcidBinary::AcidBinary(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -void nx::AcidBinary::clear() -{ - AciBinary::clear(); - mEmbeddedPublicKey = crypto::rsa::sRsa2048Key(); -} - -const crypto::rsa::sRsa2048Key & nx::AcidBinary::getNcaHeader2RsaKey() const -{ - return mEmbeddedPublicKey; -} - -void nx::AcidBinary::setNcaHeader2RsaKey(const crypto::rsa::sRsa2048Key & key) -{ - mEmbeddedPublicKey = key; -} - -bool nx::AcidBinary::isEqual(const AcidBinary & other) const -{ - return AciBinary::operator==(other) \ - && (mEmbeddedPublicKey == other.mEmbeddedPublicKey); -} - -void nx::AcidBinary::copyFrom(const AcidBinary & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - AciBinary::operator=(other); - mEmbeddedPublicKey = other.mEmbeddedPublicKey; - } -} - -bool nx::AcidBinary::operator==(const AcidBinary & other) const -{ - return isEqual(other); -} - -bool nx::AcidBinary::operator!=(const AcidBinary & other) const -{ - return !isEqual(other); -} - -void nx::AcidBinary::operator=(const AcidBinary & other) -{ - copyFrom(other); -} - -const byte_t * nx::AcidBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::AcidBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::AcidBinary::exportBinary() -{ - AciBinary::setHeaderOffset(crypto::rsa::kRsa2048Size); // not include signature - AciBinary::exportBinary(); - mBinaryBlob.alloc(AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2); - - memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mEmbeddedPublicKey.modulus, crypto::rsa::kRsa2048Size); - memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size * 2, AciBinary::getBytes(), AciBinary::getSize()); -} - -void nx::AcidBinary::signBinary(const crypto::rsa::sRsa2048Key & key) -{ - if (mBinaryBlob.getSize() == 0) - { - exportBinary(); - } - - byte_t hash[crypto::sha::kSha256HashLen]; - crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash); - - if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0) - { - throw fnd::Exception(kModuleName, "Failed to sign ACID"); - } -} - -void nx::AcidBinary::importBinary(const byte_t * bytes, size_t len) -{ - if (len <= crypto::rsa::kRsa2048Size*2) - { - throw fnd::Exception(kModuleName, "ACID binary too small"); - } - - // import aci binary past sig + pubkey - AciBinary::importBinary(bytes + crypto::rsa::kRsa2048Size * 2, len - crypto::rsa::kRsa2048Size * 2); - - // save internal copy - size_t acid_size = AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2; - if (acid_size > len) - { - throw fnd::Exception(kModuleName, "ACID binary too small"); - } - - mBinaryBlob.alloc(acid_size); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - memcpy(mEmbeddedPublicKey.modulus, bytes + crypto::rsa::kRsa2048Size, crypto::rsa::kRsa2048Size); -} - -void nx::AcidBinary::verifyBinary(const crypto::rsa::sRsa2048Key & key) const -{ - if (mBinaryBlob.getSize() == 0) - { - throw fnd::Exception(kModuleName, "No ACID binary exists to verify"); - } - - byte_t hash[crypto::sha::kSha256HashLen]; - crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash); - - if (crypto::rsa::pss::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0) - { - throw fnd::Exception(kModuleName, "Failed to verify ACID"); - } -} diff --git a/lib/libnx/source/ApplicationControlPropertyBinary.cpp b/lib/libnx/source/ApplicationControlPropertyBinary.cpp index c5f60a8..5edb57b 100644 --- a/lib/libnx/source/ApplicationControlPropertyBinary.cpp +++ b/lib/libnx/source/ApplicationControlPropertyBinary.cpp @@ -7,17 +7,92 @@ nx::ApplicationControlPropertyBinary::ApplicationControlPropertyBinary() nx::ApplicationControlPropertyBinary::ApplicationControlPropertyBinary(const ApplicationControlPropertyBinary& other) { - copyFrom(other); + *this = other; } -nx::ApplicationControlPropertyBinary::ApplicationControlPropertyBinary(const byte_t* bytes, size_t len) +void nx::ApplicationControlPropertyBinary::operator=(const ApplicationControlPropertyBinary& other) { - importBinary(bytes, len); + clear(); + mTitle = other.mTitle; + mIsbn = other.mIsbn; + mStartupUserAccount = other.mStartupUserAccount; + mTouchScreenUsageMode = other.mTouchScreenUsageMode; + mAocRegistrationType = other.mAocRegistrationType; + mAttributeFlag = other.mAttributeFlag; + mParentalControlFlag = other.mParentalControlFlag; + mScreenshotMode = other.mScreenshotMode; + mVideoCaptureMode = other.mVideoCaptureMode; + mDataLossConfirmation = other.mDataLossConfirmation; + mPlayLogPolicy = other.mPlayLogPolicy; + mPresenceGroupId = other.mPresenceGroupId; + mRatingAge = other.mRatingAge; + mDisplayVersion = other.mDisplayVersion; + mAocBaseId = other.mAocBaseId; + mSaveDatawOwnerId = other.mSaveDatawOwnerId; + mUserAccountSaveDataSize = other.mUserAccountSaveDataSize; + mDeviceSaveDataSize = other.mDeviceSaveDataSize; + mBcatDeliveryCacheStorageSize = other.mBcatDeliveryCacheStorageSize; + mApplicationErrorCodeCategory = other.mApplicationErrorCodeCategory; + mLocalCommunicationId = other.mLocalCommunicationId; + mLogoType = other.mLogoType; + mLogoHandling = other.mLogoHandling; + mRuntimeAocInstallMode = other.mRuntimeAocInstallMode; + mCrashReportMode = other.mCrashReportMode; + mHdcp = other.mHdcp; + mSeedForPsuedoDeviceId = other.mSeedForPsuedoDeviceId; + mBcatPassphase = other.mBcatPassphase; + mUserAccountSaveDataMax = other.mUserAccountSaveDataMax; + mDeviceSaveDataMax = other.mDeviceSaveDataMax; + mTemporaryStorageSize = other.mTemporaryStorageSize; + mCacheStorageSize = other.mCacheStorageSize; + mCacheStorageDataAndJournalSizeMax = other.mCacheStorageDataAndJournalSizeMax; + mCacheStorageIndex = other.mCacheStorageIndex; + mPlayLogQueryableApplicationId = other.mPlayLogQueryableApplicationId; + mPlayLogQueryCapability = other.mPlayLogQueryCapability; + mRepairFlag = other.mRepairFlag; + mProgramIndex = other.mProgramIndex; } bool nx::ApplicationControlPropertyBinary::operator==(const ApplicationControlPropertyBinary& other) const { - return isEqual(other); + return (mTitle == other.mTitle) \ + && (mIsbn == other.mIsbn) \ + && (mStartupUserAccount == other.mStartupUserAccount) \ + && (mTouchScreenUsageMode == other.mTouchScreenUsageMode) \ + && (mAocRegistrationType == other.mAocRegistrationType) \ + && (mAttributeFlag == other.mAttributeFlag) \ + && (mParentalControlFlag == other.mParentalControlFlag) \ + && (mScreenshotMode == other.mScreenshotMode) \ + && (mVideoCaptureMode == other.mVideoCaptureMode) \ + && (mDataLossConfirmation == other.mDataLossConfirmation) \ + && (mPlayLogPolicy == other.mPlayLogPolicy) \ + && (mPresenceGroupId == other.mPresenceGroupId) \ + && (mRatingAge == other.mRatingAge) \ + && (mDisplayVersion == other.mDisplayVersion) \ + && (mAocBaseId == other.mAocBaseId) \ + && (mSaveDatawOwnerId == other.mSaveDatawOwnerId) \ + && (mUserAccountSaveDataSize == other.mUserAccountSaveDataSize) \ + && (mDeviceSaveDataSize == other.mDeviceSaveDataSize) \ + && (mBcatDeliveryCacheStorageSize == other.mBcatDeliveryCacheStorageSize) \ + && (mApplicationErrorCodeCategory == other.mApplicationErrorCodeCategory) \ + && (mLocalCommunicationId == other.mLocalCommunicationId) \ + && (mLogoType == other.mLogoType) \ + && (mLogoHandling == other.mLogoHandling) \ + && (mRuntimeAocInstallMode == other.mRuntimeAocInstallMode) \ + && (mCrashReportMode == other.mCrashReportMode) \ + && (mHdcp == other.mHdcp) \ + && (mSeedForPsuedoDeviceId == other.mSeedForPsuedoDeviceId) \ + && (mBcatPassphase == other.mBcatPassphase) \ + && (mUserAccountSaveDataMax == other.mUserAccountSaveDataMax) \ + && (mDeviceSaveDataMax == other.mDeviceSaveDataMax) \ + && (mTemporaryStorageSize == other.mTemporaryStorageSize) \ + && (mCacheStorageSize == other.mCacheStorageSize) \ + && (mCacheStorageDataAndJournalSizeMax == other.mCacheStorageDataAndJournalSizeMax) \ + && (mCacheStorageIndex == other.mCacheStorageIndex) \ + && (mPlayLogQueryableApplicationId == other.mPlayLogQueryableApplicationId) \ + && (mPlayLogQueryCapability == other.mPlayLogQueryCapability) \ + && (mRepairFlag == other.mRepairFlag) \ + && (mProgramIndex == other.mProgramIndex); } bool nx::ApplicationControlPropertyBinary::operator!=(const ApplicationControlPropertyBinary& other) const @@ -25,30 +100,15 @@ bool nx::ApplicationControlPropertyBinary::operator!=(const ApplicationControlPr return !(*this == other); } -void nx::ApplicationControlPropertyBinary::operator=(const ApplicationControlPropertyBinary& other) +void nx::ApplicationControlPropertyBinary::toBytes() { - copyFrom(other); -} + mRawBinary.alloc(sizeof(nx::sApplicationControlProperty)); -const byte_t* nx::ApplicationControlPropertyBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::ApplicationControlPropertyBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::ApplicationControlPropertyBinary::exportBinary() -{ - mBinaryBlob.alloc(sizeof(nx::sApplicationControlProperty)); - - sApplicationControlProperty* data = (sApplicationControlProperty*)mBinaryBlob.getBytes(); + sApplicationControlProperty* data = (sApplicationControlProperty*)mRawBinary.data(); // strings uint32_t supported_langs = 0; - for (size_t i = 0; i < mTitle.getSize(); i++) + for (size_t i = 0; i < mTitle.size(); i++) { supported_langs = _BIT(mTitle[i].language); strncpy(data->title[mTitle[i].language].name, mTitle[i].name.c_str(), nacp::kNameLength); @@ -82,18 +142,18 @@ void nx::ApplicationControlPropertyBinary::exportBinary() // misc params data->presence_group_id = mPresenceGroupId; memset(data->rating_age, nacp::kUnusedAgeRating, nacp::kRatingAgeCount); // clear ratings - for (size_t i = 0; i < mRatingAge.getSize(); i++) + for (size_t i = 0; i < mRatingAge.size(); i++) { data->rating_age[mRatingAge[i].organisation] = mRatingAge[i].age; } data->add_on_content_base_id = mAocBaseId; data->save_data_owner_id = mSaveDatawOwnerId; - for (size_t i = 0; i < mLocalCommunicationId.getSize() && i < nacp::kLocalCommunicationIdCount; i++) + for (size_t i = 0; i < mLocalCommunicationId.size() && i < nacp::kLocalCommunicationIdCount; i++) { data->local_communication_id[i] = mLocalCommunicationId[i]; } data->seed_for_pseudo_device_id = mSeedForPsuedoDeviceId; - for (size_t i = 0; i < mPlayLogQueryableApplicationId.getSize() && i < nacp::kPlayLogQueryableApplicationIdCount; i++) + for (size_t i = 0; i < mPlayLogQueryableApplicationId.size() && i < nacp::kPlayLogQueryableApplicationIdCount; i++) { data->play_log_queryable_application_id[i] = mPlayLogQueryableApplicationId[i]; } @@ -116,7 +176,7 @@ void nx::ApplicationControlPropertyBinary::exportBinary() data->cache_storage_data_and_journal_size_max = mCacheStorageDataAndJournalSizeMax; } -void nx::ApplicationControlPropertyBinary::importBinary(const byte_t* bytes, size_t len) +void nx::ApplicationControlPropertyBinary::fromBytes(const byte_t* bytes, size_t len) { if (len < sizeof(nx::sApplicationControlProperty)) { @@ -125,10 +185,10 @@ void nx::ApplicationControlPropertyBinary::importBinary(const byte_t* bytes, siz clear(); - mBinaryBlob.alloc(sizeof(nx::sApplicationControlProperty)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(sizeof(nx::sApplicationControlProperty)); + memcpy(mRawBinary.data(), bytes, mRawBinary.size()); - const sApplicationControlProperty* data = (const sApplicationControlProperty*)mBinaryBlob.getBytes(); + const sApplicationControlProperty* data = (const sApplicationControlProperty*)mRawBinary.data(); // strings for (size_t i = 0; i < nacp::kMaxLanguageCount; i++) @@ -204,9 +264,14 @@ void nx::ApplicationControlPropertyBinary::importBinary(const byte_t* bytes, siz mCacheStorageDataAndJournalSizeMax = (int64_t)data->cache_storage_data_and_journal_size_max.get(); } +const fnd::Vec& nx::ApplicationControlPropertyBinary::getBytes() const +{ + return mRawBinary; +} + void nx::ApplicationControlPropertyBinary::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mTitle.clear(); mIsbn.clear(); mStartupUserAccount = nacp::USER_None; @@ -625,89 +690,4 @@ byte_t nx::ApplicationControlPropertyBinary::getProgramIndex() const void nx::ApplicationControlPropertyBinary::setProgramIndex(byte_t var) { mProgramIndex = var; -} - -bool nx::ApplicationControlPropertyBinary::isEqual(const ApplicationControlPropertyBinary& other) const -{ - return (mTitle == other.mTitle) \ - && (mIsbn == other.mIsbn) \ - && (mStartupUserAccount == other.mStartupUserAccount) \ - && (mTouchScreenUsageMode == other.mTouchScreenUsageMode) \ - && (mAocRegistrationType == other.mAocRegistrationType) \ - && (mAttributeFlag == other.mAttributeFlag) \ - && (mParentalControlFlag == other.mParentalControlFlag) \ - && (mScreenshotMode == other.mScreenshotMode) \ - && (mVideoCaptureMode == other.mVideoCaptureMode) \ - && (mDataLossConfirmation == other.mDataLossConfirmation) \ - && (mPlayLogPolicy == other.mPlayLogPolicy) \ - && (mPresenceGroupId == other.mPresenceGroupId) \ - && (mRatingAge == other.mRatingAge) \ - && (mDisplayVersion == other.mDisplayVersion) \ - && (mAocBaseId == other.mAocBaseId) \ - && (mSaveDatawOwnerId == other.mSaveDatawOwnerId) \ - && (mUserAccountSaveDataSize == other.mUserAccountSaveDataSize) \ - && (mDeviceSaveDataSize == other.mDeviceSaveDataSize) \ - && (mBcatDeliveryCacheStorageSize == other.mBcatDeliveryCacheStorageSize) \ - && (mApplicationErrorCodeCategory == other.mApplicationErrorCodeCategory) \ - && (mLocalCommunicationId == other.mLocalCommunicationId) \ - && (mLogoType == other.mLogoType) \ - && (mLogoHandling == other.mLogoHandling) \ - && (mRuntimeAocInstallMode == other.mRuntimeAocInstallMode) \ - && (mCrashReportMode == other.mCrashReportMode) \ - && (mHdcp == other.mHdcp) \ - && (mSeedForPsuedoDeviceId == other.mSeedForPsuedoDeviceId) \ - && (mBcatPassphase == other.mBcatPassphase) \ - && (mUserAccountSaveDataMax == other.mUserAccountSaveDataMax) \ - && (mDeviceSaveDataMax == other.mDeviceSaveDataMax) \ - && (mTemporaryStorageSize == other.mTemporaryStorageSize) \ - && (mCacheStorageSize == other.mCacheStorageSize) \ - && (mCacheStorageDataAndJournalSizeMax == other.mCacheStorageDataAndJournalSizeMax) \ - && (mCacheStorageIndex == other.mCacheStorageIndex) \ - && (mPlayLogQueryableApplicationId == other.mPlayLogQueryableApplicationId) \ - && (mPlayLogQueryCapability == other.mPlayLogQueryCapability) \ - && (mRepairFlag == other.mRepairFlag) \ - && (mProgramIndex == other.mProgramIndex); -} - -void nx::ApplicationControlPropertyBinary::copyFrom(const ApplicationControlPropertyBinary& other) -{ - clear(); - mTitle = other.mTitle; - mIsbn = other.mIsbn; - mStartupUserAccount = other.mStartupUserAccount; - mTouchScreenUsageMode = other.mTouchScreenUsageMode; - mAocRegistrationType = other.mAocRegistrationType; - mAttributeFlag = other.mAttributeFlag; - mParentalControlFlag = other.mParentalControlFlag; - mScreenshotMode = other.mScreenshotMode; - mVideoCaptureMode = other.mVideoCaptureMode; - mDataLossConfirmation = other.mDataLossConfirmation; - mPlayLogPolicy = other.mPlayLogPolicy; - mPresenceGroupId = other.mPresenceGroupId; - mRatingAge = other.mRatingAge; - mDisplayVersion = other.mDisplayVersion; - mAocBaseId = other.mAocBaseId; - mSaveDatawOwnerId = other.mSaveDatawOwnerId; - mUserAccountSaveDataSize = other.mUserAccountSaveDataSize; - mDeviceSaveDataSize = other.mDeviceSaveDataSize; - mBcatDeliveryCacheStorageSize = other.mBcatDeliveryCacheStorageSize; - mApplicationErrorCodeCategory = other.mApplicationErrorCodeCategory; - mLocalCommunicationId = other.mLocalCommunicationId; - mLogoType = other.mLogoType; - mLogoHandling = other.mLogoHandling; - mRuntimeAocInstallMode = other.mRuntimeAocInstallMode; - mCrashReportMode = other.mCrashReportMode; - mHdcp = other.mHdcp; - mSeedForPsuedoDeviceId = other.mSeedForPsuedoDeviceId; - mBcatPassphase = other.mBcatPassphase; - mUserAccountSaveDataMax = other.mUserAccountSaveDataMax; - mDeviceSaveDataMax = other.mDeviceSaveDataMax; - mTemporaryStorageSize = other.mTemporaryStorageSize; - mCacheStorageSize = other.mCacheStorageSize; - mCacheStorageDataAndJournalSizeMax = other.mCacheStorageDataAndJournalSizeMax; - mCacheStorageIndex = other.mCacheStorageIndex; - mPlayLogQueryableApplicationId = other.mPlayLogQueryableApplicationId; - mPlayLogQueryCapability = other.mPlayLogQueryCapability; - mRepairFlag = other.mRepairFlag; - mProgramIndex = other.mProgramIndex; -} +} \ No newline at end of file diff --git a/lib/libnx/source/ContentMetaBinary.cpp b/lib/libnx/source/ContentMetaBinary.cpp index 450eb61..b90de17 100644 --- a/lib/libnx/source/ContentMetaBinary.cpp +++ b/lib/libnx/source/ContentMetaBinary.cpp @@ -7,39 +7,73 @@ nx::ContentMetaBinary::ContentMetaBinary() nx::ContentMetaBinary::ContentMetaBinary(const ContentMetaBinary & other) { - copyFrom(other); + *this = other; } -nx::ContentMetaBinary::ContentMetaBinary(const byte_t * bytes, size_t len) +void nx::ContentMetaBinary::operator=(const ContentMetaBinary& other) { - importBinary(bytes, len); + if (other.getBytes().size() > 0) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + mTitleId = other.mTitleId; + mTitleVersion = other.mTitleVersion; + mType = other.mType; + mAttributes = other.mAttributes; + mRequiredDownloadSystemVersion = other.mRequiredDownloadSystemVersion; + mExtendedHeader = other.mExtendedHeader; + mApplicationMetaExtendedHeader = other.mApplicationMetaExtendedHeader; + mPatchMetaExtendedHeader = other.mPatchMetaExtendedHeader; + mAddOnContentMetaExtendedHeader = other.mAddOnContentMetaExtendedHeader; + mDeltaMetaExtendedHeader = other.mDeltaMetaExtendedHeader; + mContentInfo = other.mContentInfo; + mContentMetaInfo = other.mContentMetaInfo; + mExtendedData = other.mExtendedData; + memcpy(mDigest.data, other.mDigest.data, cnmt::kDigestLen); + } } -const byte_t * nx::ContentMetaBinary::getBytes() const +bool nx::ContentMetaBinary::operator==(const ContentMetaBinary& other) const { - return mBinaryBlob.getBytes(); + return (mTitleId == other.mTitleId) \ + && (mTitleVersion == other.mTitleVersion) \ + && (mType == other.mType) \ + && (mAttributes == other.mAttributes) \ + && (mRequiredDownloadSystemVersion == other.mRequiredDownloadSystemVersion) \ + && (mExtendedHeader == other.mExtendedHeader) \ + && (mApplicationMetaExtendedHeader == other.mApplicationMetaExtendedHeader) \ + && (mPatchMetaExtendedHeader == other.mPatchMetaExtendedHeader) \ + && (mAddOnContentMetaExtendedHeader == other.mAddOnContentMetaExtendedHeader) \ + && (mDeltaMetaExtendedHeader == other.mDeltaMetaExtendedHeader) \ + && (mContentInfo == other.mContentInfo) \ + && (mContentMetaInfo == other.mContentMetaInfo) \ + && (mExtendedData == other.mExtendedData) \ + && (memcmp(mDigest.data, other.mDigest.data, cnmt::kDigestLen) == 0); } -size_t nx::ContentMetaBinary::getSize() const +bool nx::ContentMetaBinary::operator!=(const ContentMetaBinary& other) const { - return mBinaryBlob.getSize(); + return !(*this == other); } -void nx::ContentMetaBinary::exportBinary() +void nx::ContentMetaBinary::toBytes() { throw fnd::Exception(kModuleName, "exportBinary() not implemented"); } -void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len) +void nx::ContentMetaBinary::fromBytes(const byte_t* data, size_t len) { // clear member variables clear(); // validate layout - validateBinary(bytes, len); + validateBinary(data, len); // get pointer to header structure - const sContentMetaHeader* hdr = (const sContentMetaHeader*)bytes; + const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; mTitleId = hdr->id.get(); mTitleVersion = hdr->version.get(); @@ -52,55 +86,59 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len) if (hdr->exhdr_size.get() > 0) { mExtendedHeader.alloc(hdr->exhdr_size.get()); - memcpy(mExtendedHeader.getBytes(), bytes + getExtendedHeaderOffset(), hdr->exhdr_size.get()); + memcpy(mExtendedHeader.data(), data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); switch (mType) { case (cnmt::METATYPE_APPLICATION): - mApplicationMetaExtendedHeader.patch_id = ((sApplicationMetaExtendedHeader*)mExtendedHeader.getBytes())->patch_id.get(); - mApplicationMetaExtendedHeader.required_system_version = ((sApplicationMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get(); + mApplicationMetaExtendedHeader.patch_id = ((sApplicationMetaExtendedHeader*)mExtendedHeader.data())->patch_id.get(); + mApplicationMetaExtendedHeader.required_system_version = ((sApplicationMetaExtendedHeader*)mExtendedHeader.data())->required_system_version.get(); break; case (cnmt::METATYPE_PATCH): - mPatchMetaExtendedHeader.application_id = ((sPatchMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get(); - mPatchMetaExtendedHeader.required_system_version = ((sPatchMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get(); + mPatchMetaExtendedHeader.application_id = ((sPatchMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); + mPatchMetaExtendedHeader.required_system_version = ((sPatchMetaExtendedHeader*)mExtendedHeader.data())->required_system_version.get(); break; case (cnmt::METATYPE_ADD_ON_CONTENT): - mAddOnContentMetaExtendedHeader.application_id = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get(); - mAddOnContentMetaExtendedHeader.required_system_version = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.getBytes())->required_system_version.get(); + mAddOnContentMetaExtendedHeader.application_id = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); + mAddOnContentMetaExtendedHeader.required_system_version = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.data())->required_system_version.get(); break; case (cnmt::METATYPE_DELTA): - mDeltaMetaExtendedHeader.application_id = ((sDeltaMetaExtendedHeader*)mExtendedHeader.getBytes())->application_id.get(); + mDeltaMetaExtendedHeader.application_id = ((sDeltaMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); break; default: break; } - exdata_size = getExtendedDataSize(mType, mExtendedHeader.getBytes()); + exdata_size = getExtendedDataSize(mType, mExtendedHeader.data()); } // save content info if (hdr->content_count.get() > 0) { - const sContentInfo* info = (const sContentInfo*)(bytes + getContentInfoOffset(hdr->exhdr_size.get())); + const sContentInfo* info = (const sContentInfo*)(data + getContentInfoOffset(hdr->exhdr_size.get())); + ContentInfo cinfo; for (size_t i = 0; i < hdr->content_count.get(); i++) { - mContentInfo[i].hash = info[i].content_hash; - memcpy(mContentInfo[i].nca_id, info[i].content_id, cnmt::kContentIdLen); - mContentInfo[i].size = (uint64_t)(info[i].size_lower.get()) | (uint64_t)(info[i].size_higher.get()) << 32; - mContentInfo[i].type = (cnmt::ContentType)info[i].content_type; + cinfo.hash = info[i].content_hash; + memcpy(cinfo.nca_id, info[i].content_id, cnmt::kContentIdLen); + cinfo.size = (uint64_t)(info[i].size_lower.get()) | (uint64_t)(info[i].size_higher.get()) << 32; + cinfo.type = (cnmt::ContentType)info[i].content_type; + mContentInfo.addElement(cinfo); } } // save content meta info if (hdr->content_meta_count.get() > 0) { - const sContentMetaInfo* info = (const sContentMetaInfo*)(bytes + getContentMetaInfoOffset(hdr->exhdr_size.get(), hdr->content_count.get())); + const sContentMetaInfo* info = (const sContentMetaInfo*)(data + getContentMetaInfoOffset(hdr->exhdr_size.get(), hdr->content_count.get())); + ContentMetaInfo cmeta; for (size_t i = 0; i < hdr->content_meta_count.get(); i++) - { - mContentMetaInfo[i].id = info[i].id.get(); - mContentMetaInfo[i].version = info[i].version.get(); - mContentMetaInfo[i].type = (cnmt::ContentMetaType)info[i].type; - mContentMetaInfo[i].attributes = info[i].attributes; + { + cmeta.id = info[i].id.get(); + cmeta.version = info[i].version.get(); + cmeta.type = (cnmt::ContentMetaType)info[i].type; + cmeta.attributes = info[i].attributes; + mContentMetaInfo.addElement(cmeta); } } @@ -108,17 +146,21 @@ void nx::ContentMetaBinary::importBinary(const byte_t * bytes, size_t len) if (exdata_size > 0) { mExtendedData.alloc(exdata_size); - memcpy(mExtendedData.getBytes(), bytes + getExtendedDataOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get()), exdata_size); + memcpy(mExtendedData.data(), data + getExtendedDataOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get()), exdata_size); } // save digest - memcpy(mDigest.data, bytes + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cnmt::kDigestLen); + memcpy(mDigest.data, data + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cnmt::kDigestLen); +} +const fnd::Vec& nx::ContentMetaBinary::getBytes() const +{ + return mRawBinary; } void nx::ContentMetaBinary::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mTitleId = 0; mTitleVersion = 0; mType = cnmt::METATYPE_SYSTEM_PROGRAM; @@ -245,12 +287,12 @@ void nx::ContentMetaBinary::setContentMetaInfo(const fnd::List & nx::ContentMetaBinary::getExtendedData() const { return mExtendedData; } -void nx::ContentMetaBinary::setExtendedData(const fnd::MemoryBlob & data) +void nx::ContentMetaBinary::setExtendedData(const fnd::Vec & data) { mExtendedData = data; } @@ -307,7 +349,7 @@ size_t nx::ContentMetaBinary::getExtendedDataSize(cnmt::ContentMetaType type, co return exdata_len; } -void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len) const +void nx::ContentMetaBinary::validateBinary(const byte_t * data, size_t len) const { // check if it is large enough to read the header if (len < sizeof(sContentMetaHeader)) @@ -316,7 +358,7 @@ void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len) con } // get pointer to header structure - const sContentMetaHeader* hdr = (const sContentMetaHeader*)bytes; + const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; // validate extended header size if (validateExtendedHeaderSize((cnmt::ContentMetaType)hdr->type, hdr->exhdr_size.get()) == false) @@ -331,52 +373,8 @@ void nx::ContentMetaBinary::validateBinary(const byte_t * bytes, size_t len) con } // check binary size again with extended data size - if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cnmt::ContentMetaType)hdr->type, bytes + getExtendedHeaderOffset()))) + if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cnmt::ContentMetaType)hdr->type, data + getExtendedHeaderOffset()))) { throw fnd::Exception(kModuleName, "Binary too small"); } -} - -bool nx::ContentMetaBinary::isEqual(const ContentMetaBinary & other) const -{ - return (mTitleId == other.mTitleId) \ - && (mTitleVersion == other.mTitleVersion) \ - && (mType == other.mType) \ - && (mAttributes == other.mAttributes) \ - && (mRequiredDownloadSystemVersion == other.mRequiredDownloadSystemVersion) \ - && (mExtendedHeader == other.mExtendedHeader) \ - && (mApplicationMetaExtendedHeader == other.mApplicationMetaExtendedHeader) \ - && (mPatchMetaExtendedHeader == other.mPatchMetaExtendedHeader) \ - && (mAddOnContentMetaExtendedHeader == other.mAddOnContentMetaExtendedHeader) \ - && (mDeltaMetaExtendedHeader == other.mDeltaMetaExtendedHeader) \ - && (mContentInfo == other.mContentInfo) \ - && (mContentMetaInfo == other.mContentMetaInfo) \ - && (mExtendedData == other.mExtendedData) \ - && (memcmp(mDigest.data, other.mDigest.data, cnmt::kDigestLen) == 0); -} - -void nx::ContentMetaBinary::copyFrom(const ContentMetaBinary & other) -{ - if (other.getSize() > 0) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - clear(); - mTitleId = other.mTitleId; - mTitleVersion = other.mTitleVersion; - mType = other.mType; - mAttributes = other.mAttributes; - mRequiredDownloadSystemVersion = other.mRequiredDownloadSystemVersion; - mExtendedHeader = other.mExtendedHeader; - mApplicationMetaExtendedHeader = other.mApplicationMetaExtendedHeader; - mPatchMetaExtendedHeader = other.mPatchMetaExtendedHeader; - mAddOnContentMetaExtendedHeader = other.mAddOnContentMetaExtendedHeader; - mDeltaMetaExtendedHeader = other.mDeltaMetaExtendedHeader; - mContentInfo = other.mContentInfo; - mContentMetaInfo = other.mContentMetaInfo; - mExtendedData = other.mExtendedData; - memcpy(mDigest.data, other.mDigest.data, cnmt::kDigestLen); - } -} +} \ No newline at end of file diff --git a/lib/libnx/source/FacBinary.cpp b/lib/libnx/source/FacBinary.cpp deleted file mode 100644 index a955591..0000000 --- a/lib/libnx/source/FacBinary.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include - - - -nx::FacBinary::FacBinary() -{} - -nx::FacBinary::FacBinary(const FacBinary & other) -{ - copyFrom(other); -} - -nx::FacBinary::FacBinary(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::FacBinary::operator==(const FacBinary & other) const -{ - return isEqual(other); -} - -bool nx::FacBinary::operator!=(const FacBinary & other) const -{ - return !isEqual(other); -} - -void nx::FacBinary::operator=(const FacBinary & other) -{ - copyFrom(other); -} - -const byte_t * nx::FacBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::FacBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::FacBinary::exportBinary() -{ - FacHeader::setContentOwnerIdSize(mContentOwnerIdList.getSize() * sizeof(uint32_t)); - FacHeader::setSaveDataOwnerIdSize(mSaveDataOwnerIdList.getSize() * sizeof(uint32_t)); - FacHeader::exportBinary(); - - mBinaryBlob.alloc(getFacSize()); - memcpy(mBinaryBlob.getBytes(), FacHeader::getBytes(), FacHeader::getSize()); - - uint32_t* rawContentOwnerIds = (uint32_t*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset()); - for (size_t i = 0; i < mContentOwnerIdList.getSize(); i++) - { - rawContentOwnerIds[i] = le_word(mContentOwnerIdList[i]); - } - - uint32_t* rawSaveDataOwnerIds = (uint32_t*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset()); - for (size_t i = 0; i < mSaveDataOwnerIdList.getSize(); i++) - { - rawSaveDataOwnerIds[i] = le_word(mSaveDataOwnerIdList[i]); - } -} - -void nx::FacBinary::importBinary(const byte_t * bytes, size_t len) -{ - clear(); - FacHeader::importBinary(bytes, len); - if (FacHeader::getFacSize() > len) - { - throw fnd::Exception(kModuleName, "FAC binary too small"); - } - - mBinaryBlob.alloc(FacHeader::getFacSize()); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - - uint32_t* rawContentOwnerIds = (uint32_t*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset()); - size_t rawContentOwnerIdNum = FacHeader::getContentOwnerIdSize() / sizeof(uint32_t); - for (size_t i = 0; i < rawContentOwnerIdNum; i++) - { - mContentOwnerIdList.addElement(le_word(rawContentOwnerIds[i])); - } - - uint32_t* rawSaveDataOwnerIds = (uint32_t*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset()); - size_t rawSaveDataOwnerIdNum = FacHeader::getSaveDataOwnerIdSize() / sizeof(uint32_t); - for (size_t i = 0; i < rawSaveDataOwnerIdNum; i++) - { - mSaveDataOwnerIdList.addElement(le_word(rawSaveDataOwnerIds[i])); - } -} - -bool nx::FacBinary::isEqual(const FacBinary & other) const -{ - return (FacHeader::operator==(other)) \ - && (mContentOwnerIdList == other.mContentOwnerIdList) \ - && (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList); -} - -void nx::FacBinary::copyFrom(const FacBinary & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - FacHeader::operator=(other); - mContentOwnerIdList = other.mContentOwnerIdList; - mSaveDataOwnerIdList = other.mSaveDataOwnerIdList; - } -} - -void nx::FacBinary::clear() -{ - FacHeader::clear(); - mContentOwnerIdList.clear(); - mSaveDataOwnerIdList.clear(); -} - -const fnd::List& nx::FacBinary::getContentOwnerIdList() const -{ - return mContentOwnerIdList; -} - -void nx::FacBinary::setContentOwnerIdList(const fnd::List& list) -{ - mContentOwnerIdList = list; -} - -const fnd::List& nx::FacBinary::getSaveDataOwnerIdList() const -{ - return mSaveDataOwnerIdList; -} - -void nx::FacBinary::setSaveDataOwnerIdList(const fnd::List& list) -{ - mSaveDataOwnerIdList = list; -} diff --git a/lib/libnx/source/FacHeader.cpp b/lib/libnx/source/FacHeader.cpp deleted file mode 100644 index 7c09b21..0000000 --- a/lib/libnx/source/FacHeader.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include - - - -nx::FacHeader::FacHeader() : - mFsaRights() -{ - clear(); -} - -nx::FacHeader::FacHeader(const FacHeader & other) : - mFsaRights() -{ - copyFrom(other); -} - -nx::FacHeader::FacHeader(const byte_t * bytes, size_t len) : - mFsaRights() -{ - importBinary(bytes, len); -} - -bool nx::FacHeader::operator==(const FacHeader & other) const -{ - return isEqual(other); -} - -bool nx::FacHeader::operator!=(const FacHeader & other) const -{ - return !isEqual(other); -} - -void nx::FacHeader::operator=(const FacHeader & other) -{ - copyFrom(other); -} - -const byte_t * nx::FacHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::FacHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::FacHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sFacHeader)); - sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes(); - - if (mVersion != kFacFormatVersion) - { - fnd::Exception(kModuleName, "Unsupported format version"); - } - hdr->version = (mVersion); - - uint64_t flag = 0; - for (size_t i = 0; i < mFsaRights.getSize(); i++) - { - flag |= BIT((uint64_t)mFsaRights[i]); - } - hdr->fac_flags = (flag); - - calculateOffsets(); - hdr->content_owner_ids.start = (uint32_t)(mContentOwnerIdPos.offset); - hdr->content_owner_ids.end = (uint32_t)(mContentOwnerIdPos.offset + mContentOwnerIdPos.size); - hdr->save_data_owner_ids.start = (uint32_t)(mSaveDataOwnerIdPos.offset); - hdr->save_data_owner_ids.end = (uint32_t)(mSaveDataOwnerIdPos.offset + mSaveDataOwnerIdPos.size); -} - -void nx::FacHeader::importBinary(const byte_t * bytes, size_t len) -{ - if (len < sizeof(sFacHeader)) - { - throw fnd::Exception(kModuleName, "FAC header too small"); - } - - mBinaryBlob.alloc(sizeof(sFacHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes(); - - if (hdr->version.get() != kFacFormatVersion) - { - throw fnd::Exception(kModuleName, "Unsupported FAC format version"); - } - mVersion = hdr->version.get(); - - clear(); - for (uint64_t i = 0; i < 64; i++) - { - if ((hdr->fac_flags.get() >> i) & 1) - { - mFsaRights.addElement((FsAccessFlag)i); - } - } - mContentOwnerIdPos.offset = hdr->content_owner_ids.start.get(); - mContentOwnerIdPos.size = hdr->content_owner_ids.end.get() > hdr->content_owner_ids.start.get() ? hdr->content_owner_ids.end.get() - hdr->content_owner_ids.start.get() : 0; - mSaveDataOwnerIdPos.offset = hdr->save_data_owner_ids.start.get(); - mSaveDataOwnerIdPos.size = hdr->save_data_owner_ids.end.get() > hdr->save_data_owner_ids.start.get() ? hdr->save_data_owner_ids.end.get() - hdr->save_data_owner_ids.start.get() : 0; -} - -void nx::FacHeader::clear() -{ - mFsaRights.clear(); - mContentOwnerIdPos.offset = 0; - mContentOwnerIdPos.size = 0; - mSaveDataOwnerIdPos.offset = 0; - mSaveDataOwnerIdPos.size = 0; -} - -size_t nx::FacHeader::getFacSize() const -{ - size_t savedata = getSaveDataOwnerIdOffset() + getSaveDataOwnerIdSize(); - size_t content = getContentOwnerIdOffset() + getContentOwnerIdSize(); - return MAX(MAX(savedata, content), sizeof(sFacHeader)); -} - -uint32_t nx::FacHeader::getFormatVersion() const -{ - return mVersion; -} - -void nx::FacHeader::setFormatVersion(uint32_t version) -{ - mVersion = version; -} - -const fnd::List& nx::FacHeader::getFsaRightsList() const -{ - return mFsaRights; -} - -void nx::FacHeader::setFsaRightsList(const fnd::List& list) -{ - mFsaRights.clear(); - for (size_t i = 0; i < list.getSize(); i++) - { - mFsaRights.hasElement(list[i]) ? mFsaRights.addElement(list[i]) : throw fnd::Exception(kModuleName, "FSA right already exists"); - } -} - -size_t nx::FacHeader::getContentOwnerIdOffset() const -{ - return mContentOwnerIdPos.offset; -} - -size_t nx::FacHeader::getContentOwnerIdSize() const -{ - return mContentOwnerIdPos.size; -} - -void nx::FacHeader::setContentOwnerIdSize(size_t size) -{ - mContentOwnerIdPos.size = size; -} - -size_t nx::FacHeader::getSaveDataOwnerIdOffset() const -{ - return mSaveDataOwnerIdPos.offset; -} - -size_t nx::FacHeader::getSaveDataOwnerIdSize() const -{ - return mSaveDataOwnerIdPos.size; -} - -void nx::FacHeader::setSaveDataOwnerIdSize(size_t size) -{ - mSaveDataOwnerIdPos.size = size; -} - -void nx::FacHeader::calculateOffsets() -{ - mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4); - mSaveDataOwnerIdPos.offset = mContentOwnerIdPos.offset + align(mContentOwnerIdPos.size, 4); -} - -bool nx::FacHeader::isEqual(const FacHeader & other) const -{ - return (mFsaRights == other.mFsaRights) \ - && (mContentOwnerIdPos.offset == other.mContentOwnerIdPos.offset) \ - && (mContentOwnerIdPos.size == other.mContentOwnerIdPos.size) \ - && (mSaveDataOwnerIdPos.offset == other.mSaveDataOwnerIdPos.offset) \ - && (mSaveDataOwnerIdPos.size == other.mSaveDataOwnerIdPos.size); -} - -void nx::FacHeader::copyFrom(const FacHeader & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mBinaryBlob.clear(); - mFsaRights = other.mFsaRights; - mContentOwnerIdPos.offset = other.mContentOwnerIdPos.offset; - mContentOwnerIdPos.size = other.mContentOwnerIdPos.size; - mSaveDataOwnerIdPos.offset = other.mSaveDataOwnerIdPos.offset; - mSaveDataOwnerIdPos.size = other.mSaveDataOwnerIdPos.size; - } -} diff --git a/lib/libnx/source/FileSystemAccessControlBinary.cpp b/lib/libnx/source/FileSystemAccessControlBinary.cpp new file mode 100644 index 0000000..60b1971 --- /dev/null +++ b/lib/libnx/source/FileSystemAccessControlBinary.cpp @@ -0,0 +1,205 @@ +#include + +#include + +nx::FileSystemAccessControlBinary::FileSystemAccessControlBinary() +{ + clear(); +} + +nx::FileSystemAccessControlBinary::FileSystemAccessControlBinary(const FileSystemAccessControlBinary & other) +{ + *this = other; +} + +void nx::FileSystemAccessControlBinary::operator=(const FileSystemAccessControlBinary & other) +{ + mRawBinary = other.mRawBinary; + mVersion = other.mVersion; + mFsaRights = other.mFsaRights; + mContentOwnerIdList = other.mContentOwnerIdList; + mSaveDataOwnerIdList = other.mSaveDataOwnerIdList; +} + +bool nx::FileSystemAccessControlBinary::operator==(const FileSystemAccessControlBinary & other) const +{ + return (mVersion == other.mVersion) \ + && (mFsaRights == other.mFsaRights) \ + && (mContentOwnerIdList == other.mContentOwnerIdList) \ + && (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList); +} + +bool nx::FileSystemAccessControlBinary::operator!=(const FileSystemAccessControlBinary & other) const +{ + return !(*this == other); +} + +void nx::FileSystemAccessControlBinary::toBytes() +{ + // determine section layout + struct sLayout { + uint32_t offset, size; + } content, savedata; + + content.offset = align(sizeof(sFacHeader), fac::kSectionAlignSize); + content.size = (uint32_t)(mContentOwnerIdList.size() * sizeof(uint32_t)); + savedata.offset = content.offset + align(content.size, fac::kSectionAlignSize); + savedata.size = (uint32_t)(mSaveDataOwnerIdList.size() * sizeof(uint32_t)); + + // get total size + size_t total_size = _MAX(_MAX(content.offset + content.size, savedata.offset + savedata.size), align(sizeof(sFacHeader), fac::kSectionAlignSize)); + + mRawBinary.alloc(total_size); + sFacHeader* hdr = (sFacHeader*)mRawBinary.data(); + + // set type + hdr->version = mVersion; + + // flags + uint64_t flag = 0; + for (size_t i = 0; i < mFsaRights.size(); i++) + { + flag |= _BIT((uint64_t)mFsaRights[i]); + } + hdr->fac_flags = flag; + + // set offset/size + hdr->content_owner_ids.start = content.offset; + if (content.size > 0) + hdr->content_owner_ids.end = content.offset + content.size; + hdr->save_data_owner_ids.start = savedata.offset; + if (savedata.size > 0) + hdr->save_data_owner_ids.end = savedata.offset + savedata.size; + + // set ids + le_uint32_t* content_owner_ids = (le_uint32_t*)(mRawBinary.data() + content.offset); + for (size_t i = 0; i < mContentOwnerIdList.size(); i++) + { + content_owner_ids[i] = mContentOwnerIdList[i]; + } + + le_uint32_t* save_data_owner_ids = (le_uint32_t*)(mRawBinary.data() + savedata.offset); + for (size_t i = 0; i < mSaveDataOwnerIdList.size(); i++) + { + save_data_owner_ids[i] = mSaveDataOwnerIdList[i]; + } +} + +void nx::FileSystemAccessControlBinary::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sFacHeader)) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sFacHeader hdr; + memcpy((void*)&hdr, data, sizeof(sFacHeader)); + + // check format version + if (hdr.version.get() != fac::kFacFormatVersion) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo format version unsupported"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.content_owner_ids.end.get(), hdr.save_data_owner_ids.end.get()), align(sizeof(sFacHeader), fac::kSectionAlignSize)); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); + } + + // allocate memory + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + mVersion = hdr.version.get(); + for (size_t i = 0; i < 64; i++) + { + if (_HAS_BIT(hdr.fac_flags.get(), i)) + { + mFsaRights.addElement((fac::FsAccessFlag)i); + } + } + + // save ids + if (hdr.content_owner_ids.end.get() > hdr.content_owner_ids.start.get()) + { + le_uint32_t* content_owner_ids = (le_uint32_t*)(mRawBinary.data() + hdr.content_owner_ids.start.get()); + size_t content_owner_id_num = (hdr.content_owner_ids.end.get() - hdr.content_owner_ids.start.get()) / sizeof(uint32_t); + for (size_t i = 0; i < content_owner_id_num; i++) + { + mContentOwnerIdList.addElement(content_owner_ids[i].get()); + } + } + if (hdr.save_data_owner_ids.end.get() > hdr.save_data_owner_ids.start.get()) + { + le_uint32_t* save_data_owner_ids = (le_uint32_t*)(mRawBinary.data() + hdr.save_data_owner_ids.start.get()); + size_t save_data_owner_id_num = (hdr.save_data_owner_ids.end.get() - hdr.save_data_owner_ids.start.get()) / sizeof(uint32_t); + for (size_t i = 0; i < save_data_owner_id_num; i++) + { + mSaveDataOwnerIdList.addElement(save_data_owner_ids[i].get()); + } + } +} + +const fnd::Vec& nx::FileSystemAccessControlBinary::getBytes() const +{ + return mRawBinary; +} + +void nx::FileSystemAccessControlBinary::clear() +{ + mRawBinary.clear(); + mVersion = 0; + mFsaRights.clear(); + mContentOwnerIdList.clear(); + mSaveDataOwnerIdList.clear(); +} + +uint32_t nx::FileSystemAccessControlBinary::getFormatVersion() const +{ + return mVersion; +} + +void nx::FileSystemAccessControlBinary::setFormatVersion(uint32_t format_version) +{ + mVersion = format_version; +} + +const fnd::List& nx::FileSystemAccessControlBinary::getFsaRightsList() const +{ + return mFsaRights; +} + +void nx::FileSystemAccessControlBinary::setFsaRightsList(const fnd::List& list) +{ + mFsaRights = list; +} + +const fnd::List& nx::FileSystemAccessControlBinary::getContentOwnerIdList() const +{ + return mContentOwnerIdList; +} + +void nx::FileSystemAccessControlBinary::setContentOwnerIdList(const fnd::List& list) +{ + mContentOwnerIdList = list; +} + +const fnd::List& nx::FileSystemAccessControlBinary::getSaveDataOwnerIdList() const +{ + return mSaveDataOwnerIdList; +} + +void nx::FileSystemAccessControlBinary::setSaveDataOwnerIdList(const fnd::List& list) +{ + mSaveDataOwnerIdList = list; +} \ No newline at end of file diff --git a/lib/libnx/source/HandleTableSizeEntry.cpp b/lib/libnx/source/HandleTableSizeEntry.cpp index 19a4315..c01471c 100644 --- a/lib/libnx/source/HandleTableSizeEntry.cpp +++ b/lib/libnx/source/HandleTableSizeEntry.cpp @@ -1,13 +1,11 @@ #include - - nx::HandleTableSizeEntry::HandleTableSizeEntry() : mCap(kCapId), mHandleTableSize(0) {} -nx::HandleTableSizeEntry::HandleTableSizeEntry(const KernelCapability & kernel_cap) : +nx::HandleTableSizeEntry::HandleTableSizeEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mHandleTableSize(0) { @@ -21,16 +19,33 @@ nx::HandleTableSizeEntry::HandleTableSizeEntry(uint16_t size) : setHandleTableSize(size); } -const nx::KernelCapability & nx::HandleTableSizeEntry::getKernelCapability() const +void nx::HandleTableSizeEntry::operator=(const HandleTableSizeEntry& other) +{ + mHandleTableSize = other.mHandleTableSize; + updateCapField(); +} + +bool nx::HandleTableSizeEntry::operator==(const HandleTableSizeEntry& other) const +{ + return (mHandleTableSize == other.mHandleTableSize); +} + +bool nx::HandleTableSizeEntry::operator!=(const HandleTableSizeEntry& other) const +{ + return !(*this == other); +} + + +const nx::KernelCapabilityEntry & nx::HandleTableSizeEntry::getKernelCapability() const { return mCap; } -void nx::HandleTableSizeEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::HandleTableSizeEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'HandleTableSize'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'HandleTableSize'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/HandleTableSizeHandler.cpp b/lib/libnx/source/HandleTableSizeHandler.cpp index 2b91a56..da1bda1 100644 --- a/lib/libnx/source/HandleTableSizeHandler.cpp +++ b/lib/libnx/source/HandleTableSizeHandler.cpp @@ -1,42 +1,42 @@ #include - - nx::HandleTableSizeHandler::HandleTableSizeHandler() : mIsSet(false), mEntry(0) {} +void nx::HandleTableSizeHandler::operator=(const HandleTableSizeHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + bool nx::HandleTableSizeHandler::operator==(const HandleTableSizeHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); } bool nx::HandleTableSizeHandler::operator!=(const HandleTableSizeHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::HandleTableSizeHandler::operator=(const HandleTableSizeHandler & other) +void nx::HandleTableSizeHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::HandleTableSizeHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() > kMaxKernelCapNum) + if (caps.size() > kMaxKernelCapNum) { throw fnd::Exception(kModuleName, "Too many kernel capabilities"); } - if (caps.getSize() == 0) + if (caps.size() == 0) return; mEntry.setKernelCapability(caps[0]); mIsSet = true; } -void nx::HandleTableSizeHandler::exportKernelCapabilityList(fnd::List& caps) const +void nx::HandleTableSizeHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -64,16 +64,4 @@ void nx::HandleTableSizeHandler::setHandleTableSize(uint16_t size) { mEntry.setHandleTableSize(size); mIsSet = true; -} - -void nx::HandleTableSizeHandler::copyFrom(const HandleTableSizeHandler & other) -{ - mIsSet = other.mIsSet; - mEntry.setKernelCapability(other.mEntry.getKernelCapability()); -} - -bool nx::HandleTableSizeHandler::isEqual(const HandleTableSizeHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); -} +} \ No newline at end of file diff --git a/lib/libnx/source/HierarchicalIntegrityHeader.cpp b/lib/libnx/source/HierarchicalIntegrityHeader.cpp index 3eee01d..6454400 100644 --- a/lib/libnx/source/HierarchicalIntegrityHeader.cpp +++ b/lib/libnx/source/HierarchicalIntegrityHeader.cpp @@ -8,45 +8,40 @@ nx::HierarchicalIntegrityHeader::HierarchicalIntegrityHeader() nx::HierarchicalIntegrityHeader::HierarchicalIntegrityHeader(const HierarchicalIntegrityHeader & other) { - copyFrom(other); -} - -nx::HierarchicalIntegrityHeader::HierarchicalIntegrityHeader(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::HierarchicalIntegrityHeader::operator==(const HierarchicalIntegrityHeader & other) const -{ - return isEqual(other); -} - -bool nx::HierarchicalIntegrityHeader::operator!=(const HierarchicalIntegrityHeader & other) const -{ - return !isEqual(other); + *this = other; } void nx::HierarchicalIntegrityHeader::operator=(const HierarchicalIntegrityHeader & other) { - copyFrom(other); + if (other.getBytes().size() != 0) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + mLayerInfo = other.mLayerInfo; + mMasterHashList = other.mMasterHashList; + } } -const byte_t * nx::HierarchicalIntegrityHeader::getBytes() const +bool nx::HierarchicalIntegrityHeader::operator==(const HierarchicalIntegrityHeader & other) const { - return mBinaryBlob.getBytes(); + return (mLayerInfo == other.mLayerInfo) \ + && (mMasterHashList == other.mMasterHashList); } -size_t nx::HierarchicalIntegrityHeader::getSize() const +bool nx::HierarchicalIntegrityHeader::operator!=(const HierarchicalIntegrityHeader & other) const { - return mBinaryBlob.getSize(); + return !(*this == other); } -void nx::HierarchicalIntegrityHeader::exportBinary() +void nx::HierarchicalIntegrityHeader::toBytes() { throw fnd::Exception(kModuleName, "exportBinary() not implemented"); } -void nx::HierarchicalIntegrityHeader::importBinary(const byte_t * bytes, size_t len) +void nx::HierarchicalIntegrityHeader::fromBytes(const byte_t* data, size_t len) { std::stringstream error_str; @@ -56,10 +51,10 @@ void nx::HierarchicalIntegrityHeader::importBinary(const byte_t * bytes, size_t throw fnd::Exception(kModuleName, "Header too small"); } - const nx::sHierarchicalIntegrityHeader* hdr = (const nx::sHierarchicalIntegrityHeader*)bytes; + const nx::sHierarchicalIntegrityHeader* hdr = (const nx::sHierarchicalIntegrityHeader*)data; // Validate Header Sig "IVFC" - if (hdr->signature.get() != hierarchicalintegrity::kStructSig) + if (hdr->st_magic.get() != hierarchicalintegrity::kStructMagic) { throw fnd::Exception(kModuleName, "Invalid struct magic"); } @@ -92,24 +87,29 @@ void nx::HierarchicalIntegrityHeader::importBinary(const byte_t * bytes, size_t } // copy to internal storage - mBinaryBlob.alloc(total_size); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); // save layer info - const nx::sHierarchicalIntegrityLayerInfo* layer_info = (const nx::sHierarchicalIntegrityLayerInfo*)(mBinaryBlob.getBytes() + sizeof(nx::sHierarchicalIntegrityHeader)); + const nx::sHierarchicalIntegrityLayerInfo* layer_info = (const nx::sHierarchicalIntegrityLayerInfo*)(mRawBinary.data() + sizeof(nx::sHierarchicalIntegrityHeader)); for (size_t i = 0; i < hierarchicalintegrity::kDefaultLayerNum; i++) { mLayerInfo.addElement({layer_info[i].offset.get(), layer_info[i].size.get(), layer_info[i].block_size.get()}); } // save hash list - const crypto::sha::sSha256Hash* hash_list = (const crypto::sha::sSha256Hash*)(mBinaryBlob.getBytes() + master_hash_offset); + const crypto::sha::sSha256Hash* hash_list = (const crypto::sha::sSha256Hash*)(mRawBinary.data() + master_hash_offset); for (size_t i = 0; i < hdr->master_hash_size.get()/sizeof(crypto::sha::sSha256Hash); i++) { mMasterHashList.addElement(hash_list[i]); } } +const fnd::Vec& nx::HierarchicalIntegrityHeader::getBytes() const +{ + return mRawBinary; +} + void nx::HierarchicalIntegrityHeader::clear() { mLayerInfo.clear(); @@ -134,23 +134,4 @@ const fnd::List& nx::HierarchicalIntegrityHeader::getM void nx::HierarchicalIntegrityHeader::setMasterHashList(const fnd::List& master_hash_list) { mMasterHashList = master_hash_list; -} - -bool nx::HierarchicalIntegrityHeader::isEqual(const HierarchicalIntegrityHeader & other) const -{ - return (mLayerInfo == other.mLayerInfo) \ - && (mMasterHashList == other.mMasterHashList); -} - -void nx::HierarchicalIntegrityHeader::copyFrom(const HierarchicalIntegrityHeader & other) -{ - if (other.getSize() != 0) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mLayerInfo = other.mLayerInfo; - mMasterHashList = other.mMasterHashList; - } -} +} \ No newline at end of file diff --git a/lib/libnx/source/HierarchicalSha256Header.cpp b/lib/libnx/source/HierarchicalSha256Header.cpp index a7d288d..e199075 100644 --- a/lib/libnx/source/HierarchicalSha256Header.cpp +++ b/lib/libnx/source/HierarchicalSha256Header.cpp @@ -1,7 +1,6 @@ #include #include - nx::HierarchicalSha256Header::HierarchicalSha256Header() { clear(); @@ -9,45 +8,41 @@ nx::HierarchicalSha256Header::HierarchicalSha256Header() nx::HierarchicalSha256Header::HierarchicalSha256Header(const HierarchicalSha256Header & other) { - copyFrom(other); -} - -nx::HierarchicalSha256Header::HierarchicalSha256Header(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::HierarchicalSha256Header::operator==(const HierarchicalSha256Header & other) const -{ - return isEqual(other); -} - -bool nx::HierarchicalSha256Header::operator!=(const HierarchicalSha256Header & other) const -{ - return !isEqual(other); + *this = other; } void nx::HierarchicalSha256Header::operator=(const HierarchicalSha256Header & other) { - copyFrom(other); + if (other.getBytes().size() != 0) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + mMasterHash = other.mMasterHash; + mHashBlockSize = other.mHashBlockSize; + mLayerInfo = other.mLayerInfo; + } } -const byte_t * nx::HierarchicalSha256Header::getBytes() const +bool nx::HierarchicalSha256Header::operator==(const HierarchicalSha256Header & other) const { - return mBinaryBlob.getBytes(); + return (mMasterHash == other.mMasterHash) \ + && (mHashBlockSize == other.mHashBlockSize) \ + && (mLayerInfo == other.mLayerInfo); } -size_t nx::HierarchicalSha256Header::getSize() const +bool nx::HierarchicalSha256Header::operator!=(const HierarchicalSha256Header & other) const { - return mBinaryBlob.getSize(); + return !(*this == other); } -void nx::HierarchicalSha256Header::exportBinary() +void nx::HierarchicalSha256Header::toBytes() { throw fnd::Exception(kModuleName, "exportBinary() not implemented"); } -void nx::HierarchicalSha256Header::importBinary(const byte_t * bytes, size_t len) +void nx::HierarchicalSha256Header::fromBytes(const byte_t* data, size_t len) { std::stringstream error_str; @@ -56,7 +51,7 @@ void nx::HierarchicalSha256Header::importBinary(const byte_t * bytes, size_t len throw fnd::Exception(kModuleName, "Header too small"); } - const nx::sHierarchicalSha256Header* hdr = (const nx::sHierarchicalSha256Header*)bytes; + const nx::sHierarchicalSha256Header* hdr = (const nx::sHierarchicalSha256Header*)data; if (hdr->layer_num.get() != nx::hierarchicalsha256::kDefaultLayerNum) { @@ -74,6 +69,11 @@ void nx::HierarchicalSha256Header::importBinary(const byte_t * bytes, size_t len } } +const fnd::Vec& nx::HierarchicalSha256Header::getBytes() const +{ + return mRawBinary; +} + void nx::HierarchicalSha256Header::clear() { memset(mMasterHash.bytes, 0, sizeof(crypto::sha::sSha256Hash)); @@ -109,25 +109,4 @@ const fnd::List& nx::HierarchicalSha256Hea void nx::HierarchicalSha256Header::setLayerInfo(const fnd::List& layer_info) { mLayerInfo = layer_info; -} - -bool nx::HierarchicalSha256Header::isEqual(const HierarchicalSha256Header & other) const -{ - return (mMasterHash == other.mMasterHash) \ - && (mHashBlockSize == other.mHashBlockSize) \ - && (mLayerInfo == other.mLayerInfo); -} - -void nx::HierarchicalSha256Header::copyFrom(const HierarchicalSha256Header & other) -{ - if (other.getSize() != 0) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mMasterHash = other.mMasterHash; - mHashBlockSize = other.mHashBlockSize; - mLayerInfo = other.mLayerInfo; - } -} +} \ No newline at end of file diff --git a/lib/libnx/source/InteruptEntry.cpp b/lib/libnx/source/InteruptEntry.cpp index ba25b62..ef07c4f 100644 --- a/lib/libnx/source/InteruptEntry.cpp +++ b/lib/libnx/source/InteruptEntry.cpp @@ -1,7 +1,5 @@ #include - - nx::InteruptEntry::InteruptEntry() : mCap(kCapId), mInterupt{0,0} @@ -9,7 +7,7 @@ nx::InteruptEntry::InteruptEntry() : } -nx::InteruptEntry::InteruptEntry(const KernelCapability & kernel_cap) : +nx::InteruptEntry::InteruptEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mInterupt{ 0,0 } { @@ -24,16 +22,34 @@ nx::InteruptEntry::InteruptEntry(uint32_t interupt0, uint32_t interupt1) : setInterupt(1, interupt1); } -const nx::KernelCapability & nx::InteruptEntry::getKernelCapability() const +void nx::InteruptEntry::operator=(const InteruptEntry& other) +{ + mInterupt[0] = other.mInterupt[0]; + mInterupt[1] = other.mInterupt[1]; + updateCapField(); +} + +bool nx::InteruptEntry::operator==(const InteruptEntry& other) const +{ + return (mInterupt[0] == other.mInterupt[0]) \ + && (mInterupt[1] == other.mInterupt[1]); +} + +bool nx::InteruptEntry::operator!=(const InteruptEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::InteruptEntry::getKernelCapability() const { return mCap; } -void nx::InteruptEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::InteruptEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'EnableInterupts'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'EnableInterupts'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/InteruptHandler.cpp b/lib/libnx/source/InteruptHandler.cpp index 551d52b..b2e95f1 100644 --- a/lib/libnx/source/InteruptHandler.cpp +++ b/lib/libnx/source/InteruptHandler.cpp @@ -1,41 +1,41 @@ #include - - nx::InteruptHandler::InteruptHandler() : mIsSet(false), mInterupts() {} +void nx::InteruptHandler::operator=(const InteruptHandler & other) +{ + mIsSet = other.mIsSet; + mInterupts = other.mInterupts; +} + bool nx::InteruptHandler::operator==(const InteruptHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mInterupts == other.mInterupts); } bool nx::InteruptHandler::operator!=(const InteruptHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::InteruptHandler::operator=(const InteruptHandler & other) +void nx::InteruptHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::InteruptHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() == 0) + if (caps.size() == 0) return; // convert to interupts fnd::List interupts; - for (size_t i = 0; i < caps.getSize(); i++) + for (size_t i = 0; i < caps.size(); i++) { interupts[i].setKernelCapability(caps[i]); } mInterupts.clear(); - for (size_t i = 0; i < interupts.getSize(); i++) + for (size_t i = 0; i < interupts.size(); i++) { // weird condition for first interupt if (interupts[i][1] == 0 && i == 0) @@ -58,18 +58,18 @@ void nx::InteruptHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::InteruptHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; size_t i = 0; - if (mInterupts.getSize() % 2) + if (mInterupts.size() % 2) { caps.addElement(InteruptEntry(mInterupts[i], 0).getKernelCapability()); i++; } - for (; i < mInterupts.getSize(); i += 2) + for (; i < mInterupts.size(); i += 2) { if (mInterupts[i] == InteruptEntry::kInteruptMax) { @@ -103,22 +103,10 @@ const fnd::List& nx::InteruptHandler::getInteruptList() const void nx::InteruptHandler::setInteruptList(const fnd::List& interupts) { mInterupts.clear(); - for (size_t i = 0; i < interupts.getSize(); i++) + for (size_t i = 0; i < interupts.size(); i++) { mInterupts.hasElement(interupts[i]) == false ? mInterupts.addElement(interupts[i]) : throw fnd::Exception(kModuleName, "Interupt already added"); } mIsSet = true; -} - -void nx::InteruptHandler::copyFrom(const InteruptHandler & other) -{ - mIsSet = other.mIsSet; - mInterupts = other.mInterupts; -} - -bool nx::InteruptHandler::isEqual(const InteruptHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mInterupts == other.mInterupts); -} +} \ No newline at end of file diff --git a/lib/libnx/source/KcBinary.cpp b/lib/libnx/source/KcBinary.cpp deleted file mode 100644 index 69330fe..0000000 --- a/lib/libnx/source/KcBinary.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include - - - -nx::KcBinary::KcBinary() -{} - -nx::KcBinary::KcBinary(const KcBinary & other) -{ - copyFrom(other); -} - -nx::KcBinary::KcBinary(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::KcBinary::operator==(const KcBinary & other) const -{ - return isEqual(other); -} - -bool nx::KcBinary::operator!=(const KcBinary & other) const -{ - return !isEqual(other); -} - -void nx::KcBinary::operator=(const KcBinary & other) -{ - copyFrom(other); -} - -const byte_t * nx::KcBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::KcBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::KcBinary::exportBinary() -{ - fnd::List caps; - - // get kernel capabiliteis - mThreadInfo.exportKernelCapabilityList(caps); - mSystemCalls.exportKernelCapabilityList(caps); - mMemoryMap.exportKernelCapabilityList(caps); - mInterupts.exportKernelCapabilityList(caps); - mMiscParams.exportKernelCapabilityList(caps); - mKernelVersion.exportKernelCapabilityList(caps); - mHandleTableSize.exportKernelCapabilityList(caps); - mMiscFlags.exportKernelCapabilityList(caps); - - // allocate memory - mBinaryBlob.alloc(caps.getSize() * sizeof(uint32_t)); - - // write to binary - uint32_t* raw_caps = (uint32_t*)mBinaryBlob.getBytes(); - for (size_t i = 0; i < caps.getSize(); i++) - { - raw_caps[i] = le_word(caps[i].getCap()); - } -} - -void nx::KcBinary::importBinary(const byte_t * bytes, size_t len) -{ - if ((len % sizeof(uint32_t)) != 0) - { - throw fnd::Exception(kModuleName, "KernelCapability list must be aligned to 4 bytes"); - } - - fnd::List threadInfoCaps; - fnd::List systemCallCaps; - fnd::List memoryMapCaps; - fnd::List interuptCaps; - fnd::List miscParamCaps; - fnd::List kernelVersionCaps; - fnd::List handleTableSizeCaps; - fnd::List miscFlagsCaps; - - const uint32_t* raw_caps = (const uint32_t*)bytes; - size_t cap_num = len / sizeof(uint32_t); - KernelCapability cap; - for (size_t i = 0; i < cap_num; i++) - { - cap.setCap(le_word(raw_caps[i])); - switch (cap.getType()) - { - case (KernelCapability::KC_THREAD_INFO) : - threadInfoCaps.addElement(cap); - break; - case (KernelCapability::KC_ENABLE_SYSTEM_CALLS): - systemCallCaps.addElement(cap); - break; - case (KernelCapability::KC_MEMORY_MAP): - case (KernelCapability::KC_IO_MEMORY_MAP): - memoryMapCaps.addElement(cap); - break; - case (KernelCapability::KC_ENABLE_INTERUPTS): - interuptCaps.addElement(cap); - break; - case (KernelCapability::KC_MISC_PARAMS): - miscParamCaps.addElement(cap); - break; - case (KernelCapability::KC_KERNEL_VERSION): - kernelVersionCaps.addElement(cap); - break; - case (KernelCapability::KC_HANDLE_TABLE_SIZE): - handleTableSizeCaps.addElement(cap); - break; - case (KernelCapability::KC_MISC_FLAGS): - miscFlagsCaps.addElement(cap); - break; - default: - throw fnd::Exception(kModuleName, "Unsupported kernel capability type"); - } - } - - mThreadInfo.importKernelCapabilityList(threadInfoCaps); - mSystemCalls.importKernelCapabilityList(systemCallCaps); - mMemoryMap.importKernelCapabilityList(memoryMapCaps); - mInterupts.importKernelCapabilityList(interuptCaps); - mMiscParams.importKernelCapabilityList(miscParamCaps); - mKernelVersion.importKernelCapabilityList(kernelVersionCaps); - mHandleTableSize.importKernelCapabilityList(handleTableSizeCaps); - mMiscFlags.importKernelCapabilityList(miscFlagsCaps); -} - -void nx::KcBinary::clear() -{ - mBinaryBlob.clear(); - mThreadInfo.clear(); - mSystemCalls.clear(); - mMemoryMap.clear(); - mInterupts.clear(); - mMiscParams.clear(); - mKernelVersion.clear(); - mHandleTableSize.clear(); - mMiscFlags.clear(); -} - -const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const -{ - return mThreadInfo; -} - -nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() -{ - return mThreadInfo; -} - -const nx::SystemCallHandler & nx::KcBinary::getSystemCalls() const -{ - return mSystemCalls; -} - -nx::SystemCallHandler & nx::KcBinary::getSystemCalls() -{ - return mSystemCalls; -} - -const nx::MemoryMappingHandler & nx::KcBinary::getMemoryMaps() const -{ - return mMemoryMap; -} - -nx::MemoryMappingHandler & nx::KcBinary::getMemoryMaps() -{ - return mMemoryMap; -} - -const nx::InteruptHandler & nx::KcBinary::getInterupts() const -{ - return mInterupts; -} - -nx::InteruptHandler & nx::KcBinary::getInterupts() -{ - return mInterupts; -} - -const nx::MiscParamsHandler & nx::KcBinary::getMiscParams() const -{ - return mMiscParams; -} - -nx::MiscParamsHandler & nx::KcBinary::getMiscParams() -{ - return mMiscParams; -} - -const nx::KernelVersionHandler & nx::KcBinary::getKernelVersion() const -{ - return mKernelVersion; -} - -nx::KernelVersionHandler & nx::KcBinary::getKernelVersion() -{ - return mKernelVersion; -} - -const nx::HandleTableSizeHandler & nx::KcBinary::getHandleTableSize() const -{ - return mHandleTableSize; -} - -nx::HandleTableSizeHandler & nx::KcBinary::getHandleTableSize() -{ - return mHandleTableSize; -} - -const nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags() const -{ - return mMiscFlags; -} - -nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags() -{ - return mMiscFlags; -} - -bool nx::KcBinary::isEqual(const KcBinary & other) const -{ - return (mThreadInfo == other.mThreadInfo) \ - && (mSystemCalls == other.mSystemCalls) \ - && (mMemoryMap == other.mMemoryMap) \ - && (mInterupts == other.mInterupts) \ - && (mMiscParams == other.mMiscParams) \ - && (mKernelVersion == other.mKernelVersion) \ - && (mHandleTableSize == other.mHandleTableSize) \ - && (mMiscFlags == other.mMiscFlags); -} - -void nx::KcBinary::copyFrom(const KcBinary & other) -{ - mThreadInfo = other.mThreadInfo; - mSystemCalls = other.mSystemCalls; - mMemoryMap = other.mMemoryMap; - mInterupts = other.mInterupts; - mMiscParams = other.mMiscParams; - mKernelVersion = other.mKernelVersion; - mHandleTableSize = other.mHandleTableSize; - mMiscFlags = other.mMiscFlags; -} diff --git a/lib/libnx/source/KernelCapability.cpp b/lib/libnx/source/KernelCapability.cpp deleted file mode 100644 index f924ce2..0000000 --- a/lib/libnx/source/KernelCapability.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include - -using namespace nx; - -KernelCapability::KernelCapability() : - mType(KC_INVALID) -{} - -KernelCapability::KernelCapability(KernelCapId type) : - mType(type), - mField(0) -{} - -KernelCapability::KernelCapability(KernelCapId type, uint32_t field) : - mType(type), - mField(field) -{} - -const KernelCapability & nx::KernelCapability::operator=(const KernelCapability & other) -{ - mType = other.mType; - mField = other.mField; - return *this; -} - -bool nx::KernelCapability::operator==(const KernelCapability & other) const -{ - return (mType == other.mType) \ - && (mField == other.mField); -} - -bool nx::KernelCapability::operator!=(const KernelCapability & other) const -{ - return !operator==(other); -} - -uint32_t KernelCapability::getCap() const -{ - return (mField & getFieldMask()) << getFieldShift() | getCapMask(); -} - -void KernelCapability::setCap(uint32_t cap) -{ - mType = getCapId(cap); - mField = (cap >> getFieldShift()) & getFieldMask(); -} - -KernelCapability::KernelCapId KernelCapability::getType() const -{ - return mType; -} - -void KernelCapability::setType(KernelCapId type) -{ - mType = type; -} - -uint32_t KernelCapability::getField() const -{ - return mField & getFieldMask(); -} - -void KernelCapability::setField(uint32_t field) -{ - mField = field; -} diff --git a/lib/libnx/source/KernelCapabilityBinary.cpp b/lib/libnx/source/KernelCapabilityBinary.cpp new file mode 100644 index 0000000..39f7425 --- /dev/null +++ b/lib/libnx/source/KernelCapabilityBinary.cpp @@ -0,0 +1,230 @@ +#include + +nx::KernelCapabilityBinary::KernelCapabilityBinary() +{} + +nx::KernelCapabilityBinary::KernelCapabilityBinary(const KernelCapabilityBinary & other) +{ + *this = other; +} + +void nx::KernelCapabilityBinary::operator=(const KernelCapabilityBinary & other) +{ + clear(); + mThreadInfo = other.mThreadInfo; + mSystemCalls = other.mSystemCalls; + mMemoryMap = other.mMemoryMap; + mInterupts = other.mInterupts; + mMiscParams = other.mMiscParams; + mKernelVersion = other.mKernelVersion; + mHandleTableSize = other.mHandleTableSize; + mMiscFlags = other.mMiscFlags; +} + +bool nx::KernelCapabilityBinary::operator==(const KernelCapabilityBinary & other) const +{ + return (mThreadInfo == other.mThreadInfo) \ + && (mSystemCalls == other.mSystemCalls) \ + && (mMemoryMap == other.mMemoryMap) \ + && (mInterupts == other.mInterupts) \ + && (mMiscParams == other.mMiscParams) \ + && (mKernelVersion == other.mKernelVersion) \ + && (mHandleTableSize == other.mHandleTableSize) \ + && (mMiscFlags == other.mMiscFlags); +} + +bool nx::KernelCapabilityBinary::operator!=(const KernelCapabilityBinary & other) const +{ + return !(*this == other); +} + +void nx::KernelCapabilityBinary::toBytes() +{ + fnd::List caps; + + // get kernel capabiliteis + mThreadInfo.exportKernelCapabilityList(caps); + mSystemCalls.exportKernelCapabilityList(caps); + mMemoryMap.exportKernelCapabilityList(caps); + mInterupts.exportKernelCapabilityList(caps); + mMiscParams.exportKernelCapabilityList(caps); + mKernelVersion.exportKernelCapabilityList(caps); + mHandleTableSize.exportKernelCapabilityList(caps); + mMiscFlags.exportKernelCapabilityList(caps); + + // allocate memory + mRawBinary.alloc(caps.size() * sizeof(uint32_t)); + + // write to binary + uint32_t* raw_caps = (uint32_t*)mRawBinary.data(); + for (size_t i = 0; i < caps.size(); i++) + { + raw_caps[i] = le_word(caps[i].getCap()); + } +} + +void nx::KernelCapabilityBinary::fromBytes(const byte_t * data, size_t len) +{ + if ((len % sizeof(uint32_t)) != 0) + { + throw fnd::Exception(kModuleName, "KernelCapabilityEntry list must be aligned to 4 bytes"); + } + + // save copy of KernelCapabilityBinary + mRawBinary.alloc(len); + memcpy(mRawBinary.data(), data, len); + + fnd::List threadInfoCaps; + fnd::List systemCallCaps; + fnd::List memoryMapCaps; + fnd::List interuptCaps; + fnd::List miscParamCaps; + fnd::List kernelVersionCaps; + fnd::List handleTableSizeCaps; + fnd::List miscFlagsCaps; + + const uint32_t* raw_caps = (const uint32_t*)mRawBinary.data(); + size_t cap_num = mRawBinary.size() / sizeof(uint32_t); + KernelCapabilityEntry cap; + for (size_t i = 0; i < cap_num; i++) + { + cap.setCap(le_word(raw_caps[i])); + switch (cap.getType()) + { + case (kc::KC_THREAD_INFO) : + threadInfoCaps.addElement(cap); + break; + case (kc::KC_ENABLE_SYSTEM_CALLS): + systemCallCaps.addElement(cap); + break; + case (kc::KC_MEMORY_MAP): + case (kc::KC_IO_MEMORY_MAP): + memoryMapCaps.addElement(cap); + break; + case (kc::KC_ENABLE_INTERUPTS): + interuptCaps.addElement(cap); + break; + case (kc::KC_MISC_PARAMS): + miscParamCaps.addElement(cap); + break; + case (kc::KC_KERNEL_VERSION): + kernelVersionCaps.addElement(cap); + break; + case (kc::KC_HANDLE_TABLE_SIZE): + handleTableSizeCaps.addElement(cap); + break; + case (kc::KC_MISC_FLAGS): + miscFlagsCaps.addElement(cap); + break; + default: + throw fnd::Exception(kModuleName, "Unsupported kernel capability type"); + } + } + + mThreadInfo.importKernelCapabilityList(threadInfoCaps); + mSystemCalls.importKernelCapabilityList(systemCallCaps); + mMemoryMap.importKernelCapabilityList(memoryMapCaps); + mInterupts.importKernelCapabilityList(interuptCaps); + mMiscParams.importKernelCapabilityList(miscParamCaps); + mKernelVersion.importKernelCapabilityList(kernelVersionCaps); + mHandleTableSize.importKernelCapabilityList(handleTableSizeCaps); + mMiscFlags.importKernelCapabilityList(miscFlagsCaps); +} + +const fnd::Vec& nx::KernelCapabilityBinary::getBytes() const +{ + return mRawBinary; +} + +void nx::KernelCapabilityBinary::clear() +{ + mRawBinary.clear(); + mThreadInfo.clear(); + mSystemCalls.clear(); + mMemoryMap.clear(); + mInterupts.clear(); + mMiscParams.clear(); + mKernelVersion.clear(); + mHandleTableSize.clear(); + mMiscFlags.clear(); +} + +const nx::ThreadInfoHandler & nx::KernelCapabilityBinary::getThreadInfo() const +{ + return mThreadInfo; +} + +nx::ThreadInfoHandler & nx::KernelCapabilityBinary::getThreadInfo() +{ + return mThreadInfo; +} + +const nx::SystemCallHandler & nx::KernelCapabilityBinary::getSystemCalls() const +{ + return mSystemCalls; +} + +nx::SystemCallHandler & nx::KernelCapabilityBinary::getSystemCalls() +{ + return mSystemCalls; +} + +const nx::MemoryMappingHandler & nx::KernelCapabilityBinary::getMemoryMaps() const +{ + return mMemoryMap; +} + +nx::MemoryMappingHandler & nx::KernelCapabilityBinary::getMemoryMaps() +{ + return mMemoryMap; +} + +const nx::InteruptHandler & nx::KernelCapabilityBinary::getInterupts() const +{ + return mInterupts; +} + +nx::InteruptHandler & nx::KernelCapabilityBinary::getInterupts() +{ + return mInterupts; +} + +const nx::MiscParamsHandler & nx::KernelCapabilityBinary::getMiscParams() const +{ + return mMiscParams; +} + +nx::MiscParamsHandler & nx::KernelCapabilityBinary::getMiscParams() +{ + return mMiscParams; +} + +const nx::KernelVersionHandler & nx::KernelCapabilityBinary::getKernelVersion() const +{ + return mKernelVersion; +} + +nx::KernelVersionHandler & nx::KernelCapabilityBinary::getKernelVersion() +{ + return mKernelVersion; +} + +const nx::HandleTableSizeHandler & nx::KernelCapabilityBinary::getHandleTableSize() const +{ + return mHandleTableSize; +} + +nx::HandleTableSizeHandler & nx::KernelCapabilityBinary::getHandleTableSize() +{ + return mHandleTableSize; +} + +const nx::MiscFlagsHandler & nx::KernelCapabilityBinary::getMiscFlags() const +{ + return mMiscFlags; +} + +nx::MiscFlagsHandler & nx::KernelCapabilityBinary::getMiscFlags() +{ + return mMiscFlags; +} \ No newline at end of file diff --git a/lib/libnx/source/KernelCapabilityEntry.cpp b/lib/libnx/source/KernelCapabilityEntry.cpp new file mode 100644 index 0000000..cbca030 --- /dev/null +++ b/lib/libnx/source/KernelCapabilityEntry.cpp @@ -0,0 +1,63 @@ +#include + +nx::KernelCapabilityEntry::KernelCapabilityEntry() : + mType(kc::KC_INVALID) +{} + +nx::KernelCapabilityEntry::KernelCapabilityEntry(kc::KernelCapId type) : + mType(type), + mField(0) +{} + +nx::KernelCapabilityEntry::KernelCapabilityEntry(kc::KernelCapId type, uint32_t field) : + mType(type), + mField(field) +{} + +void nx::KernelCapabilityEntry::operator=(const KernelCapabilityEntry & other) +{ + mType = other.mType; + mField = other.mField; +} + +bool nx::KernelCapabilityEntry::operator==(const KernelCapabilityEntry & other) const +{ + return (mType == other.mType) \ + && (mField == other.mField); +} + +bool nx::KernelCapabilityEntry::operator!=(const KernelCapabilityEntry & other) const +{ + return !operator==(other); +} + +uint32_t nx::KernelCapabilityEntry::getCap() const +{ + return (mField & getFieldMask()) << getFieldShift() | getCapMask(); +} + +void nx::KernelCapabilityEntry::setCap(uint32_t cap) +{ + mType = getCapId(cap); + mField = (cap >> getFieldShift()) & getFieldMask(); +} + +nx::kc::KernelCapId nx::KernelCapabilityEntry::getType() const +{ + return mType; +} + +void nx::KernelCapabilityEntry::setType(kc::KernelCapId type) +{ + mType = type; +} + +uint32_t nx::KernelCapabilityEntry::getField() const +{ + return mField & getFieldMask(); +} + +void nx::KernelCapabilityEntry::setField(uint32_t field) +{ + mField = field; +} diff --git a/lib/libnx/source/KernelVersionEntry.cpp b/lib/libnx/source/KernelVersionEntry.cpp index 69307b9..efd07ab 100644 --- a/lib/libnx/source/KernelVersionEntry.cpp +++ b/lib/libnx/source/KernelVersionEntry.cpp @@ -1,14 +1,12 @@ #include - - nx::KernelVersionEntry::KernelVersionEntry() : mCap(kCapId), mVerMajor(0), mVerMinor(0) {} -nx::KernelVersionEntry::KernelVersionEntry(const KernelCapability & kernel_cap) : +nx::KernelVersionEntry::KernelVersionEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mVerMajor(0), mVerMinor(0) @@ -25,16 +23,34 @@ nx::KernelVersionEntry::KernelVersionEntry(uint16_t major, uint8_t minor) : setVerMinor(minor); } -const nx::KernelCapability & nx::KernelVersionEntry::getKernelCapability() const +void nx::KernelVersionEntry::operator=(const KernelVersionEntry& other) +{ + mVerMajor = other.mVerMajor; + mVerMinor = other.mVerMinor; + updateCapField(); +} + +bool nx::KernelVersionEntry::operator==(const KernelVersionEntry& other) const +{ + return (mVerMajor == other.mVerMajor) \ + && (mVerMinor == other.mVerMinor); +} + +bool nx::KernelVersionEntry::operator!=(const KernelVersionEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::KernelVersionEntry::getKernelCapability() const { return mCap; } -void nx::KernelVersionEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::KernelVersionEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'KernelVersion'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'KernelVersion'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/KernelVersionHandler.cpp b/lib/libnx/source/KernelVersionHandler.cpp index aa06143..ee3e960 100644 --- a/lib/libnx/source/KernelVersionHandler.cpp +++ b/lib/libnx/source/KernelVersionHandler.cpp @@ -1,35 +1,35 @@ #include - - nx::KernelVersionHandler::KernelVersionHandler() : mIsSet(false), mEntry(0,0) {} +void nx::KernelVersionHandler::operator=(const KernelVersionHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + bool nx::KernelVersionHandler::operator==(const KernelVersionHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); } bool nx::KernelVersionHandler::operator!=(const KernelVersionHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::KernelVersionHandler::operator=(const KernelVersionHandler & other) +void nx::KernelVersionHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::KernelVersionHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() > kMaxKernelCapNum) + if (caps.size() > kMaxKernelCapNum) { throw fnd::Exception(kModuleName, "Too many kernel capabilities"); } - if (caps.getSize() == 0) + if (caps.size() == 0) return; mEntry.setKernelCapability(caps[0]); @@ -37,7 +37,7 @@ void nx::KernelVersionHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::KernelVersionHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -77,16 +77,4 @@ void nx::KernelVersionHandler::setVerMinor(uint8_t minor) { mEntry.setVerMinor(minor); mIsSet = true; -} - -void nx::KernelVersionHandler::copyFrom(const KernelVersionHandler & other) -{ - mIsSet = other.mIsSet; - mEntry.setKernelCapability(other.mEntry.getKernelCapability()); -} - -bool nx::KernelVersionHandler::isEqual(const KernelVersionHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); -} +} \ No newline at end of file diff --git a/lib/libnx/source/MemoryMappingHandler.cpp b/lib/libnx/source/MemoryMappingHandler.cpp index d8b29cf..4810f1b 100644 --- a/lib/libnx/source/MemoryMappingHandler.cpp +++ b/lib/libnx/source/MemoryMappingHandler.cpp @@ -1,48 +1,50 @@ #include #include - nx::MemoryMappingHandler::MemoryMappingHandler() : mIsSet(false) {} +void nx::MemoryMappingHandler::operator=(const MemoryMappingHandler & other) +{ + mIsSet = other.mIsSet; + mMemRange = other.mMemRange; + mMemPage = other.mMemPage; +} + bool nx::MemoryMappingHandler::operator==(const MemoryMappingHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mMemRange == other.mMemRange) \ + && (mMemPage == other.mMemPage); } bool nx::MemoryMappingHandler::operator!=(const MemoryMappingHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::MemoryMappingHandler::operator=(const MemoryMappingHandler & other) +void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() == 0) + if (caps.size() == 0) return; // get entry list fnd::List entries; - for (size_t i = 0; i < caps.getSize(); i++) + for (size_t i = 0; i < caps.size(); i++) { - entries[i].setKernelCapability(caps[i]); + entries.addElement(caps[i]); } mMemRange.clear(); mMemPage.clear(); - for (size_t i = 0; i < entries.getSize();) + for (size_t i = 0; i < entries.size();) { // has flag means "MemMap" if (entries[i].isMultiplePages()) { - // this entry is the last one or the next one isn't a memory map - if ((i + 1) == entries.getSize() || entries[i+1].isMultiplePages() == false) + if ((i + 1) == entries.size() || entries[i+1].isMultiplePages() == false) { throw fnd::Exception(kModuleName, "No paired entry"); } @@ -85,7 +87,7 @@ void nx::MemoryMappingHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::MemoryMappingHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -94,7 +96,7 @@ void nx::MemoryMappingHandler::exportKernelCapabilityList(fnd::List& nx::MemoryMappingHand const fnd::List& nx::MemoryMappingHandler::getIoMemoryMaps() const { return mMemPage; -} - -void nx::MemoryMappingHandler::copyFrom(const MemoryMappingHandler & other) -{ - mIsSet = other.mIsSet; - mMemRange = other.mMemRange; - mMemPage = other.mMemPage; -} - -bool nx::MemoryMappingHandler::isEqual(const MemoryMappingHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mMemRange == other.mMemRange) \ - && (mMemPage == other.mMemPage); -} +} \ No newline at end of file diff --git a/lib/libnx/source/MemoryPageEntry.cpp b/lib/libnx/source/MemoryPageEntry.cpp index 59c2788..3b068e6 100644 --- a/lib/libnx/source/MemoryPageEntry.cpp +++ b/lib/libnx/source/MemoryPageEntry.cpp @@ -1,16 +1,14 @@ #include - - nx::MemoryPageEntry::MemoryPageEntry() : - mCap(KernelCapability::KC_INVALID), + mCap(kc::KC_INVALID), mPage(0), mFlag(false), mUseFlag(false) {} -nx::MemoryPageEntry::MemoryPageEntry(const KernelCapability & kernel_cap) : - mCap(KernelCapability::KC_INVALID), +nx::MemoryPageEntry::MemoryPageEntry(const KernelCapabilityEntry & kernel_cap) : + mCap(kc::KC_INVALID), mPage(0), mFlag(false), mUseFlag(false) @@ -19,7 +17,7 @@ nx::MemoryPageEntry::MemoryPageEntry(const KernelCapability & kernel_cap) : } nx::MemoryPageEntry::MemoryPageEntry(uint32_t page) : - mCap(KernelCapability::KC_INVALID), + mCap(kc::KC_INVALID), mPage(0), mFlag(false), mUseFlag(false) @@ -28,7 +26,7 @@ nx::MemoryPageEntry::MemoryPageEntry(uint32_t page) : } nx::MemoryPageEntry::MemoryPageEntry(uint32_t page, bool flag) : - mCap(KernelCapability::KC_INVALID), + mCap(kc::KC_INVALID), mPage(0), mFlag(false), mUseFlag(true) @@ -37,16 +35,36 @@ nx::MemoryPageEntry::MemoryPageEntry(uint32_t page, bool flag) : setFlag(flag); } -const nx::KernelCapability & nx::MemoryPageEntry::getKernelCapability() const +void nx::MemoryPageEntry::operator=(const MemoryPageEntry& other) +{ + mPage = other.mPage; + mFlag = other.mFlag; + mUseFlag = other.mUseFlag; + updateCapField(); +} + +bool nx::MemoryPageEntry::operator==(const MemoryPageEntry& other) const +{ + return (mPage == other.mPage) \ + && (mFlag == other.mFlag) \ + && (mUseFlag == other.mUseFlag); +} + +bool nx::MemoryPageEntry::operator!=(const MemoryPageEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::MemoryPageEntry::getKernelCapability() const { return mCap; } -void nx::MemoryPageEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::MemoryPageEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { - if (kernel_cap.getType() != KernelCapability::KC_MEMORY_MAP && kernel_cap.getType() != KernelCapability::KC_IO_MEMORY_MAP) + if (kernel_cap.getType() != kc::KC_MEMORY_MAP && kernel_cap.getType() != kc::KC_IO_MEMORY_MAP) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'MemoryMap' or 'IOMemoryMap"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'MemoryMap' or 'IOMemoryMap"); } mCap = kernel_cap; diff --git a/lib/libnx/source/MiscFlagsEntry.cpp b/lib/libnx/source/MiscFlagsEntry.cpp index d5a5b8e..f0ac787 100644 --- a/lib/libnx/source/MiscFlagsEntry.cpp +++ b/lib/libnx/source/MiscFlagsEntry.cpp @@ -1,13 +1,11 @@ #include - - nx::MiscFlagsEntry::MiscFlagsEntry() : mCap(kCapId), mFlags(0) {} -nx::MiscFlagsEntry::MiscFlagsEntry(const KernelCapability & kernel_cap) : +nx::MiscFlagsEntry::MiscFlagsEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mFlags(0) { @@ -21,16 +19,32 @@ nx::MiscFlagsEntry::MiscFlagsEntry(uint32_t flags) : setFlags(flags); } -const nx::KernelCapability & nx::MiscFlagsEntry::getKernelCapability() const +void nx::MiscFlagsEntry::operator=(const MiscFlagsEntry& other) +{ + mFlags = other.mFlags; + updateCapField(); +} + +bool nx::MiscFlagsEntry::operator==(const MiscFlagsEntry& other) const +{ + return (mFlags == other.mFlags); +} + +bool nx::MiscFlagsEntry::operator!=(const MiscFlagsEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::MiscFlagsEntry::getKernelCapability() const { return mCap; } -void nx::MiscFlagsEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::MiscFlagsEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'MiscFlags'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'MiscFlags'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/MiscFlagsHandler.cpp b/lib/libnx/source/MiscFlagsHandler.cpp index a38190c..d608b4b 100644 --- a/lib/libnx/source/MiscFlagsHandler.cpp +++ b/lib/libnx/source/MiscFlagsHandler.cpp @@ -1,34 +1,34 @@ #include - - nx::MiscFlagsHandler::MiscFlagsHandler() : mIsSet(false) {} +void nx::MiscFlagsHandler::operator=(const MiscFlagsHandler & other) +{ + mIsSet = other.mIsSet; + mFlags = other.mFlags; +} + bool nx::MiscFlagsHandler::operator==(const MiscFlagsHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mFlags == other.mFlags); } bool nx::MiscFlagsHandler::operator!=(const MiscFlagsHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::MiscFlagsHandler::operator=(const MiscFlagsHandler & other) +void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() > kMaxKernelCapNum) + if (caps.size() > kMaxKernelCapNum) { throw fnd::Exception(kModuleName, "Too many kernel capabilities"); } - if (caps.getSize() == 0) + if (caps.size() == 0) return; MiscFlagsEntry entry; @@ -46,14 +46,14 @@ void nx::MiscFlagsHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::MiscFlagsHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; // convert list to word flags uint32_t flag = 0; - for (size_t i = 0; i < mFlags.getSize(); i++) + for (size_t i = 0; i < mFlags.size(); i++) { flag |= BIT(mFlags[i]); } @@ -86,16 +86,4 @@ void nx::MiscFlagsHandler::setFlagList(fnd::List flags) { mFlags = flags; mIsSet = true; -} - -void nx::MiscFlagsHandler::copyFrom(const MiscFlagsHandler & other) -{ - mIsSet = other.mIsSet; - mFlags = other.mFlags; -} - -bool nx::MiscFlagsHandler::isEqual(const MiscFlagsHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mFlags == other.mFlags); -} +} \ No newline at end of file diff --git a/lib/libnx/source/MiscParamsEntry.cpp b/lib/libnx/source/MiscParamsEntry.cpp index 4651d1e..28af0df 100644 --- a/lib/libnx/source/MiscParamsEntry.cpp +++ b/lib/libnx/source/MiscParamsEntry.cpp @@ -1,13 +1,11 @@ #include - - nx::MiscParamsEntry::MiscParamsEntry() : mCap(kCapId), mProgramType(0) {} -nx::MiscParamsEntry::MiscParamsEntry(const KernelCapability & kernel_cap) : +nx::MiscParamsEntry::MiscParamsEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mProgramType(0) { @@ -21,16 +19,32 @@ nx::MiscParamsEntry::MiscParamsEntry(uint8_t program_type) : setProgramType(program_type); } -const nx::KernelCapability & nx::MiscParamsEntry::getKernelCapability() const +void nx::MiscParamsEntry::operator=(const MiscParamsEntry& other) +{ + mProgramType = other.mProgramType; + updateCapField(); +} + +bool nx::MiscParamsEntry::operator==(const MiscParamsEntry& other) const +{ + return (mProgramType == other.mProgramType); +} + +bool nx::MiscParamsEntry::operator!=(const MiscParamsEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::MiscParamsEntry::getKernelCapability() const { return mCap; } -void nx::MiscParamsEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::MiscParamsEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'ThreadInfo'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'ThreadInfo'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/MiscParamsHandler.cpp b/lib/libnx/source/MiscParamsHandler.cpp index 9a66725..3d59650 100644 --- a/lib/libnx/source/MiscParamsHandler.cpp +++ b/lib/libnx/source/MiscParamsHandler.cpp @@ -1,35 +1,35 @@ #include - - nx::MiscParamsHandler::MiscParamsHandler() : mIsSet(false), mEntry(0) {} +void nx::MiscParamsHandler::operator=(const MiscParamsHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + bool nx::MiscParamsHandler::operator==(const MiscParamsHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); } bool nx::MiscParamsHandler::operator!=(const MiscParamsHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::MiscParamsHandler::operator=(const MiscParamsHandler & other) +void nx::MiscParamsHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::MiscParamsHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() > kMaxKernelCapNum) + if (caps.size() > kMaxKernelCapNum) { throw fnd::Exception(kModuleName, "Too many kernel capabilities"); } - if (caps.getSize() == 0) + if (caps.size() == 0) return; mEntry.setKernelCapability(caps[0]); @@ -37,7 +37,7 @@ void nx::MiscParamsHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::MiscParamsHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -65,16 +65,4 @@ void nx::MiscParamsHandler::setProgramType(uint8_t type) { mEntry.setProgramType(type); mIsSet = true; -} - -void nx::MiscParamsHandler::copyFrom(const MiscParamsHandler & other) -{ - mIsSet = other.mIsSet; - mEntry.setKernelCapability(other.mEntry.getKernelCapability()); -} - -bool nx::MiscParamsHandler::isEqual(const MiscParamsHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); -} +} \ No newline at end of file diff --git a/lib/libnx/source/NcaHeader.cpp b/lib/libnx/source/NcaHeader.cpp index 3e1d691..d41437e 100644 --- a/lib/libnx/source/NcaHeader.cpp +++ b/lib/libnx/source/NcaHeader.cpp @@ -1,21 +1,69 @@ #include -using namespace nx; - - -void NcaHeader::exportBinary() +nx::NcaHeader::NcaHeader() { - mBinaryBlob.alloc(sizeof(sNcaHeader)); - sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes(); + clear(); +} + +nx::NcaHeader::NcaHeader(const NcaHeader & other) +{ + *this = other; +} + +bool nx::NcaHeader::operator==(const NcaHeader & other) const +{ + return (mDistributionType == other.mDistributionType) \ + && (mContentType == other.mContentType) \ + && (mKeyGeneration == other.mKeyGeneration) \ + && (mKaekIndex == other.mKaekIndex) \ + && (mContentSize == other.mContentSize) \ + && (mProgramId == other.mProgramId) \ + && (mContentIndex == other.mContentIndex) \ + && (mSdkAddonVersion == other.mSdkAddonVersion) \ + && (mPartitions == other.mPartitions) \ + && (mEncAesKeys == other.mEncAesKeys); +} + +bool nx::NcaHeader::operator!=(const NcaHeader & other) const +{ + return !(*this == other); +} + +void nx::NcaHeader::operator=(const NcaHeader & other) +{ + if (other.getBytes().size()) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + mRawBinary.clear(); + mDistributionType = other.mDistributionType; + mContentType = other.mContentType; + mKeyGeneration = other.mKeyGeneration; + mKaekIndex = other.mKaekIndex; + mContentSize = other.mContentSize; + mProgramId = other.mProgramId; + mContentIndex = other.mContentIndex; + mSdkAddonVersion = other.mSdkAddonVersion; + mPartitions = other.mPartitions; + mEncAesKeys = other.mEncAesKeys; + } +} + +void nx::NcaHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sNcaHeader)); + sNcaHeader* hdr = (sNcaHeader*)mRawBinary.data(); switch(mFormatVersion) { case (NCA2_FORMAT): - hdr->signature = nca::kNca2Sig; + hdr->st_magic = nca::kNca2StructMagic; break; case (NCA3_FORMAT): - hdr->signature = nca::kNca3Sig; + hdr->st_magic = nca::kNca3StructMagic; break; default: throw fnd::Exception(kModuleName, "Unsupported format version"); @@ -41,7 +89,7 @@ void NcaHeader::exportBinary() memcpy(hdr->rights_id, mRightsId, nca::kRightsIdLen); // TODO: properly reconstruct NCA layout? atm in hands of user - for (size_t i = 0; i < mPartitions.getSize(); i++) + for (size_t i = 0; i < mPartitions.size(); i++) { // determine partition index byte_t idx = mPartitions[i].index; @@ -60,7 +108,7 @@ void NcaHeader::exportBinary() } } -void NcaHeader::importBinary(const byte_t * bytes, size_t len) +void nx::NcaHeader::fromBytes(const byte_t * data, size_t len) { if (len < sizeof(sNcaHeader)) { @@ -69,17 +117,17 @@ void NcaHeader::importBinary(const byte_t * bytes, size_t len) clear(); - mBinaryBlob.alloc(sizeof(sNcaHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader)); + mRawBinary.alloc(sizeof(sNcaHeader)); + memcpy(mRawBinary.data(), data, sizeof(sNcaHeader)); - sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes(); + sNcaHeader* hdr = (sNcaHeader*)mRawBinary.data(); - switch(hdr->signature.get()) + switch(hdr->st_magic.get()) { - case (nca::kNca2Sig) : + case (nca::kNca2StructMagic) : mFormatVersion = NCA2_FORMAT; break; - case (nca::kNca3Sig) : + case (nca::kNca3StructMagic) : mFormatVersion = NCA3_FORMAT; break; throw fnd::Exception(kModuleName, "NCA header corrupt"); @@ -87,7 +135,7 @@ void NcaHeader::importBinary(const byte_t * bytes, size_t len) mDistributionType = (nca::DistributionType)hdr->distribution_type; mContentType = (nca::ContentType)hdr->content_type; - mKeyGeneration = MAX(hdr->key_generation, hdr->key_generation_2); + mKeyGeneration = _MAX(hdr->key_generation, hdr->key_generation_2); mKaekIndex = hdr->key_area_encryption_key_index; mContentSize = *hdr->content_size; mProgramId = *hdr->program_id; @@ -110,6 +158,11 @@ void NcaHeader::importBinary(const byte_t * bytes, size_t len) } } +const fnd::Vec& nx::NcaHeader::getBytes() const +{ + return mRawBinary; +} + void nx::NcaHeader::clear() { mFormatVersion = NCA3_FORMAT; @@ -176,22 +229,22 @@ void nx::NcaHeader::setKaekIndex(byte_t index) mKaekIndex = index; } -uint64_t NcaHeader::getContentSize() const +uint64_t nx::NcaHeader::getContentSize() const { return mContentSize; } -void NcaHeader::setContentSize(uint64_t size) +void nx::NcaHeader::setContentSize(uint64_t size) { mContentSize = size; } -uint64_t NcaHeader::getProgramId() const +uint64_t nx::NcaHeader::getProgramId() const { return mProgramId; } -void NcaHeader::setProgramId(uint64_t program_id) +void nx::NcaHeader::setProgramId(uint64_t program_id) { mProgramId = program_id; } @@ -239,112 +292,36 @@ void nx::NcaHeader::setRightsId(const byte_t* rights_id) memcpy(mRightsId, rights_id, nca::kRightsIdLen); } -const fnd::List& NcaHeader::getPartitions() const +const fnd::List& nx::NcaHeader::getPartitions() const { return mPartitions; } -void NcaHeader::setPartitions(const fnd::List& partitions) +void nx::NcaHeader::setPartitions(const fnd::List& partitions) { mPartitions = partitions; - if (mPartitions.getSize() >= nca::kPartitionNum) + if (mPartitions.size() >= nca::kPartitionNum) { throw fnd::Exception(kModuleName, "Too many NCA partitions"); } } -const fnd::List& NcaHeader::getEncAesKeys() const +const fnd::List& nx::NcaHeader::getEncAesKeys() const { return mEncAesKeys; } -void NcaHeader::setEncAesKeys(const fnd::List& keys) +void nx::NcaHeader::setEncAesKeys(const fnd::List& keys) { mEncAesKeys = keys; } -uint64_t NcaHeader::blockNumToSize(uint32_t block_num) const +uint64_t nx::NcaHeader::blockNumToSize(uint32_t block_num) const { return block_num*nca::kSectorSize; } -uint32_t NcaHeader::sizeToBlockNum(uint64_t real_size) const +uint32_t nx::NcaHeader::sizeToBlockNum(uint64_t real_size) const { return (uint32_t)(align(real_size, nca::kSectorSize) / nca::kSectorSize); -} - -bool NcaHeader::isEqual(const NcaHeader & other) const -{ - return (mDistributionType == other.mDistributionType) \ - && (mContentType == other.mContentType) \ - && (mKeyGeneration == other.mKeyGeneration) \ - && (mKaekIndex == other.mKaekIndex) \ - && (mContentSize == other.mContentSize) \ - && (mProgramId == other.mProgramId) \ - && (mContentIndex == other.mContentIndex) \ - && (mSdkAddonVersion == other.mSdkAddonVersion) \ - && (mPartitions == other.mPartitions) \ - && (mEncAesKeys == other.mEncAesKeys); -} - -void NcaHeader::copyFrom(const NcaHeader & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mBinaryBlob.clear(); - mDistributionType = other.mDistributionType; - mContentType = other.mContentType; - mKeyGeneration = other.mKeyGeneration; - mKaekIndex = other.mKaekIndex; - mContentSize = other.mContentSize; - mProgramId = other.mProgramId; - mContentIndex = other.mContentIndex; - mSdkAddonVersion = other.mSdkAddonVersion; - mPartitions = other.mPartitions; - mEncAesKeys = other.mEncAesKeys; - } -} - -NcaHeader::NcaHeader() -{ - clear(); -} - -NcaHeader::NcaHeader(const NcaHeader & other) -{ - copyFrom(other); -} - -NcaHeader::NcaHeader(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool NcaHeader::operator==(const NcaHeader & other) const -{ - return isEqual(other); -} - -bool NcaHeader::operator!=(const NcaHeader & other) const -{ - return !isEqual(other); -} - -void NcaHeader::operator=(const NcaHeader & other) -{ - this->importBinary(other.getBytes(), other.getSize()); -} - -const byte_t * NcaHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t NcaHeader::getSize() const -{ - return mBinaryBlob.getSize(); } \ No newline at end of file diff --git a/lib/libnx/source/NcaUtils.cpp b/lib/libnx/source/NcaUtils.cpp index 5ebb4a1..5ec75c2 100644 --- a/lib/libnx/source/NcaUtils.cpp +++ b/lib/libnx/source/NcaUtils.cpp @@ -9,7 +9,7 @@ void nx::NcaUtils::decryptNcaHeader(const byte_t* src, byte_t* dst, const crypto crypto::aes::AesXtsMakeTweak(tweak, 1); crypto::aes::AesXtsDecryptSector(src + sectorToOffset(1), nx::nca::kSectorSize, key.key[0], key.key[1], tweak, raw_hdr); - bool useNca2SectorIndex = ((nx::sNcaHeader*)(raw_hdr))->signature.get() == nx::nca::kNca2Sig; + bool useNca2SectorIndex = ((nx::sNcaHeader*)(raw_hdr))->st_magic.get() == nx::nca::kNca2StructMagic; // decrypt whole header for (size_t i = 0; i < nx::nca::kHeaderSectorNum; i++) diff --git a/lib/libnx/source/NpdmBinary.cpp b/lib/libnx/source/NpdmBinary.cpp index acfc356..3a77972 100644 --- a/lib/libnx/source/NpdmBinary.cpp +++ b/lib/libnx/source/NpdmBinary.cpp @@ -1,136 +1,303 @@ #include +#include - -nx::NpdmBinary::NpdmBinary() : - mAci(), - mAcid() +nx::NpdmBinary::NpdmBinary() { clear(); } nx::NpdmBinary::NpdmBinary(const NpdmBinary & other) : - mAci(), - mAcid() + NpdmBinary() { - copyFrom(other); -} - -nx::NpdmBinary::NpdmBinary(const byte_t * bytes, size_t len) : - mAci(), - mAcid() -{ - importBinary(bytes, len); -} - -bool nx::NpdmBinary::operator==(const NpdmBinary & other) const -{ - return isEqual(other); -} - -bool nx::NpdmBinary::operator!=(const NpdmBinary & other) const -{ - return !isEqual(other); + *this = other; } void nx::NpdmBinary::operator=(const NpdmBinary & other) { - copyFrom(other); + mRawBinary = other.mRawBinary; + mInstructionType = other.mInstructionType; + mProcAddressSpaceType = other.mProcAddressSpaceType; + mMainThreadPriority = other.mMainThreadPriority; + mMainThreadCpuId = other.mMainThreadCpuId; + mVersion = other.mVersion; + mMainThreadStackSize = other.mMainThreadStackSize; + mName = other.mName; + mProductCode = other.mProductCode; + mAci = other.mAci; + mAcid = other.mAcid; } -void nx::NpdmBinary::exportBinary() +bool nx::NpdmBinary::operator==(const NpdmBinary & other) const { - mAci.exportBinary(); - mAcid.exportBinary(); - - setAciSize(mAci.getSize()); - setAcidSize(mAcid.getSize()); + return (mInstructionType == other.mInstructionType) \ + && (mProcAddressSpaceType == other.mProcAddressSpaceType) \ + && (mMainThreadPriority == other.mMainThreadPriority) \ + && (mMainThreadCpuId == other.mMainThreadCpuId) \ + && (mVersion == other.mVersion) \ + && (mMainThreadStackSize == other.mMainThreadStackSize) \ + && (mName == other.mName) \ + && (mProductCode == other.mProductCode) \ + && (mAci == other.mAci) \ + && (mAcid == other.mAcid); } -void nx::NpdmBinary::importBinary(const byte_t * bytes, size_t len) +bool nx::NpdmBinary::operator!=(const NpdmBinary & other) const { - // clear + return !(*this == other); +} + +void nx::NpdmBinary::toBytes() +{ + if (mAcid.getBytes().size() == 0) + mAcid.toBytes(); + + if (mAci.getBytes().size() == 0) + mAci.toBytes(); + + + // determine section layout + struct sLayout { + uint32_t offset, size; + } acid, aci; + + acid.offset = align(sizeof(sNpdmHeader), npdm::kSectionAlignSize); + acid.size = (uint32_t)mAcid.getBytes().size(); + aci.offset = acid.offset + align(acid.size, npdm::kSectionAlignSize); + aci.size = (uint32_t)mAci.getBytes().size(); + + + // get total size + size_t total_size = _MAX(_MAX(acid.offset + acid.size, aci.offset + aci.size), align(sizeof(sNpdmHeader), npdm::kSectionAlignSize)); + + mRawBinary.alloc(total_size); + sNpdmHeader* hdr = (sNpdmHeader*)mRawBinary.data(); + + // set type + hdr->st_magic = npdm::kNpdmStructMagic; + + // set variables + byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf; + hdr->flags = flag; + hdr->main_thread_priority = mMainThreadPriority; + hdr->main_thread_cpu_id = mMainThreadCpuId; + hdr->version = mVersion; + hdr->main_thread_stack_size = mMainThreadStackSize; + strncpy(hdr->name, mName.c_str(), npdm::kNameMaxLen); + strncpy(hdr->product_code, mProductCode.c_str(), npdm::kProductCodeMaxLen); + + // set offset/size + hdr->aci.offset = aci.offset; + hdr->aci.size = aci.size; + hdr->acid.offset = acid.offset; + hdr->acid.size = acid.size; + + // write aci & acid + if (mAci.getBytes().size() > 0) + { + memcpy(mRawBinary.data() + aci.offset, mAci.getBytes().data(), mAci.getBytes().size()); + } + if (mAcid.getBytes().size() > 0) + { + memcpy(mRawBinary.data() + acid.offset, mAcid.getBytes().data(), mAcid.getBytes().size()); + } +} + +void nx::NpdmBinary::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sNpdmHeader)) + { + throw fnd::Exception(kModuleName, "NPDM binary is too small"); + } + + // clear variables clear(); - // import header - NpdmHeader::importBinary(bytes, len); + // save a copy of the header + sNpdmHeader hdr; + memcpy((void*)&hdr, data, sizeof(sNpdmHeader)); + + // check magic + if (hdr.st_magic.get() != npdm::kNpdmStructMagic) + { + throw fnd::Exception(kModuleName, "NPDM header corrupt"); + } + + // save variables + byte_t flag = hdr.flags & 0xf; + mInstructionType = (npdm::InstructionType)(flag & 1); + mProcAddressSpaceType = (npdm::ProcAddrSpaceType)((flag >> 1) & 3); + mMainThreadPriority = hdr.main_thread_priority; + mMainThreadCpuId = hdr.main_thread_cpu_id; + mVersion = hdr.version.get(); + mMainThreadStackSize = hdr.main_thread_stack_size.get(); + mName = std::string(hdr.name, npdm::kNameMaxLen); + if (mName[0] == '\0') + { + mName.clear(); + } + mProductCode = std::string(hdr.product_code, npdm::kProductCodeMaxLen); + if (mProductCode[0] == '\0') + { + mProductCode.clear(); + } + + // total size + size_t total_size = _MAX(_MAX(hdr.acid.offset.get() + hdr.acid.size.get(), hdr.aci.offset.get() + hdr.aci.size.get()), sizeof(sNpdmHeader)); // check size - if (getNpdmSize() > len) + if (total_size > len) { throw fnd::Exception(kModuleName, "NPDM binary too small"); } // save local copy - mBinaryBlob.alloc(getNpdmSize()); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); // import Aci/Acid - if (getAciPos().size) + if (hdr.aci.size.get()) { - mAci.importBinary(mBinaryBlob.getBytes() + getAciPos().offset, getAciPos().size); + mAci.fromBytes(mRawBinary.data() + hdr.aci.offset.get(), hdr.aci.size.get()); } - if (getAcidPos().size) + if (hdr.acid.size.get()) { - mAcid.importBinary(mBinaryBlob.getBytes() + getAcidPos().offset, getAcidPos().size); - } - + mAcid.fromBytes(mRawBinary.data() + hdr.acid.offset.get(), hdr.acid.size.get()); + } +} + +const fnd::Vec& nx::NpdmBinary::getBytes() const +{ + return mRawBinary; } void nx::NpdmBinary::clear() { - NpdmHeader::clear(); + mRawBinary.clear(); + mInstructionType = npdm::INSTR_64BIT; + mProcAddressSpaceType = npdm::ADDR_SPACE_64BIT; + mMainThreadPriority = 0; + mMainThreadCpuId = 0; + mVersion = 0; + mMainThreadStackSize = 0; + mName.clear(); + mProductCode.clear(); mAci.clear(); mAcid.clear(); } -const nx::AciBinary & nx::NpdmBinary::getAci() const +nx::npdm::InstructionType nx::NpdmBinary::getInstructionType() const +{ + return mInstructionType; +} + +void nx::NpdmBinary::setInstructionType(npdm::InstructionType type) +{ + mInstructionType = type; +} + +nx::npdm::ProcAddrSpaceType nx::NpdmBinary::getProcAddressSpaceType() const +{ + return mProcAddressSpaceType; +} + +void nx::NpdmBinary::setProcAddressSpaceType(npdm::ProcAddrSpaceType type) +{ + mProcAddressSpaceType = type; +} + +byte_t nx::NpdmBinary::getMainThreadPriority() const +{ + return mMainThreadPriority; +} + +void nx::NpdmBinary::setMainThreadPriority(byte_t priority) +{ + if (priority > npdm::kMaxPriority) + { + throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)"); + } + + mMainThreadPriority = priority; +} + +byte_t nx::NpdmBinary::getMainThreadCpuId() const +{ + return mMainThreadCpuId; +} + +void nx::NpdmBinary::setMainThreadCpuId(byte_t core_num) +{ + mMainThreadCpuId = core_num; +} + +uint32_t nx::NpdmBinary::getVersion() const +{ + return mVersion; +} + +void nx::NpdmBinary::setVersion(uint32_t version) +{ + mVersion = version; +} + +uint32_t nx::NpdmBinary::getMainThreadStackSize() const +{ + return mMainThreadStackSize; +} + +void nx::NpdmBinary::setMainThreadStackSize(uint32_t size) +{ + mMainThreadStackSize = size; +} + +const std::string & nx::NpdmBinary::getName() const +{ + return mName; +} + +void nx::NpdmBinary::setName(const std::string & name) +{ + if (name.length() > npdm::kNameMaxLen) + { + throw fnd::Exception(kModuleName, "Name is too long"); + } + + mName = name; +} + +const std::string & nx::NpdmBinary::getProductCode() const +{ + return mProductCode; +} + +void nx::NpdmBinary::setProductCode(const std::string & product_code) +{ + if (product_code.length() > npdm::kProductCodeMaxLen) + { + throw fnd::Exception(kModuleName, "Product Code is too long"); + } + + mProductCode = product_code; +} + +const nx::AccessControlInfoBinary & nx::NpdmBinary::getAci() const { return mAci; } -void nx::NpdmBinary::setAci(const AciBinary & aci) +void nx::NpdmBinary::setAci(const AccessControlInfoBinary & aci) { mAci = aci; } -const nx::AcidBinary & nx::NpdmBinary::getAcid() const +const nx::AccessControlInfoDescBinary & nx::NpdmBinary::getAcid() const { return mAcid; } -void nx::NpdmBinary::setAcid(const AcidBinary & acid) +void nx::NpdmBinary::setAcid(const AccessControlInfoDescBinary & acid) { mAcid = acid; -} - -bool nx::NpdmBinary::isEqual(const NpdmBinary & other) const -{ - return (NpdmHeader::operator==(other)) \ - && (mAci == other.mAci) \ - && (mAcid == other.mAcid); -} - -void nx::NpdmBinary::copyFrom(const NpdmBinary & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - NpdmHeader::operator=(other); - mAci = other.mAci; - mAcid = other.mAcid; - } -} - -const byte_t * nx::NpdmBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::NpdmBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} +} \ No newline at end of file diff --git a/lib/libnx/source/NpdmHeader.cpp b/lib/libnx/source/NpdmHeader.cpp deleted file mode 100644 index db81574..0000000 --- a/lib/libnx/source/NpdmHeader.cpp +++ /dev/null @@ -1,284 +0,0 @@ -#include - - - -nx::NpdmHeader::NpdmHeader() -{ - clear(); -} - -nx::NpdmHeader::NpdmHeader(const NpdmHeader & other) -{ - copyFrom(other); -} - -nx::NpdmHeader::NpdmHeader(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool nx::NpdmHeader::operator==(const NpdmHeader & other) const -{ - return isEqual(other); -} - -bool nx::NpdmHeader::operator!=(const NpdmHeader & other) const -{ - return isEqual(other); -} - -void nx::NpdmHeader::operator=(const NpdmHeader & other) -{ - copyFrom(other); -} - -const byte_t * nx::NpdmHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::NpdmHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::NpdmHeader::calculateOffsets() -{ - mAcidPos.offset = align(sizeof(sNpdmHeader), npdm::kNpdmAlignSize); - mAciPos.offset = mAcidPos.offset + align(mAcidPos.size, npdm::kNpdmAlignSize); -} - -bool nx::NpdmHeader::isEqual(const NpdmHeader & other) const -{ - return (mInstructionType == other.mInstructionType) \ - && (mProcAddressSpaceType == other.mProcAddressSpaceType) \ - && (mMainThreadPriority == other.mMainThreadPriority) \ - && (mMainThreadCpuId == other.mMainThreadCpuId) \ - && (mVersion == other.mVersion) \ - && (mMainThreadStackSize == other.mMainThreadStackSize) \ - && (mName == other.mName) \ - && (mProductCode == other.mProductCode) \ - && (mAciPos == other.mAciPos) \ - && (mAcidPos == other.mAcidPos); -} - -void nx::NpdmHeader::copyFrom(const NpdmHeader & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - mInstructionType = other.mInstructionType; - mProcAddressSpaceType = other.mProcAddressSpaceType; - mMainThreadPriority = other.mMainThreadPriority; - mMainThreadCpuId = other.mMainThreadCpuId; - mVersion = other.mVersion; - mMainThreadStackSize = other.mMainThreadStackSize; - mName = other.mName; - mProductCode = other.mProductCode; - mAciPos = other.mAciPos; - mAcidPos = other.mAcidPos; - } -} - -void nx::NpdmHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sNpdmHeader)); - sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes(); - - hdr->signature = npdm::kNpdmStructSig; - byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf; - hdr->flags = flag; - hdr->main_thread_priority = mMainThreadPriority; - hdr->main_thread_cpu_id = mMainThreadCpuId; - hdr->version = mVersion; - hdr->main_thread_stack_size = mMainThreadStackSize; - strncpy(hdr->name, mName.c_str(), npdm::kNameMaxLen); - strncpy(hdr->product_code, mProductCode.c_str(), npdm::kProductCodeMaxLen); - - calculateOffsets(); - hdr->aci.offset = (uint32_t)mAciPos.offset; - hdr->aci.size = (uint32_t)mAciPos.size; - hdr->acid.offset = (uint32_t)mAcidPos.offset; - hdr->acid.size = (uint32_t)mAcidPos.size; -} - -void nx::NpdmHeader::importBinary(const byte_t * bytes, size_t len) -{ - if (len < sizeof(sNpdmHeader)) - { - throw fnd::Exception(kModuleName, "NPDM header too small"); - } - - clear(); - - mBinaryBlob.alloc(sizeof(sNpdmHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - sNpdmHeader* hdr = (sNpdmHeader*)mBinaryBlob.getBytes(); - - if (hdr->signature.get() != npdm::kNpdmStructSig) - { - throw fnd::Exception(kModuleName, "NPDM header corrupt"); - } - - byte_t flag = hdr->flags & 0xf; - mInstructionType = (npdm::InstructionType)(flag & 1); - mProcAddressSpaceType = (npdm::ProcAddrSpaceType)((flag >> 1) & 3); - mMainThreadPriority = hdr->main_thread_priority; - mMainThreadCpuId = hdr->main_thread_cpu_id; - mVersion = hdr->version.get(); - mMainThreadStackSize = hdr->main_thread_stack_size.get(); - mName = std::string(hdr->name, npdm::kNameMaxLen); - if (mName[0] == '\0') - { - mName.clear(); - } - mProductCode = std::string(hdr->product_code, npdm::kProductCodeMaxLen); - if (mProductCode[0] == '\0') - { - mProductCode.clear(); - } - mAciPos.offset = hdr->aci.offset.get(); - mAciPos.size = hdr->aci.size.get(); - mAcidPos.offset = hdr->acid.offset.get(); - mAcidPos.size = hdr->acid.size.get(); -} - -void nx::NpdmHeader::clear() -{ - mBinaryBlob.clear(); - mInstructionType = npdm::INSTR_64BIT; - mProcAddressSpaceType = npdm::ADDR_SPACE_64BIT; - mMainThreadPriority = 0; - mMainThreadCpuId = 0; - mVersion = 0; - mMainThreadStackSize = 0; - mName.clear(); - mProductCode.clear(); - mAciPos.offset = 0; - mAciPos.size = 0; - mAcidPos.offset = 0; - mAcidPos.size = 0; -} - -size_t nx::NpdmHeader::getNpdmSize() const -{ - return MAX(mAcidPos.offset + mAcidPos.size, mAciPos.offset + mAciPos.size); -} - -nx::npdm::InstructionType nx::NpdmHeader::getInstructionType() const -{ - return mInstructionType; -} - -void nx::NpdmHeader::setInstructionType(npdm::InstructionType type) -{ - mInstructionType = type; -} - -nx::npdm::ProcAddrSpaceType nx::NpdmHeader::getProcAddressSpaceType() const -{ - return mProcAddressSpaceType; -} - -void nx::NpdmHeader::setProcAddressSpaceType(npdm::ProcAddrSpaceType type) -{ - mProcAddressSpaceType = type; -} - -byte_t nx::NpdmHeader::getMainThreadPriority() const -{ - return mMainThreadPriority; -} - -void nx::NpdmHeader::setMainThreadPriority(byte_t priority) -{ - if (priority > npdm::kMaxPriority) - { - throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)"); - } - - mMainThreadPriority = priority; -} - -byte_t nx::NpdmHeader::getMainThreadCpuId() const -{ - return mMainThreadCpuId; -} - -void nx::NpdmHeader::setMainThreadCpuId(byte_t core_num) -{ - mMainThreadCpuId = core_num; -} - -uint32_t nx::NpdmHeader::getVersion() const -{ - return mVersion; -} - -void nx::NpdmHeader::setVersion(uint32_t version) -{ - mVersion = version; -} - -uint32_t nx::NpdmHeader::getMainThreadStackSize() const -{ - return mMainThreadStackSize; -} - -void nx::NpdmHeader::setMainThreadStackSize(uint32_t size) -{ - mMainThreadStackSize = size; -} - -const std::string & nx::NpdmHeader::getName() const -{ - return mName; -} - -void nx::NpdmHeader::setName(const std::string & name) -{ - if (name.length() > npdm::kNameMaxLen) - { - throw fnd::Exception(kModuleName, "Name is too long"); - } - - mName = name; -} - -const std::string & nx::NpdmHeader::getProductCode() const -{ - return mProductCode; -} - -void nx::NpdmHeader::setProductCode(const std::string & product_code) -{ - if (product_code.length() > npdm::kProductCodeMaxLen) - { - throw fnd::Exception(kModuleName, "Product Code is too long"); - } - - mProductCode = product_code; -} - -const nx::NpdmHeader::sSection & nx::NpdmHeader::getAciPos() const -{ - return mAciPos; -} - -void nx::NpdmHeader::setAciSize(size_t size) -{ - mAciPos.size = size; -} - -const nx::NpdmHeader::sSection & nx::NpdmHeader::getAcidPos() const -{ - return mAcidPos; -} - -void nx::NpdmHeader::setAcidSize(size_t size) -{ - mAcidPos.size = size; -} diff --git a/lib/libnx/source/NroHeader.cpp b/lib/libnx/source/NroHeader.cpp index 8d031b8..dfd2ba3 100644 --- a/lib/libnx/source/NroHeader.cpp +++ b/lib/libnx/source/NroHeader.cpp @@ -7,17 +7,38 @@ nx::NroHeader::NroHeader() nx::NroHeader::NroHeader(const NroHeader& other) { - copyFrom(other); + *this = other; } -nx::NroHeader::NroHeader(const byte_t* bytes, size_t len) +void nx::NroHeader::operator=(const NroHeader& other) { - importBinary(bytes, len); + clear(); + mRoCrt = other.mRoCrt; + mNroSize = other.mNroSize; + mTextInfo = other.mTextInfo; + mTextInfo = other.mTextInfo; + mRoInfo = other.mRoInfo; + mDataInfo = other.mDataInfo; + mBssSize = other.mBssSize; + mModuleId = other.mModuleId; + mRoEmbeddedInfo = other.mRoEmbeddedInfo; + mRoDynStrInfo = other.mRoDynStrInfo; + mRoDynSymInfo = other.mRoDynSymInfo; } bool nx::NroHeader::operator==(const NroHeader& other) const { - return isEqual(other); + return (mRoCrt == other.mRoCrt) \ + && (mNroSize == other.mNroSize) \ + && (mTextInfo == other.mTextInfo) \ + && (mTextInfo == other.mTextInfo) \ + && (mRoInfo == other.mRoInfo) \ + && (mDataInfo == other.mDataInfo) \ + && (mBssSize == other.mBssSize) \ + && (mModuleId == other.mModuleId) \ + && (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \ + && (mRoDynStrInfo == other.mRoDynStrInfo) \ + && (mRoDynSymInfo == other.mRoDynSymInfo); } bool nx::NroHeader::operator!=(const NroHeader& other) const @@ -25,28 +46,13 @@ bool nx::NroHeader::operator!=(const NroHeader& other) const return !(*this == other); } -void nx::NroHeader::operator=(const NroHeader& other) +void nx::NroHeader::toBytes() { - copyFrom(other); -} - -const byte_t* nx::NroHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::NroHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::NroHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sNroHeader)); - nx::sNroHeader* hdr = (nx::sNroHeader*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sNroHeader)); + nx::sNroHeader* hdr = (nx::sNroHeader*)mRawBinary.data(); // set header identifers - hdr->signature = nro::kNroSig; + hdr->st_magic = nro::kNroStructMagic; hdr->format_version = nro::kDefaultFormatVersion; hdr->flags = 0; @@ -87,7 +93,7 @@ void nx::NroHeader::exportBinary() hdr->dyn_sym.size = mRoDynSymInfo.size; } -void nx::NroHeader::importBinary(const byte_t* bytes, size_t len) +void nx::NroHeader::fromBytes(const byte_t* data, size_t len) { // check input data size if (len < sizeof(sNroHeader)) @@ -99,14 +105,14 @@ void nx::NroHeader::importBinary(const byte_t* bytes, size_t len) clear(); // allocate internal local binary copy - mBinaryBlob.alloc(sizeof(sNroHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(sizeof(sNroHeader)); + memcpy(mRawBinary.data(), data, mRawBinary.size()); // get sNroHeader ptr - const nx::sNroHeader* hdr = (const nx::sNroHeader*)mBinaryBlob.getBytes(); + const nx::sNroHeader* hdr = (const nx::sNroHeader*)mRawBinary.data(); // check NRO signature - if (hdr->signature.get() != nro::kNroSig) + if (hdr->st_magic.get() != nro::kNroStructMagic) { throw fnd::Exception(kModuleName, "NRO header corrupt (unrecognised header signature)"); } @@ -144,9 +150,14 @@ void nx::NroHeader::importBinary(const byte_t* bytes, size_t len) mRoDynSymInfo.size = hdr->dyn_sym.size.get(); } +const fnd::Vec& nx::NroHeader::getBytes() const +{ + return mRawBinary; +} + void nx::NroHeader::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); memset(&mRoCrt, 0, sizeof(mRoCrt)); memset(&mTextInfo, 0, sizeof(mTextInfo)); memset(&mRoInfo, 0, sizeof(mRoInfo)); @@ -256,35 +267,4 @@ const nx::NroHeader::sSection& nx::NroHeader::getRoDynSymInfo() const void nx::NroHeader::setRoDynSymInfo(const sSection& info) { mRoDynSymInfo = info; -} - -bool nx::NroHeader::isEqual(const NroHeader& other) const -{ - return (mRoCrt == other.mRoCrt) \ - && (mNroSize == other.mNroSize) \ - && (mTextInfo == other.mTextInfo) \ - && (mTextInfo == other.mTextInfo) \ - && (mRoInfo == other.mRoInfo) \ - && (mDataInfo == other.mDataInfo) \ - && (mBssSize == other.mBssSize) \ - && (mModuleId == other.mModuleId) \ - && (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \ - && (mRoDynStrInfo == other.mRoDynStrInfo) \ - && (mRoDynSymInfo == other.mRoDynSymInfo); -} - -void nx::NroHeader::copyFrom(const NroHeader& other) -{ - clear(); - mRoCrt = other.mRoCrt; - mNroSize = other.mNroSize; - mTextInfo = other.mTextInfo; - mTextInfo = other.mTextInfo; - mRoInfo = other.mRoInfo; - mDataInfo = other.mDataInfo; - mBssSize = other.mBssSize; - mModuleId = other.mModuleId; - mRoEmbeddedInfo = other.mRoEmbeddedInfo; - mRoDynStrInfo = other.mRoDynStrInfo; - mRoDynSymInfo = other.mRoDynSymInfo; } \ No newline at end of file diff --git a/lib/libnx/source/NsoHeader.cpp b/lib/libnx/source/NsoHeader.cpp index 55521ec..4612786 100644 --- a/lib/libnx/source/NsoHeader.cpp +++ b/lib/libnx/source/NsoHeader.cpp @@ -2,22 +2,40 @@ nx::NsoHeader::NsoHeader() { - + clear(); } nx::NsoHeader::NsoHeader(const NsoHeader& other) { - copyFrom(other); + *this = other; } -nx::NsoHeader::NsoHeader(const byte_t* bytes, size_t len) +void nx::NsoHeader::operator=(const NsoHeader& other) { - importBinary(bytes, len); + clear(); + mModuleId = other.mModuleId; + mBssSize = other.mBssSize; + mTextSegmentInfo = other.mTextSegmentInfo; + mRoSegmentInfo = other.mRoSegmentInfo; + mDataSegmentInfo = other.mDataSegmentInfo; + mModuleNameInfo = other.mModuleNameInfo; + mRoEmbeddedInfo = other.mRoEmbeddedInfo; + mRoDynStrInfo = other.mRoDynStrInfo; + mRoDynSymInfo = other.mRoDynSymInfo; } + bool nx::NsoHeader::operator==(const NsoHeader& other) const { - return isEqual(other); + return (mModuleId == other.mModuleId) \ + && (mBssSize == other.mBssSize) \ + && (mTextSegmentInfo == other.mTextSegmentInfo) \ + && (mRoSegmentInfo == other.mRoSegmentInfo) \ + && (mDataSegmentInfo == other.mDataSegmentInfo) \ + && (mModuleNameInfo == other.mModuleNameInfo) \ + && (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \ + && (mRoDynStrInfo == other.mRoDynStrInfo) \ + && (mRoDynSymInfo == other.mRoDynSymInfo); } bool nx::NsoHeader::operator!=(const NsoHeader& other) const @@ -25,28 +43,13 @@ bool nx::NsoHeader::operator!=(const NsoHeader& other) const return !(*this == other); } -void nx::NsoHeader::operator=(const NsoHeader& other) +void nx::NsoHeader::toBytes() { - copyFrom(other); -} - -const byte_t* nx::NsoHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::NsoHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void nx::NsoHeader::exportBinary() -{ - mBinaryBlob.alloc(sizeof(sNsoHeader)); - nx::sNsoHeader* hdr = (nx::sNsoHeader*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sNsoHeader)); + nx::sNsoHeader* hdr = (nx::sNsoHeader*)mRawBinary.data(); // set header identifers - hdr->signature = nso::kNsoSig; + hdr->st_magic = nso::kNsoStructMagic; hdr->format_version = nso::kDefaultFormatVersion; // variable to store flags before commiting to header @@ -122,7 +125,7 @@ void nx::NsoHeader::exportBinary() hdr->flags = flags; } -void nx::NsoHeader::importBinary(const byte_t* bytes, size_t len) +void nx::NsoHeader::fromBytes(const byte_t* data, size_t len) { // check input data size if (len < sizeof(sNsoHeader)) @@ -134,14 +137,14 @@ void nx::NsoHeader::importBinary(const byte_t* bytes, size_t len) clear(); // allocate internal local binary copy - mBinaryBlob.alloc(sizeof(sNsoHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(sizeof(sNsoHeader)); + memcpy(mRawBinary.data(), data, mRawBinary.size()); // get sNsoHeader ptr - const nx::sNsoHeader* hdr = (const nx::sNsoHeader*)mBinaryBlob.getBytes(); + const nx::sNsoHeader* hdr = (const nx::sNsoHeader*)mRawBinary.data(); // check NSO signature - if (hdr->signature.get() != nso::kNsoSig) + if (hdr->st_magic.get() != nso::kNsoStructMagic) { throw fnd::Exception(kModuleName, "NSO header corrupt (unrecognised header signature)"); } @@ -193,9 +196,14 @@ void nx::NsoHeader::importBinary(const byte_t* bytes, size_t len) mRoDynSymInfo.size = hdr->dyn_sym.size.get(); } +const fnd::Vec& nx::NsoHeader::getBytes() const +{ + return mRawBinary; +} + void nx::NsoHeader::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); memset(&mModuleId, 0, sizeof(mModuleId)); mBssSize = 0; memset(&mTextSegmentInfo, 0, sizeof(mTextSegmentInfo)); @@ -295,30 +303,4 @@ const nx::NsoHeader::sLayout& nx::NsoHeader::getRoDynSymInfo() const void nx::NsoHeader::setRoDynSymInfo(const sLayout& info) { mRoDynSymInfo = info; -} - -bool nx::NsoHeader::isEqual(const NsoHeader& other) const -{ - return (mModuleId == other.mModuleId) \ - && (mBssSize == other.mBssSize) \ - && (mTextSegmentInfo == other.mTextSegmentInfo) \ - && (mRoSegmentInfo == other.mRoSegmentInfo) \ - && (mDataSegmentInfo == other.mDataSegmentInfo) \ - && (mModuleNameInfo == other.mModuleNameInfo) \ - && (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \ - && (mRoDynStrInfo == other.mRoDynStrInfo) \ - && (mRoDynSymInfo == other.mRoDynSymInfo); -} -void nx::NsoHeader::copyFrom(const NsoHeader& other) -{ - clear(); - mModuleId = other.mModuleId; - mBssSize = other.mBssSize; - mTextSegmentInfo = other.mTextSegmentInfo; - mRoSegmentInfo = other.mRoSegmentInfo; - mDataSegmentInfo = other.mDataSegmentInfo; - mModuleNameInfo = other.mModuleNameInfo; - mRoEmbeddedInfo = other.mRoEmbeddedInfo; - mRoDynStrInfo = other.mRoDynStrInfo; - mRoDynSymInfo = other.mRoDynSymInfo; } \ No newline at end of file diff --git a/lib/libnx/source/PfsHeader.cpp b/lib/libnx/source/PfsHeader.cpp index 1d6af09..7fdae51 100644 --- a/lib/libnx/source/PfsHeader.cpp +++ b/lib/libnx/source/PfsHeader.cpp @@ -1,61 +1,87 @@ #include - - nx::PfsHeader::PfsHeader() -{} +{ + clear(); +} nx::PfsHeader::PfsHeader(const PfsHeader & other) { - copyFrom(other); + *this = other; } -nx::PfsHeader::PfsHeader(const byte_t * bytes, size_t len) +void nx::PfsHeader::operator=(const PfsHeader & other) { - importBinary(bytes, len); + if (other.getBytes().size()) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + mFsType = other.mFsType; + mFileList = other.mFileList; + } } -void nx::PfsHeader::exportBinary() +bool nx::PfsHeader::operator==(const PfsHeader & other) const +{ + return (mFsType == other.mFsType) \ + && (mFileList == other.mFileList); +} + +bool nx::PfsHeader::operator!=(const PfsHeader & other) const +{ + return !(*this == other); +} + +const fnd::Vec& nx::PfsHeader::getBytes() const +{ + return mRawBinary; +} + + +void nx::PfsHeader::toBytes() { // calculate name table size size_t name_table_size = 0; - for (size_t i = 0; i < mFileList.getSize(); i++) + for (size_t i = 0; i < mFileList.size(); i++) { name_table_size += mFileList[i].name.length() + 1; } - size_t pfs_header_size = align(sizeof(sPfsHeader) + getFileEntrySize(mFsType) * mFileList.getSize() + name_table_size, pfs::kHeaderAlign); + size_t pfs_header_size = align(sizeof(sPfsHeader) + getFileEntrySize(mFsType) * mFileList.size() + name_table_size, pfs::kHeaderAlign); // align name_table_size - name_table_size = pfs_header_size - (sizeof(sPfsHeader) + getFileEntrySize(mFsType) * mFileList.getSize()); + name_table_size = pfs_header_size - (sizeof(sPfsHeader) + getFileEntrySize(mFsType) * mFileList.size()); // allocate pfs header binary - mBinaryBlob.alloc(pfs_header_size); - sPfsHeader* hdr = (sPfsHeader*)mBinaryBlob.getBytes(); + mRawBinary.alloc(pfs_header_size); + sPfsHeader* hdr = (sPfsHeader*)mRawBinary.data(); // set header fields switch (mFsType) { case (TYPE_PFS0): - hdr->signature = pfs::kPfsSig; + hdr->st_magic = pfs::kPfsStructMagic; break; case (TYPE_HFS0): - hdr->signature = pfs::kHashedPfsSig; + hdr->st_magic = pfs::kHashedPfsStructMagic; break; } - hdr->file_num = (uint32_t)mFileList.getSize(); + hdr->file_num = (uint32_t)mFileList.size(); hdr->name_table_size = (uint32_t)name_table_size; // set file entries if (mFsType == TYPE_PFS0) { - sPfsFile* raw_files = (sPfsFile*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader)); - char* raw_name_table = (char*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader) + sizeof(sPfsFile) * mFileList.getSize()); + sPfsFile* raw_files = (sPfsFile*)(mRawBinary.data() + sizeof(sPfsHeader)); + char* raw_name_table = (char*)(mRawBinary.data() + sizeof(sPfsHeader) + sizeof(sPfsFile) * mFileList.size()); size_t raw_name_table_pos = 0; calculateOffsets(pfs_header_size); - for (size_t i = 0; i < mFileList.getSize(); i++) + for (size_t i = 0; i < mFileList.size(); i++) { raw_files[i].data_offset = (mFileList[i].offset - pfs_header_size); raw_files[i].size = mFileList[i].size; @@ -67,12 +93,12 @@ void nx::PfsHeader::exportBinary() } else if (mFsType == TYPE_HFS0) { - sHashedPfsFile* raw_files = (sHashedPfsFile*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader)); - char* raw_name_table = (char*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader) + sizeof(sHashedPfsFile) * mFileList.getSize()); + sHashedPfsFile* raw_files = (sHashedPfsFile*)(mRawBinary.data() + sizeof(sPfsHeader)); + char* raw_name_table = (char*)(mRawBinary.data() + sizeof(sPfsHeader) + sizeof(sHashedPfsFile) * mFileList.size()); size_t raw_name_table_pos = 0; calculateOffsets(pfs_header_size); - for (size_t i = 0; i < mFileList.getSize(); i++) + for (size_t i = 0; i < mFileList.size(); i++) { raw_files[i].data_offset = (mFileList[i].offset - pfs_header_size); raw_files[i].size = mFileList[i].size; @@ -87,27 +113,30 @@ void nx::PfsHeader::exportBinary() } -void nx::PfsHeader::importBinary(const byte_t * bytes, size_t len) +void nx::PfsHeader::fromBytes(const byte_t* data, size_t len) { // check input length meets minimum size if (len < sizeof(sPfsHeader)) { throw fnd::Exception(kModuleName, "PFS header too small"); } + + // clear variables + clear(); // import minimum header - mBinaryBlob.alloc(sizeof(sPfsHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - const sPfsHeader* hdr = (const sPfsHeader*)mBinaryBlob.getBytes(); + mRawBinary.alloc(sizeof(sPfsHeader)); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + const sPfsHeader* hdr = (const sPfsHeader*)mRawBinary.data(); // check struct signature FsType fs_type; - switch(hdr->signature.get()) + switch(hdr->st_magic.get()) { - case (pfs::kPfsSig): + case (pfs::kPfsStructMagic): fs_type = TYPE_PFS0; break; - case (pfs::kHashedPfsSig): + case (pfs::kHashedPfsStructMagic): fs_type = TYPE_HFS0; break; default: @@ -124,19 +153,16 @@ void nx::PfsHeader::importBinary(const byte_t * bytes, size_t len) } // import full header - mBinaryBlob.alloc(pfs_full_header_size); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - hdr = (const sPfsHeader*)mBinaryBlob.getBytes(); - - // clear variables - clear(); + mRawBinary.alloc(pfs_full_header_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + hdr = (const sPfsHeader*)mRawBinary.data(); mFsType = fs_type; if (mFsType == TYPE_PFS0) { // get pointers to raw data - const sPfsFile* raw_files = (const sPfsFile*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader)); - const char* raw_name_table = (const char*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader) + sizeof(sPfsFile) * hdr->file_num.get()); + const sPfsFile* raw_files = (const sPfsFile*)(mRawBinary.data() + sizeof(sPfsHeader)); + const char* raw_name_table = (const char*)(mRawBinary.data() + sizeof(sPfsHeader) + sizeof(sPfsFile) * hdr->file_num.get()); // process file entries for (size_t i = 0; i < hdr->file_num.get(); i++) @@ -151,8 +177,8 @@ void nx::PfsHeader::importBinary(const byte_t * bytes, size_t len) else if (mFsType == TYPE_HFS0) { // get pointers to raw data - const sHashedPfsFile* raw_files = (const sHashedPfsFile*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader)); - const char* raw_name_table = (const char*)(mBinaryBlob.getBytes() + sizeof(sPfsHeader) + sizeof(sHashedPfsFile) * hdr->file_num.get()); + const sHashedPfsFile* raw_files = (const sHashedPfsFile*)(mRawBinary.data() + sizeof(sPfsHeader)); + const char* raw_name_table = (const char*)(mRawBinary.data() + sizeof(sPfsHeader) + sizeof(sHashedPfsFile) * hdr->file_num.get()); // process file entries for (size_t i = 0; i < hdr->file_num.get(); i++) @@ -171,7 +197,7 @@ void nx::PfsHeader::importBinary(const byte_t * bytes, size_t len) void nx::PfsHeader::clear() { - mBinaryBlob.clear(); + mRawBinary.clear(); mFsType = TYPE_PFS0; mFileList.clear(); } @@ -220,52 +246,8 @@ size_t nx::PfsHeader::getFileEntrySize(FsType fs_type) void nx::PfsHeader::calculateOffsets(size_t data_offset) { - for (size_t i = 0; i < mFileList.getSize(); i++) + for (size_t i = 0; i < mFileList.size(); i++) { mFileList[i].offset = (i == 0) ? data_offset : mFileList[i - 1].offset + mFileList[i - 1].size; } -} - -bool nx::PfsHeader::isEqual(const PfsHeader & other) const -{ - return (mFsType == other.mFsType) && (mFileList == other.mFileList); -} - -void nx::PfsHeader::copyFrom(const PfsHeader & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - clear(); - mFsType = other.mFsType; - mFileList = other.mFileList; - } -} - -bool nx::PfsHeader::operator==(const PfsHeader & other) const -{ - return isEqual(other); -} - -bool nx::PfsHeader::operator!=(const PfsHeader & other) const -{ - return !isEqual(other); -} - -void nx::PfsHeader::operator=(const PfsHeader & other) -{ - copyFrom(other); -} - -const byte_t * nx::PfsHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::PfsHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} +} \ No newline at end of file diff --git a/lib/libnx/source/SacBinary.cpp b/lib/libnx/source/SacBinary.cpp deleted file mode 100644 index 81efb30..0000000 --- a/lib/libnx/source/SacBinary.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -using namespace nx; - -SacBinary::SacBinary() -{ -} - -SacBinary::SacBinary(const SacBinary & other) -{ - copyFrom(other); -} - -SacBinary::SacBinary(const byte_t * bytes, size_t len) -{ - importBinary(bytes, len); -} - -bool SacBinary::operator==(const SacBinary & other) const -{ - return isEqual(other); -} - -bool SacBinary::operator!=(const SacBinary & other) const -{ - return !isEqual(other); -} - -void SacBinary::operator=(const SacBinary & other) -{ - copyFrom(other); -} - -const byte_t * SacBinary::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t SacBinary::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void SacBinary::exportBinary() -{ - size_t totalSize = 0; - for (size_t i = 0; i < mServices.getSize(); i++) - { - mServices[i].exportBinary(); - totalSize += mServices[i].getSize(); - } - - mBinaryBlob.alloc(totalSize); - for (size_t i = 0, pos = 0; i < mServices.getSize(); pos += mServices[i].getSize(), i++) - { - memcpy((mBinaryBlob.getBytes() + pos), mServices[i].getBytes(), mServices[i].getSize()); - } -} - -void SacBinary::importBinary(const byte_t * bytes, size_t len) -{ - clear(); - mBinaryBlob.alloc(len); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - - SacEntry svc; - for (size_t pos = 0; pos < len; pos += mServices.atBack().getSize()) - { - svc.importBinary((const byte_t*)(mBinaryBlob.getBytes() + pos), len - pos); - mServices.addElement(svc); - } -} - -void nx::SacBinary::clear() -{ - mBinaryBlob.clear(); - mServices.clear(); -} - -const fnd::List& SacBinary::getServiceList() const -{ - return mServices; -} - -void SacBinary::addService(const SacEntry& service) -{ - mServices.addElement(service); -} - -bool SacBinary::isEqual(const SacBinary & other) const -{ - return mServices == other.mServices; -} - -void SacBinary::copyFrom(const SacBinary & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - this->mBinaryBlob.clear(); - this->mServices = other.mServices; - } -} diff --git a/lib/libnx/source/SacEntry.cpp b/lib/libnx/source/SacEntry.cpp deleted file mode 100644 index d6dc2d4..0000000 --- a/lib/libnx/source/SacEntry.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include - -using namespace nx; - -SacEntry::SacEntry() : - mIsServer(false), - mName("") -{ -} - -SacEntry::SacEntry(const std::string & name, bool isServer) : - mIsServer(isServer), - mName(name) -{ - exportBinary(); -} - -SacEntry::SacEntry(const SacEntry & other) -{ - copyFrom(other); -} - -bool SacEntry::operator==(const SacEntry & other) const -{ - return isEqual(other); -} - -bool SacEntry::operator!=(const SacEntry & other) const -{ - return !isEqual(other); -} - -void SacEntry::operator=(const SacEntry & other) -{ - copyFrom(other); -} - -const byte_t * SacEntry::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t SacEntry::getSize() const -{ - return mBinaryBlob.getSize(); -} - -void SacEntry::exportBinary() -{ - try { - mBinaryBlob.alloc(mName.size() + 1); - } - catch (const fnd::Exception& e) - { - throw fnd::Exception(kModuleName, "Failed to allocate memory for SacEntry: " + std::string(e.what())); - } - - if (mName.length() == 0) - { - throw fnd::Exception(kModuleName, "Service name is empty"); - } - - if (mName.length() > kMaxServiceNameLen) - { - throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); - } - - // copy data into binary blob - mBinaryBlob[0] = (mIsServer ? SAC_IS_SERVER : 0) | ((mName.length()-1) & SAC_NAME_LEN_MASK); // bug? - memcpy(mBinaryBlob.getBytes() + 1, mName.c_str(), mName.length()); -} - -void SacEntry::importBinary(const byte_t * bytes, size_t len) -{ - bool isServer = (bytes[0] & SAC_IS_SERVER) == SAC_IS_SERVER; - size_t nameLen = (bytes[0] & SAC_NAME_LEN_MASK) + 1; // bug? - - if (nameLen+1 > len) - { - throw fnd::Exception(kModuleName, "SAC entry is too small"); - } - - if (nameLen == 0) - { - throw fnd::Exception(kModuleName, "SAC entry has no service name"); - } - else if (nameLen > kMaxServiceNameLen) - { - throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); - } - - mBinaryBlob.alloc(nameLen + 1); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); - - mIsServer = isServer; - mName = std::string((const char*)(mBinaryBlob.getBytes() + 1), nameLen); -} - -void nx::SacEntry::clear() -{ - mIsServer = false; - mName.clear(); -} - -bool SacEntry::isServer() const -{ - return mIsServer; -} - -void SacEntry::setIsServer(bool isServer) -{ - mIsServer = isServer; -} - -const std::string & SacEntry::getName() const -{ - return mName; -} - -void SacEntry::setName(const std::string & name) -{ - if (name.length() > kMaxServiceNameLen) - { - throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); - } - - mName = name; -} - -bool SacEntry::isEqual(const SacEntry & other) const -{ - return (mIsServer == other.mIsServer) \ - && (mName == other.mName); -} - -void SacEntry::copyFrom(const SacEntry & other) -{ - if (other.getSize()) - { - importBinary(other.getBytes(), other.getSize()); - } - else - { - this->mIsServer = other.mIsServer; - this->mName = other.mName; - } -} diff --git a/lib/libnx/source/ServiceAccessControlBinary.cpp b/lib/libnx/source/ServiceAccessControlBinary.cpp new file mode 100644 index 0000000..b46f4f9 --- /dev/null +++ b/lib/libnx/source/ServiceAccessControlBinary.cpp @@ -0,0 +1,78 @@ +#include + +nx::ServiceAccessControlBinary::ServiceAccessControlBinary() +{ + clear(); +} + +nx::ServiceAccessControlBinary::ServiceAccessControlBinary(const ServiceAccessControlBinary & other) +{ + *this = other; +} + +void nx::ServiceAccessControlBinary::operator=(const ServiceAccessControlBinary & other) +{ + mRawBinary = other.mRawBinary; + mServices = other.mServices; +} + +bool nx::ServiceAccessControlBinary::operator==(const ServiceAccessControlBinary & other) const +{ + return (mServices == other.mServices); +} + +bool nx::ServiceAccessControlBinary::operator!=(const ServiceAccessControlBinary & other) const +{ + return !(*this == other); +} + +void nx::ServiceAccessControlBinary::toBytes() +{ + size_t totalSize = 0; + for (size_t i = 0; i < mServices.size(); i++) + { + mServices[i].toBytes(); + totalSize += mServices[i].getBytes().size(); + } + + mRawBinary.alloc(totalSize); + for (size_t i = 0, pos = 0; i < mServices.size(); pos += mServices[i].getBytes().size(), i++) + { + memcpy((mRawBinary.data() + pos), mServices[i].getBytes().data(), mServices[i].getBytes().size()); + } +} + +void nx::ServiceAccessControlBinary::fromBytes(const byte_t* data, size_t len) +{ + clear(); + mRawBinary.alloc(len); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + ServiceAccessControlEntry sac; + for (size_t pos = 0; pos < len; pos += mServices.atBack().getBytes().size()) + { + sac.fromBytes((const byte_t*)(mRawBinary.data() + pos), len - pos); + mServices.addElement(sac); + } +} + +const fnd::Vec& nx::ServiceAccessControlBinary::getBytes() const +{ + return mRawBinary; +} + +void nx::ServiceAccessControlBinary::clear() +{ + mRawBinary.clear(); + mServices.clear(); +} + +const fnd::List& nx::ServiceAccessControlBinary::getServiceList() const +{ + return mServices; +} + +void nx::ServiceAccessControlBinary::addService(const ServiceAccessControlEntry& service) +{ + mServices.addElement(service); +} \ No newline at end of file diff --git a/lib/libnx/source/ServiceAccessControlEntry.cpp b/lib/libnx/source/ServiceAccessControlEntry.cpp new file mode 100644 index 0000000..00d3b9c --- /dev/null +++ b/lib/libnx/source/ServiceAccessControlEntry.cpp @@ -0,0 +1,131 @@ +#include + +nx::ServiceAccessControlEntry::ServiceAccessControlEntry() +{ + clear(); +} + +nx::ServiceAccessControlEntry::ServiceAccessControlEntry(const std::string & name, bool isServer) : + mIsServer(isServer), + mName(name) +{ + toBytes(); +} + +nx::ServiceAccessControlEntry::ServiceAccessControlEntry(const ServiceAccessControlEntry & other) +{ + *this = other; +} + +void nx::ServiceAccessControlEntry::operator=(const ServiceAccessControlEntry & other) +{ + if (other.getBytes().size()) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + this->mIsServer = other.mIsServer; + this->mName = other.mName; + } +} + +bool nx::ServiceAccessControlEntry::operator==(const ServiceAccessControlEntry & other) const +{ + return (mIsServer == other.mIsServer) \ + && (mName == other.mName); +} + +bool nx::ServiceAccessControlEntry::operator!=(const ServiceAccessControlEntry & other) const +{ + return !(*this == other); +} + + +void nx::ServiceAccessControlEntry::toBytes() +{ + try { + mRawBinary.alloc(mName.size() + 1); + } + catch (const fnd::Exception& e) + { + throw fnd::Exception(kModuleName, "Failed to allocate memory for ServiceAccessControlEntry: " + std::string(e.what())); + } + + if (mName.length() == 0) + { + throw fnd::Exception(kModuleName, "Service name is empty"); + } + + if (mName.length() > kMaxServiceNameLen) + { + throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); + } + + // copy data into binary blob + mRawBinary[0] = (mIsServer ? SAC_IS_SERVER : 0) | ((mName.length()-1) & SAC_NAME_LEN_MASK); // bug? + memcpy(mRawBinary.data() + 1, mName.c_str(), mName.length()); +} + +void nx::ServiceAccessControlEntry::fromBytes(const byte_t* data, size_t len) +{ + bool isServer = (data[0] & SAC_IS_SERVER) == SAC_IS_SERVER; + size_t nameLen = (data[0] & SAC_NAME_LEN_MASK) + 1; // bug? + + if (nameLen+1 > len) + { + throw fnd::Exception(kModuleName, "SAC entry is too small"); + } + + if (nameLen == 0) + { + throw fnd::Exception(kModuleName, "SAC entry has no service name"); + } + else if (nameLen > kMaxServiceNameLen) + { + throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); + } + + mRawBinary.alloc(nameLen + 1); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + mIsServer = isServer; + mName = std::string((const char*)(mRawBinary.data() + 1), nameLen); +} + +const fnd::Vec& nx::ServiceAccessControlEntry::getBytes() const +{ + return mRawBinary; +} + +void nx::ServiceAccessControlEntry::clear() +{ + mIsServer = false; + mName.clear(); +} + +bool nx::ServiceAccessControlEntry::isServer() const +{ + return mIsServer; +} + +void nx::ServiceAccessControlEntry::setIsServer(bool isServer) +{ + mIsServer = isServer; +} + +const std::string & nx::ServiceAccessControlEntry::getName() const +{ + return mName; +} + +void nx::ServiceAccessControlEntry::setName(const std::string & name) +{ + if (name.length() > kMaxServiceNameLen) + { + throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)"); + } + + mName = name; +} \ No newline at end of file diff --git a/lib/libnx/source/SystemCallEntry.cpp b/lib/libnx/source/SystemCallEntry.cpp index 6d0f54c..bf4a764 100644 --- a/lib/libnx/source/SystemCallEntry.cpp +++ b/lib/libnx/source/SystemCallEntry.cpp @@ -1,7 +1,5 @@ #include - - nx::SystemCallEntry::SystemCallEntry() : mCap(kCapId), mSystemCallUpper(0), @@ -10,7 +8,7 @@ nx::SystemCallEntry::SystemCallEntry() : } -nx::SystemCallEntry::SystemCallEntry(const KernelCapability & kernel_cap) : +nx::SystemCallEntry::SystemCallEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mSystemCallUpper(0), mSystemCallLower(0) @@ -27,16 +25,34 @@ nx::SystemCallEntry::SystemCallEntry(uint32_t upper_bits, uint32_t lower_bits) : setSystemCallLowerBits(lower_bits); } -const nx::KernelCapability & nx::SystemCallEntry::getKernelCapability() const +void nx::SystemCallEntry::operator=(const SystemCallEntry& other) +{ + mSystemCallUpper = other.mSystemCallUpper; + mSystemCallLower = other.mSystemCallLower; + updateCapField(); +} + +bool nx::SystemCallEntry::operator==(const SystemCallEntry& other) const +{ + return (mSystemCallUpper == other.mSystemCallUpper) \ + && (mSystemCallLower == other.mSystemCallLower); +} + +bool nx::SystemCallEntry::operator!=(const SystemCallEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::SystemCallEntry::getKernelCapability() const { return mCap; } -void nx::SystemCallEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::SystemCallEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'EnableSystemCalls'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'EnableSystemCalls'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/SystemCallHandler.cpp b/lib/libnx/source/SystemCallHandler.cpp index ee2d313..da6d677 100644 --- a/lib/libnx/source/SystemCallHandler.cpp +++ b/lib/libnx/source/SystemCallHandler.cpp @@ -1,36 +1,37 @@ #include #include - nx::SystemCallHandler::SystemCallHandler() : mIsSet(false), mSystemCalls() {} +void nx::SystemCallHandler::operator=(const SystemCallHandler & other) +{ + mIsSet = other.mIsSet; + mSystemCalls = other.mSystemCalls; +} + bool nx::SystemCallHandler::operator==(const SystemCallHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mSystemCalls == other.mSystemCalls); } bool nx::SystemCallHandler::operator!=(const SystemCallHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::SystemCallHandler::operator=(const SystemCallHandler & other) +void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() == 0) + if (caps.size() == 0) return; SystemCallEntry entry; uint8_t syscallUpper, syscall; - for (size_t i = 0; i < caps.getSize(); i++) + for (size_t i = 0; i < caps.size(); i++) { entry.setKernelCapability(caps[i]); syscallUpper = 24 * entry.getSystemCallUpperBits(); @@ -48,7 +49,7 @@ void nx::SystemCallHandler::importKernelCapabilityList(const fnd::List& caps) const +void nx::SystemCallHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -60,7 +61,7 @@ void nx::SystemCallHandler::exportKernelCapabilityList(fnd::List kMaxSystemCall) { @@ -70,7 +71,7 @@ void nx::SystemCallHandler::exportKernelCapabilityList(fnd::List& nx::SystemCallHandler::getSystemCalls() const void nx::SystemCallHandler::setSystemCallList(const fnd::List& calls) { mSystemCalls.clear(); - for (size_t i = 0; i < calls.getSize(); i++) + for (size_t i = 0; i < calls.size(); i++) { if (mSystemCalls[i] > kMaxSystemCall) { @@ -109,16 +110,4 @@ void nx::SystemCallHandler::setSystemCallList(const fnd::List& calls) } mIsSet = true; -} - -void nx::SystemCallHandler::copyFrom(const SystemCallHandler & other) -{ - mIsSet = other.mIsSet; - mSystemCalls = other.mSystemCalls; -} - -bool nx::SystemCallHandler::isEqual(const SystemCallHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mSystemCalls == other.mSystemCalls); -} +} \ No newline at end of file diff --git a/lib/libnx/source/ThreadInfoEntry.cpp b/lib/libnx/source/ThreadInfoEntry.cpp index 6323383..00cd7c8 100644 --- a/lib/libnx/source/ThreadInfoEntry.cpp +++ b/lib/libnx/source/ThreadInfoEntry.cpp @@ -1,7 +1,5 @@ #include - - nx::ThreadInfoEntry::ThreadInfoEntry() : mCap(kCapId), mMinPriority(kDefaultPriority), @@ -10,7 +8,7 @@ nx::ThreadInfoEntry::ThreadInfoEntry() : mMaxCpuId(kDefaultCpuId) {} -nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) : +nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapabilityEntry & kernel_cap) : mCap(kCapId), mMinPriority(kDefaultPriority), mMaxPriority(kDefaultPriority), @@ -33,16 +31,38 @@ nx::ThreadInfoEntry::ThreadInfoEntry(uint8_t min_priority, uint8_t max_priority, setMaxCpuId(max_core_number); } -const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const +void nx::ThreadInfoEntry::operator=(const ThreadInfoEntry& other) +{ + mMinPriority = other.mMinPriority; + mMaxPriority = other.mMaxPriority; + mMinCpuId = other.mMinCpuId; + mMaxCpuId = other.mMaxCpuId; + updateCapField(); +} + +bool nx::ThreadInfoEntry::operator==(const ThreadInfoEntry& other) const +{ + return (mMinPriority == other.mMinPriority) \ + && (mMaxPriority == other.mMaxPriority) \ + && (mMinCpuId == other.mMinCpuId) \ + && (mMaxCpuId == other.mMaxCpuId); +} + +bool nx::ThreadInfoEntry::operator!=(const ThreadInfoEntry& other) const +{ + return !(*this == other); +} + +const nx::KernelCapabilityEntry & nx::ThreadInfoEntry::getKernelCapability() const { return mCap; } -void nx::ThreadInfoEntry::setKernelCapability(const KernelCapability & kernel_cap) +void nx::ThreadInfoEntry::setKernelCapability(const KernelCapabilityEntry & kernel_cap) { if (kernel_cap.getType() != kCapId) { - throw fnd::Exception(kModuleName, "KernelCapability is not type 'ThreadInfo'"); + throw fnd::Exception(kModuleName, "KernelCapabilityEntry is not type 'ThreadInfo'"); } mCap = kernel_cap; diff --git a/lib/libnx/source/ThreadInfoHandler.cpp b/lib/libnx/source/ThreadInfoHandler.cpp index f40e31a..da906db 100644 --- a/lib/libnx/source/ThreadInfoHandler.cpp +++ b/lib/libnx/source/ThreadInfoHandler.cpp @@ -1,42 +1,42 @@ #include - - nx::ThreadInfoHandler::ThreadInfoHandler() : mIsSet(false), mEntry(0,0,0,0) {} +void nx::ThreadInfoHandler::operator=(const ThreadInfoHandler & other) +{ + mIsSet = other.mIsSet; + mEntry.setKernelCapability(other.mEntry.getKernelCapability()); +} + bool nx::ThreadInfoHandler::operator==(const ThreadInfoHandler & other) const { - return isEqual(other); + return (mIsSet == other.mIsSet) \ + && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); } bool nx::ThreadInfoHandler::operator!=(const ThreadInfoHandler & other) const { - return !isEqual(other); + return !(*this == other); } -void nx::ThreadInfoHandler::operator=(const ThreadInfoHandler & other) +void nx::ThreadInfoHandler::importKernelCapabilityList(const fnd::List& caps) { - copyFrom(other); -} - -void nx::ThreadInfoHandler::importKernelCapabilityList(const fnd::List& caps) -{ - if (caps.getSize() > kMaxKernelCapNum) + if (caps.size() > kMaxKernelCapNum) { throw fnd::Exception(kModuleName, "Too many kernel capabilities"); } - if (caps.getSize() == 0) + if (caps.size() == 0) return; mEntry.setKernelCapability(caps[0]); mIsSet = true; } -void nx::ThreadInfoHandler::exportKernelCapabilityList(fnd::List& caps) const +void nx::ThreadInfoHandler::exportKernelCapabilityList(fnd::List& caps) const { if (isSet() == false) return; @@ -100,16 +100,4 @@ void nx::ThreadInfoHandler::setMaxCpuId(uint8_t core_num) { mEntry.setMaxCpuId(core_num); mIsSet = true; -} - -void nx::ThreadInfoHandler::copyFrom(const ThreadInfoHandler & other) -{ - mIsSet = other.mIsSet; - mEntry.setKernelCapability(other.mEntry.getKernelCapability()); -} - -bool nx::ThreadInfoHandler::isEqual(const ThreadInfoHandler & other) const -{ - return (mIsSet == other.mIsSet) \ - && (mEntry.getKernelCapability() == other.mEntry.getKernelCapability()); -} +} \ No newline at end of file diff --git a/lib/libnx/source/XciHeader.cpp b/lib/libnx/source/XciHeader.cpp index 7c896de..a65b23b 100644 --- a/lib/libnx/source/XciHeader.cpp +++ b/lib/libnx/source/XciHeader.cpp @@ -1,39 +1,16 @@ #include -bool nx::XciHeader::isEqual(const XciHeader& other) const +nx::XciHeader::XciHeader() { - return ( mRomAreaStartPage == other.mRomAreaStartPage \ - && mBackupAreaStartPage == other.mBackupAreaStartPage \ - && mKekIndex == other.mKekIndex \ - && mTitleKeyDecIndex == other.mTitleKeyDecIndex \ - && mRomSize == other.mRomSize \ - && mCardHeaderVersion == other.mCardHeaderVersion \ - && mFlags == other.mFlags \ - && mPackageId == other.mPackageId \ - && mValidDataEndPage == other.mValidDataEndPage \ - && mAesCbcIv == other.mAesCbcIv \ - && mPartitionFsHeaderAddress == other.mPartitionFsHeaderAddress \ - && mPartitionFsHeaderSize == other.mPartitionFsHeaderSize \ - && mPartitionFsHeaderHash == other.mPartitionFsHeaderHash \ - && mInitialDataHash == other.mInitialDataHash \ - && mSelSec == other.mSelSec \ - && mSelT1Key == other.mSelT1Key \ - && mSelKey == other.mSelKey \ - && mLimAreaPage == other.mLimAreaPage \ - && mFwVersion[0] == other.mFwVersion[0] \ - && mFwVersion[1] == other.mFwVersion[1] \ - && mAccCtrl1 == other.mAccCtrl1 \ - && mWait1TimeRead == other.mWait1TimeRead \ - && mWait2TimeRead == other.mWait2TimeRead \ - && mWait1TimeWrite == other.mWait1TimeWrite \ - && mWait2TimeWrite == other.mWait2TimeWrite \ - && mFwMode == other.mFwMode \ - && mUppVersion == other.mUppVersion \ - && memcmp(mUppHash, other.mUppHash, xci::kUppHashLen) \ - && mUppId == other.mUppId ); + clear(); } -void nx::XciHeader::copyFrom(const XciHeader& other) +nx::XciHeader::XciHeader(const XciHeader& other) +{ + *this = other; +} + +void nx::XciHeader::operator=(const XciHeader& other) { mRomAreaStartPage = other.mRomAreaStartPage; mBackupAreaStartPage = other.mBackupAreaStartPage; @@ -66,51 +43,50 @@ void nx::XciHeader::copyFrom(const XciHeader& other) mUppId = other.mUppId; } -nx::XciHeader::XciHeader() -{ - -} - -nx::XciHeader::XciHeader(const XciHeader& other) -{ - importBinary(other.getBytes(), other.getSize()); -} -nx::XciHeader::XciHeader(const byte_t* bytes, size_t len) -{ - importBinary(bytes, len); -} - bool nx::XciHeader::operator==(const XciHeader& other) const { - return isEqual(other); + return (mRomAreaStartPage == other.mRomAreaStartPage) + && (mBackupAreaStartPage == other.mBackupAreaStartPage) + && (mKekIndex == other.mKekIndex) + && (mTitleKeyDecIndex == other.mTitleKeyDecIndex) + && (mRomSize == other.mRomSize) + && (mCardHeaderVersion == other.mCardHeaderVersion) + && (mFlags == other.mFlags) + && (mPackageId == other.mPackageId) + && (mValidDataEndPage == other.mValidDataEndPage) + && (mAesCbcIv == other.mAesCbcIv) + && (mPartitionFsHeaderAddress == other.mPartitionFsHeaderAddress) + && (mPartitionFsHeaderSize == other.mPartitionFsHeaderSize) + && (mPartitionFsHeaderHash == other.mPartitionFsHeaderHash) + && (mInitialDataHash == other.mInitialDataHash) + && (mSelSec == other.mSelSec) + && (mSelT1Key == other.mSelT1Key) + && (mSelKey == other.mSelKey) + && (mLimAreaPage == other.mLimAreaPage) + && (mFwVersion[0] == other.mFwVersion[0]) + && (mFwVersion[1] == other.mFwVersion[1]) + && (mAccCtrl1 == other.mAccCtrl1) + && (mWait1TimeRead == other.mWait1TimeRead) + && (mWait2TimeRead == other.mWait2TimeRead) + && (mWait1TimeWrite == other.mWait1TimeWrite) + && (mWait2TimeWrite == other.mWait2TimeWrite) + && (mFwMode == other.mFwMode) + && (mUppVersion == other.mUppVersion) + && (memcmp(mUppHash, other.mUppHash, xci::kUppHashLen) == 0) + && (mUppId == other.mUppId); } + bool nx::XciHeader::operator!=(const XciHeader& other) const { - return isEqual(other) == false; -} -void nx::XciHeader::operator=(const XciHeader& other) -{ - copyFrom(other); + return !(*this == other); } -// to be used after export -const byte_t* nx::XciHeader::getBytes() const -{ - return mBinaryBlob.getBytes(); -} - -size_t nx::XciHeader::getSize() const -{ - return mBinaryBlob.getSize(); -} - -// export/import binary -void nx::XciHeader::exportBinary() +void nx::XciHeader::toBytes() { fnd::Exception(kModuleName, "exportBinary() not implemented"); } -void nx::XciHeader::importBinary(const byte_t* bytes, size_t len) +void nx::XciHeader::fromBytes(const byte_t* data, size_t len) { // check input data size if (len < sizeof(sXciHeader)) @@ -122,14 +98,14 @@ void nx::XciHeader::importBinary(const byte_t* bytes, size_t len) clear(); // allocate internal local binary copy - mBinaryBlob.alloc(sizeof(sXciHeader)); - memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + mRawBinary.alloc(sizeof(sXciHeader)); + memcpy(mRawBinary.data(), data, mRawBinary.size()); // get sXciHeader ptr - const nx::sXciHeader* hdr = (const nx::sXciHeader*)mBinaryBlob.getBytes(); + const nx::sXciHeader* hdr = (const nx::sXciHeader*)mRawBinary.data(); // check XCI signature - if (hdr->signature.get() != xci::kXciSig) + if (hdr->st_magic.get() != xci::kXciStructMagic) { throw fnd::Exception(kModuleName, "XCI header corrupt"); } @@ -172,6 +148,11 @@ void nx::XciHeader::importBinary(const byte_t* bytes, size_t len) } +const fnd::Vec& nx::XciHeader::getBytes() const +{ + return mRawBinary; +} + // variables void nx::XciHeader::clear() { diff --git a/programs/nstool/source/AesCtrWrappedIFile.cpp b/programs/nstool/source/AesCtrWrappedIFile.cpp index 4a1cc71..4dd5c05 100644 --- a/programs/nstool/source/AesCtrWrappedIFile.cpp +++ b/programs/nstool/source/AesCtrWrappedIFile.cpp @@ -39,18 +39,18 @@ void AesCtrWrappedIFile::read(byte_t* out, size_t len) for (size_t i = 0; i < cache_reads; i++) { - read_len = MIN(len - (i * kCacheSize), kCacheSize); + read_len = _MIN(len - (i * kCacheSize), kCacheSize); read_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); //printf("[%x] AesCtrWrappedIFile::read() CACHE READ: readlen=%" PRIx64 "\n", this, read_len); mFile->seek(read_pos); - mFile->read(mCache.getBytes(), kCacheSizeAllocSize); + mFile->read(mCache.data(), kCacheSizeAllocSize); crypto::aes::AesIncrementCounter(mBaseCtr.iv, read_pos>>4, mCurrentCtr.iv); - crypto::aes::AesCtr(mCache.getBytes(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.getBytes()); + crypto::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); - memcpy(out + (i * kCacheSize), mCache.getBytes() + (mFileOffset & 0xf), read_len); + memcpy(out + (i * kCacheSize), mCache.data() + (mFileOffset & 0xf), read_len); } seek(mFileOffset + len); @@ -71,18 +71,18 @@ void AesCtrWrappedIFile::write(const byte_t* in, size_t len) for (size_t i = 0; i < cache_writes; i++) { - write_len = MIN(len - (i * kCacheSize), kCacheSize); + write_len = _MIN(len - (i * kCacheSize), kCacheSize); write_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); //printf("[%x] AesCtrWrappedIFile::read() CACHE READ: readlen=%" PRIx64 "\n", this, read_len); - memcpy(mCache.getBytes() + (mFileOffset & 0xf), in + (i * kCacheSize), write_len); + memcpy(mCache.data() + (mFileOffset & 0xf), in + (i * kCacheSize), write_len); crypto::aes::AesIncrementCounter(mBaseCtr.iv, write_pos>>4, mCurrentCtr.iv); - crypto::aes::AesCtr(mCache.getBytes(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.getBytes()); + crypto::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); mFile->seek(write_pos); - mFile->write(mCache.getBytes(), kCacheSizeAllocSize); + mFile->write(mCache.data(), kCacheSizeAllocSize); } seek(mFileOffset + len); @@ -90,18 +90,18 @@ void AesCtrWrappedIFile::write(const byte_t* in, size_t len) /* for (size_t i = 0; i < (len / kAesCtrScratchSize); i++) { - memcpy(mScratch.getBytes() + mBlockOffset, out + (i * kAesCtrScratchSize), kAesCtrScratchSize); - crypto::aes::AesCtr(mScratch.getBytes(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.getBytes()); - mFile->write(mScratch.getBytes() + mBlockOffset, kAesCtrScratchSize); + memcpy(mScratch.data() + mBlockOffset, out + (i * kAesCtrScratchSize), kAesCtrScratchSize); + crypto::aes::AesCtr(mScratch.data(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.data()); + mFile->write(mScratch.data() + mBlockOffset, kAesCtrScratchSize); } if (len % kAesCtrScratchSize) { size_t write_len = len % kAesCtrScratchSize; size_t write_pos = ((len / kAesCtrScratchSize) * kAesCtrScratchSize); - memcpy(mScratch.getBytes() + mBlockOffset, out + write_pos, write_len); - crypto::aes::AesCtr(mScratch.getBytes(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.getBytes()); - mFile->write(mScratch.getBytes() + mBlockOffset, write_len); + memcpy(mScratch.data() + mBlockOffset, out + write_pos, write_len); + crypto::aes::AesCtr(mScratch.data(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.data()); + mFile->write(mScratch.data() + mBlockOffset, write_len); } */ seek(mFileOffset + len); diff --git a/programs/nstool/source/AesCtrWrappedIFile.h b/programs/nstool/source/AesCtrWrappedIFile.h index 11a6165..dbbd3e0 100644 --- a/programs/nstool/source/AesCtrWrappedIFile.h +++ b/programs/nstool/source/AesCtrWrappedIFile.h @@ -1,5 +1,5 @@ #include -#include +#include #include class AesCtrWrappedIFile : public fnd::IFile @@ -25,5 +25,5 @@ private: crypto::aes::sAesIvCtr mBaseCtr, mCurrentCtr; size_t mFileOffset; - fnd::MemoryBlob mCache; + fnd::Vec mCache; }; \ No newline at end of file diff --git a/programs/nstool/source/AssetProcess.cpp b/programs/nstool/source/AssetProcess.cpp index a818c59..65d759c 100644 --- a/programs/nstool/source/AssetProcess.cpp +++ b/programs/nstool/source/AssetProcess.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "AssetProcess.h" #include "OffsetAdjustedIFile.h" @@ -73,16 +73,16 @@ void AssetProcess::setRomfsExtractPath(const std::string& path) void AssetProcess::importHeader() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile->size() < sizeof(nx::sAssetHeader)) { throw fnd::Exception(kModuleName, "Corrupt ASET: file too small"); } scratch.alloc(sizeof(nx::sAssetHeader)); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mHdr.importBinary(scratch.getBytes(), scratch.getSize()); + mHdr.fromBytes(scratch.data(), scratch.size()); } void AssetProcess::processSections() @@ -93,11 +93,11 @@ void AssetProcess::processSections() throw fnd::Exception(kModuleName, "ASET geometry for icon beyond file size"); fnd::SimpleFile outfile(mIconExtractPath.var, fnd::SimpleFile::Create); - fnd::MemoryBlob cache; + fnd::Vec cache; cache.alloc(mHdr.getIconInfo().size); - mFile->read(cache.getBytes(), mHdr.getIconInfo().offset, cache.getSize()); - outfile.write(cache.getBytes(), cache.getSize()); + mFile->read(cache.data(), mHdr.getIconInfo().offset, cache.size()); + outfile.write(cache.data(), cache.size()); outfile.close(); } @@ -109,11 +109,11 @@ void AssetProcess::processSections() if (mNacpExtractPath.isSet) { fnd::SimpleFile outfile(mNacpExtractPath.var, fnd::SimpleFile::Create); - fnd::MemoryBlob cache; + fnd::Vec cache; cache.alloc(mHdr.getNacpInfo().size); - mFile->read(cache.getBytes(), mHdr.getNacpInfo().offset, cache.getSize()); - outfile.write(cache.getBytes(), cache.getSize()); + mFile->read(cache.data(), mHdr.getNacpInfo().offset, cache.size()); + outfile.write(cache.data(), cache.size()); outfile.close(); } diff --git a/programs/nstool/source/CnmtProcess.cpp b/programs/nstool/source/CnmtProcess.cpp index 22fd0f6..8f2e95d 100644 --- a/programs/nstool/source/CnmtProcess.cpp +++ b/programs/nstool/source/CnmtProcess.cpp @@ -100,10 +100,10 @@ void CnmtProcess::displayCmnt() default: break; } - if (mCnmt.getContentInfo().getSize() > 0) + if (mCnmt.getContentInfo().size() > 0) { printf(" ContentInfo:\n"); - for (size_t i = 0; i < mCnmt.getContentInfo().getSize(); i++) + for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++) { const nx::ContentMetaBinary::ContentInfo& info = mCnmt.getContentInfo()[i]; printf(" %d\n", (int)i); @@ -117,10 +117,10 @@ void CnmtProcess::displayCmnt() printf("\n"); } } - if (mCnmt.getContentMetaInfo().getSize() > 0) + if (mCnmt.getContentMetaInfo().size() > 0) { printf(" ContentMetaInfo:\n"); - for (size_t i = 0; i < mCnmt.getContentMetaInfo().getSize(); i++) + for (size_t i = 0; i < mCnmt.getContentMetaInfo().size(); i++) { const nx::ContentMetaBinary::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i]; printf(" %d\n", (int)i); @@ -159,7 +159,7 @@ CnmtProcess::~CnmtProcess() void CnmtProcess::process() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile == nullptr) { @@ -167,9 +167,9 @@ void CnmtProcess::process() } scratch.alloc(mFile->size()); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mCnmt.importBinary(scratch.getBytes(), scratch.getSize()); + mCnmt.fromBytes(scratch.data(), scratch.size()); if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) displayCmnt(); diff --git a/programs/nstool/source/ElfSymbolParser.cpp b/programs/nstool/source/ElfSymbolParser.cpp index 6ef477f..9808a19 100644 --- a/programs/nstool/source/ElfSymbolParser.cpp +++ b/programs/nstool/source/ElfSymbolParser.cpp @@ -5,19 +5,19 @@ ElfSymbolParser::ElfSymbolParser() mSymbolList.clear(); } +void ElfSymbolParser::operator=(const ElfSymbolParser& other) +{ + mSymbolList = other.mSymbolList; +} + bool ElfSymbolParser::operator==(const ElfSymbolParser& other) const { - return isEqual(other); + return mSymbolList == other.mSymbolList; } bool ElfSymbolParser::operator!=(const ElfSymbolParser& other) const { - return !isEqual(other); -} - -void ElfSymbolParser::operator=(const ElfSymbolParser& other) -{ - copyFrom(other); + return !(*this == other); } void ElfSymbolParser::parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit) @@ -59,14 +59,4 @@ void ElfSymbolParser::parseData(const byte_t *dyn_sym, size_t dyn_sym_size, cons const fnd::List& ElfSymbolParser::getSymbolList() const { return mSymbolList; -} - -bool ElfSymbolParser::isEqual(const ElfSymbolParser& other) const -{ - return mSymbolList == other.mSymbolList; -} - -void ElfSymbolParser::copyFrom(const ElfSymbolParser& other) -{ - mSymbolList = other.mSymbolList; -} +} \ No newline at end of file diff --git a/programs/nstool/source/ElfSymbolParser.h b/programs/nstool/source/ElfSymbolParser.h index a30a570..751b535 100644 --- a/programs/nstool/source/ElfSymbolParser.h +++ b/programs/nstool/source/ElfSymbolParser.h @@ -34,9 +34,9 @@ public: ElfSymbolParser(); + void operator=(const ElfSymbolParser& other); bool operator==(const ElfSymbolParser& other) const; bool operator!=(const ElfSymbolParser& other) const; - void operator=(const ElfSymbolParser& other); void parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit); @@ -45,7 +45,4 @@ private: // data fnd::List mSymbolList; - - bool isEqual(const ElfSymbolParser& other) const; - void copyFrom(const ElfSymbolParser& other); }; \ No newline at end of file diff --git a/programs/nstool/source/HashTreeMeta.cpp b/programs/nstool/source/HashTreeMeta.cpp index d1e9abd..a8d4d41 100644 --- a/programs/nstool/source/HashTreeMeta.cpp +++ b/programs/nstool/source/HashTreeMeta.cpp @@ -9,79 +9,47 @@ HashTreeMeta::HashTreeMeta() : } -HashTreeMeta::HashTreeMeta(const nx::HierarchicalIntegrityHeader& hdr) : - mLayerInfo(), - mDataLayer(), - mMasterHashList(), - mDoAlignHashToBlock(false) +HashTreeMeta::HashTreeMeta(const byte_t* data, size_t len, HashTreeType type) : + HashTreeMeta() { - importHierarchicalIntergityHeader(hdr); -} - -HashTreeMeta::HashTreeMeta(const nx::HierarchicalSha256Header& hdr) : - mLayerInfo(), - mDataLayer(), - mMasterHashList(), - mDoAlignHashToBlock(false) -{ - importHierarchicalSha256Header(hdr); -} - -bool HashTreeMeta::operator==(const HashTreeMeta& other) const -{ - return isEqual(other); -} - -bool HashTreeMeta::operator!=(const HashTreeMeta& other) const -{ - return !isEqual(other); + importData(data, len, type); } void HashTreeMeta::operator=(const HashTreeMeta& other) { - copyFrom(other); + mLayerInfo = other.mLayerInfo; + mDataLayer = other.mDataLayer; + mMasterHashList = other.mMasterHashList; + mDoAlignHashToBlock = other.mDoAlignHashToBlock; } -void HashTreeMeta::importHierarchicalIntergityHeader(const nx::HierarchicalIntegrityHeader& hdr) +bool HashTreeMeta::operator==(const HashTreeMeta& other) const { - mDoAlignHashToBlock = true; - for (size_t i = 0; i < hdr.getLayerInfo().getSize(); i++) - { - sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); - if (i+1 == hdr.getLayerInfo().getSize()) - { - mDataLayer = layer; - } - else - { - mLayerInfo.addElement(layer); - } - } - mMasterHashList = hdr.getMasterHashList(); + return (mLayerInfo == other.mLayerInfo) \ + && (mDataLayer == other.mDataLayer) \ + && (mMasterHashList == other.mMasterHashList) \ + && (mDoAlignHashToBlock == other.mDoAlignHashToBlock); } -void HashTreeMeta::importHierarchicalSha256Header(const nx::HierarchicalSha256Header& hdr) +bool HashTreeMeta::operator!=(const HashTreeMeta& other) const { - mDoAlignHashToBlock = false; - for (size_t i = 0; i < hdr.getLayerInfo().getSize(); i++) + return !(*this == other); +} + +void HashTreeMeta::importData(const byte_t* data, size_t len, HashTreeType type) +{ + if (type == HASH_TYPE_INTEGRITY) { - sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = hdr.getHashBlockSize(); - if (i+1 == hdr.getLayerInfo().getSize()) - { - mDataLayer = layer; - } - else - { - mLayerInfo.addElement(layer); - } + nx::HierarchicalIntegrityHeader hdr; + hdr.fromBytes(data, len); + importHierarchicalIntergityHeader(hdr); + } + else if (type == HASH_TYPE_SHA256) + { + nx::HierarchicalSha256Header hdr; + hdr.fromBytes(data, len); + importHierarchicalSha256Header(hdr); } - mMasterHashList.addElement(hdr.getMasterHash()); } const fnd::List& HashTreeMeta::getHashLayerInfo() const @@ -124,18 +92,44 @@ void HashTreeMeta::setAlignHashToBlock(bool doAlign) mDoAlignHashToBlock = doAlign; } -bool HashTreeMeta::isEqual(const HashTreeMeta& other) const +void HashTreeMeta::importHierarchicalIntergityHeader(const nx::HierarchicalIntegrityHeader& hdr) { - return (mLayerInfo == other.mLayerInfo) \ - && (mDataLayer == other.mDataLayer) \ - && (mMasterHashList == other.mMasterHashList) \ - && (mDoAlignHashToBlock == other.mDoAlignHashToBlock); + mDoAlignHashToBlock = true; + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); + if (i+1 == hdr.getLayerInfo().size()) + { + mDataLayer = layer; + } + else + { + mLayerInfo.addElement(layer); + } + } + mMasterHashList = hdr.getMasterHashList(); } -void HashTreeMeta::copyFrom(const HashTreeMeta& other) +void HashTreeMeta::importHierarchicalSha256Header(const nx::HierarchicalSha256Header& hdr) { - mLayerInfo = other.mLayerInfo; - mDataLayer = other.mDataLayer; - mMasterHashList = other.mMasterHashList; - mDoAlignHashToBlock = other.mDoAlignHashToBlock; -} + mDoAlignHashToBlock = false; + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = hdr.getHashBlockSize(); + if (i+1 == hdr.getLayerInfo().size()) + { + mDataLayer = layer; + } + else + { + mLayerInfo.addElement(layer); + } + } + mMasterHashList.addElement(hdr.getMasterHash()); +} \ No newline at end of file diff --git a/programs/nstool/source/HashTreeMeta.h b/programs/nstool/source/HashTreeMeta.h index 474be89..f8225a2 100644 --- a/programs/nstool/source/HashTreeMeta.h +++ b/programs/nstool/source/HashTreeMeta.h @@ -5,6 +5,12 @@ class HashTreeMeta { public: + enum HashTreeType + { + HASH_TYPE_INTEGRITY, + HASH_TYPE_SHA256 + }; + struct sLayer { size_t offset; @@ -30,15 +36,13 @@ public: }; HashTreeMeta(); - HashTreeMeta(const nx::HierarchicalIntegrityHeader& hdr); - HashTreeMeta(const nx::HierarchicalSha256Header& hdr); + HashTreeMeta(const byte_t* data, size_t len, HashTreeType type); + void operator=(const HashTreeMeta& other); bool operator==(const HashTreeMeta& other) const; bool operator!=(const HashTreeMeta& other) const; - void operator=(const HashTreeMeta& other); - void importHierarchicalIntergityHeader(const nx::HierarchicalIntegrityHeader& hdr); - void importHierarchicalSha256Header(const nx::HierarchicalSha256Header& hdr); + void importData(const byte_t* data, size_t len, HashTreeType type); const fnd::List& getHashLayerInfo() const; void setHashLayerInfo(const fnd::List& layer_info); @@ -57,8 +61,8 @@ private: fnd::List mLayerInfo; sLayer mDataLayer; fnd::List mMasterHashList; - bool mDoAlignHashToBlock; + bool mDoAlignHashToBlock; - bool isEqual(const HashTreeMeta& other) const; - void copyFrom(const HashTreeMeta& other); + void importHierarchicalIntergityHeader(const nx::HierarchicalIntegrityHeader& hdr); + void importHierarchicalSha256Header(const nx::HierarchicalSha256Header& hdr); }; \ No newline at end of file diff --git a/programs/nstool/source/HashTreeWrappedIFile.cpp b/programs/nstool/source/HashTreeWrappedIFile.cpp index 39783dd..e8e5140 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.cpp +++ b/programs/nstool/source/HashTreeWrappedIFile.cpp @@ -68,7 +68,7 @@ void HashTreeWrappedIFile::read(byte_t* out, size_t len) readData(start_block + (i * mCacheBlockNum), block_read_len); // export the section of data that is relevant - memcpy(out + block_export_pos, mCache.getBytes() + block_export_offset, block_export_size); + memcpy(out + block_export_pos, mCache.data() + block_export_offset, block_export_size); // update export position block_export_pos += block_export_size; @@ -97,19 +97,19 @@ void HashTreeWrappedIFile::write(const byte_t* out, size_t offset, size_t len) void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) { crypto::sha::sSha256Hash hash; - fnd::MemoryBlob cur, prev; + fnd::Vec cur, prev; mAlignHashCalcToBlock = hdr.getAlignHashToBlock(); // copy master hash into prev - prev.alloc(sizeof(crypto::sha::sSha256Hash) * hdr.getMasterHashList().getSize()); - for (size_t i = 0; i < hdr.getMasterHashList().getSize(); i++) + prev.alloc(sizeof(crypto::sha::sSha256Hash) * hdr.getMasterHashList().size()); + for (size_t i = 0; i < hdr.getMasterHashList().size(); i++) { - ((crypto::sha::sSha256Hash*)prev.getBytes())[i] = hdr.getMasterHashList()[i]; + ((crypto::sha::sSha256Hash*)prev.data())[i] = hdr.getMasterHashList()[i]; } // check each hash layer - for (size_t i = 0; i < hdr.getHashLayerInfo().getSize(); i++) + for (size_t i = 0; i < hdr.getHashLayerInfo().size(); i++) { // get block size const HashTreeMeta::sLayer& layer = hdr.getHashLayerInfo()[i]; @@ -118,15 +118,15 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) cur.alloc(align(layer.size, layer.block_size)); // read layer - mFile->read(cur.getBytes(), layer.offset, layer.size); + mFile->read(cur.data(), layer.offset, layer.size); // validate blocks size_t validate_size; - for (size_t j = 0; j < cur.getSize() / layer.block_size; j++) + for (size_t j = 0; j < cur.size() / layer.block_size; j++) { - validate_size = mAlignHashCalcToBlock? layer.block_size : MIN(layer.size - (j * layer.block_size), layer.block_size); - crypto::sha::Sha256(cur.getBytes() + (j * layer.block_size), validate_size, hash.bytes); - if (hash.compare(prev.getBytes() + j * sizeof(crypto::sha::sSha256Hash)) == false) + validate_size = mAlignHashCalcToBlock? layer.block_size : _MIN(layer.size - (j * layer.block_size), layer.block_size); + crypto::sha::Sha256(cur.data() + (j * layer.block_size), validate_size, hash.bytes); + if (hash.compare(prev.data() + j * sizeof(crypto::sha::sSha256Hash)) == false) { mErrorSs << "Hash tree layer verification failed (layer: " << i << ", block: " << j << ")"; throw fnd::Exception(kModuleName, mErrorSs.str()); @@ -138,8 +138,8 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) } // save last layer as hash table for data layer - crypto::sha::sSha256Hash* hash_list = (crypto::sha::sSha256Hash*)prev.getBytes(); - for (size_t i = 0; i < prev.getSize() / sizeof(crypto::sha::sSha256Hash); i++) + crypto::sha::sSha256Hash* hash_list = (crypto::sha::sSha256Hash*)prev.data(); + for (size_t i = 0; i < prev.size() / sizeof(crypto::sha::sSha256Hash); i++) { mDataHashLayer.addElement(hash_list[i]); } @@ -168,7 +168,7 @@ void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) if ((block_offset + block_num) == getBlockNum(mData->size())) { read_len = (block_num-1) * mDataBlockSize + getRemanderBlockReadSize(mData->size()); - memset(mCache.getBytes(), 0, block_num * mDataBlockSize); + memset(mCache.data(), 0, block_num * mDataBlockSize); } else if ((block_offset + block_num) < getBlockNum(mData->size())) { @@ -180,7 +180,7 @@ void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) } // read - mData->read(mCache.getBytes(), block_offset * mDataBlockSize, read_len); + mData->read(mCache.data(), block_offset * mDataBlockSize, read_len); if (block_num > mCacheBlockNum) { @@ -193,8 +193,8 @@ void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) size_t validate_size; for (size_t i = 0; i < block_num; i++) { - validate_size = mAlignHashCalcToBlock? mDataBlockSize : MIN(read_len - (i * mDataBlockSize), mDataBlockSize); - crypto::sha::Sha256(mCache.getBytes() + (i * mDataBlockSize), validate_size, hash.bytes); + validate_size = mAlignHashCalcToBlock? mDataBlockSize : _MIN(read_len - (i * mDataBlockSize), mDataBlockSize); + crypto::sha::Sha256(mCache.data() + (i * mDataBlockSize), validate_size, hash.bytes); if (hash != mDataHashLayer[block_offset + i]) { mErrorSs << "Hash tree layer verification failed (layer: data, block: " << (block_offset + i) << " ( " << i << "/" << block_num-1 << " ), offset: 0x" << std::hex << ((block_offset + i) * mDataBlockSize) << ", size: 0x" << std::hex << validate_size <<")"; diff --git a/programs/nstool/source/HashTreeWrappedIFile.h b/programs/nstool/source/HashTreeWrappedIFile.h index cb89ae8..fa65e13 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.h +++ b/programs/nstool/source/HashTreeWrappedIFile.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include "HashTreeMeta.h" @@ -33,7 +33,7 @@ private: fnd::List mDataHashLayer; bool mAlignHashCalcToBlock; - fnd::MemoryBlob mCache; + fnd::Vec mCache; size_t mCacheBlockNum; inline size_t getOffsetBlock(size_t offset) const { return offset / mDataBlockSize; } diff --git a/programs/nstool/source/NacpProcess.cpp b/programs/nstool/source/NacpProcess.cpp index ce7dc66..2c87992 100644 --- a/programs/nstool/source/NacpProcess.cpp +++ b/programs/nstool/source/NacpProcess.cpp @@ -441,7 +441,7 @@ NacpProcess::~NacpProcess() void NacpProcess::process() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile == nullptr) { @@ -449,9 +449,9 @@ void NacpProcess::process() } scratch.alloc(mFile->size()); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mNacp.importBinary(scratch.getBytes(), scratch.getSize()); + mNacp.fromBytes(scratch.data(), scratch.size()); if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) displayNacp(); @@ -485,7 +485,7 @@ void NacpProcess::displayNacp() printf(" DisplayVersion: %s\n", mNacp.getDisplayVersion().c_str()); if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) printf(" ISBN: %s\n", mNacp.getIsbn().c_str()); - for (size_t i = 0; i < mNacp.getTitle().getSize(); i++) + for (size_t i = 0; i < mNacp.getTitle().size(); i++) { printf(" %s Title:\n", getLanguageStr(mNacp.getTitle()[i].language)); printf(" Name: %s\n", mNacp.getTitle()[i].name.c_str()); @@ -501,17 +501,17 @@ void NacpProcess::displayNacp() printf(" Play Log:\n"); printf(" PlayLogPolicy: %s\n", getPlayLogPolicyStr(mNacp.getPlayLogPolicy())); printf(" PlayLogQueryCapability: %s\n", getPlayLogQueryCapabilityStr(mNacp.getPlayLogQueryCapability())); - if (mNacp.getPlayLogQueryableApplicationId().getSize() > 0) + if (mNacp.getPlayLogQueryableApplicationId().size() > 0) { printf(" PlayLogQueryableApplicationId:\n"); - for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().getSize(); i++) + for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().size(); i++) { printf(" 0x%016" PRIx64 "\n", mNacp.getPlayLogQueryableApplicationId()[i]); } } printf(" Parental Controls:\n"); printf(" ParentalControlFlag: %s\n", getParentalControlFlagStr(mNacp.getParentalControlFlag())); - for (size_t i = 0; i < mNacp.getRatingAge().getSize(); i++) + for (size_t i = 0; i < mNacp.getRatingAge().size(); i++) { printf(" Age Restriction:\n"); printf(" Agency: %s\n", getOrganisationStr(mNacp.getRatingAge()[i].organisation)); @@ -524,11 +524,11 @@ void NacpProcess::displayNacp() printf(" BcatPassphase: %s\n", mNacp.getBcatPassphase().c_str()); printf(" DeliveryCacheStorageSize: 0x%016" PRIx64 "\n", mNacp.getBcatDeliveryCacheStorageSize()); } - if (mNacp.getLocalCommunicationId().getSize() > 0) + if (mNacp.getLocalCommunicationId().size() > 0) { printf(" Local Area Communication:\n"); printf(" LocalCommunicationId:\n"); - for (size_t i = 0; i < mNacp.getLocalCommunicationId().getSize(); i++) + for (size_t i = 0; i < mNacp.getLocalCommunicationId().size(); i++) { printf(" 0x%016" PRIx64 "\n", mNacp.getLocalCommunicationId()[i]); } diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index c90ebff..89f5d80 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -253,8 +253,6 @@ NcaProcess::~NcaProcess() void NcaProcess::process() { - fnd::MemoryBlob scratch; - if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); @@ -270,7 +268,7 @@ void NcaProcess::process() crypto::sha::Sha256((byte_t*)&mHdrBlock.header, sizeof(nx::sNcaHeader), mHdrHash.bytes); // proccess main header - mHdr.importBinary((byte_t*)&mHdrBlock.header, sizeof(nx::sNcaHeader)); + mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(nx::sNcaHeader)); // determine keys generateNcaBodyEncryptionKeys(); @@ -423,7 +421,7 @@ void NcaProcess::generateNcaBodyEncryptionKeys() { crypto::aes::sAes128Key keak_aesctr_key = zero_aesctr_key; crypto::aes::sAesXts128Key keak_aesxts_key = zero_aesxts_key; - for (size_t i = 0; i < mBodyKeys.keak_list.getSize(); i++) + for (size_t i = 0; i < mBodyKeys.keak_list.size(); i++) { if (mBodyKeys.keak_list[i].index == nx::nca::KEY_AESCTR && mBodyKeys.keak_list[i].decrypted) { @@ -485,7 +483,7 @@ void NcaProcess::generatePartitionConfiguration() { std::stringstream error; - for (size_t i = 0; i < mHdr.getPartitions().getSize(); i++) + for (size_t i = 0; i < mHdr.getPartitions().size(); i++) { // get reference to relevant structures const nx::NcaHeader::sPartition& partition = mHdr.getPartitions()[i]; @@ -523,10 +521,9 @@ void NcaProcess::generatePartitionConfiguration() info.hash_type = (nx::nca::HashType)fs_header.hash_type; info.enc_type = (nx::nca::EncryptionType)fs_header.encryption_type; if (info.hash_type == nx::nca::HASH_HIERARCHICAL_SHA256) - info.hash_tree_meta.importHierarchicalSha256Header(nx::HierarchicalSha256Header(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen)); + info.hash_tree_meta.importData(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen, HashTreeMeta::HASH_TYPE_SHA256); else if (info.hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY) - info.hash_tree_meta.importHierarchicalIntergityHeader(nx::HierarchicalIntegrityHeader(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen)); - + info.hash_tree_meta.importData(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen, HashTreeMeta::HASH_TYPE_INTEGRITY); // create reader try @@ -614,14 +611,14 @@ void NcaProcess::validateNcaSignatures() // open main.npdm if (exefs.getPfsHeader().getFileList().hasElement(kNpdmExefsPath) == true) { - const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)]; + const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath); NpdmProcess npdm; npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE, file.offset, file.size), OWN_IFILE); npdm.setCliOutputMode(0); npdm.process(); - if (crypto::rsa::pss::rsaVerify(npdm.getNpdmBinary().getAcid().getNcaHeader2RsaKey(), crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0) + if (crypto::rsa::pss::rsaVerify(npdm.getNpdmBinary().getAcid().getNcaHeaderSignature2Key(), crypto::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0) { printf("[WARNING] NCA Header ACID Signature: FAIL \n"); } @@ -631,8 +628,6 @@ void NcaProcess::validateNcaSignatures() { printf("[WARNING] NCA Header ACID Signature: FAIL (\"%s\" not present in ExeFs)\n", kNpdmExefsPath.c_str()); } - - } else { @@ -670,13 +665,13 @@ void NcaProcess::displayHeader() } - if (mBodyKeys.keak_list.getSize() > 0 && _HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) + if (mBodyKeys.keak_list.size() > 0 && _HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) { printf(" Key Area: \n"); printf(" <--------------------------------------------------------------------------->\n"); printf(" | IDX | ENCRYPTED KEY | DECRYPTED KEY |\n"); printf(" |-----|----------------------------------|----------------------------------|\n"); - for (size_t i = 0; i < mBodyKeys.keak_list.getSize(); i++) + for (size_t i = 0; i < mBodyKeys.keak_list.size(); i++) { printf(" | %3d | ", mBodyKeys.keak_list[i].index); @@ -698,7 +693,7 @@ void NcaProcess::displayHeader() if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) { printf(" Partitions:\n"); - for (size_t i = 0; i < mHdr.getPartitions().getSize(); i++) + for (size_t i = 0; i < mHdr.getPartitions().size(); i++) { sPartitionInfo& info = mPartitions[i]; @@ -721,8 +716,8 @@ void NcaProcess::displayHeader() printf(" HierarchicalIntegrity Header:\n"); //printf(" TypeId: 0x%x\n", hash_hdr.type_id.get()); //printf(" MasterHashSize: 0x%x\n", hash_hdr.master_hash_size.get()); - //printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize()); - for (size_t j = 0; j < hash_hdr.getHashLayerInfo().getSize(); j++) + //printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().size()); + for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) { printf(" Hash Layer %d:\n", (int)j); printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[j].offset); @@ -734,7 +729,7 @@ void NcaProcess::displayHeader() printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().offset); printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getDataLayer().size); printf(" BlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size); - for (size_t j = 0; j < hash_hdr.getMasterHashList().getSize(); j++) + for (size_t j = 0; j < hash_hdr.getMasterHashList().size(); j++) { printf(" Master Hash %d: ", (int)j); fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[j].bytes, sizeof(crypto::sha::sSha256Hash)); @@ -747,7 +742,7 @@ void NcaProcess::displayHeader() printf(" Master Hash: "); fnd::SimpleTextOutput::hexDump(hash_hdr.getMasterHashList()[0].bytes, sizeof(crypto::sha::sSha256Hash)); printf(" HashBlockSize: 0x%" PRIx32 "\n", (uint32_t)hash_hdr.getDataLayer().block_size); - //printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().getSize()); + //printf(" LayerNum: %d\n", hash_hdr.getLayerInfo().size()); printf(" Hash Layer:\n"); printf(" Offset: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].offset); printf(" Size: 0x%" PRIx64 "\n", (uint64_t)hash_hdr.getHashLayerInfo()[0].size); @@ -770,7 +765,7 @@ void NcaProcess::displayHeader() void NcaProcess::processPartitions() { - for (size_t i = 0; i < mHdr.getPartitions().getSize(); i++) + for (size_t i = 0; i < mHdr.getPartitions().size(); i++) { size_t index = mHdr.getPartitions()[i].index; struct sPartitionInfo& partition = mPartitions[index]; diff --git a/programs/nstool/source/NpdmProcess.cpp b/programs/nstool/source/NpdmProcess.cpp index 0fabe7d..c87cc65 100644 --- a/programs/nstool/source/NpdmProcess.cpp +++ b/programs/nstool/source/NpdmProcess.cpp @@ -19,7 +19,7 @@ NpdmProcess::~NpdmProcess() void NpdmProcess::process() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile == nullptr) { @@ -27,9 +27,9 @@ void NpdmProcess::process() } scratch.alloc(mFile->size()); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mNpdm.importBinary(scratch.getBytes(), scratch.getSize()); + mNpdm.fromBytes(scratch.data(), scratch.size()); if (mVerify) { @@ -44,17 +44,17 @@ void NpdmProcess::process() // aci binary displayAciHdr(mNpdm.getAci()); - displayFac(mNpdm.getAci().getFac()); - displaySac(mNpdm.getAci().getSac()); - displayKernelCap(mNpdm.getAci().getKc()); + displayFac(mNpdm.getAci().getFileSystemAccessControl()); + displaySac(mNpdm.getAci().getServiceAccessControl()); + displayKernelCap(mNpdm.getAci().getKernelCapabilities()); // acid binary if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - displayAciHdr(mNpdm.getAcid()); - displayFac(mNpdm.getAcid().getFac()); - displaySac(mNpdm.getAcid().getSac()); - displayKernelCap(mNpdm.getAcid().getKc()); + displayAciDescHdr(mNpdm.getAcid()); + displayFac(mNpdm.getAcid().getFileSystemAccessControl()); + displaySac(mNpdm.getAcid().getServiceAccessControl()); + displayKernelCap(mNpdm.getAcid().getKernelCapabilities()); } } } @@ -87,7 +87,41 @@ const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const const std::string kInstructionType[2] = { "32Bit", "64Bit" }; const std::string kProcAddrSpace[4] = { "Unknown", "64Bit", "32Bit", "32Bit no reserved" }; -const std::string kAciType[2] = { "ACI0", "ACID" }; +const std::string kAcidFlag[32] = +{ + "Production", + "UnqualifiedApproval", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown" +}; const std::string kMiscFlag[15] = { "EnableDebug", "ForceDebug", "bit2", "bit3", "bit4", "bit5", "bit6", "bit7", "bit8", "bit9", "bit10", "bit11", "bit12", "bit13", "bit14"}; const std::string kFsaFlag[64] = { @@ -293,10 +327,10 @@ const std::string kMemMapType[2] = { "Io", "Static" }; const std::string kAcidTarget[2] = { "Development", "Production" }; -void NpdmProcess::validateAcidSignature(const nx::AcidBinary& acid) +void NpdmProcess::validateAcidSignature(const nx::AccessControlInfoDescBinary& acid) { try { - acid.verifyBinary(mKeyset->acid_sign_key); + acid.validateSignature(mKeyset->acid_sign_key); } catch (...) { printf("[WARNING] ACID Signature: FAIL\n"); @@ -304,206 +338,198 @@ void NpdmProcess::validateAcidSignature(const nx::AcidBinary& acid) } -void NpdmProcess::validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBinary& acid) +void NpdmProcess::validateAciFromAcid(const nx::AccessControlInfoBinary& aci, const nx::AccessControlInfoDescBinary& acid) { // check Program ID - if (acid.getProgramIdMin() > 0 && aci.getProgramId() < acid.getProgramIdMin()) + if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min) { printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n"); } - else if (acid.getProgramIdMax() > 0 && aci.getProgramId() > acid.getProgramIdMax()) + else if (acid.getProgramIdRestrict().max > 0 && aci.getProgramId() > acid.getProgramIdRestrict().max) { printf("[WARNING] ACI ProgramId: FAIL (Outside Legal Range)\n"); } - // Check FAC - if (aci.getFac().getFormatVersion() != acid.getFac().getFormatVersion()) - { - printf("[WARNING] ACI/FAC FormatVersion: FAIL (%d != %d (expected))\n", aci.getFac().getFormatVersion(),acid.getFac().getFormatVersion()); - } - - for (size_t i = 0; i < aci.getFac().getFsaRightsList().getSize(); i++) + for (size_t i = 0; i < aci.getFileSystemAccessControl().getFsaRightsList().size(); i++) { bool fsaRightFound = false; - for (size_t j = 0; j < acid.getFac().getFsaRightsList().getSize() && fsaRightFound == false; j++) + for (size_t j = 0; j < acid.getFileSystemAccessControl().getFsaRightsList().size() && fsaRightFound == false; j++) { - if (aci.getFac().getFsaRightsList()[i] == acid.getFac().getFsaRightsList()[j]) + if (aci.getFileSystemAccessControl().getFsaRightsList()[i] == acid.getFileSystemAccessControl().getFsaRightsList()[j]) fsaRightFound = true; } if (fsaRightFound == false) { - printf("[WARNING] ACI/FAC FsaRights: FAIL (%s not permitted)\n", kFsaFlag[aci.getFac().getFsaRightsList()[i]].c_str()); + printf("[WARNING] ACI/FAC FsaRights: FAIL (%s not permitted)\n", kFsaFlag[aci.getFileSystemAccessControl().getFsaRightsList()[i]].c_str()); } } - for (size_t i = 0; i < aci.getFac().getContentOwnerIdList().getSize(); i++) + for (size_t i = 0; i < aci.getFileSystemAccessControl().getContentOwnerIdList().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getFac().getContentOwnerIdList().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getFileSystemAccessControl().getContentOwnerIdList().size() && rightFound == false; j++) { - if (aci.getFac().getContentOwnerIdList()[i] == acid.getFac().getContentOwnerIdList()[j]) + if (aci.getFileSystemAccessControl().getContentOwnerIdList()[i] == acid.getFileSystemAccessControl().getContentOwnerIdList()[j]) rightFound = true; } if (rightFound == false) { - printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getContentOwnerIdList()[i]); + printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFileSystemAccessControl().getContentOwnerIdList()[i]); } } - for (size_t i = 0; i < aci.getFac().getSaveDataOwnerIdList().getSize(); i++) + for (size_t i = 0; i < aci.getFileSystemAccessControl().getSaveDataOwnerIdList().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getFac().getSaveDataOwnerIdList().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getFileSystemAccessControl().getSaveDataOwnerIdList().size() && rightFound == false; j++) { - if (aci.getFac().getSaveDataOwnerIdList()[i] == acid.getFac().getSaveDataOwnerIdList()[j]) + if (aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i] == acid.getFileSystemAccessControl().getSaveDataOwnerIdList()[j]) rightFound = true; } if (rightFound == false) { - printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFac().getSaveDataOwnerIdList()[i]); + printf("[WARNING] ACI/FAC ContentOwnerId: FAIL (%08x not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i]); } } // check SAC - for (size_t i = 0; i < aci.getSac().getServiceList().getSize(); i++) + for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getSac().getServiceList().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getServiceAccessControl().getServiceList().size() && rightFound == false; j++) { - if (aci.getSac().getServiceList()[i] == acid.getSac().getServiceList()[j]) + if (aci.getServiceAccessControl().getServiceList()[i] == acid.getServiceAccessControl().getServiceList()[j]) rightFound = true; } if (rightFound == false) { - - printf("[WARNING] ACI/SAC ServiceList: FAIL (%s%s not permitted)\n", aci.getSac().getServiceList()[i].getName().c_str(), aci.getSac().getServiceList()[i].isServer()? " (Server)" : ""); + printf("[WARNING] ACI/SAC ServiceList: FAIL (%s%s not permitted)\n", aci.getServiceAccessControl().getServiceList()[i].getName().c_str(), aci.getServiceAccessControl().getServiceList()[i].isServer()? " (Server)" : ""); } } // check KC // check thread info - if (aci.getKc().getThreadInfo().getMaxCpuId() != acid.getKc().getThreadInfo().getMaxCpuId()) + if (aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() != acid.getKernelCapabilities().getThreadInfo().getMaxCpuId()) { - printf("[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxCpuId()); + printf("[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (%d not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMaxCpuId()); } - if (aci.getKc().getThreadInfo().getMinCpuId() != acid.getKc().getThreadInfo().getMinCpuId()) + if (aci.getKernelCapabilities().getThreadInfo().getMinCpuId() != acid.getKernelCapabilities().getThreadInfo().getMinCpuId()) { - printf("[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinCpuId()); + printf("[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (%d not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMinCpuId()); } - if (aci.getKc().getThreadInfo().getMaxPriority() != acid.getKc().getThreadInfo().getMaxPriority()) + if (aci.getKernelCapabilities().getThreadInfo().getMaxPriority() != acid.getKernelCapabilities().getThreadInfo().getMaxPriority()) { - printf("[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMaxPriority()); + printf("[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (%d not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMaxPriority()); } - if (aci.getKc().getThreadInfo().getMinPriority() != acid.getKc().getThreadInfo().getMinPriority()) + if (aci.getKernelCapabilities().getThreadInfo().getMinPriority() != acid.getKernelCapabilities().getThreadInfo().getMinPriority()) { - printf("[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (%d not permitted)\n", aci.getKc().getThreadInfo().getMinPriority()); + printf("[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (%d not permitted)\n", aci.getKernelCapabilities().getThreadInfo().getMinPriority()); } // check system calls - for (size_t i = 0; i < aci.getKc().getSystemCalls().getSystemCalls().getSize(); i++) + for (size_t i = 0; i < aci.getKernelCapabilities().getSystemCalls().getSystemCalls().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getKc().getSystemCalls().getSystemCalls().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getKernelCapabilities().getSystemCalls().getSystemCalls().size() && rightFound == false; j++) { - if (aci.getKc().getSystemCalls().getSystemCalls()[i] == acid.getKc().getSystemCalls().getSystemCalls()[j]) + if (aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i] == acid.getKernelCapabilities().getSystemCalls().getSystemCalls()[j]) rightFound = true; } if (rightFound == false) { - - printf("[WARNING] ACI/KC SystemCallList: FAIL (%s not permitted)\n", kSysCall[aci.getKc().getSystemCalls().getSystemCalls()[i]].c_str()); + printf("[WARNING] ACI/KC SystemCallList: FAIL (%s not permitted)\n", kSysCall[aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i]].c_str()); } } // check memory maps - for (size_t i = 0; i < aci.getKc().getMemoryMaps().getMemoryMaps().getSize(); i++) + for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getKc().getMemoryMaps().getMemoryMaps().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size() && rightFound == false; j++) { - if (aci.getKc().getMemoryMaps().getMemoryMaps()[i] == acid.getKc().getMemoryMaps().getMemoryMaps()[j]) + if (aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[j]) rightFound = true; } if (rightFound == false) { - const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKc().getMemoryMaps().getMemoryMaps()[i]; + const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i]; printf("[WARNING] ACI/KC MemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str()); } } - for (size_t i = 0; i < aci.getKc().getMemoryMaps().getIoMemoryMaps().getSize(); i++) + for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getKc().getMemoryMaps().getIoMemoryMaps().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size() && rightFound == false; j++) { - if (aci.getKc().getMemoryMaps().getIoMemoryMaps()[i] == acid.getKc().getMemoryMaps().getIoMemoryMaps()[j]) + if (aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[j]) rightFound = true; } if (rightFound == false) { - const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKc().getMemoryMaps().getIoMemoryMaps()[i]; + const nx::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i]; printf("[WARNING] ACI/KC IoMemoryMap: FAIL (0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s) not permitted)\n", (uint64_t)map.addr << 12, ((uint64_t)(map.addr + map.size) << 12) - 1, kMemMapPerm[map.perm].c_str(), kMemMapType[map.type].c_str()); } } // check interupts - for (size_t i = 0; i < aci.getKc().getInterupts().getInteruptList().getSize(); i++) + for (size_t i = 0; i < aci.getKernelCapabilities().getInterupts().getInteruptList().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getKc().getInterupts().getInteruptList().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getKernelCapabilities().getInterupts().getInteruptList().size() && rightFound == false; j++) { - if (aci.getKc().getInterupts().getInteruptList()[i] == acid.getKc().getInterupts().getInteruptList()[j]) + if (aci.getKernelCapabilities().getInterupts().getInteruptList()[i] == acid.getKernelCapabilities().getInterupts().getInteruptList()[j]) rightFound = true; } if (rightFound == false) { - printf("[WARNING] ACI/KC InteruptsList: FAIL (0x%0x not permitted)\n", aci.getKc().getInterupts().getInteruptList()[i]); + printf("[WARNING] ACI/KC InteruptsList: FAIL (0x%0x not permitted)\n", aci.getKernelCapabilities().getInterupts().getInteruptList()[i]); } } // check misc params - if (aci.getKc().getMiscParams().getProgramType() != acid.getKc().getMiscParams().getProgramType()) + if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) { - printf("[WARNING] ACI/KC ProgramType: FAIL (%d not permitted)\n", aci.getKc().getMiscParams().getProgramType()); + printf("[WARNING] ACI/KC ProgramType: FAIL (%d not permitted)\n", aci.getKernelCapabilities().getMiscParams().getProgramType()); } // check kernel version - uint32_t aciKernelVersion = (uint32_t)aci.getKc().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKc().getKernelVersion().getVerMinor(); - uint32_t acidKernelVersion = (uint32_t)acid.getKc().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKc().getKernelVersion().getVerMinor(); + uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); + uint32_t acidKernelVersion = (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMinor(); if (aciKernelVersion < acidKernelVersion) { - printf("[WARNING] ACI/KC RequiredKernelVersion: FAIL (%d.%d not permitted)\n", aci.getKc().getKernelVersion().getVerMajor(), aci.getKc().getKernelVersion().getVerMinor()); + printf("[WARNING] ACI/KC RequiredKernelVersion: FAIL (%d.%d not permitted)\n", aci.getKernelCapabilities().getKernelVersion().getVerMajor(), aci.getKernelCapabilities().getKernelVersion().getVerMinor()); } // check handle table size - if (aci.getKc().getHandleTableSize().getHandleTableSize() > acid.getKc().getHandleTableSize().getHandleTableSize()) + if (aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() > acid.getKernelCapabilities().getHandleTableSize().getHandleTableSize()) { - printf("[WARNING] ACI/KC HandleTableSize: FAIL (0x%x too large)\n", aci.getKc().getHandleTableSize().getHandleTableSize()); + printf("[WARNING] ACI/KC HandleTableSize: FAIL (0x%x too large)\n", aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize()); } // check misc flags - for (size_t i = 0; i < aci.getKc().getMiscFlags().getFlagList().getSize(); i++) + for (size_t i = 0; i < aci.getKernelCapabilities().getMiscFlags().getFlagList().size(); i++) { bool rightFound = false; - for (size_t j = 0; j < acid.getKc().getMiscFlags().getFlagList().getSize() && rightFound == false; j++) + for (size_t j = 0; j < acid.getKernelCapabilities().getMiscFlags().getFlagList().size() && rightFound == false; j++) { - if (aci.getKc().getMiscFlags().getFlagList()[i] == acid.getKc().getMiscFlags().getFlagList()[j]) + if (aci.getKernelCapabilities().getMiscFlags().getFlagList()[i] == acid.getKernelCapabilities().getMiscFlags().getFlagList()[j]) rightFound = true; } if (rightFound == false) { - printf("[WARNING] ACI/KC MiscFlag: FAIL (%s not permitted)\n", kMiscFlag[aci.getKc().getMiscFlags().getFlagList()[i]].c_str()); + printf("[WARNING] ACI/KC MiscFlag: FAIL (%s not permitted)\n", kMiscFlag[aci.getKernelCapabilities().getMiscFlags().getFlagList()[i]].c_str()); } } } -void NpdmProcess::displayNpdmHeader(const nx::NpdmHeader& hdr) +void NpdmProcess::displayNpdmHeader(const nx::NpdmBinary& hdr) { printf("[NPDM HEADER]\n"); printf(" Process Architecture Params:\n"); @@ -522,43 +548,46 @@ void NpdmProcess::displayNpdmHeader(const nx::NpdmHeader& hdr) } } -void NpdmProcess::displayAciHdr(const nx::AciHeader& aci) +void NpdmProcess::displayAciHdr(const nx::AccessControlInfoBinary& aci) { printf("[Access Control Info]\n"); - printf(" ACI Type: %s\n", kAciType[aci.getAciType()].c_str()); - if (aci.getAciType() == nx::AciBinary::TYPE_ACI0) - { - printf(" ProgramID: %016" PRIx64 "\n", aci.getProgramId()); - } - else if (aci.getAciType() == nx::AciBinary::TYPE_ACID) - { - - printf(" ACID Size: %" PRIx64 "\n", (uint64_t)aci.getAcidSize()); - printf(" Flags: \n"); - printf(" Production: %s\n", aci.isProduction() ? "TRUE" : "FALSE"); - printf(" UnqualifiedApproval: %s\n", aci.isUnqualifiedApproval() ? "TRUE" : "FALSE"); - printf(" ProgramID Restriction\n"); - printf(" Min: %016" PRIx64 "\n", aci.getProgramIdMin()); - printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax()); - - } + printf(" ProgramID: 0x%016" PRIx64 "\n", aci.getProgramId()); } -void NpdmProcess::displayFac(const nx::FacBinary& fac) +void NpdmProcess::displayAciDescHdr(const nx::AccessControlInfoDescBinary& acid) +{ + printf("[Access Control Info Desc]\n"); + if (acid.getFlagList().size() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + printf(" Flags: \n"); + for (size_t i = 0; i < acid.getFlagList().size(); i++) + { + printf(" %s (%d)\n", kAcidFlag[acid.getFlagList()[i]].c_str(), acid.getFlagList()[i]); + } + } + printf(" ProgramID Restriction\n"); + printf(" Min: 0x%016" PRIx64 "\n", acid.getProgramIdRestrict().min); + printf(" Max: 0x%016" PRIx64 "\n", acid.getProgramIdRestrict().max); +} + +void NpdmProcess::displayFac(const nx::FileSystemAccessControlBinary& fac) { printf("[FS Access Control]\n"); - printf(" Format Version: %d\n", fac.getFormatVersion()); + printf(" Format Version: %d\n", fac.getFormatVersion()); - if (fac.getFsaRightsList().getSize()) + if (fac.getFsaRightsList().size()) { printf(" FS Rights:\n"); - for (size_t i = 0; i < fac.getFsaRightsList().getSize(); i++) + for (size_t i = 0; i < fac.getFsaRightsList().size(); i++) { if (i % 10 == 0) { printf("%s ", i != 0 ? "\n" : ""); } - printf("%s%s", kFsaFlag[fac.getFsaRightsList()[i]].c_str(), fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack() ? ", " : "\n"); + printf("%s", kFsaFlag[fac.getFsaRightsList()[i]].c_str()); + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + printf(" (bit %" PRId32 ")", fac.getFsaRightsList()[i]); + printf("%s", fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack() ? ", " : "\n"); } } else @@ -566,18 +595,18 @@ void NpdmProcess::displayFac(const nx::FacBinary& fac) printf(" FS Rights: NONE\n"); } - if (fac.getContentOwnerIdList().getSize()) + if (fac.getContentOwnerIdList().size()) { printf(" Content Owner IDs:\n"); - for (size_t i = 0; i < fac.getContentOwnerIdList().getSize(); i++) + for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++) { printf(" 0x%08x\n", fac.getContentOwnerIdList()[i]); } } - if (fac.getSaveDataOwnerIdList().getSize()) + if (fac.getSaveDataOwnerIdList().size()) { printf(" Save Data Owner IDs:\n"); - for (size_t i = 0; i < fac.getSaveDataOwnerIdList().getSize(); i++) + for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) { printf(" 0x%08x\n", fac.getSaveDataOwnerIdList()[i]); } @@ -585,11 +614,11 @@ void NpdmProcess::displayFac(const nx::FacBinary& fac) } -void NpdmProcess::displaySac(const nx::SacBinary& sac) +void NpdmProcess::displaySac(const nx::ServiceAccessControlBinary& sac) { printf("[Service Access Control]\n"); printf(" Service List:\n"); - for (size_t i = 0; i < sac.getServiceList().getSize(); i++) + for (size_t i = 0; i < sac.getServiceList().size(); i++) { if (i % 10 == 0) { @@ -599,7 +628,7 @@ void NpdmProcess::displaySac(const nx::SacBinary& sac) } } -void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) +void NpdmProcess::displayKernelCap(const nx::KernelCapabilityBinary& kern) { printf("[Kernel Capabilities]\n"); if (kern.getThreadInfo().isSet()) @@ -618,7 +647,7 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) printf(" SystemCalls:"); printf("\n "); size_t lineLen = 0; - for (size_t i = 0; i < syscalls.getSize(); i++) + for (size_t i = 0; i < syscalls.size(); i++) { if (lineLen > 60) { @@ -635,12 +664,12 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) fnd::List ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); printf(" MemoryMaps:\n"); - for (size_t i = 0; i < maps.getSize(); i++) + for (size_t i = 0; i < maps.size(); i++) { printf(" 0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s)\n", (uint64_t)maps[i].addr << 12, ((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1, kMemMapPerm[maps[i].perm].c_str(), kMemMapType[maps[i].type].c_str()); } //printf(" IoMaps:\n"); - for (size_t i = 0; i < ioMaps.getSize(); i++) + for (size_t i = 0; i < ioMaps.size(); i++) { printf(" 0x%016" PRIx64 " - 0x%016" PRIx64 " (perm=%s) (type=%s)\n", (uint64_t)ioMaps[i].addr << 12, ((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1, kMemMapPerm[ioMaps[i].perm].c_str(), kMemMapType[ioMaps[i].type].c_str()); } @@ -649,7 +678,7 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) { fnd::List interupts = kern.getInterupts().getInteruptList(); printf(" Interupts Flags:\n"); - for (uint32_t i = 0; i < interupts.getSize(); i++) + for (uint32_t i = 0; i < interupts.size(); i++) { if (i % 10 == 0) { @@ -675,7 +704,7 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) fnd::List flagList = kern.getMiscFlags().getFlagList(); printf(" Misc Flags:\n"); - for (uint32_t i = 0; i < flagList.getSize(); i++) + for (uint32_t i = 0; i < flagList.size(); i++) { if (i % 10 == 0) { diff --git a/programs/nstool/source/NpdmProcess.h b/programs/nstool/source/NpdmProcess.h index 4500d0f..12264c8 100644 --- a/programs/nstool/source/NpdmProcess.h +++ b/programs/nstool/source/NpdmProcess.h @@ -32,12 +32,13 @@ private: nx::NpdmBinary mNpdm; - void validateAcidSignature(const nx::AcidBinary& acid); - void validateAciFromAcid(const nx::AciBinary& aci, const nx::AcidBinary& acid); + void validateAcidSignature(const nx::AccessControlInfoDescBinary& acid); + void validateAciFromAcid(const nx::AccessControlInfoBinary& aci, const nx::AccessControlInfoDescBinary& acid); - void displayNpdmHeader(const nx::NpdmHeader& hdr); - void displayAciHdr(const nx::AciHeader& aci); - void displayFac(const nx::FacBinary& fac); - void displaySac(const nx::SacBinary& sac); - void displayKernelCap(const nx::KcBinary& kern); + void displayNpdmHeader(const nx::NpdmBinary& hdr); + void displayAciHdr(const nx::AccessControlInfoBinary& aci); + void displayAciDescHdr(const nx::AccessControlInfoDescBinary& aci); + void displayFac(const nx::FileSystemAccessControlBinary& fac); + void displaySac(const nx::ServiceAccessControlBinary& sac); + void displayKernelCap(const nx::KernelCapabilityBinary& kern); }; \ No newline at end of file diff --git a/programs/nstool/source/NroProcess.cpp b/programs/nstool/source/NroProcess.cpp index 0f56c02..f7aace2 100644 --- a/programs/nstool/source/NroProcess.cpp +++ b/programs/nstool/source/NroProcess.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include "OffsetAdjustedIFile.h" @@ -93,20 +93,20 @@ void NroProcess::setAssetRomfsExtractPath(const std::string& path) void NroProcess::importHeader() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile->size() < sizeof(nx::sNroHeader)) { throw fnd::Exception(kModuleName, "Corrupt NRO: file too small"); } scratch.alloc(sizeof(nx::sNroHeader)); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mHdr.importBinary(scratch.getBytes(), scratch.getSize()); + mHdr.fromBytes(scratch.data(), scratch.size()); // setup homebrew extension - nx::sNroHeader* raw_hdr = (nx::sNroHeader*)scratch.getBytes(); - if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nx::nro::kNroHomebrewSig && mFile->size() > mHdr.getNroSize()) + nx::sNroHeader* raw_hdr = (nx::sNroHeader*)scratch.data(); + if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nx::nro::kNroHomebrewStructMagic && mFile->size() > mHdr.getNroSize()) { mIsHomebrewNro = true; mAssetProc.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getNroSize(), mFile->size() - mHdr.getNroSize()), true); @@ -120,11 +120,11 @@ void NroProcess::importHeader() void NroProcess::importCodeSegments() { mTextBlob.alloc(mHdr.getTextInfo().size); - mFile->read(mTextBlob.getBytes(), mHdr.getTextInfo().memory_offset, mTextBlob.getSize()); + mFile->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size()); mRoBlob.alloc(mHdr.getRoInfo().size); - mFile->read(mRoBlob.getBytes(), mHdr.getRoInfo().memory_offset, mRoBlob.getSize()); + mFile->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size()); mDataBlob.alloc(mHdr.getDataInfo().size); - mFile->read(mDataBlob.getBytes(), mHdr.getDataInfo().memory_offset, mDataBlob.getSize()); + mFile->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size()); } void NroProcess::displayHeader() @@ -168,7 +168,7 @@ void NroProcess::displayHeader() void NroProcess::processRoMeta() { - if (mRoBlob.getSize()) + if (mRoBlob.size()) { // setup ro metadata mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().memory_offset, mHdr.getRoEmbeddedInfo().size); diff --git a/programs/nstool/source/NroProcess.h b/programs/nstool/source/NroProcess.h index 5c68a21..3c5ee99 100644 --- a/programs/nstool/source/NroProcess.h +++ b/programs/nstool/source/NroProcess.h @@ -41,7 +41,7 @@ private: bool mVerify; nx::NroHeader mHdr; - fnd::MemoryBlob mTextBlob, mRoBlob, mDataBlob; + fnd::Vec mTextBlob, mRoBlob, mDataBlob; RoMetadataProcess mRoMeta; bool mIsHomebrewNro; AssetProcess mAssetProc; diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index ff8a9b9..ac68f3a 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include "OffsetAdjustedIFile.h" #include "NsoProcess.h" @@ -68,21 +68,21 @@ void NsoProcess::setListSymbols(bool listSymbols) void NsoProcess::importHeader() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile->size() < sizeof(nx::sNsoHeader)) { throw fnd::Exception(kModuleName, "Corrupt NSO: file too small"); } scratch.alloc(sizeof(nx::sNsoHeader)); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); - mHdr.importBinary(scratch.getBytes(), scratch.getSize()); + mHdr.fromBytes(scratch.data(), scratch.size()); } void NsoProcess::importCodeSegments() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; uint32_t decompressed_len; crypto::sha::sSha256Hash calc_hash; @@ -90,10 +90,10 @@ void NsoProcess::importCodeSegments() if (mHdr.getTextSegmentInfo().is_compressed) { scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mFile->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); - compress::lz4::decompressData(scratch.getBytes(), (uint32_t)scratch.getSize(), mTextBlob.getBytes(), (uint32_t)mTextBlob.getSize(), decompressed_len); - if (decompressed_len != mTextBlob.getSize()) + compress::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len); + if (decompressed_len != mTextBlob.size()) { throw fnd::Exception(kModuleName, "NSO text segment failed to decompress"); } @@ -101,11 +101,11 @@ void NsoProcess::importCodeSegments() else { mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mFile->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize()); + mFile->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); } if (mHdr.getTextSegmentInfo().is_hashed) { - crypto::sha::Sha256(mTextBlob.getBytes(), mTextBlob.getSize(), calc_hash.bytes); + crypto::sha::Sha256(mTextBlob.data(), mTextBlob.size(), calc_hash.bytes); if (calc_hash != mHdr.getTextSegmentInfo().hash) { throw fnd::Exception(kModuleName, "NSO text segment failed SHA256 verification"); @@ -116,10 +116,10 @@ void NsoProcess::importCodeSegments() if (mHdr.getRoSegmentInfo().is_compressed) { scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mFile->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); - compress::lz4::decompressData(scratch.getBytes(), (uint32_t)scratch.getSize(), mRoBlob.getBytes(), (uint32_t)mRoBlob.getSize(), decompressed_len); - if (decompressed_len != mRoBlob.getSize()) + compress::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len); + if (decompressed_len != mRoBlob.size()) { throw fnd::Exception(kModuleName, "NSO ro segment failed to decompress"); } @@ -127,11 +127,11 @@ void NsoProcess::importCodeSegments() else { mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mFile->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize()); + mFile->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); } if (mHdr.getRoSegmentInfo().is_hashed) { - crypto::sha::Sha256(mRoBlob.getBytes(), mRoBlob.getSize(), calc_hash.bytes); + crypto::sha::Sha256(mRoBlob.data(), mRoBlob.size(), calc_hash.bytes); if (calc_hash != mHdr.getRoSegmentInfo().hash) { throw fnd::Exception(kModuleName, "NSO ro segment failed SHA256 verification"); @@ -142,10 +142,10 @@ void NsoProcess::importCodeSegments() if (mHdr.getDataSegmentInfo().is_compressed) { scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mFile->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); - compress::lz4::decompressData(scratch.getBytes(), (uint32_t)scratch.getSize(), mDataBlob.getBytes(), (uint32_t)mDataBlob.getSize(), decompressed_len); - if (decompressed_len != mDataBlob.getSize()) + compress::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len); + if (decompressed_len != mDataBlob.size()) { throw fnd::Exception(kModuleName, "NSO data segment failed to decompress"); } @@ -153,11 +153,11 @@ void NsoProcess::importCodeSegments() else { mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mFile->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize()); + mFile->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); } if (mHdr.getDataSegmentInfo().is_hashed) { - crypto::sha::Sha256(mDataBlob.getBytes(), mDataBlob.getSize(), calc_hash.bytes); + crypto::sha::Sha256(mDataBlob.data(), mDataBlob.size(), calc_hash.bytes); if (calc_hash != mHdr.getDataSegmentInfo().hash) { throw fnd::Exception(kModuleName, "NSO data segment failed SHA256 verification"); @@ -237,7 +237,7 @@ void NsoProcess::displayNsoHeader() void NsoProcess::processRoMeta() { - if (mRoBlob.getSize()) + if (mRoBlob.size()) { // setup ro metadata mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size); diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index 5a24ba2..3fcecec 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -37,7 +37,7 @@ private: bool mListSymbols; nx::NsoHeader mHdr; - fnd::MemoryBlob mTextBlob, mRoBlob, mDataBlob; + fnd::Vec mTextBlob, mRoBlob, mDataBlob; RoMetadataProcess mRoMeta; void importHeader(); diff --git a/programs/nstool/source/OffsetAdjustedIFile.cpp b/programs/nstool/source/OffsetAdjustedIFile.cpp index 9938883..ad127f1 100644 --- a/programs/nstool/source/OffsetAdjustedIFile.cpp +++ b/programs/nstool/source/OffsetAdjustedIFile.cpp @@ -25,7 +25,7 @@ size_t OffsetAdjustedIFile::size() void OffsetAdjustedIFile::seek(size_t offset) { - mCurrentOffset = MIN(offset, mSize); + mCurrentOffset = _MIN(offset, mSize); } void OffsetAdjustedIFile::read(byte_t* out, size_t len) diff --git a/programs/nstool/source/PfsProcess.cpp b/programs/nstool/source/PfsProcess.cpp index a6ff585..59f2921 100644 --- a/programs/nstool/source/PfsProcess.cpp +++ b/programs/nstool/source/PfsProcess.cpp @@ -25,7 +25,7 @@ PfsProcess::~PfsProcess() void PfsProcess::process() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile == nullptr) { @@ -34,17 +34,17 @@ void PfsProcess::process() // open minimum header to get full header size scratch.alloc(sizeof(nx::sPfsHeader)); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); - if (validateHeaderMagic(((nx::sPfsHeader*)scratch.getBytes())) == false) + mFile->read(scratch.data(), 0, scratch.size()); + if (validateHeaderMagic(((nx::sPfsHeader*)scratch.data())) == false) { throw fnd::Exception(kModuleName, "Corrupt Header"); } - size_t pfsHeaderSize = determineHeaderSize(((nx::sPfsHeader*)scratch.getBytes())); + size_t pfsHeaderSize = determineHeaderSize(((nx::sPfsHeader*)scratch.data())); // open minimum header to get full header size scratch.alloc(pfsHeaderSize); - mFile->read(scratch.getBytes(), 0, scratch.getSize()); - mPfs.importBinary(scratch.getBytes(), scratch.getSize()); + mFile->read(scratch.data(), 0, scratch.size()); + mPfs.fromBytes(scratch.data(), scratch.size()); if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) { @@ -99,14 +99,14 @@ void PfsProcess::displayHeader() { printf("[PartitionFS]\n"); printf(" Type: %s\n", mPfs.getFsType() == mPfs.TYPE_PFS0? "PFS0" : "HFS0"); - printf(" FileNum: %" PRId64 "\n", (uint64_t)mPfs.getFileList().getSize()); + printf(" FileNum: %" PRId64 "\n", (uint64_t)mPfs.getFileList().size()); if (mMountName.empty() == false) printf(" MountPoint: %s%s\n", mMountName.c_str(), mMountName.at(mMountName.length()-1) != '/' ? "/" : ""); } void PfsProcess::displayFs() { - for (size_t i = 0; i < mPfs.getFileList().getSize(); i++) + for (size_t i = 0; i < mPfs.getFileList().size(); i++) { printf(" %s", mPfs.getFileList()[i].name.c_str()); if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) @@ -127,7 +127,7 @@ void PfsProcess::displayFs() size_t PfsProcess::determineHeaderSize(const nx::sPfsHeader* hdr) { size_t fileEntrySize = 0; - if (hdr->signature.get() == nx::pfs::kPfsSig) + if (hdr->st_magic.get() == nx::pfs::kPfsStructMagic) fileEntrySize = sizeof(nx::sPfsFile); else fileEntrySize = sizeof(nx::sHashedPfsFile); @@ -137,18 +137,18 @@ size_t PfsProcess::determineHeaderSize(const nx::sPfsHeader* hdr) bool PfsProcess::validateHeaderMagic(const nx::sPfsHeader* hdr) { - return hdr->signature.get() == nx::pfs::kPfsSig || hdr->signature.get() == nx::pfs::kHashedPfsSig; + return hdr->st_magic.get() == nx::pfs::kPfsStructMagic || hdr->st_magic.get() == nx::pfs::kHashedPfsStructMagic; } void PfsProcess::validateHfs() { crypto::sha::sSha256Hash hash; const fnd::List& file = mPfs.getFileList(); - for (size_t i = 0; i < file.getSize(); i++) + for (size_t i = 0; i < file.size(); i++) { mCache.alloc(file[i].hash_protected_size); - mFile->read(mCache.getBytes(), file[i].offset, file[i].hash_protected_size); - crypto::sha::Sha256(mCache.getBytes(), file[i].hash_protected_size, hash.bytes); + mFile->read(mCache.data(), file[i].offset, file[i].hash_protected_size); + crypto::sha::Sha256(mCache.data(), file[i].hash_protected_size, hash.bytes); if (hash != file[i].hash) { printf("[WARNING] HFS0 %s%s%s: FAIL (bad hash)\n", !mMountName.empty()? mMountName.c_str() : "", (!mMountName.empty() && mMountName.at(mMountName.length()-1) != '/' )? "/" : "", file[i].name.c_str()); @@ -168,7 +168,7 @@ void PfsProcess::extractFs() const fnd::List& file = mPfs.getFileList(); std::string file_path; - for (size_t i = 0; i < file.getSize(); i++) + for (size_t i = 0; i < file.size(); i++) { file_path.clear(); fnd::io::appendToPath(file_path, mExtractPath); @@ -181,8 +181,8 @@ void PfsProcess::extractFs() mFile->seek(file[i].offset); for (size_t j = 0; j < ((file[i].size / kCacheSize) + ((file[i].size % kCacheSize) != 0)); j++) { - mFile->read(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize)); - outFile.write(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize)); + mFile->read(mCache.data(), _MIN(file[i].size - (kCacheSize * j),kCacheSize)); + outFile.write(mCache.data(), _MIN(file[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); } diff --git a/programs/nstool/source/PfsProcess.h b/programs/nstool/source/PfsProcess.h index 441a738..3c90db9 100644 --- a/programs/nstool/source/PfsProcess.h +++ b/programs/nstool/source/PfsProcess.h @@ -40,7 +40,7 @@ private: std::string mMountName; bool mListFs; - fnd::MemoryBlob mCache; + fnd::Vec mCache; nx::PfsHeader mPfs; diff --git a/programs/nstool/source/RoMetadataProcess.cpp b/programs/nstool/source/RoMetadataProcess.cpp index ceeb424..89b891a 100644 --- a/programs/nstool/source/RoMetadataProcess.cpp +++ b/programs/nstool/source/RoMetadataProcess.cpp @@ -23,7 +23,7 @@ RoMetadataProcess::RoMetadataProcess() : void RoMetadataProcess::process() { - if (mRoBlob.getSize() == 0) + if (mRoBlob.size() == 0) { throw fnd::Exception(kModuleName, "No ro binary set."); } @@ -33,7 +33,7 @@ void RoMetadataProcess::process() displayRoMetaData(); } -void RoMetadataProcess::setRoBinary(const fnd::MemoryBlob& bin) +void RoMetadataProcess::setRoBinary(const fnd::Vec& bin) { mRoBlob = bin; } @@ -78,7 +78,7 @@ void RoMetadataProcess::importApiList() { if (mApiInfo.size > 0) { - std::stringstream list_stream(std::string((char*)mRoBlob.getBytes() + mApiInfo.offset, mApiInfo.size)); + std::stringstream list_stream(std::string((char*)mRoBlob.data() + mApiInfo.offset, mApiInfo.size)); std::string api_str; while(std::getline(list_stream, api_str, (char)0x00)) @@ -98,7 +98,7 @@ void RoMetadataProcess::importApiList() if (mDynSym.size > 0) { - mSymbolList.parseData(mRoBlob.getBytes() + mDynSym.offset, mDynSym.size, mRoBlob.getBytes() + mDynStr.offset, mDynStr.size, mInstructionType == nx::npdm::INSTR_64BIT); + mSymbolList.parseData(mRoBlob.data() + mDynSym.offset, mDynSym.size, mRoBlob.data() + mDynStr.offset, mDynStr.size, mInstructionType == nx::npdm::INSTR_64BIT); } } @@ -138,10 +138,10 @@ void RoMetadataProcess::displayRoMetaData() } } } - if (mSymbolList.getSymbolList().getSize() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) + if (mSymbolList.getSymbolList().size() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) { printf("[Symbol List]\n"); - for (size_t i = 0; i < mSymbolList.getSymbolList().getSize(); i++) + for (size_t i = 0; i < mSymbolList.getSymbolList().size(); i++) { const ElfSymbolParser::sElfSymbol& symbol = mSymbolList.getSymbolList()[i]; printf(" %s [SHN=%s (%04x)][STT=%s][STB=%s]\n", symbol.name.c_str(), getSectionIndexStr(symbol.shn_index), symbol.shn_index, getSymbolTypeStr(symbol.symbol_type), getSymbolBindingStr(symbol.symbol_binding)); diff --git a/programs/nstool/source/RoMetadataProcess.h b/programs/nstool/source/RoMetadataProcess.h index cf58f7e..5ac36c7 100644 --- a/programs/nstool/source/RoMetadataProcess.h +++ b/programs/nstool/source/RoMetadataProcess.h @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include @@ -17,7 +17,7 @@ public: void process(); - void setRoBinary(const fnd::MemoryBlob& bin); + void setRoBinary(const fnd::Vec& bin); void setApiInfo(size_t offset, size_t size); void setDynSym(size_t offset, size_t size); void setDynStr(size_t offset, size_t size); @@ -45,7 +45,7 @@ private: sLayout mApiInfo; sLayout mDynSym; sLayout mDynStr; - fnd::MemoryBlob mRoBlob; + fnd::Vec mRoBlob; std::vector mSdkVerApiList; std::vector mPublicApiList; std::vector mDebugApiList; diff --git a/programs/nstool/source/RomfsProcess.cpp b/programs/nstool/source/RomfsProcess.cpp index 5f2e34e..47982f5 100644 --- a/programs/nstool/source/RomfsProcess.cpp +++ b/programs/nstool/source/RomfsProcess.cpp @@ -36,7 +36,6 @@ void RomfsProcess::process() } resolveRomfs(); - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) { displayHeader(); @@ -44,7 +43,7 @@ void RomfsProcess::process() displayFs(); } if (mExtract) - extractFs(); + extractFs(); } void RomfsProcess::setInputFile(fnd::IFile* file, bool ownIFile) @@ -111,11 +110,11 @@ void RomfsProcess::displayDir(const sDirectory& dir, size_t tab) const printf("%s\n", dir.name.c_str()); } - for (size_t i = 0; i < dir.dir_list.getSize(); i++) + for (size_t i = 0; i < dir.dir_list.size(); i++) { displayDir(dir.dir_list[i], tab+1); } - for (size_t i = 0; i < dir.file_list.getSize(); i++) + for (size_t i = 0; i < dir.file_list.size(); i++) { displayFile(dir.file_list[i], tab+1); } @@ -150,7 +149,7 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir) // extract files fnd::SimpleFile outFile; - for (size_t i = 0; i < dir.file_list.getSize(); i++) + for (size_t i = 0; i < dir.file_list.size(); i++) { file_path.clear(); fnd::io::appendToPath(file_path, dir_path); @@ -163,13 +162,13 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir) mFile->seek(dir.file_list[i].offset); for (size_t j = 0; j < ((dir.file_list[i].size / kCacheSize) + ((dir.file_list[i].size % kCacheSize) != 0)); j++) { - mFile->read(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); - outFile.write(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); + mFile->read(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); + outFile.write(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); } - for (size_t i = 0; i < dir.dir_list.getSize(); i++) + for (size_t i = 0; i < dir.dir_list.size(); i++) { extractDir(dir_path, dir.dir_list[i]); } @@ -266,15 +265,15 @@ void RomfsProcess::resolveRomfs() // read directory nodes mDirNodes.alloc(mHdr.sections[nx::romfs::DIR_NODE_TABLE].size.get()); - mFile->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize()); + mFile->read(mDirNodes.data(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.size()); //printf("[RAW DIR NODES]\n"); - //fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.getBytes(), mDirNodes.getSize()); + //fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.data(), mDirNodes.size()); // read file nodes mFileNodes.alloc(mHdr.sections[nx::romfs::FILE_NODE_TABLE].size.get()); - mFile->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize()); + mFile->read(mFileNodes.data(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.size()); //printf("[RAW FILE NODES]\n"); - //fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.getBytes(), mFileNodes.getSize()); + //fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.data(), mFileNodes.size()); // A logic check on the root directory node if ( get_dir_node(0)->parent.get() != 0 \ diff --git a/programs/nstool/source/RomfsProcess.h b/programs/nstool/source/RomfsProcess.h index 169ac4c..032139c 100644 --- a/programs/nstool/source/RomfsProcess.h +++ b/programs/nstool/source/RomfsProcess.h @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -20,12 +20,11 @@ public: fnd::List dir_list; fnd::List file_list; - sDirectory& operator=(const sDirectory& other) + void operator=(const sDirectory& other) { name = other.name; dir_list = other.dir_list; file_list = other.file_list; - return *this; } bool operator==(const sDirectory& other) const @@ -44,11 +43,6 @@ public: { return (name == other); } - - bool operator!=(const std::string& other) const - { - return !operator==(other); - } }; struct sFile @@ -57,12 +51,11 @@ public: uint64_t offset; uint64_t size; - sFile& operator=(const sFile& other) + void operator=(const sFile& other) { name = other.name; offset = other.offset; size = other.size; - return *this; } bool operator==(const sFile& other) const @@ -81,11 +74,6 @@ public: { return (name == other); } - - bool operator!=(const std::string& other) const - { - return !operator==(other); - } }; RomfsProcess(); @@ -118,17 +106,17 @@ private: std::string mMountName; bool mListFs; - fnd::MemoryBlob mCache; + fnd::Vec mCache; size_t mDirNum; size_t mFileNum; nx::sRomfsHeader mHdr; - fnd::MemoryBlob mDirNodes; - fnd::MemoryBlob mFileNodes; + fnd::Vec mDirNodes; + fnd::Vec mFileNodes; sDirectory mRootDir; - inline nx::sRomfsDirEntry* get_dir_node(uint32_t offset) { return (nx::sRomfsDirEntry*)(mDirNodes.getBytes() + offset); } - inline nx::sRomfsFileEntry* get_file_node(uint32_t offset) { return (nx::sRomfsFileEntry*)(mFileNodes.getBytes() + offset); } + inline nx::sRomfsDirEntry* get_dir_node(uint32_t offset) { return (nx::sRomfsDirEntry*)(mDirNodes.data() + offset); } + inline nx::sRomfsFileEntry* get_file_node(uint32_t offset) { return (nx::sRomfsFileEntry*)(mFileNodes.data() + offset); } void printTab(size_t tab) const; diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index bdaa973..ce6975a 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -708,37 +708,35 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path) static const size_t kMaxReadSize = 0x4000; FileType file_type = FILE_INVALID; fnd::SimpleFile file; - fnd::MemoryBlob scratch; + fnd::Vec scratch; // open file file.open(path, file.Read); // read file - scratch.alloc(MIN(kMaxReadSize, file.size())); - file.read(scratch.getBytes(), 0, scratch.getSize()); + scratch.alloc(_MIN(kMaxReadSize, file.size())); + file.read(scratch.data(), 0, scratch.size()); // close file file.close(); - - - // _QUICK_CAST resolves to a pointer of type 'st' located at scratch.getBytes() + 'oft' -#define _QUICK_CAST(st, oft) ((st*)(scratch.getBytes() + (oft))) -#define _ASSERT_SIZE(size) (scratch.getSize() >= (size)) + // _TYPE_PTR resolves to a pointer of type 'st' located at scratch.data() +#define _TYPE_PTR(st) ((st*)(scratch.data())) +#define _ASSERT_SIZE(sz) (scratch.size() >= (sz)) // test npdm - if (_ASSERT_SIZE(sizeof(nx::sXciHeaderPage)) && _QUICK_CAST(nx::sXciHeaderPage, 0)->header.signature.get() == nx::xci::kXciSig) + if (_ASSERT_SIZE(sizeof(nx::sXciHeaderPage)) && _TYPE_PTR(nx::sXciHeaderPage)->header.st_magic.get() == nx::xci::kXciStructMagic) file_type = FILE_XCI; // test pfs0 - else if (_ASSERT_SIZE(sizeof(nx::sPfsHeader)) && _QUICK_CAST(nx::sPfsHeader, 0)->signature.get() == nx::pfs::kPfsSig) + else if (_ASSERT_SIZE(sizeof(nx::sPfsHeader)) && _TYPE_PTR(nx::sPfsHeader)->st_magic.get() == nx::pfs::kPfsStructMagic) file_type = FILE_PARTITIONFS; // test hfs0 - else if (_ASSERT_SIZE(sizeof(nx::sPfsHeader)) && _QUICK_CAST(nx::sPfsHeader, 0)->signature.get() == nx::pfs::kHashedPfsSig) + else if (_ASSERT_SIZE(sizeof(nx::sPfsHeader)) && _TYPE_PTR(nx::sPfsHeader)->st_magic.get() == nx::pfs::kHashedPfsStructMagic) file_type = FILE_PARTITIONFS; // test romfs - else if (_ASSERT_SIZE(sizeof(nx::sRomfsHeader)) && _QUICK_CAST(nx::sRomfsHeader, 0)->header_size.get() == sizeof(nx::sRomfsHeader) && _QUICK_CAST(nx::sRomfsHeader, 0)->sections[1].offset.get() == (_QUICK_CAST(nx::sRomfsHeader, 0)->sections[0].offset.get() + _QUICK_CAST(nx::sRomfsHeader, 0)->sections[0].size.get())) + else if (_ASSERT_SIZE(sizeof(nx::sRomfsHeader)) && _TYPE_PTR(nx::sRomfsHeader)->header_size.get() == sizeof(nx::sRomfsHeader) && _TYPE_PTR(nx::sRomfsHeader)->sections[1].offset.get() == (_TYPE_PTR(nx::sRomfsHeader)->sections[0].offset.get() + _TYPE_PTR(nx::sRomfsHeader)->sections[0].size.get())) file_type = FILE_ROMFS; // test npdm - else if (_ASSERT_SIZE(sizeof(nx::sNpdmHeader)) && _QUICK_CAST(nx::sNpdmHeader, 0)->signature.get() == nx::npdm::kNpdmStructSig) + else if (_ASSERT_SIZE(sizeof(nx::sNpdmHeader)) && _TYPE_PTR(nx::sNpdmHeader)->st_magic.get() == nx::npdm::kNpdmStructMagic) file_type = FILE_NPDM; // test nca else if (determineValidNcaFromSample(scratch)) @@ -750,62 +748,62 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path) else if (determineValidNacpFromSample(scratch)) file_type = FILE_NACP; // test nso - else if (_ASSERT_SIZE(sizeof(nx::sNsoHeader)) && _QUICK_CAST(nx::sNsoHeader, 0)->signature.get() == nx::nso::kNsoSig) + else if (_ASSERT_SIZE(sizeof(nx::sNsoHeader)) && _TYPE_PTR(nx::sNsoHeader)->st_magic.get() == nx::nso::kNsoStructMagic) file_type = FILE_NSO; // test nso - else if (_ASSERT_SIZE(sizeof(nx::sNroHeader)) && _QUICK_CAST(nx::sNroHeader, 0)->signature.get() == nx::nro::kNroSig) + else if (_ASSERT_SIZE(sizeof(nx::sNroHeader)) && _TYPE_PTR(nx::sNroHeader)->st_magic.get() == nx::nro::kNroStructMagic) file_type = FILE_NRO; // test hb asset - else if (_ASSERT_SIZE(sizeof(nx::sAssetHeader)) && _QUICK_CAST(nx::sAssetHeader, 0)->signature.get() == nx::aset::kAssetSig) + else if (_ASSERT_SIZE(sizeof(nx::sAssetHeader)) && _TYPE_PTR(nx::sAssetHeader)->st_magic.get() == nx::aset::kAssetStructMagic) file_type = FILE_HB_ASSET; // else unrecognised else file_type = FILE_INVALID; #undef _ASSERT_SIZE -#undef _QUICK_CAST +#undef _TYPE_PTR return file_type; } -bool UserSettings::determineValidNcaFromSample(const fnd::MemoryBlob& sample) const +bool UserSettings::determineValidNcaFromSample(const fnd::Vec& sample) const { // prepare decrypted NCA data byte_t nca_raw[nx::nca::kHeaderSize]; nx::sNcaHeader* nca_header = (nx::sNcaHeader*)(nca_raw + nx::NcaUtils::sectorToOffset(1)); - if (sample.getSize() < nx::nca::kHeaderSize) + if (sample.size() < nx::nca::kHeaderSize) return false; - nx::NcaUtils::decryptNcaHeader(sample.getBytes(), nca_raw, mKeyset.nca.header_key); + nx::NcaUtils::decryptNcaHeader(sample.data(), nca_raw, mKeyset.nca.header_key); - if (nca_header->signature.get() != nx::nca::kNca2Sig && nca_header->signature.get() != nx::nca::kNca3Sig) + if (nca_header->st_magic.get() != nx::nca::kNca2StructMagic && nca_header->st_magic.get() != nx::nca::kNca3StructMagic) return false; return true; } -bool UserSettings::determineValidCnmtFromSample(const fnd::MemoryBlob& sample) const +bool UserSettings::determineValidCnmtFromSample(const fnd::Vec& sample) const { - if (sample.getSize() < sizeof(nx::sContentMetaHeader)) + if (sample.size() < sizeof(nx::sContentMetaHeader)) return false; - const nx::sContentMetaHeader* data = (const nx::sContentMetaHeader*)sample.getBytes(); + const nx::sContentMetaHeader* data = (const nx::sContentMetaHeader*)sample.data(); size_t minimum_size = sizeof(nx::sContentMetaHeader) + data->exhdr_size.get() + data->content_count.get() * sizeof(nx::sContentInfo) + data->content_meta_count.get() * sizeof(nx::sContentMetaInfo) + nx::cnmt::kDigestLen; - if (sample.getSize() < minimum_size) + if (sample.size() < minimum_size) return false; if (data->type == nx::cnmt::METATYPE_APPLICATION) { - const nx::sApplicationMetaExtendedHeader* meta = (const nx::sApplicationMetaExtendedHeader*)(sample.getBytes() + sizeof(nx::sContentMetaHeader)); + const nx::sApplicationMetaExtendedHeader* meta = (const nx::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nx::sContentMetaHeader)); if ((meta->patch_id.get() & data->id.get()) != data->id.get()) return false; } else if (data->type == nx::cnmt::METATYPE_PATCH) { - const nx::sPatchMetaExtendedHeader* meta = (const nx::sPatchMetaExtendedHeader*)(sample.getBytes() + sizeof(nx::sContentMetaHeader)); + const nx::sPatchMetaExtendedHeader* meta = (const nx::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nx::sContentMetaHeader)); if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) return false; @@ -813,31 +811,31 @@ bool UserSettings::determineValidCnmtFromSample(const fnd::MemoryBlob& sample) c } else if (data->type == nx::cnmt::METATYPE_ADD_ON_CONTENT) { - const nx::sAddOnContentMetaExtendedHeader* meta = (const nx::sAddOnContentMetaExtendedHeader*)(sample.getBytes() + sizeof(nx::sContentMetaHeader)); + const nx::sAddOnContentMetaExtendedHeader* meta = (const nx::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nx::sContentMetaHeader)); if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) return false; } else if (data->type == nx::cnmt::METATYPE_DELTA) { - const nx::sDeltaMetaExtendedHeader* meta = (const nx::sDeltaMetaExtendedHeader*)(sample.getBytes() + sizeof(nx::sContentMetaHeader)); + const nx::sDeltaMetaExtendedHeader* meta = (const nx::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nx::sContentMetaHeader)); if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) return false; minimum_size += meta->extended_data_size.get(); } - if (sample.getSize() != minimum_size) + if (sample.size() != minimum_size) return false; return true; } -bool UserSettings::determineValidNacpFromSample(const fnd::MemoryBlob& sample) const +bool UserSettings::determineValidNacpFromSample(const fnd::Vec& sample) const { - if (sample.getSize() != sizeof(nx::sApplicationControlProperty)) + if (sample.size() != sizeof(nx::sApplicationControlProperty)) return false; - const nx::sApplicationControlProperty* data = (const nx::sApplicationControlProperty*)sample.getBytes(); + const nx::sApplicationControlProperty* data = (const nx::sApplicationControlProperty*)sample.data(); if (data->logo_type > nx::nacp::LOGO_Nintendo) return false; diff --git a/programs/nstool/source/UserSettings.h b/programs/nstool/source/UserSettings.h index 0744b41..d7c27b9 100644 --- a/programs/nstool/source/UserSettings.h +++ b/programs/nstool/source/UserSettings.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include "nstool.h" @@ -103,8 +103,8 @@ private: void decodeHexStringToBytes(const std::string& name, const std::string& str, byte_t* out, size_t out_len); FileType getFileTypeFromString(const std::string& type_str); FileType determineFileTypeFromFile(const std::string& path); - bool determineValidNcaFromSample(const fnd::MemoryBlob& sample) const; - bool determineValidCnmtFromSample(const fnd::MemoryBlob& sample) const; - bool determineValidNacpFromSample(const fnd::MemoryBlob& sample) const; + bool determineValidNcaFromSample(const fnd::Vec& sample) const; + bool determineValidCnmtFromSample(const fnd::Vec& sample) const; + bool determineValidNacpFromSample(const fnd::Vec& sample) const; nx::npdm::InstructionType getInstructionTypeFromString(const std::string& type_str); }; \ No newline at end of file diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/XciProcess.cpp index b1afc3e..cdf604b 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/XciProcess.cpp @@ -25,7 +25,7 @@ XciProcess::~XciProcess() void XciProcess::process() { - fnd::MemoryBlob scratch; + fnd::Vec scratch; if (mFile == nullptr) { @@ -37,7 +37,7 @@ void XciProcess::process() // allocate memory for and decrypt sXciHeader scratch.alloc(sizeof(nx::sXciHeader)); - nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.getBytes(), mKeyset->xci.header_key.key); + nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), mKeyset->xci.header_key.key); // validate header signature if (mVerify) @@ -46,7 +46,7 @@ void XciProcess::process() } // deserialise header - mHdr.importBinary(scratch.getBytes(), scratch.getSize()); + mHdr.fromBytes(scratch.data(), scratch.size()); // display header if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) @@ -82,7 +82,7 @@ void XciProcess::setVerifyMode(bool verify) void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) { - mExtractInfo.push_back({partition_name, extract_path}); + mExtractInfo.addElement({partition_name, extract_path}); } void XciProcess::setListFs(bool list_fs) @@ -219,11 +219,11 @@ void XciProcess::displayHeader() bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) { - fnd::MemoryBlob scratch; + fnd::Vec scratch; crypto::sha::sSha256Hash calc_hash; scratch.alloc(len); - mFile->read(scratch.getBytes(), offset, len); - crypto::sha::Sha256(scratch.getBytes(), scratch.getSize(), calc_hash.bytes); + mFile->read(scratch.data(), offset, scratch.size()); + crypto::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes); return calc_hash.compare(test_hash); } @@ -254,7 +254,7 @@ void XciProcess::processRootPfs() void XciProcess::processPartitionPfs() { const fnd::List& rootPartitions = mRootPfs.getPfsHeader().getFileList(); - for (size_t i = 0; i < rootPartitions.getSize(); i++) + for (size_t i = 0; i < rootPartitions.size(); i++) { // this must be validated here because only the size of the root partiton header is known at verification time if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].hash_protected_size, rootPartitions[i].hash.bytes) == false) @@ -268,13 +268,9 @@ void XciProcess::processPartitionPfs() tmp.setVerifyMode(mVerify); tmp.setCliOutputMode(mCliOutputMode); tmp.setMountPointName(kXciMountPointName + rootPartitions[i].name); - for (size_t j = 0; j < mExtractInfo.size(); j++) - { - if (mExtractInfo[j].partition_name == rootPartitions[i].name) - { - tmp.setExtractPath(mExtractInfo[j].extract_path); - } - } + if (mExtractInfo.hasElement(rootPartitions[i].name)) + tmp.setExtractPath(mExtractInfo.getElement(rootPartitions[i].name).extract_path); + tmp.process(); } } \ No newline at end of file diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/XciProcess.h index 7be23a4..224c308 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/XciProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "nstool.h" @@ -41,6 +42,17 @@ private: { std::string partition_name; std::string extract_path; + + void operator=(const sExtractInfo& other) + { + partition_name = other.partition_name; + extract_path = other.extract_path; + } + + bool operator==(const std::string& name) const + { + return name == partition_name; + } }; bool mListFs; @@ -48,7 +60,7 @@ private: nx::sXciHeaderPage mHdrPage; nx::XciHeader mHdr; PfsProcess mRootPfs; - std::vector mExtractInfo; + fnd::List mExtractInfo; void displayHeader(); bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);