mirror of
https://github.com/jakcron/nstool
synced 2024-11-23 05:59:29 +00:00
Merge pull request #27 from jakcron/ticket-development
Improve ES Ticket support and add ES Cert support.
This commit is contained in:
commit
100fd479d4
18 changed files with 1543 additions and 701 deletions
61
lib/libcrypto/include/crypto/ecdsa.h
Normal file
61
lib/libcrypto/include/crypto/ecdsa.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
namespace ecdsa
|
||||||
|
{
|
||||||
|
const size_t kEcdsa240Size = 0x1E;
|
||||||
|
|
||||||
|
enum EcdsaType
|
||||||
|
{
|
||||||
|
ECDSA_240,
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack (push, 1)
|
||||||
|
struct sEcdsa240Point
|
||||||
|
{
|
||||||
|
uint8_t r[kEcdsa240Size];
|
||||||
|
uint8_t s[kEcdsa240Size];
|
||||||
|
|
||||||
|
void operator=(const sEcdsa240Point& other)
|
||||||
|
{
|
||||||
|
memcpy(this->r, r, kEcdsa240Size);
|
||||||
|
memcpy(this->s, s, kEcdsa240Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const sEcdsa240Point& other) const
|
||||||
|
{
|
||||||
|
return memcmp(this->r, other.r, kEcdsa240Size) == 0 \
|
||||||
|
&& memcmp(this->s, other.s, kEcdsa240Size) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const sEcdsa240Point& other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sEcdsa240PrivateKey
|
||||||
|
{
|
||||||
|
uint8_t k[kEcdsa240Size];
|
||||||
|
|
||||||
|
void operator=(const sEcdsa240PrivateKey& other)
|
||||||
|
{
|
||||||
|
memcpy(this->k, k, kEcdsa240Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const sEcdsa240PrivateKey& other) const
|
||||||
|
{
|
||||||
|
return memcmp(this->k, other.k, kEcdsa240Size) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const sEcdsa240PrivateKey& other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#pragma pack (pop)
|
||||||
|
}
|
||||||
|
}
|
69
lib/libes/include/es/CertificateBody.h
Normal file
69
lib/libes/include/es/CertificateBody.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
#include <es/cert.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
class CertificateBody
|
||||||
|
: public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CertificateBody();
|
||||||
|
CertificateBody(const CertificateBody& other);
|
||||||
|
|
||||||
|
void operator=(const CertificateBody& other);
|
||||||
|
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;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
const std::string& getIssuer() const;
|
||||||
|
void setIssuer(const std::string& issuer);
|
||||||
|
|
||||||
|
es::cert::PublicKeyType getPublicKeyType() const;
|
||||||
|
void setPublicKeyType(cert::PublicKeyType type);
|
||||||
|
|
||||||
|
const std::string& getSubject() const;
|
||||||
|
void setSubject(const std::string& subject);
|
||||||
|
|
||||||
|
uint32_t getCertId() const;
|
||||||
|
void setCertId(uint32_t id);
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa4096Key& getRsa4098PublicKey() const;
|
||||||
|
void setRsa4098PublicKey(const crypto::rsa::sRsa4096Key& key);
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa2048Key& getRsa2048PublicKey() const;
|
||||||
|
void setRsa2048PublicKey(const crypto::rsa::sRsa2048Key& key);
|
||||||
|
|
||||||
|
const crypto::ecdsa::sEcdsa240Point& getEcdsa240PublicKey() const;
|
||||||
|
void setEcdsa240PublicKey(const crypto::ecdsa::sEcdsa240Point& key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "CERTIFICATE_BODY";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
std::string mIssuer;
|
||||||
|
std::string mSubject;
|
||||||
|
uint32_t mCertId;
|
||||||
|
cert::PublicKeyType mPublicKeyType;
|
||||||
|
|
||||||
|
crypto::rsa::sRsa4096Key mRsa4096PublicKey;
|
||||||
|
crypto::rsa::sRsa2048Key mRsa2048PublicKey;
|
||||||
|
crypto::ecdsa::sEcdsa240Point mEcdsa240PublicKey;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool isEqual(const CertificateBody& other) const;
|
||||||
|
void copyFrom(const CertificateBody& other);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,171 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <fnd/MemoryBlob.h>
|
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
|
||||||
#include <crypto/rsa.h>
|
|
||||||
|
|
||||||
namespace es
|
|
||||||
{
|
|
||||||
class ETicketBody_V2 :
|
|
||||||
public fnd::ISerialiseableBinary
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum TitleKeyEncType
|
|
||||||
{
|
|
||||||
AES128_CBC,
|
|
||||||
RSA2048
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LicenseType
|
|
||||||
{
|
|
||||||
ES_LICENSE_PERMANENT = 0,
|
|
||||||
ES_LICENSE_DEMO = 1,
|
|
||||||
ES_LICENSE_TRIAL = 2,
|
|
||||||
ES_LICENSE_RENTAL = 3,
|
|
||||||
ES_LICENSE_SUBSCRIPTION = 4,
|
|
||||||
ES_LICENSE_SERVICE = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
ETicketBody_V2();
|
|
||||||
ETicketBody_V2(const ETicketBody_V2& other);
|
|
||||||
ETicketBody_V2(const byte_t* bytes, size_t len);
|
|
||||||
|
|
||||||
bool operator==(const ETicketBody_V2& other) const;
|
|
||||||
bool operator!=(const ETicketBody_V2& other) const;
|
|
||||||
void operator=(const ETicketBody_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);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
virtual void clear();
|
|
||||||
|
|
||||||
const std::string& getIssuer() const;
|
|
||||||
void setIssuer(const std::string& issuer);
|
|
||||||
|
|
||||||
const byte_t* getEncTitleKey() const;
|
|
||||||
void setEncTitleKey(const byte_t* data, size_t len);
|
|
||||||
|
|
||||||
TitleKeyEncType getTitleKeyEncType() const;
|
|
||||||
void setTitleKeyEncType(TitleKeyEncType type);
|
|
||||||
|
|
||||||
uint16_t getTicketVersion() const;
|
|
||||||
void setTicketVersion(uint16_t version);
|
|
||||||
|
|
||||||
LicenseType getLicenseType() const;
|
|
||||||
void setLicenseType(LicenseType type);
|
|
||||||
|
|
||||||
byte_t getCommonKeyId() const;
|
|
||||||
void setCommonKeyId(byte_t id);
|
|
||||||
|
|
||||||
bool isPreInstall() const;
|
|
||||||
void setIsPreInstall(bool isPreInstall);
|
|
||||||
|
|
||||||
bool isSharedTitle() const;
|
|
||||||
void setIsSharedTitle(bool isSharedTitle);
|
|
||||||
|
|
||||||
bool allowAllContent() const;
|
|
||||||
void setAllowAllContent(bool allowAllContent);
|
|
||||||
|
|
||||||
const byte_t* getReservedRegion() const;
|
|
||||||
void setReservedRegion(const byte_t* data, size_t len);
|
|
||||||
|
|
||||||
uint64_t getTicketId() const;
|
|
||||||
void setTicketId(uint64_t id);
|
|
||||||
|
|
||||||
uint64_t getDeviceId() const;
|
|
||||||
void setDeviceId(uint64_t id);
|
|
||||||
|
|
||||||
const byte_t* getRightsId() const;
|
|
||||||
void setRightsId(const byte_t* id);
|
|
||||||
|
|
||||||
uint32_t getAccountId() const;
|
|
||||||
void setAccountId(uint32_t id);
|
|
||||||
|
|
||||||
uint32_t getSectionTotalSize() const;
|
|
||||||
void setSectionTotalSize(uint32_t size);
|
|
||||||
|
|
||||||
uint32_t getSectionHeaderOffset() const;
|
|
||||||
void setSectionHeaderOffset(uint32_t offset);
|
|
||||||
|
|
||||||
uint16_t getSectionNum() const;
|
|
||||||
void setSectionNum(uint16_t num);
|
|
||||||
|
|
||||||
uint16_t getSectionEntrySize() const;
|
|
||||||
void setSectionEntrySize(uint16_t size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string kModuleName = "ES_ETICKET_BODY_V2";
|
|
||||||
static const size_t kIssuerLen = 0x40;
|
|
||||||
static const byte_t kFormatVersion = 2;
|
|
||||||
static const size_t kEncTitleKeyLen = crypto::rsa::kRsa2048Size;
|
|
||||||
static const size_t kReservedRegionLen = 8;
|
|
||||||
static const size_t kRightsIdLen = 16;
|
|
||||||
|
|
||||||
enum PropertyMaskFlags
|
|
||||||
{
|
|
||||||
FLAG_PRE_INSTALL,
|
|
||||||
FLAG_SHARED_TITLE,
|
|
||||||
FLAG_ALLOW_ALL_CONTENT
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack (push, 1)
|
|
||||||
struct sTicketBody_v2
|
|
||||||
{
|
|
||||||
char issuer[kIssuerLen];
|
|
||||||
byte_t enc_title_key[kEncTitleKeyLen];
|
|
||||||
byte_t format_version;
|
|
||||||
byte_t title_key_enc_type;
|
|
||||||
le_uint16_t ticket_version;
|
|
||||||
byte_t license_type;
|
|
||||||
byte_t common_key_id;
|
|
||||||
byte_t property_mask;
|
|
||||||
byte_t reserved_0;
|
|
||||||
byte_t reserved_region[kReservedRegionLen]; // explicitly reserved
|
|
||||||
le_uint64_t ticket_id;
|
|
||||||
le_uint64_t device_id;
|
|
||||||
byte_t rights_id[kRightsIdLen];
|
|
||||||
le_uint32_t account_id;
|
|
||||||
le_uint32_t sect_total_size;
|
|
||||||
le_uint32_t sect_header_offset;
|
|
||||||
le_uint16_t sect_num;
|
|
||||||
le_uint16_t sect_entry_size;
|
|
||||||
|
|
||||||
};
|
|
||||||
#pragma pack (pop)
|
|
||||||
|
|
||||||
// raw binary
|
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
|
||||||
|
|
||||||
// variables
|
|
||||||
std::string mIssuer;
|
|
||||||
byte_t mEncTitleKey[kEncTitleKeyLen];
|
|
||||||
TitleKeyEncType mEncType; // 0 = aes-cbc, 1 = rsa2048
|
|
||||||
uint16_t mTicketVersion;
|
|
||||||
LicenseType mLicenseType;
|
|
||||||
byte_t mCommonKeyId;
|
|
||||||
bool mPreInstall;
|
|
||||||
bool mSharedTitle;
|
|
||||||
bool mAllowAllContent;
|
|
||||||
byte_t mReservedRegion[kReservedRegionLen]; // explicitly reserved
|
|
||||||
uint64_t mTicketId;
|
|
||||||
uint64_t mDeviceId;
|
|
||||||
byte_t mRightsId[kRightsIdLen];
|
|
||||||
uint32_t mAccountId;
|
|
||||||
uint32_t mSectTotalSize;
|
|
||||||
uint32_t mSectHeaderOffset;
|
|
||||||
uint16_t mSectNum;
|
|
||||||
uint16_t mSectEntrySize;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
bool isEqual(const ETicketBody_V2& other) const;
|
|
||||||
void copyFrom(const ETicketBody_V2& other);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <fnd/MemoryBlob.h>
|
|
||||||
#include <fnd/List.h>
|
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
|
||||||
|
|
||||||
namespace es
|
|
||||||
{
|
|
||||||
class ETicketContentRecord_V1 :
|
|
||||||
public fnd::ISerialiseableBinary
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ETicketContentRecord_V1();
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string kModuleName = "ETICKET_CONTENT_RECORD_V1";
|
|
||||||
|
|
||||||
#pragma pack (push, 1)
|
|
||||||
struct sContentRecord_v1
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static const size_t kAccessMaskSize = 0x80;
|
|
||||||
static const uint16_t kGroupMask = 0xFC00;
|
|
||||||
static const uint16_t kAccessMaskMask = 0x3FF;
|
|
||||||
|
|
||||||
be_uint32_t group;
|
|
||||||
byte_t access_mask[kAccessMaskSize];
|
|
||||||
public:
|
|
||||||
uint32_t index_group() const { return group.get(); }
|
|
||||||
bool is_index_enabled(uint16_t index) const
|
|
||||||
{
|
|
||||||
return (index_group() == get_group(index)) \
|
|
||||||
&& ((access_mask[get_access_mask(index) / 8] & BIT(get_access_mask(index) % 8)) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() { memset(this, 0, sizeof(sContentRecord_v1)); }
|
|
||||||
|
|
||||||
void set_index_group(uint16_t index) { group = get_group(index); }
|
|
||||||
void enable_index(uint16_t index) { access_mask[get_access_mask(index) / 8] |= BIT(get_access_mask(index) % 8); }
|
|
||||||
void disable_index(uint16_t index) { access_mask[get_access_mask(index) / 8] &= ~BIT(get_access_mask(index) % 8); }
|
|
||||||
|
|
||||||
inline uint16_t get_access_mask(uint16_t index) const { return index & kAccessMaskMask; }
|
|
||||||
inline uint16_t get_group(uint16_t index) const { return index & kGroupMask; }
|
|
||||||
};
|
|
||||||
#pragma pack (pop)
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <fnd/MemoryBlob.h>
|
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
|
||||||
|
|
||||||
namespace es
|
|
||||||
{
|
|
||||||
class ETicketSectionHeader_V2 :
|
|
||||||
public fnd::ISerialiseableBinary
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum SectionType
|
|
||||||
{
|
|
||||||
PERMANENT = 1,
|
|
||||||
SUBSCRIPTION = 2,
|
|
||||||
CONTENT = 3,
|
|
||||||
CONTENT_CONSUMPTION = 4,
|
|
||||||
ACCESS_TITLE = 5,
|
|
||||||
LIMITED_RESOURCE = 6,
|
|
||||||
};
|
|
||||||
|
|
||||||
ETicketSectionHeader_V2();
|
|
||||||
ETicketSectionHeader_V2(const ETicketSectionHeader_V2& other);
|
|
||||||
ETicketSectionHeader_V2(const byte_t* bytes, size_t len);
|
|
||||||
|
|
||||||
bool operator==(const ETicketSectionHeader_V2& other) const;
|
|
||||||
bool operator!=(const ETicketSectionHeader_V2& other) const;
|
|
||||||
void operator=(const ETicketSectionHeader_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);
|
|
||||||
|
|
||||||
// variables
|
|
||||||
virtual void clear();
|
|
||||||
|
|
||||||
uint32_t getSectionOffset() const;
|
|
||||||
void setSectionOffset(uint32_t offset);
|
|
||||||
|
|
||||||
uint32_t getRecordSize() const;
|
|
||||||
void setRecordSize(uint32_t size);
|
|
||||||
|
|
||||||
uint32_t getSectionSize() const;
|
|
||||||
void getSectionSize(uint32_t size);
|
|
||||||
|
|
||||||
uint16_t getRecordNum() const;
|
|
||||||
void setRecordNum(uint16_t record_num);
|
|
||||||
|
|
||||||
SectionType getSectionType() const;
|
|
||||||
void setSectionType(SectionType type);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string kModuleName = "ETICKET_SECTION_HEADER_V2";
|
|
||||||
#pragma pack (push, 1)
|
|
||||||
struct sSectionHeader_v2
|
|
||||||
{
|
|
||||||
le_uint32_t section_offset;
|
|
||||||
le_uint32_t record_size;
|
|
||||||
le_uint32_t section_size;
|
|
||||||
le_uint16_t record_num;
|
|
||||||
le_uint16_t section_type;
|
|
||||||
};
|
|
||||||
#pragma pack (pop)
|
|
||||||
|
|
||||||
// raw binary
|
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
|
||||||
|
|
||||||
// variables
|
|
||||||
uint32_t mSectionOffset;
|
|
||||||
uint32_t mRecordSize;
|
|
||||||
uint32_t mSectionSize;
|
|
||||||
uint16_t mRecordNum;
|
|
||||||
SectionType mSectionType;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
bool isEqual(const ETicketSectionHeader_V2& other) const;
|
|
||||||
void copyFrom(const ETicketSectionHeader_V2& other);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
66
lib/libes/include/es/SectionHeader_V2.h
Normal file
66
lib/libes/include/es/SectionHeader_V2.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
#include <es/ticket.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
class SectionHeader_V2 :
|
||||||
|
public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SectionHeader_V2();
|
||||||
|
SectionHeader_V2(const SectionHeader_V2& other);
|
||||||
|
SectionHeader_V2(const byte_t* bytes, size_t len);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// variables
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
uint32_t getSectionOffset() const;
|
||||||
|
void setSectionOffset(uint32_t offset);
|
||||||
|
|
||||||
|
uint32_t getRecordSize() const;
|
||||||
|
void setRecordSize(uint32_t size);
|
||||||
|
|
||||||
|
uint32_t getSectionSize() const;
|
||||||
|
void getSectionSize(uint32_t size);
|
||||||
|
|
||||||
|
uint16_t getRecordNum() const;
|
||||||
|
void setRecordNum(uint16_t record_num);
|
||||||
|
|
||||||
|
ticket::SectionType getSectionType() const;
|
||||||
|
void setSectionType(ticket::SectionType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "SECTION_HEADER_V2";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
uint32_t mSectionOffset;
|
||||||
|
uint32_t mRecordSize;
|
||||||
|
uint32_t mSectionSize;
|
||||||
|
uint16_t mRecordNum;
|
||||||
|
ticket::SectionType mSectionType;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool isEqual(const SectionHeader_V2& other) const;
|
||||||
|
void copyFrom(const SectionHeader_V2& other);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
53
lib/libes/include/es/SignatureBlock.h
Normal file
53
lib/libes/include/es/SignatureBlock.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
#include <es/sign.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
class SignatureBlock
|
||||||
|
: public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SignatureBlock();
|
||||||
|
SignatureBlock(const SignatureBlock& other);
|
||||||
|
|
||||||
|
void operator=(const SignatureBlock& other);
|
||||||
|
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;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
es::sign::SignType getSignType() const;
|
||||||
|
void setSignType(es::sign::SignType type);
|
||||||
|
|
||||||
|
bool isLittleEndian() const;
|
||||||
|
void setLittleEndian(bool isLE);
|
||||||
|
|
||||||
|
const fnd::MemoryBlob& getSignature() const;
|
||||||
|
void setSignature(const fnd::MemoryBlob& signature);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "SIGNATURE_BLOCK";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
es::sign::SignType mSignType;
|
||||||
|
bool mIsLittleEndian;
|
||||||
|
fnd::MemoryBlob mSignature;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool isEqual(const SignatureBlock& other) const;
|
||||||
|
void copyFrom(const SignatureBlock& other);
|
||||||
|
};
|
||||||
|
}
|
113
lib/libes/include/es/SignedData.h
Normal file
113
lib/libes/include/es/SignedData.h
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
#include <es/SignatureBlock.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
class SignedData
|
||||||
|
: public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SignedData()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
SignedData(const SignedData& other)
|
||||||
|
{
|
||||||
|
copyFrom(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 importBinary(const byte_t* src, size_t size)
|
||||||
|
{
|
||||||
|
mSignature.importBinary(src, size);
|
||||||
|
mBody.importBinary(src + mSignature.getSize(), size - mSignature.getSize());
|
||||||
|
|
||||||
|
mBinaryBlob.alloc(mSignature.getSize() + mBody.getSize());
|
||||||
|
memcpy(mBinaryBlob.getBytes(), src, mBinaryBlob.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void exportBinary()
|
||||||
|
{
|
||||||
|
mSignature.exportBinary();
|
||||||
|
mBody.exportBinary();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "SIGNED_DATA";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
118
lib/libes/include/es/TicketBody_V2.h
Normal file
118
lib/libes/include/es/TicketBody_V2.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
#include <es/ticket.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
class TicketBody_V2 :
|
||||||
|
public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TicketBody_V2();
|
||||||
|
TicketBody_V2(const TicketBody_V2& other);
|
||||||
|
TicketBody_V2(const byte_t* bytes, size_t len);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// variables
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
const std::string& getIssuer() const;
|
||||||
|
void setIssuer(const std::string& issuer);
|
||||||
|
|
||||||
|
const byte_t* getEncTitleKey() const;
|
||||||
|
void setEncTitleKey(const byte_t* data, size_t len);
|
||||||
|
|
||||||
|
ticket::TitleKeyEncType getTitleKeyEncType() const;
|
||||||
|
void setTitleKeyEncType(ticket::TitleKeyEncType type);
|
||||||
|
|
||||||
|
uint16_t getTicketVersion() const;
|
||||||
|
void setTicketVersion(uint16_t version);
|
||||||
|
|
||||||
|
ticket::LicenseType getLicenseType() const;
|
||||||
|
void setLicenseType(ticket::LicenseType type);
|
||||||
|
|
||||||
|
byte_t getCommonKeyId() const;
|
||||||
|
void setCommonKeyId(byte_t id);
|
||||||
|
|
||||||
|
bool isPreInstall() const;
|
||||||
|
void setIsPreInstall(bool isPreInstall);
|
||||||
|
|
||||||
|
bool isSharedTitle() const;
|
||||||
|
void setIsSharedTitle(bool isSharedTitle);
|
||||||
|
|
||||||
|
bool allowAllContent() const;
|
||||||
|
void setAllowAllContent(bool allowAllContent);
|
||||||
|
|
||||||
|
const byte_t* getReservedRegion() const;
|
||||||
|
void setReservedRegion(const byte_t* data, size_t len);
|
||||||
|
|
||||||
|
uint64_t getTicketId() const;
|
||||||
|
void setTicketId(uint64_t id);
|
||||||
|
|
||||||
|
uint64_t getDeviceId() const;
|
||||||
|
void setDeviceId(uint64_t id);
|
||||||
|
|
||||||
|
const byte_t* getRightsId() const;
|
||||||
|
void setRightsId(const byte_t* id);
|
||||||
|
|
||||||
|
uint32_t getAccountId() const;
|
||||||
|
void setAccountId(uint32_t id);
|
||||||
|
|
||||||
|
uint32_t getSectionTotalSize() const;
|
||||||
|
void setSectionTotalSize(uint32_t size);
|
||||||
|
|
||||||
|
uint32_t getSectionHeaderOffset() const;
|
||||||
|
void setSectionHeaderOffset(uint32_t offset);
|
||||||
|
|
||||||
|
uint16_t getSectionNum() const;
|
||||||
|
void setSectionNum(uint16_t num);
|
||||||
|
|
||||||
|
uint16_t getSectionEntrySize() const;
|
||||||
|
void setSectionEntrySize(uint16_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "TICKET_BODY_V2";
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
std::string mIssuer;
|
||||||
|
byte_t mEncTitleKey[ticket::kEncTitleKeySize];
|
||||||
|
ticket::TitleKeyEncType mEncType;
|
||||||
|
uint16_t mTicketVersion;
|
||||||
|
ticket::LicenseType mLicenseType;
|
||||||
|
byte_t mCommonKeyId;
|
||||||
|
bool mPreInstall;
|
||||||
|
bool mSharedTitle;
|
||||||
|
bool mAllowAllContent;
|
||||||
|
byte_t mReservedRegion[ticket::kReservedRegionSize]; // explicitly reserved
|
||||||
|
uint64_t mTicketId;
|
||||||
|
uint64_t mDeviceId;
|
||||||
|
byte_t mRightsId[ticket::kRightsIdSize];
|
||||||
|
uint32_t mAccountId;
|
||||||
|
uint32_t mSectTotalSize;
|
||||||
|
uint32_t mSectHeaderOffset;
|
||||||
|
uint16_t mSectNum;
|
||||||
|
uint16_t mSectEntrySize;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool isEqual(const TicketBody_V2& other) const;
|
||||||
|
void copyFrom(const TicketBody_V2& other);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
51
lib/libes/include/es/cert.h
Normal file
51
lib/libes/include/es/cert.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <crypto/aes.h>
|
||||||
|
#include <crypto/rsa.h>
|
||||||
|
#include <crypto/ecdsa.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
namespace cert
|
||||||
|
{
|
||||||
|
enum PublicKeyType
|
||||||
|
{
|
||||||
|
RSA4096,
|
||||||
|
RSA2048,
|
||||||
|
ECDSA240
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kIssuerSize = 0x40;
|
||||||
|
static const size_t kSubjectSize = 0x40;
|
||||||
|
}
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sCertificateHeader
|
||||||
|
{
|
||||||
|
char issuer[cert::kIssuerSize];
|
||||||
|
be_uint32_t key_type;
|
||||||
|
char subject[cert::kSubjectSize];
|
||||||
|
be_uint32_t cert_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRsa4096PublicKeyBlock
|
||||||
|
{
|
||||||
|
byte_t modulus[crypto::rsa::kRsa4096Size];
|
||||||
|
byte_t public_exponent[crypto::rsa::kRsaPublicExponentSize];
|
||||||
|
byte_t padding[0x34];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRsa2048PublicKeyBlock
|
||||||
|
{
|
||||||
|
byte_t modulus[crypto::rsa::kRsa2048Size];
|
||||||
|
byte_t public_exponent[crypto::rsa::kRsaPublicExponentSize];
|
||||||
|
byte_t padding[0x34];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sEcdsa240PublicKeyBlock
|
||||||
|
{
|
||||||
|
crypto::ecdsa::sEcdsa240Point public_key;
|
||||||
|
byte_t padding[0x3C];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
46
lib/libes/include/es/sign.h
Normal file
46
lib/libes/include/es/sign.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <crypto/aes.h>
|
||||||
|
#include <crypto/rsa.h>
|
||||||
|
#include <crypto/ecdsa.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
namespace sign
|
||||||
|
{
|
||||||
|
enum SignType
|
||||||
|
{
|
||||||
|
SIGN_RSA4096_SHA1 = 0x10000,
|
||||||
|
SIGN_RSA2048_SHA1,
|
||||||
|
SIGN_ECDSA240_SHA1,
|
||||||
|
SIGN_RSA4096_SHA256,
|
||||||
|
SIGN_RSA2048_SHA256,
|
||||||
|
SIGN_ECDSA240_SHA256,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kEcdsaSigSize = 0x3C;
|
||||||
|
}
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sRsa4096SignBlock
|
||||||
|
{
|
||||||
|
be_uint32_t sign_type;
|
||||||
|
byte_t signature[crypto::rsa::kRsa4096Size];
|
||||||
|
byte_t padding[0x3C];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRsa2048SignBlock
|
||||||
|
{
|
||||||
|
be_uint32_t sign_type;
|
||||||
|
byte_t signature[crypto::rsa::kRsa2048Size];
|
||||||
|
byte_t padding[0x3C];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sEcdsa240SignBlock
|
||||||
|
{
|
||||||
|
be_uint32_t sign_type;
|
||||||
|
byte_t signature[sign::kEcdsaSigSize];
|
||||||
|
byte_t padding[0x40];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
108
lib/libes/include/es/ticket.h
Normal file
108
lib/libes/include/es/ticket.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <crypto/rsa.h>
|
||||||
|
|
||||||
|
namespace es
|
||||||
|
{
|
||||||
|
namespace ticket
|
||||||
|
{
|
||||||
|
enum TitleKeyEncType
|
||||||
|
{
|
||||||
|
AES128_CBC,
|
||||||
|
RSA2048
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LicenseType
|
||||||
|
{
|
||||||
|
LICENSE_PERMANENT = 0,
|
||||||
|
LICENSE_DEMO = 1,
|
||||||
|
LICENSE_TRIAL = 2,
|
||||||
|
LICENSE_RENTAL = 3,
|
||||||
|
LICENSE_SUBSCRIPTION = 4,
|
||||||
|
LICENSE_SERVICE = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PropertyMaskFlags
|
||||||
|
{
|
||||||
|
FLAG_PRE_INSTALL,
|
||||||
|
FLAG_SHARED_TITLE,
|
||||||
|
FLAG_ALLOW_ALL_CONTENT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SectionType
|
||||||
|
{
|
||||||
|
SECTION_PERMANENT = 1,
|
||||||
|
SECTION_SUBSCRIPTION = 2,
|
||||||
|
SECTION_CONTENT = 3,
|
||||||
|
SECTION_CONTENT_CONSUMPTION = 4,
|
||||||
|
SECTION_ACCESS_TITLE = 5,
|
||||||
|
SECTION_LIMITED_RESOURCE = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kIssuerSize = 0x40;
|
||||||
|
static const byte_t kFormatVersion = 2;
|
||||||
|
static const size_t kEncTitleKeySize = crypto::rsa::kRsa2048Size;
|
||||||
|
static const size_t kReservedRegionSize = 8;
|
||||||
|
static const size_t kRightsIdSize = 16;
|
||||||
|
}
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sTicketBody_v2
|
||||||
|
{
|
||||||
|
char issuer[ticket::kIssuerSize];
|
||||||
|
byte_t enc_title_key[ticket::kEncTitleKeySize];
|
||||||
|
byte_t format_version;
|
||||||
|
byte_t title_key_enc_type;
|
||||||
|
le_uint16_t ticket_version;
|
||||||
|
byte_t license_type;
|
||||||
|
byte_t common_key_id;
|
||||||
|
byte_t property_mask;
|
||||||
|
byte_t reserved_0;
|
||||||
|
byte_t reserved_region[ticket::kReservedRegionSize]; // explicitly reserved
|
||||||
|
le_uint64_t ticket_id;
|
||||||
|
le_uint64_t device_id;
|
||||||
|
byte_t rights_id[ticket::kRightsIdSize];
|
||||||
|
le_uint32_t account_id;
|
||||||
|
le_uint32_t sect_total_size;
|
||||||
|
le_uint32_t sect_header_offset;
|
||||||
|
le_uint16_t sect_num;
|
||||||
|
le_uint16_t sect_entry_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sSectionHeader_v2
|
||||||
|
{
|
||||||
|
le_uint32_t section_offset;
|
||||||
|
le_uint32_t record_size;
|
||||||
|
le_uint32_t section_size;
|
||||||
|
le_uint16_t record_num;
|
||||||
|
le_uint16_t section_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sContentRecord_v1
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static const size_t kAccessMaskSize = 0x80;
|
||||||
|
static const uint16_t kGroupMask = 0xFC00;
|
||||||
|
static const uint16_t kAccessMaskMask = 0x3FF;
|
||||||
|
|
||||||
|
be_uint32_t group;
|
||||||
|
byte_t access_mask[kAccessMaskSize];
|
||||||
|
public:
|
||||||
|
uint32_t index_group() const { return group.get(); }
|
||||||
|
bool is_index_enabled(uint16_t index) const
|
||||||
|
{
|
||||||
|
return (index_group() == get_group(index)) \
|
||||||
|
&& ((access_mask[get_access_mask(index) / 8] & BIT(get_access_mask(index) % 8)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() { memset(this, 0, sizeof(sContentRecord_v1)); }
|
||||||
|
|
||||||
|
void set_index_group(uint16_t index) { group = get_group(index); }
|
||||||
|
void enable_index(uint16_t index) { access_mask[get_access_mask(index) / 8] |= BIT(get_access_mask(index) % 8); }
|
||||||
|
void disable_index(uint16_t index) { access_mask[get_access_mask(index) / 8] &= ~BIT(get_access_mask(index) % 8); }
|
||||||
|
|
||||||
|
inline uint16_t get_access_mask(uint16_t index) const { return index & kAccessMaskMask; }
|
||||||
|
inline uint16_t get_group(uint16_t index) const { return index & kGroupMask; }
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
269
lib/libes/source/CertificateBody.cpp
Normal file
269
lib/libes/source/CertificateBody.cpp
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
#include <es/CertificateBody.h>
|
||||||
|
|
||||||
|
es::CertificateBody::CertificateBody()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
es::CertificateBody::CertificateBody(const CertificateBody& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::operator=(const CertificateBody& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::CertificateBody::operator==(const CertificateBody& other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::CertificateBody::operator!=(const CertificateBody& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::importBinary(const byte_t* src, size_t size)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// check minimum size
|
||||||
|
if (size < sizeof(sCertificateHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Certificate too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
const sCertificateHeader* hdr = (const sCertificateHeader*)src;
|
||||||
|
|
||||||
|
// get public key size
|
||||||
|
size_t pubkeySize = 0;
|
||||||
|
switch (hdr->key_type.get())
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check total size
|
||||||
|
if (size < (sizeof(sCertificateHeader) + pubkeySize))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Certificate too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// save raw binary
|
||||||
|
mBinaryBlob.alloc((sizeof(sCertificateHeader) + pubkeySize));
|
||||||
|
memcpy(mBinaryBlob.getBytes(), src, mBinaryBlob.getSize());
|
||||||
|
|
||||||
|
// save hdr variables
|
||||||
|
hdr = (const sCertificateHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
|
if (hdr->issuer[0] != 0)
|
||||||
|
mIssuer = std::string(hdr->issuer, cert::kIssuerSize);
|
||||||
|
mPublicKeyType = (cert::PublicKeyType)hdr->key_type.get();
|
||||||
|
if (hdr->subject[0] != 0)
|
||||||
|
mSubject = std::string(hdr->subject, cert::kSubjectSize);
|
||||||
|
mCertId = hdr->cert_id.get();
|
||||||
|
|
||||||
|
// save public key
|
||||||
|
if (mPublicKeyType == cert::RSA4096)
|
||||||
|
{
|
||||||
|
const sRsa4096PublicKeyBlock* pubkey = (const sRsa4096PublicKeyBlock*)(mBinaryBlob.getBytes() + 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));
|
||||||
|
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));
|
||||||
|
mEcdsa240PublicKey = pubkey->public_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::exportBinary()
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t* es::CertificateBody::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t es::CertificateBody::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::clear()
|
||||||
|
{
|
||||||
|
mIssuer.clear();
|
||||||
|
mSubject.clear();
|
||||||
|
mCertId = 0;
|
||||||
|
mPublicKeyType = cert::RSA2048;
|
||||||
|
|
||||||
|
memset(&mRsa4096PublicKey, 0, sizeof(crypto::rsa::sRsa4096Key));
|
||||||
|
memset(&mRsa2048PublicKey, 0, sizeof(crypto::rsa::sRsa2048Key));
|
||||||
|
memset(&mEcdsa240PublicKey, 0, sizeof(crypto::ecdsa::sEcdsa240Point));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& es::CertificateBody::getIssuer() const
|
||||||
|
{
|
||||||
|
return mIssuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setIssuer(const std::string& issuer)
|
||||||
|
{
|
||||||
|
if (issuer.size() > cert::kIssuerSize)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Issuer name too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIssuer = issuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
es::cert::PublicKeyType es::CertificateBody::getPublicKeyType() const
|
||||||
|
{
|
||||||
|
return mPublicKeyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setPublicKeyType(cert::PublicKeyType type)
|
||||||
|
{
|
||||||
|
mPublicKeyType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& es::CertificateBody::getSubject() const
|
||||||
|
{
|
||||||
|
return mSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setSubject(const std::string& subject)
|
||||||
|
{
|
||||||
|
if (subject.size() > cert::kSubjectSize)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Subject name too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
mSubject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t es::CertificateBody::getCertId() const
|
||||||
|
{
|
||||||
|
return mCertId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setCertId(uint32_t id)
|
||||||
|
{
|
||||||
|
mCertId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa4096Key& es::CertificateBody::getRsa4098PublicKey() const
|
||||||
|
{
|
||||||
|
return mRsa4096PublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setRsa4098PublicKey(const crypto::rsa::sRsa4096Key& key)
|
||||||
|
{
|
||||||
|
mRsa4096PublicKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::rsa::sRsa2048Key& es::CertificateBody::getRsa2048PublicKey() const
|
||||||
|
{
|
||||||
|
return mRsa2048PublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::CertificateBody::setRsa2048PublicKey(const crypto::rsa::sRsa2048Key& key)
|
||||||
|
{
|
||||||
|
mRsa2048PublicKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::ecdsa::sEcdsa240Point& es::CertificateBody::getEcdsa240PublicKey() const
|
||||||
|
{
|
||||||
|
return mEcdsa240PublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -1,366 +0,0 @@
|
||||||
#include <es/ETicketBody_V2.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
es::ETicketBody_V2::ETicketBody_V2()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
es::ETicketBody_V2::ETicketBody_V2(const ETicketBody_V2 & other)
|
|
||||||
{
|
|
||||||
copyFrom(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
es::ETicketBody_V2::ETicketBody_V2(const byte_t * bytes, size_t len)
|
|
||||||
{
|
|
||||||
importBinary(bytes, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::operator==(const ETicketBody_V2 & other) const
|
|
||||||
{
|
|
||||||
return isEqual(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::operator!=(const ETicketBody_V2 & other) const
|
|
||||||
{
|
|
||||||
return !isEqual(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::operator=(const ETicketBody_V2 & other)
|
|
||||||
{
|
|
||||||
copyFrom(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte_t * es::ETicketBody_V2::getBytes() const
|
|
||||||
{
|
|
||||||
return mBinaryBlob.getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t es::ETicketBody_V2::getSize() const
|
|
||||||
{
|
|
||||||
return mBinaryBlob.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::isEqual(const ETicketBody_V2 & other) const
|
|
||||||
{
|
|
||||||
return (mIssuer == other.mIssuer) \
|
|
||||||
&& (memcmp(mEncTitleKey, other.mEncTitleKey, kEncTitleKeyLen) == 0) \
|
|
||||||
&& (mEncType == other.mEncType) \
|
|
||||||
&& (mTicketVersion == other.mTicketVersion) \
|
|
||||||
&& (mLicenseType == other.mLicenseType) \
|
|
||||||
&& (mPreInstall == other.mPreInstall) \
|
|
||||||
&& (mSharedTitle == other.mSharedTitle) \
|
|
||||||
&& (mAllowAllContent == other.mAllowAllContent) \
|
|
||||||
&& (memcmp(mReservedRegion, other.mReservedRegion, kReservedRegionLen) == 0) \
|
|
||||||
&& (mTicketId == other.mTicketId) \
|
|
||||||
&& (mDeviceId == other.mDeviceId) \
|
|
||||||
&& (memcmp(mRightsId, other.mRightsId, kRightsIdLen) == 0) \
|
|
||||||
&& (mAccountId == other.mAccountId) \
|
|
||||||
&& (mSectTotalSize == other.mSectTotalSize) \
|
|
||||||
&& (mSectHeaderOffset == other.mSectHeaderOffset) \
|
|
||||||
&& (mSectNum == other.mSectNum) \
|
|
||||||
&& (mSectEntrySize == other.mSectEntrySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::copyFrom(const ETicketBody_V2 & other)
|
|
||||||
{
|
|
||||||
if (other.getSize())
|
|
||||||
{
|
|
||||||
importBinary(other.getBytes(), other.getSize());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
mIssuer = other.mIssuer;
|
|
||||||
memcpy(mEncTitleKey, other.mEncTitleKey, kEncTitleKeyLen);
|
|
||||||
mEncType = other.mEncType;
|
|
||||||
mTicketVersion = other.mTicketVersion;
|
|
||||||
mLicenseType = other.mLicenseType;
|
|
||||||
mPreInstall = other.mPreInstall;
|
|
||||||
mSharedTitle = other.mSharedTitle;
|
|
||||||
mAllowAllContent = other.mAllowAllContent;
|
|
||||||
memcpy(mReservedRegion, other.mReservedRegion, kReservedRegionLen);
|
|
||||||
mTicketId = other.mTicketId;
|
|
||||||
mDeviceId = other.mDeviceId;
|
|
||||||
memcpy(mRightsId, other.mRightsId, kRightsIdLen);
|
|
||||||
mAccountId = other.mAccountId;
|
|
||||||
mSectTotalSize = other.mSectTotalSize;
|
|
||||||
mSectHeaderOffset = other.mSectHeaderOffset;
|
|
||||||
mSectNum = other.mSectNum;
|
|
||||||
mSectEntrySize = other.mSectEntrySize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::exportBinary()
|
|
||||||
{
|
|
||||||
mBinaryBlob.alloc(sizeof(sTicketBody_v2));
|
|
||||||
sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes();
|
|
||||||
|
|
||||||
body->format_version = (kFormatVersion);
|
|
||||||
|
|
||||||
strncmp(body->issuer, mIssuer.c_str(), kIssuerLen);
|
|
||||||
memcpy(body->enc_title_key, mEncTitleKey, kEncTitleKeyLen);
|
|
||||||
body->title_key_enc_type = (mEncType);
|
|
||||||
body->ticket_version = (mTicketVersion);
|
|
||||||
byte_t property_mask = 0;
|
|
||||||
property_mask |= mPreInstall ? BIT(FLAG_PRE_INSTALL) : 0;
|
|
||||||
property_mask |= mSharedTitle ? BIT(FLAG_SHARED_TITLE) : 0;
|
|
||||||
property_mask |= mAllowAllContent ? BIT(FLAG_ALLOW_ALL_CONTENT) : 0;
|
|
||||||
body->property_mask = (property_mask);
|
|
||||||
memcpy(body->reserved_region, mReservedRegion, kReservedRegionLen);
|
|
||||||
body->ticket_id = (mTicketId);
|
|
||||||
body->device_id = (mDeviceId);
|
|
||||||
memcmp(body->rights_id, mRightsId, kRightsIdLen);
|
|
||||||
body->account_id = (mAccountId);
|
|
||||||
body->sect_total_size = (mSectTotalSize);
|
|
||||||
body->sect_header_offset = (mSectHeaderOffset);
|
|
||||||
body->sect_num = (mSectNum);
|
|
||||||
body->sect_entry_size = (mSectEntrySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::importBinary(const byte_t * bytes, size_t len)
|
|
||||||
{
|
|
||||||
if (len < sizeof(sTicketBody_v2))
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "Header size too small");
|
|
||||||
}
|
|
||||||
|
|
||||||
clear();
|
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sTicketBody_v2));
|
|
||||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
|
||||||
sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes();
|
|
||||||
|
|
||||||
if (body->format_version != kFormatVersion)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "Unsupported format version");
|
|
||||||
}
|
|
||||||
|
|
||||||
mIssuer.append(body->issuer, kIssuerLen);
|
|
||||||
memcpy(mEncTitleKey, body->enc_title_key, kEncTitleKeyLen);
|
|
||||||
mEncType = (TitleKeyEncType)body->title_key_enc_type;
|
|
||||||
mTicketVersion = body->ticket_version.get();
|
|
||||||
mLicenseType = (LicenseType)body->license_type;
|
|
||||||
mPreInstall = (body->property_mask & BIT(FLAG_PRE_INSTALL)) == BIT(FLAG_PRE_INSTALL);
|
|
||||||
mSharedTitle = (body->property_mask & BIT(FLAG_SHARED_TITLE)) == BIT(FLAG_SHARED_TITLE);
|
|
||||||
mAllowAllContent = (body->property_mask & BIT(FLAG_ALLOW_ALL_CONTENT)) == BIT(FLAG_ALLOW_ALL_CONTENT);
|
|
||||||
memcpy(mReservedRegion, body->reserved_region, kReservedRegionLen);
|
|
||||||
mTicketId = body->ticket_id.get();
|
|
||||||
mDeviceId = body->device_id.get();
|
|
||||||
memcpy(mRightsId, body->rights_id, kRightsIdLen);
|
|
||||||
mAccountId = body->account_id.get();
|
|
||||||
mSectTotalSize = body->sect_total_size.get();
|
|
||||||
mSectHeaderOffset = body->sect_header_offset.get();
|
|
||||||
mSectNum = body->sect_num.get();
|
|
||||||
mSectEntrySize = body->sect_entry_size.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::clear()
|
|
||||||
{
|
|
||||||
mBinaryBlob.clear();
|
|
||||||
mIssuer.clear();
|
|
||||||
memset(mEncTitleKey, 0, kEncTitleKeyLen);
|
|
||||||
mEncType = AES128_CBC;
|
|
||||||
mTicketVersion = 0;
|
|
||||||
mLicenseType = ES_LICENSE_PERMANENT;
|
|
||||||
mPreInstall = false;
|
|
||||||
mSharedTitle = false;
|
|
||||||
mAllowAllContent = false;
|
|
||||||
memset(mReservedRegion, 0, kReservedRegionLen);
|
|
||||||
mTicketId = 0;
|
|
||||||
mDeviceId = 0;
|
|
||||||
memset(mRightsId, 0, kRightsIdLen);
|
|
||||||
mAccountId = 0;
|
|
||||||
mSectTotalSize = 0;
|
|
||||||
mSectHeaderOffset = 0;
|
|
||||||
mSectNum = 0;
|
|
||||||
mSectEntrySize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string & es::ETicketBody_V2::getIssuer() const
|
|
||||||
{
|
|
||||||
return mIssuer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setIssuer(const std::string & issuer)
|
|
||||||
{
|
|
||||||
if (issuer.length() > kIssuerLen)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "Issuer is too long");
|
|
||||||
}
|
|
||||||
|
|
||||||
mIssuer = issuer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte_t * es::ETicketBody_V2::getEncTitleKey() const
|
|
||||||
{
|
|
||||||
return mEncTitleKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setEncTitleKey(const byte_t * data, size_t len)
|
|
||||||
{
|
|
||||||
memset(mEncTitleKey, 0, kEncTitleKeyLen);
|
|
||||||
memcpy(mEncTitleKey, data, MIN(len, kEncTitleKeyLen));
|
|
||||||
}
|
|
||||||
|
|
||||||
es::ETicketBody_V2::TitleKeyEncType es::ETicketBody_V2::getTitleKeyEncType() const
|
|
||||||
{
|
|
||||||
return mEncType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setTitleKeyEncType(TitleKeyEncType type)
|
|
||||||
{
|
|
||||||
mEncType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t es::ETicketBody_V2::getTicketVersion() const
|
|
||||||
{
|
|
||||||
return mTicketVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setTicketVersion(uint16_t version)
|
|
||||||
{
|
|
||||||
mTicketVersion = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
es::ETicketBody_V2::LicenseType es::ETicketBody_V2::getLicenseType() const
|
|
||||||
{
|
|
||||||
return mLicenseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setLicenseType(LicenseType type)
|
|
||||||
{
|
|
||||||
mLicenseType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_t es::ETicketBody_V2::getCommonKeyId() const
|
|
||||||
{
|
|
||||||
return mCommonKeyId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setCommonKeyId(byte_t id)
|
|
||||||
{
|
|
||||||
mCommonKeyId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::isPreInstall() const
|
|
||||||
{
|
|
||||||
return mPreInstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setIsPreInstall(bool isPreInstall)
|
|
||||||
{
|
|
||||||
mPreInstall = isPreInstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::isSharedTitle() const
|
|
||||||
{
|
|
||||||
return mSharedTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setIsSharedTitle(bool isSharedTitle)
|
|
||||||
{
|
|
||||||
mSharedTitle = isSharedTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool es::ETicketBody_V2::allowAllContent() const
|
|
||||||
{
|
|
||||||
return mAllowAllContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setAllowAllContent(bool allowAllContent)
|
|
||||||
{
|
|
||||||
mAllowAllContent = allowAllContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte_t * es::ETicketBody_V2::getReservedRegion() const
|
|
||||||
{
|
|
||||||
return mReservedRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setReservedRegion(const byte_t * data, size_t len)
|
|
||||||
{
|
|
||||||
memset(mReservedRegion, 0, kReservedRegionLen);
|
|
||||||
memcpy(mReservedRegion, data, MIN(len, kReservedRegionLen));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t es::ETicketBody_V2::getTicketId() const
|
|
||||||
{
|
|
||||||
return mTicketId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setTicketId(uint64_t id)
|
|
||||||
{
|
|
||||||
mTicketId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t es::ETicketBody_V2::getDeviceId() const
|
|
||||||
{
|
|
||||||
return mDeviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setDeviceId(uint64_t id)
|
|
||||||
{
|
|
||||||
mDeviceId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte_t * es::ETicketBody_V2::getRightsId() const
|
|
||||||
{
|
|
||||||
return mRightsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setRightsId(const byte_t * id)
|
|
||||||
{
|
|
||||||
memcpy(mRightsId, id, kRightsIdLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t es::ETicketBody_V2::getAccountId() const
|
|
||||||
{
|
|
||||||
return mAccountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setAccountId(uint32_t id)
|
|
||||||
{
|
|
||||||
mAccountId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t es::ETicketBody_V2::getSectionTotalSize() const
|
|
||||||
{
|
|
||||||
return mSectTotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setSectionTotalSize(uint32_t size)
|
|
||||||
{
|
|
||||||
mSectTotalSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t es::ETicketBody_V2::getSectionHeaderOffset() const
|
|
||||||
{
|
|
||||||
return mSectHeaderOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setSectionHeaderOffset(uint32_t offset)
|
|
||||||
{
|
|
||||||
mSectHeaderOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t es::ETicketBody_V2::getSectionNum() const
|
|
||||||
{
|
|
||||||
return mSectNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setSectionNum(uint16_t num)
|
|
||||||
{
|
|
||||||
mSectNum = num;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t es::ETicketBody_V2::getSectionEntrySize() const
|
|
||||||
{
|
|
||||||
return mSectEntrySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void es::ETicketBody_V2::setSectionEntrySize(uint16_t size)
|
|
||||||
{
|
|
||||||
mSectEntrySize = size;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include <es/ETicketContentRecord_V1.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
es::ETicketContentRecord_V1::ETicketContentRecord_V1()
|
|
||||||
{}
|
|
|
@ -1,46 +1,46 @@
|
||||||
#include <es/ETicketSectionHeader_V2.h>
|
#include <es/SectionHeader_V2.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
es::ETicketSectionHeader_V2::ETicketSectionHeader_V2()
|
es::SectionHeader_V2::SectionHeader_V2()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
es::ETicketSectionHeader_V2::ETicketSectionHeader_V2(const ETicketSectionHeader_V2 & other)
|
es::SectionHeader_V2::SectionHeader_V2(const SectionHeader_V2 & other)
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
copyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
es::ETicketSectionHeader_V2::ETicketSectionHeader_V2(const byte_t * bytes, size_t len)
|
es::SectionHeader_V2::SectionHeader_V2(const byte_t * bytes, size_t len)
|
||||||
{
|
{
|
||||||
importBinary(bytes, len);
|
importBinary(bytes, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool es::ETicketSectionHeader_V2::operator==(const ETicketSectionHeader_V2 & other) const
|
bool es::SectionHeader_V2::operator==(const SectionHeader_V2 & other) const
|
||||||
{
|
{
|
||||||
return isEqual(other);
|
return isEqual(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool es::ETicketSectionHeader_V2::operator!=(const ETicketSectionHeader_V2 & other) const
|
bool es::SectionHeader_V2::operator!=(const SectionHeader_V2 & other) const
|
||||||
{
|
{
|
||||||
return !isEqual(other);
|
return !isEqual(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::operator=(const ETicketSectionHeader_V2 & other)
|
void es::SectionHeader_V2::operator=(const SectionHeader_V2 & other)
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
copyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
const byte_t * es::ETicketSectionHeader_V2::getBytes() const
|
const byte_t * es::SectionHeader_V2::getBytes() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getBytes();
|
return mBinaryBlob.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t es::ETicketSectionHeader_V2::getSize() const
|
size_t es::SectionHeader_V2::getSize() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.getSize();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::exportBinary()
|
void es::SectionHeader_V2::exportBinary()
|
||||||
{
|
{
|
||||||
mBinaryBlob.alloc(sizeof(sSectionHeader_v2));
|
mBinaryBlob.alloc(sizeof(sSectionHeader_v2));
|
||||||
sSectionHeader_v2* hdr = (sSectionHeader_v2*)mBinaryBlob.getBytes();
|
sSectionHeader_v2* hdr = (sSectionHeader_v2*)mBinaryBlob.getBytes();
|
||||||
|
@ -52,7 +52,7 @@ void es::ETicketSectionHeader_V2::exportBinary()
|
||||||
hdr->section_type = (mSectionType);
|
hdr->section_type = (mSectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::importBinary(const byte_t * bytes, size_t len)
|
void es::SectionHeader_V2::importBinary(const byte_t * bytes, size_t len)
|
||||||
{
|
{
|
||||||
if (len < sizeof(sSectionHeader_v2))
|
if (len < sizeof(sSectionHeader_v2))
|
||||||
{
|
{
|
||||||
|
@ -69,10 +69,10 @@ void es::ETicketSectionHeader_V2::importBinary(const byte_t * bytes, size_t len)
|
||||||
mRecordSize = hdr->record_size.get();
|
mRecordSize = hdr->record_size.get();
|
||||||
mSectionSize = hdr->section_size.get();
|
mSectionSize = hdr->section_size.get();
|
||||||
mRecordNum = hdr->record_num.get();
|
mRecordNum = hdr->record_num.get();
|
||||||
mSectionType = (SectionType)hdr->section_type.get();
|
mSectionType = (ticket::SectionType)hdr->section_type.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool es::ETicketSectionHeader_V2::isEqual(const ETicketSectionHeader_V2 & other) const
|
bool es::SectionHeader_V2::isEqual(const SectionHeader_V2 & other) const
|
||||||
{
|
{
|
||||||
return (mSectionOffset == other.mSectionOffset) \
|
return (mSectionOffset == other.mSectionOffset) \
|
||||||
&& (mRecordSize == other.mRecordSize) \
|
&& (mRecordSize == other.mRecordSize) \
|
||||||
|
@ -81,7 +81,7 @@ bool es::ETicketSectionHeader_V2::isEqual(const ETicketSectionHeader_V2 & other)
|
||||||
&& (mSectionType == other.mSectionType);
|
&& (mSectionType == other.mSectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::copyFrom(const ETicketSectionHeader_V2 & other)
|
void es::SectionHeader_V2::copyFrom(const SectionHeader_V2 & other)
|
||||||
{
|
{
|
||||||
if (other.getSize())
|
if (other.getSize())
|
||||||
{
|
{
|
||||||
|
@ -98,62 +98,62 @@ void es::ETicketSectionHeader_V2::copyFrom(const ETicketSectionHeader_V2 & other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::clear()
|
void es::SectionHeader_V2::clear()
|
||||||
{
|
{
|
||||||
mBinaryBlob.clear();
|
mBinaryBlob.clear();
|
||||||
mSectionOffset = 0;
|
mSectionOffset = 0;
|
||||||
mRecordSize = 0;
|
mRecordSize = 0;
|
||||||
mSectionSize = 0;
|
mSectionSize = 0;
|
||||||
mRecordNum = 0;
|
mRecordNum = 0;
|
||||||
mSectionType = PERMANENT;
|
mSectionType = ticket::SECTION_PERMANENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t es::ETicketSectionHeader_V2::getSectionOffset() const
|
uint32_t es::SectionHeader_V2::getSectionOffset() const
|
||||||
{
|
{
|
||||||
return mSectionOffset;
|
return mSectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::setSectionOffset(uint32_t offset)
|
void es::SectionHeader_V2::setSectionOffset(uint32_t offset)
|
||||||
{
|
{
|
||||||
mSectionOffset = offset;
|
mSectionOffset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t es::ETicketSectionHeader_V2::getRecordSize() const
|
uint32_t es::SectionHeader_V2::getRecordSize() const
|
||||||
{
|
{
|
||||||
return mRecordSize;
|
return mRecordSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::setRecordSize(uint32_t size)
|
void es::SectionHeader_V2::setRecordSize(uint32_t size)
|
||||||
{
|
{
|
||||||
mRecordSize = size;
|
mRecordSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t es::ETicketSectionHeader_V2::getSectionSize() const
|
uint32_t es::SectionHeader_V2::getSectionSize() const
|
||||||
{
|
{
|
||||||
return mSectionSize;
|
return mSectionSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::getSectionSize(uint32_t size)
|
void es::SectionHeader_V2::getSectionSize(uint32_t size)
|
||||||
{
|
{
|
||||||
mSectionSize = size;
|
mSectionSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t es::ETicketSectionHeader_V2::getRecordNum() const
|
uint16_t es::SectionHeader_V2::getRecordNum() const
|
||||||
{
|
{
|
||||||
return mRecordNum;
|
return mRecordNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::setRecordNum(uint16_t record_num)
|
void es::SectionHeader_V2::setRecordNum(uint16_t record_num)
|
||||||
{
|
{
|
||||||
mRecordNum = record_num;
|
mRecordNum = record_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
es::ETicketSectionHeader_V2::SectionType es::ETicketSectionHeader_V2::getSectionType() const
|
es::ticket::SectionType es::SectionHeader_V2::getSectionType() const
|
||||||
{
|
{
|
||||||
return mSectionType;
|
return mSectionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void es::ETicketSectionHeader_V2::setSectionType(SectionType type)
|
void es::SectionHeader_V2::setSectionType(ticket::SectionType type)
|
||||||
{
|
{
|
||||||
mSectionType = type;
|
mSectionType = type;
|
||||||
}
|
}
|
197
lib/libes/source/SignatureBlock.cpp
Normal file
197
lib/libes/source/SignatureBlock.cpp
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
#include <es/SignatureBlock.h>
|
||||||
|
|
||||||
|
es::SignatureBlock::SignatureBlock()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
es::SignatureBlock::SignatureBlock(const SignatureBlock& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::operator=(const SignatureBlock& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::SignatureBlock::operator==(const SignatureBlock& other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::SignatureBlock::operator!=(const SignatureBlock& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::importBinary(const byte_t* src, size_t size)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
size_t totalSize = 0;
|
||||||
|
size_t sigSize = 0;
|
||||||
|
uint32_t signType = 0;
|
||||||
|
|
||||||
|
// try Big Endian sign type
|
||||||
|
signType = ((be_uint32_t*)src)->get();
|
||||||
|
switch (signType)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try Big Endian sign type
|
||||||
|
if (totalSize == 0)
|
||||||
|
{
|
||||||
|
signType = ((le_uint32_t*)src)->get();
|
||||||
|
switch (signType)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsLittleEndian = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalSize > size)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Certificate too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
mBinaryBlob.alloc(totalSize);
|
||||||
|
memcpy(mBinaryBlob.getBytes(), src, totalSize);
|
||||||
|
|
||||||
|
mSignType = (sign::SignType)signType;
|
||||||
|
mSignature.alloc(sigSize);
|
||||||
|
memcpy(mSignature.getBytes(), mBinaryBlob.getBytes() + 4, sigSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::exportBinary()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::clear()
|
||||||
|
{
|
||||||
|
mBinaryBlob.clear();
|
||||||
|
mSignType = sign::SIGN_RSA4096_SHA1;
|
||||||
|
mIsLittleEndian = false;
|
||||||
|
mSignature.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
es::sign::SignType es::SignatureBlock::getSignType() const
|
||||||
|
{
|
||||||
|
return mSignType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::setSignType(es::sign::SignType type)
|
||||||
|
{
|
||||||
|
mSignType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::SignatureBlock::isLittleEndian() const
|
||||||
|
{
|
||||||
|
return mIsLittleEndian;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::setLittleEndian(bool isLE)
|
||||||
|
{
|
||||||
|
mIsLittleEndian = isLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::MemoryBlob& es::SignatureBlock::getSignature() const
|
||||||
|
{
|
||||||
|
return mSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::SignatureBlock::setSignature(const fnd::MemoryBlob& 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;
|
||||||
|
}
|
366
lib/libes/source/TicketBody_V2.cpp
Normal file
366
lib/libes/source/TicketBody_V2.cpp
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
#include <es/TicketBody_V2.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
es::TicketBody_V2::TicketBody_V2()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::operator=(const TicketBody_V2 & other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t * es::TicketBody_V2::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t es::TicketBody_V2::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::exportBinary()
|
||||||
|
{
|
||||||
|
mBinaryBlob.alloc(sizeof(sTicketBody_v2));
|
||||||
|
sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
|
body->format_version = (ticket::kFormatVersion);
|
||||||
|
|
||||||
|
strncmp(body->issuer, mIssuer.c_str(), ticket::kIssuerSize);
|
||||||
|
memcpy(body->enc_title_key, mEncTitleKey, ticket::kEncTitleKeySize);
|
||||||
|
body->title_key_enc_type = (mEncType);
|
||||||
|
body->ticket_version = (mTicketVersion);
|
||||||
|
byte_t property_mask = 0;
|
||||||
|
property_mask |= mPreInstall ? _BIT(ticket::FLAG_PRE_INSTALL) : 0;
|
||||||
|
property_mask |= mSharedTitle ? _BIT(ticket::FLAG_SHARED_TITLE) : 0;
|
||||||
|
property_mask |= mAllowAllContent ? _BIT(ticket::FLAG_ALLOW_ALL_CONTENT) : 0;
|
||||||
|
body->property_mask = (property_mask);
|
||||||
|
memcpy(body->reserved_region, mReservedRegion, ticket::kReservedRegionSize);
|
||||||
|
body->ticket_id = (mTicketId);
|
||||||
|
body->device_id = (mDeviceId);
|
||||||
|
memcmp(body->rights_id, mRightsId, ticket::kRightsIdSize);
|
||||||
|
body->account_id = (mAccountId);
|
||||||
|
body->sect_total_size = (mSectTotalSize);
|
||||||
|
body->sect_header_offset = (mSectHeaderOffset);
|
||||||
|
body->sect_num = (mSectNum);
|
||||||
|
body->sect_entry_size = (mSectEntrySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::importBinary(const byte_t * bytes, size_t len)
|
||||||
|
{
|
||||||
|
if (len < sizeof(sTicketBody_v2))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Header size too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
mBinaryBlob.alloc(sizeof(sTicketBody_v2));
|
||||||
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
sTicketBody_v2* body = (sTicketBody_v2*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
|
if (body->format_version != ticket::kFormatVersion)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Unsupported format version");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIssuer.append(body->issuer, ticket::kIssuerSize);
|
||||||
|
memcpy(mEncTitleKey, body->enc_title_key, ticket::kEncTitleKeySize);
|
||||||
|
mEncType = (ticket::TitleKeyEncType)body->title_key_enc_type;
|
||||||
|
mTicketVersion = body->ticket_version.get();
|
||||||
|
mLicenseType = (ticket::LicenseType)body->license_type;
|
||||||
|
mPreInstall = _HAS_BIT(body->property_mask, ticket::FLAG_PRE_INSTALL);
|
||||||
|
mSharedTitle = _HAS_BIT(body->property_mask, ticket::FLAG_SHARED_TITLE);
|
||||||
|
mAllowAllContent = _HAS_BIT(body->property_mask, ticket::FLAG_ALLOW_ALL_CONTENT);
|
||||||
|
memcpy(mReservedRegion, body->reserved_region, ticket::kReservedRegionSize);
|
||||||
|
mTicketId = body->ticket_id.get();
|
||||||
|
mDeviceId = body->device_id.get();
|
||||||
|
memcpy(mRightsId, body->rights_id, ticket::kRightsIdSize);
|
||||||
|
mAccountId = body->account_id.get();
|
||||||
|
mSectTotalSize = body->sect_total_size.get();
|
||||||
|
mSectHeaderOffset = body->sect_header_offset.get();
|
||||||
|
mSectNum = body->sect_num.get();
|
||||||
|
mSectEntrySize = body->sect_entry_size.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::clear()
|
||||||
|
{
|
||||||
|
mBinaryBlob.clear();
|
||||||
|
mIssuer.clear();
|
||||||
|
memset(mEncTitleKey, 0, ticket::kEncTitleKeySize);
|
||||||
|
mEncType = ticket::AES128_CBC;
|
||||||
|
mTicketVersion = 0;
|
||||||
|
mLicenseType = ticket::LICENSE_PERMANENT;
|
||||||
|
mPreInstall = false;
|
||||||
|
mSharedTitle = false;
|
||||||
|
mAllowAllContent = false;
|
||||||
|
memset(mReservedRegion, 0, ticket::kReservedRegionSize);
|
||||||
|
mTicketId = 0;
|
||||||
|
mDeviceId = 0;
|
||||||
|
memset(mRightsId, 0, ticket::kRightsIdSize);
|
||||||
|
mAccountId = 0;
|
||||||
|
mSectTotalSize = 0;
|
||||||
|
mSectHeaderOffset = 0;
|
||||||
|
mSectNum = 0;
|
||||||
|
mSectEntrySize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & es::TicketBody_V2::getIssuer() const
|
||||||
|
{
|
||||||
|
return mIssuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setIssuer(const std::string & issuer)
|
||||||
|
{
|
||||||
|
if (issuer.length() > ticket::kIssuerSize)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Issuer is too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
mIssuer = issuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t * es::TicketBody_V2::getEncTitleKey() const
|
||||||
|
{
|
||||||
|
return mEncTitleKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setEncTitleKey(const byte_t * data, size_t len)
|
||||||
|
{
|
||||||
|
memset(mEncTitleKey, 0, ticket::kEncTitleKeySize);
|
||||||
|
memcpy(mEncTitleKey, data, MIN(len, ticket::kEncTitleKeySize));
|
||||||
|
}
|
||||||
|
|
||||||
|
es::ticket::TitleKeyEncType es::TicketBody_V2::getTitleKeyEncType() const
|
||||||
|
{
|
||||||
|
return mEncType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setTitleKeyEncType(ticket::TitleKeyEncType type)
|
||||||
|
{
|
||||||
|
mEncType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t es::TicketBody_V2::getTicketVersion() const
|
||||||
|
{
|
||||||
|
return mTicketVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setTicketVersion(uint16_t version)
|
||||||
|
{
|
||||||
|
mTicketVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
es::ticket::LicenseType es::TicketBody_V2::getLicenseType() const
|
||||||
|
{
|
||||||
|
return mLicenseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setLicenseType(ticket::LicenseType type)
|
||||||
|
{
|
||||||
|
mLicenseType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t es::TicketBody_V2::getCommonKeyId() const
|
||||||
|
{
|
||||||
|
return mCommonKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setCommonKeyId(byte_t id)
|
||||||
|
{
|
||||||
|
mCommonKeyId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::TicketBody_V2::isPreInstall() const
|
||||||
|
{
|
||||||
|
return mPreInstall;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setIsPreInstall(bool isPreInstall)
|
||||||
|
{
|
||||||
|
mPreInstall = isPreInstall;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::TicketBody_V2::isSharedTitle() const
|
||||||
|
{
|
||||||
|
return mSharedTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setIsSharedTitle(bool isSharedTitle)
|
||||||
|
{
|
||||||
|
mSharedTitle = isSharedTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool es::TicketBody_V2::allowAllContent() const
|
||||||
|
{
|
||||||
|
return mAllowAllContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setAllowAllContent(bool allowAllContent)
|
||||||
|
{
|
||||||
|
mAllowAllContent = allowAllContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t * es::TicketBody_V2::getReservedRegion() const
|
||||||
|
{
|
||||||
|
return mReservedRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setReservedRegion(const byte_t * data, size_t len)
|
||||||
|
{
|
||||||
|
memset(mReservedRegion, 0, ticket::kReservedRegionSize);
|
||||||
|
memcpy(mReservedRegion, data, MIN(len, ticket::kReservedRegionSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t es::TicketBody_V2::getTicketId() const
|
||||||
|
{
|
||||||
|
return mTicketId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setTicketId(uint64_t id)
|
||||||
|
{
|
||||||
|
mTicketId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t es::TicketBody_V2::getDeviceId() const
|
||||||
|
{
|
||||||
|
return mDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setDeviceId(uint64_t id)
|
||||||
|
{
|
||||||
|
mDeviceId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t * es::TicketBody_V2::getRightsId() const
|
||||||
|
{
|
||||||
|
return mRightsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setRightsId(const byte_t * id)
|
||||||
|
{
|
||||||
|
memcpy(mRightsId, id, ticket::kRightsIdSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t es::TicketBody_V2::getAccountId() const
|
||||||
|
{
|
||||||
|
return mAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setAccountId(uint32_t id)
|
||||||
|
{
|
||||||
|
mAccountId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t es::TicketBody_V2::getSectionTotalSize() const
|
||||||
|
{
|
||||||
|
return mSectTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setSectionTotalSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mSectTotalSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t es::TicketBody_V2::getSectionHeaderOffset() const
|
||||||
|
{
|
||||||
|
return mSectHeaderOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setSectionHeaderOffset(uint32_t offset)
|
||||||
|
{
|
||||||
|
mSectHeaderOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t es::TicketBody_V2::getSectionNum() const
|
||||||
|
{
|
||||||
|
return mSectNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void es::TicketBody_V2::setSectionNum(uint16_t num)
|
||||||
|
{
|
||||||
|
mSectNum = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t es::TicketBody_V2::getSectionEntrySize() const
|
||||||
|
{
|
||||||
|
return mSectEntrySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue