Merge pull request #6926 from leoetlino/hardcoded-numbers

IOSC: Remove some hardcoded offsets and magic numbers
This commit is contained in:
Léo Lam 2018-05-27 14:17:28 +02:00 committed by GitHub
commit 3798127cf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 54 deletions

View File

@ -241,7 +241,7 @@ static void silly_random(u8* rndArea, u8 count)
} }
} }
std::array<u8, 60> Sign(const u8* key, const u8* hash) Signature Sign(const u8* key, const u8* hash)
{ {
u8 e[30]{}; u8 e[30]{};
memcpy(e + 10, hash, 20); memcpy(e + 10, hash, 20);
@ -272,7 +272,7 @@ std::array<u8, 60> Sign(const u8* key, const u8* hash)
bn_inv(minv, m, ec_N, sizeof(minv)); bn_inv(minv, m, ec_N, sizeof(minv));
bn_mul(s.data.data(), minv, kk, ec_N, 30); bn_mul(s.data.data(), minv, kk, ec_N, 30);
std::array<u8, 60> signature; Signature signature;
std::copy(r.data.cbegin(), r.data.cend(), signature.begin()); std::copy(r.data.cbegin(), r.data.cend(), signature.begin());
std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30); std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30);
return signature; return signature;
@ -300,10 +300,10 @@ bool VerifySignature(const u8* public_key, const u8* signature, const u8* hash)
return (bn_compare(rx.data(), R, 30) == 0); return (bn_compare(rx.data(), R, 30) == 0);
} }
std::array<u8, 60> PrivToPub(const u8* key) PublicKey PrivToPub(const u8* key)
{ {
const Point data = key * ec_G; const Point data = key * ec_G;
std::array<u8, 60> result; PublicKey result;
std::copy_n(data.Data(), result.size(), result.begin()); std::copy_n(data.Data(), result.size(), result.begin());
return result; return result;
} }

View File

@ -10,8 +10,11 @@
namespace Common::ec namespace Common::ec
{ {
using Signature = std::array<u8, 60>;
using PublicKey = std::array<u8, 60>;
/// Generate a signature using ECDSA. /// Generate a signature using ECDSA.
std::array<u8, 60> Sign(const u8* key, const u8* hash); Signature Sign(const u8* key, const u8* hash);
/// Check a signature using ECDSA. /// Check a signature using ECDSA.
/// ///
@ -24,5 +27,5 @@ bool VerifySignature(const u8* public_key, const u8* signature, const u8* hash);
std::array<u8, 60> ComputeSharedSecret(const u8* private_key, const u8* public_key); std::array<u8, 60> ComputeSharedSecret(const u8* private_key, const u8* public_key);
/// Convert a ECC private key (30 bytes) to a public key (60 bytes). /// Convert a ECC private key (30 bytes) to a public key (60 bytes).
std::array<u8, 60> PrivToPub(const u8* key); PublicKey PrivToPub(const u8* key);
} // namespace Common::ec } // namespace Common::ec

View File

@ -454,9 +454,10 @@ void WiiSave::do_sig()
} }
// Sign the data. // Sign the data.
IOS::Certificate ap_cert; IOS::CertECC ap_cert;
IOS::ECCSignature ap_sig; Common::ec::Signature ap_sig;
m_ios.GetIOSC().Sign(ap_sig.data(), ap_cert.data(), Titles::SYSTEM_MENU, data.get(), data_size); m_ios.GetIOSC().Sign(ap_sig.data(), reinterpret_cast<u8*>(&ap_cert), Titles::SYSTEM_MENU,
data.get(), data_size);
// Write signatures. // Write signatures.
data_file.Open(m_encrypted_save_path, "ab"); data_file.Open(m_encrypted_save_path, "ab");
@ -469,9 +470,9 @@ void WiiSave::do_sig()
data_file.WriteArray(ap_sig.data(), ap_sig.size()); data_file.WriteArray(ap_sig.data(), ap_sig.size());
const u32 SIGNATURE_END_MAGIC = Common::swap32(0x2f536969); const u32 SIGNATURE_END_MAGIC = Common::swap32(0x2f536969);
data_file.WriteArray(&SIGNATURE_END_MAGIC, 1); data_file.WriteArray(&SIGNATURE_END_MAGIC, 1);
const IOS::Certificate device_certificate = m_ios.GetIOSC().GetDeviceCertificate(); const IOS::CertECC device_certificate = m_ios.GetIOSC().GetDeviceCertificate();
data_file.WriteArray(device_certificate.data(), device_certificate.size()); data_file.WriteArray(&device_certificate, 1);
data_file.WriteArray(ap_cert.data(), ap_cert.size()); data_file.WriteArray(&ap_cert, 1);
m_valid = data_file.IsGood(); m_valid = data_file.IsGood();
} }

View File

@ -8,12 +8,14 @@
#include <mbedtls/sha1.h> #include <mbedtls/sha1.h>
#include "Common/Crypto/ec.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h" #include "Common/ScopeGuard.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/IOS/ES/Formats.h" #include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IOSC.h"
#include "Core/IOS/Uids.h" #include "Core/IOS/Uids.h"
namespace IOS namespace IOS
@ -96,8 +98,8 @@ IPCCommandResult ES::GetDeviceCertificate(const IOCtlVRequest& request)
INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICECERT"); INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICECERT");
const auto cert = m_ios.GetIOSC().GetDeviceCertificate(); const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
Memory::CopyToEmu(request.io_vectors[0].address, cert.data(), cert.size()); Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
return GetDefaultReply(IPC_SUCCESS); return GetDefaultReply(IPC_SUCCESS);
} }
@ -197,7 +199,7 @@ IPCCommandResult ES::VerifySign(const IOCtlVRequest& request)
{ {
if (!request.HasNumberOfValidVectors(3, 0)) if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL); return GetDefaultReply(ES_EINVAL);
if (request.in_vectors[1].size != sizeof(IOS::ECCSignature)) if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
return GetDefaultReply(ES_EINVAL); return GetDefaultReply(ES_EINVAL);
std::vector<u8> hash(request.in_vectors[0].size); std::vector<u8> hash(request.in_vectors[0].size);

View File

@ -73,7 +73,7 @@ struct BootMiiKeyDump
u32 ms_id; // 0x200 u32 ms_id; // 0x200
u32 ca_id; // 0x204 u32 ca_id; // 0x204
u32 ng_key_id; // 0x208 u32 ng_key_id; // 0x208
IOS::ECCSignature ng_sig; // 0x20c Common::ec::Signature ng_sig; // 0x20c
struct Counter struct Counter
{ {
u8 boot2version; u8 boot2version;
@ -108,7 +108,7 @@ constexpr std::array<u8, 30> DEFAULT_PRIVATE_KEY = {{
}}; }};
// clang-format off // clang-format off
constexpr ECCSignature DEFAULT_SIGNATURE = {{ constexpr Common::ec::Signature DEFAULT_SIGNATURE = {{
// R // R
0x00, 0xD8, 0x81, 0x63, 0xB2, 0x00, 0x6B, 0x0B, 0x54, 0x82, 0x88, 0x63, 0x81, 0x1C, 0x00, 0x71, 0x00, 0xD8, 0x81, 0x63, 0xB2, 0x00, 0x6B, 0x0B, 0x54, 0x82, 0x88, 0x63, 0x81, 0x1C, 0x00, 0x71,
0x12, 0xED, 0xB7, 0xFD, 0x21, 0xAB, 0x0E, 0x50, 0x0E, 0x1F, 0xBF, 0x78, 0xAD, 0x37, 0x12, 0xED, 0xB7, 0xFD, 0x21, 0xAB, 0x0E, 0x50, 0x0E, 0x1F, 0xBF, 0x78, 0xAD, 0x37,
@ -417,29 +417,25 @@ u32 IOSC::GetDeviceId() const
// Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org> // Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
// Licensed under the terms of the GNU GPL, version 2 // Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
static Certificate MakeBlankSigECCert(const std::string& signer, const std::string& name, static CertECC MakeBlankEccCert(const std::string& issuer, const std::string& name,
const u8* private_key, u32 key_id) const u8* private_key, u32 key_id)
{ {
Certificate cert_out{}; CertECC cert{};
const u32 type = Common::swap32(static_cast<u32>(SignatureType::ECC)); cert.signature.type = SignatureType(Common::swap32(u32(SignatureType::ECC)));
std::memcpy(cert_out.data(), &type, sizeof(type)); std::strncpy(cert.signature.issuer, issuer.c_str(), 0x40);
std::strncpy(reinterpret_cast<char*>(cert_out.data()) + 0x80, signer.c_str(), 0x40); cert.header.public_key_type = PublicKeyType(Common::swap32(u32(PublicKeyType::ECC)));
const u32 two = Common::swap32(2); std::strncpy(cert.header.name, name.c_str(), 0x40);
std::memcpy(cert_out.data() + 0xc0, &two, sizeof(two)); cert.header.id = Common::swap32(key_id);
std::strncpy(reinterpret_cast<char*>(cert_out.data()) + 0xc4, name.c_str(), 0x40); cert.public_key = Common::ec::PrivToPub(private_key);
const u32 swapped_key_id = Common::swap32(key_id); return cert;
std::memcpy(cert_out.data() + 0x104, &swapped_key_id, sizeof(swapped_key_id));
const std::array<u8, 60> public_key = Common::ec::PrivToPub(private_key);
std::copy(public_key.cbegin(), public_key.cend(), cert_out.begin() + 0x108);
return cert_out;
} }
Certificate IOSC::GetDeviceCertificate() const CertECC IOSC::GetDeviceCertificate() const
{ {
const std::string name = StringFromFormat("NG%08x", GetDeviceId()); const std::string name = StringFromFormat("NG%08x", GetDeviceId());
auto cert = MakeBlankSigECCert(StringFromFormat("Root-CA%08x-MS%08x", m_ca_id, m_ms_id), name, auto cert = MakeBlankEccCert(StringFromFormat("Root-CA%08x-MS%08x", m_ca_id, m_ms_id), name,
m_key_entries[HANDLE_CONSOLE_KEY].data.data(), m_console_key_id); m_key_entries[HANDLE_CONSOLE_KEY].data.data(), m_console_key_id);
std::copy(m_console_signature.begin(), m_console_signature.end(), cert.begin() + 4); cert.signature.sig = m_console_signature;
return cert; return cert;
} }
@ -456,15 +452,16 @@ void IOSC::Sign(u8* sig_out, u8* ap_cert_out, u64 title_id, const u8* data, u32
const std::string signer = const std::string signer =
StringFromFormat("Root-CA%08x-MS%08x-NG%08x", m_ca_id, m_ms_id, GetDeviceId()); StringFromFormat("Root-CA%08x-MS%08x-NG%08x", m_ca_id, m_ms_id, GetDeviceId());
const std::string name = StringFromFormat("AP%016" PRIx64, title_id); const std::string name = StringFromFormat("AP%016" PRIx64, title_id);
const auto cert = MakeBlankSigECCert(signer, name, ap_priv.data(), 0); CertECC cert = MakeBlankEccCert(signer, name, ap_priv.data(), 0);
std::copy(cert.begin(), cert.end(), ap_cert_out); // Sign the AP cert.
const size_t skip = offsetof(CertECC, signature.issuer);
mbedtls_sha1(ap_cert_out + 0x80, 0x100, hash.data()); mbedtls_sha1(reinterpret_cast<const u8*>(&cert) + skip, sizeof(cert) - skip, hash.data());
auto signature = Common::ec::Sign(m_key_entries[HANDLE_CONSOLE_KEY].data.data(), hash.data()); cert.signature.sig = Common::ec::Sign(m_key_entries[HANDLE_CONSOLE_KEY].data.data(), hash.data());
std::copy(signature.cbegin(), signature.cend(), ap_cert_out + 4); std::memcpy(ap_cert_out, &cert, sizeof(cert));
// Sign the data.
mbedtls_sha1(data, data_size, hash.data()); mbedtls_sha1(data, data_size, hash.data());
signature = Common::ec::Sign(ap_priv.data(), hash.data()); const auto signature = Common::ec::Sign(ap_priv.data(), hash.data());
std::copy(signature.cbegin(), signature.cend(), sig_out); std::copy(signature.cbegin(), signature.cend(), sig_out);
} }

View File

@ -13,6 +13,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Crypto/AES.h" #include "Common/Crypto/AES.h"
#include "Common/Crypto/ec.h"
class PointerWrap; class PointerWrap;
@ -59,7 +60,7 @@ static_assert(sizeof(SignatureRSA2048) == 0x180, "Wrong size for SignatureRSA204
struct SignatureECC struct SignatureECC
{ {
SignatureType type; SignatureType type;
u8 sig[0x3c]; Common::ec::Signature sig;
u8 fill[0x40]; u8 fill[0x40];
char issuer[0x40]; char issuer[0x40];
}; };
@ -74,7 +75,6 @@ struct CertHeader
}; };
using RSA2048PublicKey = std::array<u8, 0x100>; using RSA2048PublicKey = std::array<u8, 0x100>;
using ECCPublicKey = std::array<u8, 60>;
struct CertRSA4096RSA2048 struct CertRSA4096RSA2048
{ {
@ -101,7 +101,7 @@ struct CertRSA2048ECC
{ {
SignatureRSA2048 signature; SignatureRSA2048 signature;
CertHeader header; CertHeader header;
ECCPublicKey public_key; Common::ec::PublicKey public_key;
std::array<u8, 60> padding; std::array<u8, 60> padding;
}; };
static_assert(sizeof(CertRSA2048ECC) == 0x240, "Wrong size for CertRSA2048ECC"); static_assert(sizeof(CertRSA2048ECC) == 0x240, "Wrong size for CertRSA2048ECC");
@ -111,15 +111,12 @@ struct CertECC
{ {
SignatureECC signature; SignatureECC signature;
CertHeader header; CertHeader header;
ECCPublicKey public_key; Common::ec::PublicKey public_key;
std::array<u8, 60> padding; std::array<u8, 60> padding;
}; };
static_assert(sizeof(CertECC) == 0x180, "Wrong size for CertECC"); static_assert(sizeof(CertECC) == 0x180, "Wrong size for CertECC");
#pragma pack(pop) #pragma pack(pop)
using ECCSignature = std::array<u8, 60>;
using Certificate = std::array<u8, 0x180>;
namespace HLE namespace HLE
{ {
enum ReturnCode : s32; enum ReturnCode : s32;
@ -223,7 +220,7 @@ public:
bool IsUsingDefaultId() const; bool IsUsingDefaultId() const;
u32 GetDeviceId() const; u32 GetDeviceId() const;
Certificate GetDeviceCertificate() const; CertECC GetDeviceCertificate() const;
void Sign(u8* sig_out, u8* ap_cert_out, u64 title_id, const u8* data, u32 data_size) const; void Sign(u8* sig_out, u8* ap_cert_out, u64 title_id, const u8* data, u32 data_size) const;
void DoState(PointerWrap& p); void DoState(PointerWrap& p);
@ -268,7 +265,7 @@ private:
KeyEntries m_key_entries; KeyEntries m_key_entries;
KeyEntry m_root_key_entry; KeyEntry m_root_key_entry;
ECCSignature m_console_signature{}; Common::ec::Signature m_console_signature{};
// Retail keyblob are issued by CA00000001. Default to 1 even though IOSC actually defaults to 2. // Retail keyblob are issued by CA00000001. Default to 1 even though IOSC actually defaults to 2.
u32 m_ms_id = 2; u32 m_ms_id = 2;
u32 m_ca_id = 1; u32 m_ca_id = 1;