Browse Source
Merge pull request #13159 from liamwhite/web-error
Merge pull request #13159 from liamwhite/web-error
core: enable error applet, add stubs for web appletpull/15/merge
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 494 additions and 45 deletions
-
2src/common/settings.h
-
3src/core/CMakeLists.txt
-
23src/core/hle/service/acc/acc.cpp
-
2src/core/hle/service/acc/acc_u1.cpp
-
5src/core/hle/service/am/am_types.h
-
4src/core/hle/service/am/service/common_state_getter.cpp
-
3src/core/hle/service/am/service/common_state_getter.h
-
40src/core/hle/service/erpt/erpt.cpp
-
72src/core/hle/service/filesystem/fsp/fsp_srv.cpp
-
16src/core/hle/service/filesystem/fsp/fsp_srv.h
-
13src/core/hle/service/ldn/monitor_service.cpp
-
1src/core/hle/service/ldn/monitor_service.h
-
5src/core/hle/service/set/settings_types.h
-
16src/core/hle/service/set/system_settings_server.cpp
-
2src/core/hle/service/set/system_settings_server.h
-
156src/core/hle/service/ssl/cert_store.cpp
-
42src/core/hle/service/ssl/cert_store.h
-
25src/core/hle/service/ssl/ssl.cpp
-
107src/core/hle/service/ssl/ssl_types.h
-
2src/yuzu/configuration/configure_applets.cpp
@ -0,0 +1,156 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "common/alignment.h"
|
||||
|
#include "core/core.h"
|
||||
|
#include "core/file_sys/content_archive.h"
|
||||
|
#include "core/file_sys/nca_metadata.h"
|
||||
|
#include "core/file_sys/registered_cache.h"
|
||||
|
#include "core/file_sys/romfs.h"
|
||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||
|
#include "core/hle/service/ssl/cert_store.h"
|
||||
|
|
||||
|
namespace Service::SSL { |
||||
|
|
||||
|
// https://switchbrew.org/wiki/SSL_services#CertStore
|
||||
|
|
||||
|
CertStore::CertStore(Core::System& system) { |
||||
|
constexpr u64 CertStoreDataId = 0x0100000000000800ULL; |
||||
|
|
||||
|
auto& fsc = system.GetFileSystemController(); |
||||
|
|
||||
|
// Attempt to load certificate data from storage
|
||||
|
const auto nca = |
||||
|
fsc.GetSystemNANDContents()->GetEntry(CertStoreDataId, FileSys::ContentRecordType::Data); |
||||
|
if (!nca) { |
||||
|
return; |
||||
|
} |
||||
|
const auto romfs = nca->GetRomFS(); |
||||
|
if (!romfs) { |
||||
|
return; |
||||
|
} |
||||
|
const auto extracted = FileSys::ExtractRomFS(romfs); |
||||
|
if (!extracted) { |
||||
|
LOG_ERROR(Service_SSL, "CertStore could not be extracted, corrupt RomFS?"); |
||||
|
return; |
||||
|
} |
||||
|
const auto cert_store_file = extracted->GetFile("ssl_TrustedCerts.bdf"); |
||||
|
if (!cert_store_file) { |
||||
|
LOG_ERROR(Service_SSL, "Failed to find trusted certificates in CertStore"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Read and verify the header.
|
||||
|
CertStoreHeader header; |
||||
|
cert_store_file->ReadObject(std::addressof(header)); |
||||
|
|
||||
|
if (header.magic != Common::MakeMagic('s', 's', 'l', 'T')) { |
||||
|
LOG_ERROR(Service_SSL, "Invalid certificate store magic"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Ensure the file can contains the number of entries it says it does.
|
||||
|
const u64 expected_size = sizeof(header) + sizeof(CertStoreEntry) * header.num_entries; |
||||
|
const u64 actual_size = cert_store_file->GetSize(); |
||||
|
if (actual_size < expected_size) { |
||||
|
LOG_ERROR(Service_SSL, "Size mismatch, expected at least {} bytes, got {}", expected_size, |
||||
|
actual_size); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Read entries.
|
||||
|
std::vector<CertStoreEntry> entries(header.num_entries); |
||||
|
cert_store_file->ReadArray(entries.data(), header.num_entries, sizeof(header)); |
||||
|
|
||||
|
// Insert into memory store.
|
||||
|
for (const auto& entry : entries) { |
||||
|
m_certs.emplace(entry.certificate_id, |
||||
|
Certificate{ |
||||
|
.status = entry.certificate_status, |
||||
|
.der_data = cert_store_file->ReadBytes( |
||||
|
entry.der_size, entry.der_offset + sizeof(header)), |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
CertStore::~CertStore() = default; |
||||
|
|
||||
|
template <typename F> |
||||
|
void CertStore::ForEachCertificate(std::span<const CaCertificateId> certificate_ids, F&& f) { |
||||
|
if (certificate_ids.size() == 1 && certificate_ids.front() == CaCertificateId::All) { |
||||
|
for (const auto& entry : m_certs) { |
||||
|
f(entry); |
||||
|
} |
||||
|
} else { |
||||
|
for (const auto certificate_id : certificate_ids) { |
||||
|
const auto entry = m_certs.find(certificate_id); |
||||
|
if (entry == m_certs.end()) { |
||||
|
continue; |
||||
|
} |
||||
|
f(*entry); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Result CertStore::GetCertificates(u32* out_num_entries, std::span<u8> out_data, |
||||
|
std::span<const CaCertificateId> certificate_ids) { |
||||
|
// Ensure the buffer is large enough to hold the output.
|
||||
|
u32 required_size; |
||||
|
R_TRY(this->GetCertificateBufSize(std::addressof(required_size), out_num_entries, |
||||
|
certificate_ids)); |
||||
|
R_UNLESS(out_data.size_bytes() >= required_size, ResultUnknown); |
||||
|
|
||||
|
// Make parallel arrays.
|
||||
|
std::vector<BuiltInCertificateInfo> cert_infos; |
||||
|
std::vector<u8> der_datas; |
||||
|
|
||||
|
const u32 der_data_offset = (*out_num_entries + 1) * sizeof(BuiltInCertificateInfo); |
||||
|
u32 cur_der_offset = der_data_offset; |
||||
|
|
||||
|
// Fill output.
|
||||
|
this->ForEachCertificate(certificate_ids, [&](auto& entry) { |
||||
|
const auto& [status, cur_der_data] = entry.second; |
||||
|
BuiltInCertificateInfo cert_info{ |
||||
|
.cert_id = entry.first, |
||||
|
.status = status, |
||||
|
.der_size = cur_der_data.size(), |
||||
|
.der_offset = cur_der_offset, |
||||
|
}; |
||||
|
|
||||
|
cert_infos.push_back(cert_info); |
||||
|
der_datas.insert(der_datas.end(), cur_der_data.begin(), cur_der_data.end()); |
||||
|
cur_der_offset += static_cast<u32>(cur_der_data.size()); |
||||
|
}); |
||||
|
|
||||
|
// Append terminator entry.
|
||||
|
cert_infos.push_back(BuiltInCertificateInfo{ |
||||
|
.cert_id = CaCertificateId::All, |
||||
|
.status = TrustedCertStatus::Invalid, |
||||
|
.der_size = 0, |
||||
|
.der_offset = 0, |
||||
|
}); |
||||
|
|
||||
|
// Write to output span.
|
||||
|
std::memcpy(out_data.data(), cert_infos.data(), |
||||
|
cert_infos.size() * sizeof(BuiltInCertificateInfo)); |
||||
|
std::memcpy(out_data.data() + der_data_offset, der_datas.data(), der_datas.size()); |
||||
|
|
||||
|
R_SUCCEED(); |
||||
|
} |
||||
|
|
||||
|
Result CertStore::GetCertificateBufSize(u32* out_size, u32* out_num_entries, |
||||
|
std::span<const CaCertificateId> certificate_ids) { |
||||
|
// Output size is at least the size of the terminator entry.
|
||||
|
*out_size = sizeof(BuiltInCertificateInfo); |
||||
|
*out_num_entries = 0; |
||||
|
|
||||
|
this->ForEachCertificate(certificate_ids, [&](auto& entry) { |
||||
|
*out_size += sizeof(BuiltInCertificateInfo); |
||||
|
*out_size += Common::AlignUp(static_cast<u32>(entry.second.der_data.size()), 4); |
||||
|
(*out_num_entries)++; |
||||
|
}); |
||||
|
|
||||
|
R_SUCCEED(); |
||||
|
} |
||||
|
|
||||
|
} // namespace Service::SSL
|
||||
@ -0,0 +1,42 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <map> |
||||
|
#include <span> |
||||
|
#include <vector> |
||||
|
|
||||
|
#include "core/hle/result.h" |
||||
|
#include "core/hle/service/ssl/ssl_types.h" |
||||
|
|
||||
|
namespace Core { |
||||
|
class System; |
||||
|
} |
||||
|
|
||||
|
namespace Service::SSL { |
||||
|
|
||||
|
class CertStore { |
||||
|
public: |
||||
|
explicit CertStore(Core::System& system); |
||||
|
~CertStore(); |
||||
|
|
||||
|
Result GetCertificates(u32* out_num_entries, std::span<u8> out_data, |
||||
|
std::span<const CaCertificateId> certificate_ids); |
||||
|
Result GetCertificateBufSize(u32* out_size, u32* out_num_entries, |
||||
|
std::span<const CaCertificateId> certificate_ids); |
||||
|
|
||||
|
private: |
||||
|
template <typename F> |
||||
|
void ForEachCertificate(std::span<const CaCertificateId> certs, F&& f); |
||||
|
|
||||
|
private: |
||||
|
struct Certificate { |
||||
|
TrustedCertStatus status; |
||||
|
std::vector<u8> der_data; |
||||
|
}; |
||||
|
|
||||
|
std::map<CaCertificateId, Certificate> m_certs; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Service::SSL |
||||
@ -0,0 +1,107 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Service::SSL { |
||||
|
|
||||
|
enum class CaCertificateId : s32 { |
||||
|
All = -1, |
||||
|
NintendoCAG3 = 1, |
||||
|
NintendoClass2CAG3 = 2, |
||||
|
NintendoRootCAG4 = 3, |
||||
|
AmazonRootCA1 = 1000, |
||||
|
StarfieldServicesRootCertificateAuthorityG2 = 1001, |
||||
|
AddTrustExternalCARoot = 1002, |
||||
|
COMODOCertificationAuthority = 1003, |
||||
|
UTNDATACorpSGC = 1004, |
||||
|
UTNUSERFirstHardware = 1005, |
||||
|
BaltimoreCyberTrustRoot = 1006, |
||||
|
CybertrustGlobalRoot = 1007, |
||||
|
VerizonGlobalRootCA = 1008, |
||||
|
DigiCertAssuredIDRootCA = 1009, |
||||
|
DigiCertAssuredIDRootG2 = 1010, |
||||
|
DigiCertGlobalRootCA = 1011, |
||||
|
DigiCertGlobalRootG2 = 1012, |
||||
|
DigiCertHighAssuranceEVRootCA = 1013, |
||||
|
EntrustnetCertificationAuthority2048 = 1014, |
||||
|
EntrustRootCertificationAuthority = 1015, |
||||
|
EntrustRootCertificationAuthorityG2 = 1016, |
||||
|
GeoTrustGlobalCA2 = 1017, |
||||
|
GeoTrustGlobalCA = 1018, |
||||
|
GeoTrustPrimaryCertificationAuthorityG3 = 1019, |
||||
|
GeoTrustPrimaryCertificationAuthority = 1020, |
||||
|
GlobalSignRootCA = 1021, |
||||
|
GlobalSignRootCAR2 = 1022, |
||||
|
GlobalSignRootCAR3 = 1023, |
||||
|
GoDaddyClass2CertificationAuthority = 1024, |
||||
|
GoDaddyRootCertificateAuthorityG2 = 1025, |
||||
|
StarfieldClass2CertificationAuthority = 1026, |
||||
|
StarfieldRootCertificateAuthorityG2 = 1027, |
||||
|
thawtePrimaryRootCAG3 = 1028, |
||||
|
thawtePrimaryRootCA = 1029, |
||||
|
VeriSignClass3PublicPrimaryCertificationAuthorityG3 = 1030, |
||||
|
VeriSignClass3PublicPrimaryCertificationAuthorityG5 = 1031, |
||||
|
VeriSignUniversalRootCertificationAuthority = 1032, |
||||
|
DSTRootCAX3 = 1033, |
||||
|
USERTrustRsaCertificationAuthority = 1034, |
||||
|
ISRGRootX10 = 1035, |
||||
|
USERTrustEccCertificationAuthority = 1036, |
||||
|
COMODORsaCertificationAuthority = 1037, |
||||
|
COMODOEccCertificationAuthority = 1038, |
||||
|
AmazonRootCA2 = 1039, |
||||
|
AmazonRootCA3 = 1040, |
||||
|
AmazonRootCA4 = 1041, |
||||
|
DigiCertAssuredIDRootG3 = 1042, |
||||
|
DigiCertGlobalRootG3 = 1043, |
||||
|
DigiCertTrustedRootG4 = 1044, |
||||
|
EntrustRootCertificationAuthorityEC1 = 1045, |
||||
|
EntrustRootCertificationAuthorityG4 = 1046, |
||||
|
GlobalSignECCRootCAR4 = 1047, |
||||
|
GlobalSignECCRootCAR5 = 1048, |
||||
|
GlobalSignECCRootCAR6 = 1049, |
||||
|
GTSRootR1 = 1050, |
||||
|
GTSRootR2 = 1051, |
||||
|
GTSRootR3 = 1052, |
||||
|
GTSRootR4 = 1053, |
||||
|
SecurityCommunicationRootCA = 1054, |
||||
|
GlobalSignRootE4 = 1055, |
||||
|
GlobalSignRootR4 = 1056, |
||||
|
TTeleSecGlobalRootClass2 = 1057, |
||||
|
DigiCertTLSECCP384RootG5 = 1058, |
||||
|
DigiCertTLSRSA4096RootG5 = 1059, |
||||
|
}; |
||||
|
|
||||
|
enum class TrustedCertStatus : s32 { |
||||
|
Invalid = -1, |
||||
|
Removed = 0, |
||||
|
EnabledTrusted = 1, |
||||
|
EnabledNotTrusted = 2, |
||||
|
Revoked = 3, |
||||
|
}; |
||||
|
|
||||
|
struct BuiltInCertificateInfo { |
||||
|
CaCertificateId cert_id; |
||||
|
TrustedCertStatus status; |
||||
|
u64 der_size; |
||||
|
u64 der_offset; |
||||
|
}; |
||||
|
static_assert(sizeof(BuiltInCertificateInfo) == 0x18, "BuiltInCertificateInfo has incorrect size."); |
||||
|
|
||||
|
struct CertStoreHeader { |
||||
|
u32 magic; |
||||
|
u32 num_entries; |
||||
|
}; |
||||
|
static_assert(sizeof(CertStoreHeader) == 0x8, "CertStoreHeader has incorrect size."); |
||||
|
|
||||
|
struct CertStoreEntry { |
||||
|
CaCertificateId certificate_id; |
||||
|
TrustedCertStatus certificate_status; |
||||
|
u32 der_size; |
||||
|
u32 der_offset; |
||||
|
}; |
||||
|
static_assert(sizeof(CertStoreEntry) == 0x10, "CertStoreEntry has incorrect size."); |
||||
|
|
||||
|
} // namespace Service::SSL |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue