feat(libSceSsl): implement sceSslGetCaList, sceSslFreeCaList and sceSslUnloadCert
PPSA11386 imports sceSslGetCaList and sceSslFreeCaList and PPSA15508 imports sceSslUnloadCert; on main all three are missing and the loaders of both titles stop on them. No root certificate bundle is shipped and no loaded certificate is kept, so an SSL context holds no certificates: sceSslGetCaList clears the list and returns NOT_FOUND, as sceSslGetCaCerts does; sceSslFreeCaList accepts only that cleared list; sceSslUnloadCert has nothing to drop and is assumed to return 0. A null list returns the invalid-argument code that sceSslGetCaCerts and KytyPS5 return. An unknown context and a list sceSslGetCaList did not return throw, as their codes are not confirmed. Signatures and the SceSslCaList layout follow SharpProspero and shadPS4. guest_ssl_tests now links libc, as guest_http2_tests does, so an exception thrown from libSceSsl unwinds with the same unwinder that resumes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
57f96fd2b3
commit
33184a1b33
|
|
@ -5,7 +5,8 @@ configure_windows_unwind(libSceSsl)
|
|||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_ssl_tests ${LIBS_INCLUDE_DIR}/tests/GuestSsl.cpp)
|
||||
target_include_directories(guest_ssl_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_ssl_tests PRIVATE libSceSsl)
|
||||
target_link_libraries(guest_ssl_tests PRIVATE libSceSsl libc)
|
||||
configure_windows_unwind(guest_ssl_tests)
|
||||
add_test(NAME guest_ssl COMMAND guest_ssl_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_ssl PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <map>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
// No network is emulated: contexts, templates and requests can be created, but any request
|
||||
// that would touch the network fails with the library's network error.
|
||||
|
|
@ -37,6 +38,17 @@ struct SslCaCerts {
|
|||
void* pool;
|
||||
};
|
||||
|
||||
struct SslCaList {
|
||||
void** certs;
|
||||
int num;
|
||||
};
|
||||
static_assert(sizeof(SslCaList) == 16);
|
||||
|
||||
void RequireContext(const char* function, int sslCtxId) {
|
||||
std::lock_guard lock(g_poolsMutex);
|
||||
if (!g_pools.contains(sslCtxId)) throw std::invalid_argument(std::string(function) + ": unknown context");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -55,6 +67,20 @@ int APS5_VABI sceSslGetCaCerts(int ssl_ctx_id, void* ca_certs) {
|
|||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSslGetCaList(int sslCtxId, SslCaList* caList) {
|
||||
if (!caList) return ERROR_INVALID_ARG;
|
||||
RequireContext(__func__, sslCtxId);
|
||||
*caList = {};
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSslFreeCaList(int sslCtxId, SslCaList* caList) {
|
||||
if (!caList) return ERROR_INVALID_ARG;
|
||||
RequireContext(__func__, sslCtxId);
|
||||
if (caList->certs || caList->num) throw std::invalid_argument("sceSslFreeCaList: list not returned by sceSslGetCaList");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSslInit_nid_postfix(uint64_t pool_size) {
|
||||
const int id = g_nextHandle.fetch_add(1, std::memory_order_relaxed);
|
||||
std::lock_guard lock(g_poolsMutex);
|
||||
|
|
@ -83,6 +109,11 @@ int APS5_VABI sceSslLoadCert() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSslUnloadCert(int sslCtxId) {
|
||||
RequireContext(__func__, sslCtxId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSslGetMemoryPoolStats(int ssl_ctx_id, SslMemoryPoolStats* stats) {
|
||||
if (stats == nullptr) APS5_INVALID_ARG_EX;
|
||||
std::lock_guard lock(g_poolsMutex);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,16 @@
|
|||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceSslInit_nid_postfix(std::size_t);
|
||||
int APS5_VABI sceSslTerm_nid_postfix(int);
|
||||
int APS5_VABI sceSslGetCaCerts(int, void*);
|
||||
int APS5_VABI sceSslFreeCaCerts(int, void*);
|
||||
int APS5_VABI sceSslGetCaList(int, void*);
|
||||
int APS5_VABI sceSslFreeCaList(int, void*);
|
||||
int APS5_VABI sceSslUnloadCert(int);
|
||||
}
|
||||
|
||||
struct SslMemoryPoolStats {
|
||||
|
|
@ -20,12 +25,27 @@ extern "C" int APS5_VABI sceSslGetMemoryPoolStats(int, SslMemoryPoolStats*);
|
|||
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
|
||||
template <typename TCall>
|
||||
static bool Throws(TCall call) {
|
||||
try {
|
||||
call();
|
||||
} catch (const std::exception&) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct SslCaCerts {
|
||||
void* certs;
|
||||
std::size_t num;
|
||||
void* pool;
|
||||
};
|
||||
|
||||
struct SslCaList {
|
||||
void** certs;
|
||||
int num;
|
||||
};
|
||||
|
||||
int main() {
|
||||
constexpr int notFound = static_cast<int>(0x8095F004);
|
||||
constexpr int invalidArg = static_cast<int>(0x8095177A);
|
||||
|
|
@ -46,4 +66,33 @@ int main() {
|
|||
certs = {&marker, 3, &marker};
|
||||
Require(sceSslFreeCaCerts(context, &certs) == 0);
|
||||
Require(certs.certs == nullptr && certs.num == 0 && certs.pool == nullptr);
|
||||
|
||||
Require(sceSslGetCaList(context, nullptr) == invalidArg);
|
||||
Require(sceSslFreeCaList(context, nullptr) == invalidArg);
|
||||
|
||||
void* handle = ▮
|
||||
SslCaList list{&handle, 3};
|
||||
Require(sceSslGetCaList(context, &list) == notFound);
|
||||
Require(list.certs == nullptr && list.num == 0);
|
||||
Require(sceSslFreeCaList(context, &list) == 0);
|
||||
Require(list.certs == nullptr && list.num == 0);
|
||||
|
||||
SslCaList foreign{&handle, 1};
|
||||
Require(Throws([&] { sceSslFreeCaList(context, &foreign); }));
|
||||
foreign = {nullptr, 1};
|
||||
Require(Throws([&] { sceSslFreeCaList(context, &foreign); }));
|
||||
foreign = {&handle, 0};
|
||||
Require(Throws([&] { sceSslFreeCaList(context, &foreign); }));
|
||||
|
||||
Require(sceSslUnloadCert(context) == 0);
|
||||
Require(sceSslGetCaList(context, &list) == notFound);
|
||||
Require(list.certs == nullptr && list.num == 0);
|
||||
|
||||
Require(sceSslTerm_nid_postfix(context) == 0);
|
||||
Require(sceSslGetCaList(context, nullptr) == invalidArg);
|
||||
Require(sceSslFreeCaList(context, nullptr) == invalidArg);
|
||||
list = {&handle, 3};
|
||||
Require(Throws([&] { sceSslGetCaList(context, &list); }));
|
||||
Require(Throws([&] { sceSslFreeCaList(context, &list); }));
|
||||
Require(Throws([&] { sceSslUnloadCert(context); }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [sceKernelGetOperationMode](../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - the signature `(int* mode, int* submode)` comes from PPSA12544, which logs both values after the call; the values are unknown and 0 is reported for both, as in the [prosper](https://github.com/mattias800/prosper/pull/4153) reimplementation. Null outputs throw
|
||||
- Font, Http2, Net, Ssl, SystemService and libkernel exports imported by PPSA12544 and added without an implementation have unknown signatures
|
||||
- [sceHttp2GetMemoryPoolStats, sceSslGetMemoryPoolStats, sceNetGetMemoryPoolStats](../../core/libs/prx/libSceNet/Export.cpp) (libSceHttp2, libSceSsl, libSceNet) - signatures `(int id, stats*)` and the statistics layouts (pool size, peak and current use, and for Http2 and Ssl a 32-bit reserved field) follow the PS4 SDK's `SceHttp2MemoryPoolStats`, `SceSslMemoryPoolStats` and `SceNetMemoryPoolStats`, not confirmed for the PS5. The pool size is the one given at init or pool creation; nothing is allocated from these pools, so the peak and current use are 0. Net returns `EBADF` for an unknown pool and `EINVAL` for a null output, as its other pool calls do; for Http2 and Ssl the error codes are unknown, so both cases throw
|
||||
- [sceSslGetCaList, sceSslFreeCaList, sceSslUnloadCert](../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - signatures and the 16-byte `SceSslCaList` layout (an array of certificate handles and a 32-bit count) follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Http.cs) and shadPS4's `OrbisSslCaList`, not confirmed for the PS5. On the console the list holds the certificate authorities the SSL service has; [shadPS4](https://github.com/shadps4-emu/shadPS4/pull/4104) returns a placeholder certificate from `sceSslGetCaCerts` because Rise of the Tomb Raider fails its initialization checks without one. No root certificate bundle is shipped and no loaded certificate is kept, so here a context holds none: `sceSslGetCaList` clears the list and returns `NOT_FOUND`, as `sceSslGetCaCerts` does, `sceSslFreeCaList` accepts only that cleared list, and `sceSslUnloadCert` (imported by PPSA15508) has nothing to drop and is assumed to return 0. A null list returns `0x8095177A`, which `sceSslGetCaCerts` and [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/59183dbfa81ed7efdff6069177fed50de0552725/src/libs/network.cpp) return for a null argument (shadPS4, PS4, returns `0x8095F007`). An unknown context throws (KytyPS5 returns `SSL_ERROR_INVALID_ID`, `0x8095F006`, from `sceSslGetCaCerts`), and so does a list `sceSslGetCaList` did not return
|
||||
- [sceHttp2SetResolveRetry](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2) - signature `(int id, int32_t retry)` from libSceHttp's `sceHttpSetResolveRetry`; the value is accepted and ignored like the other Http2 settings, since no request reaches the network
|
||||
- [sceHttp2WebSocketCreateRequest, sceHttp2WebSocketCloseAsync, sceHttp2WebSocketSendTextMessageAsync, sceHttp2WebSocketSendDataMessageAsync](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2) - imported by PPSA16064 and not called during its start-up; unknown signatures
|
||||
- [libSceVrSetupDialog](../../core/libs/prx/libSceVrSetupDialog/Export.cpp), and the Share, NpTrophy2, NpEntitlementAccess and WebBrowserDialog exports imported by PPSA12544's Unity plugins and added without an implementation, have unknown signatures
|
||||
|
|
|
|||
Loading…
Reference in New Issue