diff --git a/Source/Core/Common/Crypto/ec.cpp b/Source/Core/Common/Crypto/ec.cpp index b9a0ca6491..9a57300f89 100644 --- a/Source/Core/Common/Crypto/ec.cpp +++ b/Source/Core/Common/Crypto/ec.cpp @@ -241,7 +241,7 @@ static void silly_random(u8* rndArea, u8 count) } } -std::array Sign(const u8* key, const u8* hash) +Signature Sign(const u8* key, const u8* hash) { u8 e[30]{}; memcpy(e + 10, hash, 20); @@ -272,7 +272,7 @@ std::array Sign(const u8* key, const u8* hash) bn_inv(minv, m, ec_N, sizeof(minv)); bn_mul(s.data.data(), minv, kk, ec_N, 30); - std::array signature; + Signature signature; std::copy(r.data.cbegin(), r.data.cend(), signature.begin()); std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30); 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); } -std::array PrivToPub(const u8* key) +PublicKey PrivToPub(const u8* key) { const Point data = key * ec_G; - std::array result; + PublicKey result; std::copy_n(data.Data(), result.size(), result.begin()); return result; } diff --git a/Source/Core/Common/Crypto/ec.h b/Source/Core/Common/Crypto/ec.h index 442bbec311..5b21dd96cc 100644 --- a/Source/Core/Common/Crypto/ec.h +++ b/Source/Core/Common/Crypto/ec.h @@ -10,8 +10,11 @@ namespace Common::ec { +using Signature = std::array; +using PublicKey = std::array; + /// Generate a signature using ECDSA. -std::array Sign(const u8* key, const u8* hash); +Signature Sign(const u8* key, const u8* hash); /// Check a signature using ECDSA. /// @@ -24,5 +27,5 @@ bool VerifySignature(const u8* public_key, const u8* signature, const u8* hash); std::array ComputeSharedSecret(const u8* private_key, const u8* public_key); /// Convert a ECC private key (30 bytes) to a public key (60 bytes). -std::array PrivToPub(const u8* key); +PublicKey PrivToPub(const u8* key); } // namespace Common::ec diff --git a/Source/Core/Core/HW/WiiSave.cpp b/Source/Core/Core/HW/WiiSave.cpp index 88f4a8aa0c..cf376cb501 100644 --- a/Source/Core/Core/HW/WiiSave.cpp +++ b/Source/Core/Core/HW/WiiSave.cpp @@ -454,9 +454,10 @@ void WiiSave::do_sig() } // Sign the data. - IOS::Certificate ap_cert; - IOS::ECCSignature ap_sig; - m_ios.GetIOSC().Sign(ap_sig.data(), ap_cert.data(), Titles::SYSTEM_MENU, data.get(), data_size); + IOS::CertECC ap_cert; + Common::ec::Signature ap_sig; + m_ios.GetIOSC().Sign(ap_sig.data(), reinterpret_cast(&ap_cert), Titles::SYSTEM_MENU, + data.get(), data_size); // Write signatures. 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()); const u32 SIGNATURE_END_MAGIC = Common::swap32(0x2f536969); data_file.WriteArray(&SIGNATURE_END_MAGIC, 1); - const IOS::Certificate device_certificate = m_ios.GetIOSC().GetDeviceCertificate(); - data_file.WriteArray(device_certificate.data(), device_certificate.size()); - data_file.WriteArray(ap_cert.data(), ap_cert.size()); + const IOS::CertECC device_certificate = m_ios.GetIOSC().GetDeviceCertificate(); + data_file.WriteArray(&device_certificate, 1); + data_file.WriteArray(&ap_cert, 1); m_valid = data_file.IsGood(); } diff --git a/Source/Core/Core/IOS/ES/Identity.cpp b/Source/Core/Core/IOS/ES/Identity.cpp index 87ff012cb6..6805bd62b1 100644 --- a/Source/Core/Core/IOS/ES/Identity.cpp +++ b/Source/Core/Core/IOS/ES/Identity.cpp @@ -8,12 +8,14 @@ #include +#include "Common/Crypto/ec.h" #include "Common/Logging/Log.h" #include "Common/ScopeGuard.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" #include "Core/IOS/ES/Formats.h" +#include "Core/IOS/IOSC.h" #include "Core/IOS/Uids.h" namespace IOS @@ -96,8 +98,8 @@ IPCCommandResult ES::GetDeviceCertificate(const IOCtlVRequest& request) INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICECERT"); - const auto cert = m_ios.GetIOSC().GetDeviceCertificate(); - Memory::CopyToEmu(request.io_vectors[0].address, cert.data(), cert.size()); + const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate(); + Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert)); return GetDefaultReply(IPC_SUCCESS); } @@ -197,7 +199,7 @@ IPCCommandResult ES::VerifySign(const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 0)) 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); std::vector hash(request.in_vectors[0].size); diff --git a/Source/Core/Core/IOS/IOSC.cpp b/Source/Core/Core/IOS/IOSC.cpp index bba688dd4d..362a235cb1 100644 --- a/Source/Core/Core/IOS/IOSC.cpp +++ b/Source/Core/Core/IOS/IOSC.cpp @@ -70,10 +70,10 @@ struct BootMiiKeyDump u32 unk2; // 0x17C std::array eeprom_pad; // 0x180 - u32 ms_id; // 0x200 - u32 ca_id; // 0x204 - u32 ng_key_id; // 0x208 - IOS::ECCSignature ng_sig; // 0x20c + u32 ms_id; // 0x200 + u32 ca_id; // 0x204 + u32 ng_key_id; // 0x208 + Common::ec::Signature ng_sig; // 0x20c struct Counter { u8 boot2version; @@ -108,7 +108,7 @@ constexpr std::array DEFAULT_PRIVATE_KEY = {{ }}; // clang-format off -constexpr ECCSignature DEFAULT_SIGNATURE = {{ +constexpr Common::ec::Signature DEFAULT_SIGNATURE = {{ // R 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, @@ -417,29 +417,25 @@ u32 IOSC::GetDeviceId() const // Copyright 2007,2008 Segher Boessenkool // Licensed under the terms of the GNU GPL, version 2 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt -static Certificate MakeBlankSigECCert(const std::string& signer, const std::string& name, - const u8* private_key, u32 key_id) +static CertECC MakeBlankEccCert(const std::string& issuer, const std::string& name, + const u8* private_key, u32 key_id) { - Certificate cert_out{}; - const u32 type = Common::swap32(static_cast(SignatureType::ECC)); - std::memcpy(cert_out.data(), &type, sizeof(type)); - std::strncpy(reinterpret_cast(cert_out.data()) + 0x80, signer.c_str(), 0x40); - const u32 two = Common::swap32(2); - std::memcpy(cert_out.data() + 0xc0, &two, sizeof(two)); - std::strncpy(reinterpret_cast(cert_out.data()) + 0xc4, name.c_str(), 0x40); - const u32 swapped_key_id = Common::swap32(key_id); - std::memcpy(cert_out.data() + 0x104, &swapped_key_id, sizeof(swapped_key_id)); - const std::array public_key = Common::ec::PrivToPub(private_key); - std::copy(public_key.cbegin(), public_key.cend(), cert_out.begin() + 0x108); - return cert_out; + CertECC cert{}; + cert.signature.type = SignatureType(Common::swap32(u32(SignatureType::ECC))); + std::strncpy(cert.signature.issuer, issuer.c_str(), 0x40); + cert.header.public_key_type = PublicKeyType(Common::swap32(u32(PublicKeyType::ECC))); + std::strncpy(cert.header.name, name.c_str(), 0x40); + cert.header.id = Common::swap32(key_id); + cert.public_key = Common::ec::PrivToPub(private_key); + return cert; } -Certificate IOSC::GetDeviceCertificate() const +CertECC IOSC::GetDeviceCertificate() const { const std::string name = StringFromFormat("NG%08x", GetDeviceId()); - auto cert = MakeBlankSigECCert(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); - std::copy(m_console_signature.begin(), m_console_signature.end(), cert.begin() + 4); + 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); + cert.signature.sig = m_console_signature; 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 = 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 auto cert = MakeBlankSigECCert(signer, name, ap_priv.data(), 0); - std::copy(cert.begin(), cert.end(), ap_cert_out); - - mbedtls_sha1(ap_cert_out + 0x80, 0x100, hash.data()); - auto signature = Common::ec::Sign(m_key_entries[HANDLE_CONSOLE_KEY].data.data(), hash.data()); - std::copy(signature.cbegin(), signature.cend(), ap_cert_out + 4); + CertECC cert = MakeBlankEccCert(signer, name, ap_priv.data(), 0); + // Sign the AP cert. + const size_t skip = offsetof(CertECC, signature.issuer); + mbedtls_sha1(reinterpret_cast(&cert) + skip, sizeof(cert) - skip, hash.data()); + cert.signature.sig = Common::ec::Sign(m_key_entries[HANDLE_CONSOLE_KEY].data.data(), hash.data()); + std::memcpy(ap_cert_out, &cert, sizeof(cert)); + // Sign the 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); } diff --git a/Source/Core/Core/IOS/IOSC.h b/Source/Core/Core/IOS/IOSC.h index 735e2ed6cc..8155a5f0a7 100644 --- a/Source/Core/Core/IOS/IOSC.h +++ b/Source/Core/Core/IOS/IOSC.h @@ -13,6 +13,7 @@ #include "Common/CommonTypes.h" #include "Common/Crypto/AES.h" +#include "Common/Crypto/ec.h" class PointerWrap; @@ -59,7 +60,7 @@ static_assert(sizeof(SignatureRSA2048) == 0x180, "Wrong size for SignatureRSA204 struct SignatureECC { SignatureType type; - u8 sig[0x3c]; + Common::ec::Signature sig; u8 fill[0x40]; char issuer[0x40]; }; @@ -74,7 +75,6 @@ struct CertHeader }; using RSA2048PublicKey = std::array; -using ECCPublicKey = std::array; struct CertRSA4096RSA2048 { @@ -101,7 +101,7 @@ struct CertRSA2048ECC { SignatureRSA2048 signature; CertHeader header; - ECCPublicKey public_key; + Common::ec::PublicKey public_key; std::array padding; }; static_assert(sizeof(CertRSA2048ECC) == 0x240, "Wrong size for CertRSA2048ECC"); @@ -111,15 +111,12 @@ struct CertECC { SignatureECC signature; CertHeader header; - ECCPublicKey public_key; + Common::ec::PublicKey public_key; std::array padding; }; static_assert(sizeof(CertECC) == 0x180, "Wrong size for CertECC"); #pragma pack(pop) -using ECCSignature = std::array; -using Certificate = std::array; - namespace HLE { enum ReturnCode : s32; @@ -223,7 +220,7 @@ public: bool IsUsingDefaultId() 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 DoState(PointerWrap& p); @@ -268,7 +265,7 @@ private: KeyEntries m_key_entries; 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. u32 m_ms_id = 2; u32 m_ca_id = 1;