mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-30 14:35:17 -04:00
fs: add gc validation wrappers for hac2l
This commit is contained in:
parent
32d443977e
commit
2d984822c6
15 changed files with 939 additions and 6 deletions
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/gc/impl/gc_gc_crypto.hpp>
|
||||
|
||||
namespace ams::gc::impl {
|
||||
|
||||
class EmbeddedDataHolder {
|
||||
NON_COPYABLE(EmbeddedDataHolder);
|
||||
NON_MOVEABLE(EmbeddedDataHolder);
|
||||
friend class GcCrypto;
|
||||
private:
|
||||
struct ConcatenatedGcLibraryEmbeddedKeys {
|
||||
u8 enc_hmac_key_for_cv[GcCrypto::GcHmacKeyLength];
|
||||
u8 enc_hmac_key_for_key_and_iv[GcCrypto::GcHmacKeyLength];
|
||||
u8 enc_cv_constant_value[GcCrypto::GcCvConstLength];
|
||||
u8 enc_rsa_oaep_label_hash[GcCrypto::GcSha256HashLength];
|
||||
};
|
||||
static_assert(util::is_pod<ConcatenatedGcLibraryEmbeddedKeys>::value);
|
||||
static_assert(sizeof(ConcatenatedGcLibraryEmbeddedKeys) == 0x70);
|
||||
private:
|
||||
static bool s_is_dev;
|
||||
static const void *s_ca_public_exponent;
|
||||
static const void *s_ca1_modulus;
|
||||
static const void *s_ca9_modulus;
|
||||
static const void *s_ca10_modulus;
|
||||
static const void *s_ca10_certificate_modulus;
|
||||
static const void *s_card_header_key;
|
||||
public:
|
||||
static Result SetLibraryEmbeddedKeys(bool is_dev = GcCrypto::CheckDevelopmentSpl());
|
||||
private:
|
||||
static Result DecryptoEmbeddedKeys(ConcatenatedGcLibraryEmbeddedKeys *out, size_t out_size, bool is_dev = GcCrypto::CheckDevelopmentSpl());
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/gc/impl/gc_types.hpp>
|
||||
|
||||
namespace ams::gc::impl {
|
||||
|
||||
class GcCrypto {
|
||||
NON_COPYABLE(GcCrypto);
|
||||
NON_MOVEABLE(GcCrypto);
|
||||
public:
|
||||
static constexpr size_t GcRsaKeyLength = crypto::Rsa2048PssSha256Verifier::ModulusSize;
|
||||
static constexpr size_t GcRsaPublicExponentLength = 3;
|
||||
static constexpr size_t GcAesKeyLength = crypto::AesEncryptor128::KeySize;
|
||||
static constexpr size_t GcAesCbcIvLength = crypto::Aes128CbcEncryptor::IvSize;
|
||||
static constexpr size_t GcHmacKeyLength = 0x20;
|
||||
static constexpr size_t GcCvConstLength = 0x10;
|
||||
static constexpr size_t GcSha256HashLength = crypto::Sha256Generator::HashSize;
|
||||
public:
|
||||
static bool CheckDevelopmentSpl();
|
||||
static Result DecryptAesKeySpl(void *dst, size_t dst_size, const void *src, size_t src_size, s32 generation, u32 option);
|
||||
|
||||
static Result VerifyCardHeader(const void *header_buffer, size_t header_size, const void *modulus, size_t modulus_size);
|
||||
|
||||
static Result EncryptCardHeader(void *header, size_t header_size);
|
||||
static Result DecryptCardHeader(void *header, size_t header_size);
|
||||
|
||||
static Result VerifyT1CardCertificate(const void *cert_buffer, size_t cert_size);
|
||||
|
||||
static Result VerifyCa10Certificate(const void *cert_buffer, size_t cert_size);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::gc::impl {
|
||||
|
||||
struct CardInitialDataPayload {
|
||||
u8 package_id[8];
|
||||
u8 reserved_8[8];
|
||||
u8 auth_data[0x10];
|
||||
u8 auth_mac[0x10];
|
||||
u8 auth_nonce[0xC];
|
||||
};
|
||||
static_assert(util::is_pod<CardInitialDataPayload>::value);
|
||||
static_assert(sizeof(CardInitialDataPayload) == 0x3C);
|
||||
|
||||
struct CardInitialData {
|
||||
CardInitialDataPayload payload;
|
||||
u8 padding[0x200 - sizeof(CardInitialDataPayload)];
|
||||
};
|
||||
static_assert(util::is_pod<CardInitialData>::value);
|
||||
static_assert(sizeof(CardInitialData) == 0x200);
|
||||
|
||||
struct CardHeaderKeyIndex {
|
||||
using KekIndex = util::BitPack8::Field<0, 4, u8>;
|
||||
using TitleKeyDecIndex = util::BitPack8::Field<KekIndex::Next, 4, u8>;
|
||||
|
||||
static_assert(TitleKeyDecIndex::Next == BITSIZEOF(u8));
|
||||
};
|
||||
|
||||
struct CardHeaderEncryptedData {
|
||||
u32 fw_version[2];
|
||||
u32 acc_ctrl_1;
|
||||
u32 wait_1_time_read;
|
||||
u32 wait_2_time_read;
|
||||
u32 wait_1_time_write;
|
||||
u32 wait_2_time_write;
|
||||
u32 fw_mode;
|
||||
u32 cup_version;
|
||||
u8 compatibility_type;
|
||||
u8 reserved_25;
|
||||
u8 reserved_26;
|
||||
u8 reserved_27;
|
||||
u8 upp_hash[8];
|
||||
u64 cup_id;
|
||||
u8 reserved_38[0x38];
|
||||
};
|
||||
static_assert(util::is_pod<CardHeaderEncryptedData>::value);
|
||||
static_assert(sizeof(CardHeaderEncryptedData) == 0x70);
|
||||
|
||||
enum MemoryCapacity : u8 {
|
||||
MemoryCapacity_1GB = 0xFA,
|
||||
MemoryCapacity_2GB = 0xF8,
|
||||
MemoryCapacity_4GB = 0xF0,
|
||||
MemoryCapacity_8GB = 0xE0,
|
||||
MemoryCapacity_16GB = 0xE1,
|
||||
MemoryCapacity_32GB = 0xE2,
|
||||
};
|
||||
|
||||
enum AccessControl1ClockRate : u32 {
|
||||
AccessControl1ClockRate_25MHz = 0x00A10011,
|
||||
AccessControl1ClockRate_50MHz = 0x00A10010,
|
||||
};
|
||||
|
||||
struct CardHeader {
|
||||
static constexpr u32 Magic = util::FourCC<'H','E','A','D'>::Code;
|
||||
|
||||
u32 magic;
|
||||
u32 rom_area_start_page;
|
||||
u32 backup_area_start_page;
|
||||
util::BitPack8 key_index;
|
||||
u8 rom_size;
|
||||
u8 version;
|
||||
u8 flags;
|
||||
u8 package_id[8];
|
||||
u32 valid_data_end_page;
|
||||
u8 reserved_11C[4];
|
||||
u8 iv[crypto::Aes128CbcDecryptor::IvSize];
|
||||
u64 partition_fs_header_address;
|
||||
u64 partition_fs_header_size;
|
||||
u8 partition_fs_header_hash[crypto::Sha256Generator::HashSize];
|
||||
u8 initial_data_hash[crypto::Sha256Generator::HashSize];
|
||||
u32 sel_sec;
|
||||
u32 sel_t1_key;
|
||||
u32 sel_key;
|
||||
u32 lim_area_page;
|
||||
|
||||
union {
|
||||
u8 raw_encrypted_data[sizeof(CardHeaderEncryptedData)];
|
||||
CardHeaderEncryptedData encrypted_data;
|
||||
};
|
||||
};
|
||||
static_assert(util::is_pod<CardHeader>::value);
|
||||
static_assert(sizeof(CardHeader) == 0x100);
|
||||
|
||||
struct CardHeaderWithSignature {
|
||||
u8 signature[crypto::Rsa2048Pkcs1Sha256Verifier::SignatureSize];
|
||||
CardHeader data;
|
||||
};
|
||||
static_assert(util::is_pod<CardHeaderWithSignature>::value);
|
||||
static_assert(sizeof(CardHeaderWithSignature) == 0x200);
|
||||
|
||||
static constexpr size_t CardDeviceIdLength = 0x10;
|
||||
|
||||
struct T1CardCertificate {
|
||||
static constexpr u32 Magic = util::FourCC<'C','E','R','T'>::Code;
|
||||
|
||||
u8 signature[crypto::Rsa2048Pkcs1Sha256Verifier::SignatureSize];
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u8 kek_index;
|
||||
u8 flags[7];
|
||||
u8 t1_card_device_id[CardDeviceIdLength];
|
||||
u8 iv[crypto::Aes128CtrEncryptor::IvSize];
|
||||
u8 hw_key[crypto::Aes128CtrEncryptor::KeySize];
|
||||
u8 reserved[0xC0];
|
||||
u8 padding[0x200];
|
||||
};
|
||||
static_assert(util::is_pod<T1CardCertificate>::value);
|
||||
static_assert(sizeof(T1CardCertificate) == 0x400);
|
||||
|
||||
struct Ca10Certificate {
|
||||
u8 signature[crypto::Rsa2048Pkcs1Sha256Verifier::SignatureSize];
|
||||
u8 unk_100[0x200];
|
||||
u8 modulus[crypto::Rsa2048Pkcs1Sha256Verifier::ModulusSize];
|
||||
};
|
||||
static_assert(util::is_pod<Ca10Certificate>::value);
|
||||
static_assert(sizeof(Ca10Certificate) == 0x400);
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue