mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-03 12:57:27 +00:00
Merge feat/libressl-x509-lookup into feat/libressl-verify-param-host
# Conflicts: # core/libs/prx/libSceLibreSsl/Export.cpp # core/libs/prx/libSceLibreSsl/include/Api.hpp # core/libs/prx/libSceLibreSsl/src/X509Store.cpp # docs/dev/debt/libSceLibreSsl.md
This commit is contained in:
commit
95643ecaab
9 files changed
+592
-50
No files matched your search
@@ -120,3 +120,33 @@ if(BUILD_TESTING)
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceLibreSsl>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_sources(libSceLibreSsl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/X509VerifyParam.cpp)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_libressl_x509_verify_param_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/X509VerifyParam.cpp)
|
||||
target_include_directories(guest_libressl_x509_verify_param_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_libressl_x509_verify_param_tests PRIVATE libSceLibreSsl libc)
|
||||
configure_windows_unwind(guest_libressl_x509_verify_param_tests)
|
||||
add_test(NAME guest_libressl_x509_verify_param COMMAND guest_libressl_x509_verify_param_tests)
|
||||
add_test(NAME guest_libressl_x509_verify_param_allocator COMMAND guest_libressl_x509_verify_param_tests allocator)
|
||||
set_tests_properties(guest_libressl_x509_verify_param guest_libressl_x509_verify_param_allocator PROPERTIES TIMEOUT 30)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_libressl_x509_verify_param guest_libressl_x509_verify_param_allocator PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceLibreSsl>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_libressl_x509_lookup_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/X509Lookup.cpp)
|
||||
target_include_directories(guest_libressl_x509_lookup_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_libressl_x509_lookup_tests PRIVATE libSceLibreSsl libc)
|
||||
configure_windows_unwind(guest_libressl_x509_lookup_tests)
|
||||
add_test(NAME guest_libressl_x509_lookup COMMAND guest_libressl_x509_lookup_tests)
|
||||
add_test(NAME guest_libressl_x509_lookup_allocator COMMAND guest_libressl_x509_lookup_tests allocator)
|
||||
set_tests_properties(guest_libressl_x509_lookup guest_libressl_x509_lookup_allocator PROPERTIES TIMEOUT 30)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_libressl_x509_lookup guest_libressl_x509_lookup_allocator PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceLibreSsl>")
|
||||
endif()
|
||||
endif()
|
||||
@@ -1503,11 +1503,6 @@ int APS5_VABI X509_INFO_free_nid_postfix(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_LOOKUP_file_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_NAME_ENTRY_get_data_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
@@ -1583,21 +1578,6 @@ int APS5_VABI X509_STORE_add_crl_nid_postfix(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_STORE_add_lookup_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_VERIFY_PARAM_set_hostflags_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_check_issued_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
||||
@@ -41,6 +41,27 @@ struct LibreSslX509Store {
|
||||
std::int32_t references;
|
||||
};
|
||||
|
||||
struct LibreSslX509LookupMethod {
|
||||
const char* name;
|
||||
void* newItem;
|
||||
void* free;
|
||||
void* init;
|
||||
void* shutdown;
|
||||
void* ctrl;
|
||||
void* getBySubject;
|
||||
void* getByIssuerSerial;
|
||||
void* getByFingerprint;
|
||||
void* getByAlias;
|
||||
};
|
||||
|
||||
struct LibreSslX509Lookup {
|
||||
std::int32_t init;
|
||||
std::int32_t skip;
|
||||
LibreSslX509LookupMethod* method;
|
||||
char* methodData;
|
||||
LibreSslX509Store* storeContext;
|
||||
};
|
||||
|
||||
inline constexpr int MaxRounds = 14;
|
||||
|
||||
struct AesKey {
|
||||
@@ -395,7 +416,7 @@ int APS5_VABI X509_EXTENSION_get_critical_nid_postfix(void);
|
||||
int APS5_VABI X509_EXTENSION_get_data_nid_postfix(void);
|
||||
int APS5_VABI X509_EXTENSION_get_object_nid_postfix(void);
|
||||
int APS5_VABI X509_INFO_free_nid_postfix(void);
|
||||
int APS5_VABI X509_LOOKUP_file_nid_postfix(void);
|
||||
LibreSslX509LookupMethod* APS5_VABI X509_LOOKUP_file_nid_postfix(void);
|
||||
int APS5_VABI X509_NAME_ENTRY_get_data_nid_postfix(void);
|
||||
int APS5_VABI X509_NAME_get_entry_nid_postfix(void);
|
||||
int APS5_VABI X509_NAME_get_index_by_NID_nid_postfix(void);
|
||||
@@ -411,13 +432,13 @@ int APS5_VABI X509_STORE_CTX_get_ex_data_nid_postfix(void);
|
||||
int APS5_VABI X509_STORE_CTX_set_error_nid_postfix(void);
|
||||
int APS5_VABI X509_STORE_add_cert_nid_postfix(void);
|
||||
int APS5_VABI X509_STORE_add_crl_nid_postfix(void);
|
||||
int APS5_VABI X509_STORE_add_lookup_nid_postfix(void);
|
||||
LibreSslX509Lookup* APS5_VABI X509_STORE_add_lookup_nid_postfix(LibreSslX509Store* store, LibreSslX509LookupMethod* method);
|
||||
void APS5_VABI X509_STORE_free_nid_postfix(LibreSslX509Store* store);
|
||||
LibreSslX509Store* APS5_VABI X509_STORE_new_nid_postfix(void);
|
||||
int APS5_VABI X509_STORE_set_flags_nid_postfix(LibreSslX509Store* store, std::uint64_t flags);
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_host_nid_postfix(LibreSslX509VerifyParam* param, const char* name, std::size_t length);
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(void);
|
||||
int APS5_VABI X509_VERIFY_PARAM_set_hostflags_nid_postfix(void);
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(LibreSslX509VerifyParam* param, const char* text);
|
||||
void APS5_VABI X509_VERIFY_PARAM_set_hostflags_nid_postfix(LibreSslX509VerifyParam* param, std::uint32_t flags);
|
||||
int APS5_VABI X509_check_issued_nid_postfix(void);
|
||||
int APS5_VABI X509_free_nid_postfix(void);
|
||||
int APS5_VABI X509_get_ext_d2i_nid_postfix(void);
|
||||
|
||||
@@ -25,6 +25,13 @@ static_assert(offsetof(LibreSslX509Store, param) == 24);
|
||||
static_assert(offsetof(LibreSslX509Store, callbacks) == 32);
|
||||
static_assert(offsetof(LibreSslX509Store, exData) == 120);
|
||||
static_assert(offsetof(LibreSslX509Store, references) == 128);
|
||||
static_assert(sizeof(LibreSslX509LookupMethod) == 80);
|
||||
static_assert(offsetof(LibreSslX509LookupMethod, shutdown) == 32);
|
||||
static_assert(offsetof(LibreSslX509LookupMethod, ctrl) == 40);
|
||||
static_assert(sizeof(LibreSslX509Lookup) == 32);
|
||||
static_assert(offsetof(LibreSslX509Lookup, method) == 8);
|
||||
static_assert(offsetof(LibreSslX509Lookup, methodData) == 16);
|
||||
static_assert(offsetof(LibreSslX509Lookup, storeContext) == 24);
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -52,6 +59,14 @@ int APS5_VABI CompareObjects(const void*, const void*) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI LoadFile(LibreSslX509Lookup*, int, const char*, std::int64_t, char**) {
|
||||
NotImplemented_nid_no_patch("X509_LOOKUP_file: loading certificates and CRLs from a file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LibreSslX509LookupMethod fileLookup{"Load file into cache", nullptr, nullptr, nullptr, nullptr,
|
||||
reinterpret_cast<void*>(LoadFile), nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
Stack* NewStack(Compare compare) {
|
||||
auto* stack = static_cast<Stack*>(malloc_nid_postfix(sizeof(Stack)));
|
||||
if (!stack) return nullptr;
|
||||
@@ -94,6 +109,14 @@ bool Push(Stack* stack, void* element, const char* function) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeLookup(LibreSslX509Lookup* lookup, bool shutdown, const char* function) {
|
||||
if (!lookup) NotImplemented_nid_no_patch(function);
|
||||
const auto* method = lookup->method;
|
||||
if (shutdown && method && method->shutdown) NotImplemented_nid_no_patch("X509_LOOKUP shutdown callback");
|
||||
if (method && method->free) NotImplemented_nid_no_patch("X509_LOOKUP free callback");
|
||||
free_nid_postfix(lookup);
|
||||
}
|
||||
|
||||
bool HoldsElements(const Stack* stack, const char* function) {
|
||||
if (!stack || stack->num <= 0) return false;
|
||||
char** const elements = Elements(stack, function);
|
||||
@@ -166,7 +189,11 @@ void APS5_VABI X509_STORE_free_nid_postfix(LibreSslX509Store* store) {
|
||||
if (!store) return;
|
||||
if (std::atomic_ref<std::int32_t>(store->references).fetch_sub(1) - 1 > 0) return;
|
||||
auto* lookupMethods = static_cast<Stack*>(store->lookupMethods);
|
||||
if (lookupMethods && lookupMethods->num > 0) NotImplemented_nid_no_patch("X509_STORE_free: lookup methods");
|
||||
if (lookupMethods && lookupMethods->num > 0) {
|
||||
char** const lookups = Elements(lookupMethods, __func__);
|
||||
for (int index = 0; index < lookupMethods->num; ++index)
|
||||
FreeLookup(reinterpret_cast<LibreSslX509Lookup*>(lookups[index]), true, __func__);
|
||||
}
|
||||
FreeStack(lookupMethods);
|
||||
auto* objects = static_cast<Stack*>(store->objects);
|
||||
if (HoldsElements(objects, __func__)) NotImplemented_nid_no_patch("X509_STORE_free: stored certificates and CRLs");
|
||||
@@ -183,6 +210,35 @@ int APS5_VABI X509_STORE_set_flags_nid_postfix(LibreSslX509Store* store, std::ui
|
||||
return 1;
|
||||
}
|
||||
|
||||
LibreSslX509LookupMethod* APS5_VABI X509_LOOKUP_file_nid_postfix(void) {
|
||||
return &fileLookup;
|
||||
}
|
||||
|
||||
LibreSslX509Lookup* APS5_VABI X509_STORE_add_lookup_nid_postfix(LibreSslX509Store* store, LibreSslX509LookupMethod* method) {
|
||||
if (!store) NotImplemented_nid_no_patch(__func__);
|
||||
auto* lookupMethods = static_cast<Stack*>(store->lookupMethods);
|
||||
if (lookupMethods && lookupMethods->num > 0) {
|
||||
char** const lookups = Elements(lookupMethods, __func__);
|
||||
for (int index = 0; index < lookupMethods->num; ++index) {
|
||||
auto* lookup = reinterpret_cast<LibreSslX509Lookup*>(lookups[index]);
|
||||
if (!lookup) NotImplemented_nid_no_patch(__func__);
|
||||
if (lookup->method == method) return lookup;
|
||||
}
|
||||
}
|
||||
if (!method) NotImplemented_nid_no_patch(__func__);
|
||||
if (method->newItem) NotImplemented_nid_no_patch("X509_LOOKUP new_item callback");
|
||||
auto* lookup = static_cast<LibreSslX509Lookup*>(malloc_nid_postfix(sizeof(LibreSslX509Lookup)));
|
||||
if (!lookup) return nullptr;
|
||||
lookup->init = 0;
|
||||
lookup->skip = 0;
|
||||
lookup->method = method;
|
||||
lookup->methodData = nullptr;
|
||||
lookup->storeContext = store;
|
||||
if (Push(lookupMethods, lookup, __func__)) return lookup;
|
||||
FreeLookup(lookup, false, __func__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_host_nid_postfix(LibreSslX509VerifyParam* param, const char* name, std::size_t length) {
|
||||
if (!param || !param->id) NotImplemented_nid_no_patch(__func__);
|
||||
auto* id = param->id;
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "prx/libSceLibreSsl/libSceLibreSsl.hpp"
|
||||
#include "prx/libc/include/Api.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
struct Ipv6Text {
|
||||
unsigned char bytes[16];
|
||||
int total;
|
||||
int zeroPosition;
|
||||
int zeroCount;
|
||||
};
|
||||
|
||||
bool Ipv4FromText(unsigned char* out, const char* text) {
|
||||
int parts[4];
|
||||
if (sscanf_nid_postfix(text, "%d.%d.%d.%d", &parts[0], &parts[1], &parts[2], &parts[3]) != 4) return false;
|
||||
for (int part : parts) {
|
||||
if (part < 0 || part > 255) return false;
|
||||
}
|
||||
for (int index = 0; index < 4; ++index) out[index] = static_cast<unsigned char>(parts[index]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ipv6Hex(unsigned char* out, const char* text, int length) {
|
||||
if (length > 4) return false;
|
||||
unsigned int number = 0;
|
||||
while (length--) {
|
||||
const unsigned char character = static_cast<unsigned char>(*text++);
|
||||
number <<= 4;
|
||||
if (character >= '0' && character <= '9') number |= character - '0';
|
||||
else if (character >= 'A' && character <= 'F') number |= character - 'A' + 10;
|
||||
else if (character >= 'a' && character <= 'f') number |= character - 'a' + 10;
|
||||
else return false;
|
||||
}
|
||||
out[0] = static_cast<unsigned char>(number >> 8);
|
||||
out[1] = static_cast<unsigned char>(number & 0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ipv6Element(const char* element, int length, Ipv6Text& state) {
|
||||
if (state.total == 16) return false;
|
||||
if (length == 0) {
|
||||
if (state.zeroPosition == -1) state.zeroPosition = state.total;
|
||||
else if (state.zeroPosition != state.total) return false;
|
||||
++state.zeroCount;
|
||||
return true;
|
||||
}
|
||||
if (length > 4) {
|
||||
if (state.total > 12 || element[length]) return false;
|
||||
if (!Ipv4FromText(state.bytes + state.total, element)) return false;
|
||||
state.total += 4;
|
||||
return true;
|
||||
}
|
||||
if (!Ipv6Hex(state.bytes + state.total, element, length)) return false;
|
||||
state.total += 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ipv6Elements(const char* text, Ipv6Text& state) {
|
||||
const char* start = text;
|
||||
for (;;) {
|
||||
const char* separator = std::strchr(start, ':');
|
||||
bool accepted;
|
||||
if (separator == start || !*start) {
|
||||
accepted = Ipv6Element(nullptr, 0, state);
|
||||
} else {
|
||||
const char* last = separator ? separator - 1 : start + std::strlen(start) - 1;
|
||||
accepted = Ipv6Element(start, static_cast<int>(last - start + 1), state);
|
||||
}
|
||||
if (!accepted) return false;
|
||||
if (!separator) return true;
|
||||
start = separator + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ipv6FromText(unsigned char* out, const char* text) {
|
||||
Ipv6Text state{{}, 0, -1, 0};
|
||||
if (!Ipv6Elements(text, state)) return false;
|
||||
if (state.zeroPosition == -1) {
|
||||
if (state.total != 16) return false;
|
||||
std::memcpy(out, state.bytes, 16);
|
||||
return true;
|
||||
}
|
||||
if (state.total == 16 || state.zeroCount > 3) return false;
|
||||
if (state.zeroCount == 3 && state.total > 0) return false;
|
||||
if (state.zeroCount == 2 && state.zeroPosition != 0 && state.zeroPosition != state.total) return false;
|
||||
if (state.zeroCount == 1 && (state.zeroPosition == 0 || state.zeroPosition == state.total)) return false;
|
||||
std::memcpy(out, state.bytes, state.zeroPosition);
|
||||
std::memset(out + state.zeroPosition, 0, 16 - state.total);
|
||||
if (state.total != state.zeroPosition)
|
||||
std::memcpy(out + state.zeroPosition + 16 - state.total, state.bytes + state.zeroPosition, state.total - state.zeroPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t AddressFromText(unsigned char* out, const char* text) {
|
||||
if (std::strchr(text, ':')) return Ipv6FromText(out, text) ? 16 : 0;
|
||||
return Ipv4FromText(out, text) ? 4 : 0;
|
||||
}
|
||||
|
||||
LibreSslX509VerifyParamId* Identity(LibreSslX509VerifyParam* param, const char* function) {
|
||||
if (!param || !param->id) NotImplemented_nid_no_patch(function);
|
||||
return param->id;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
void APS5_VABI X509_VERIFY_PARAM_set_hostflags_nid_postfix(LibreSslX509VerifyParam* param, std::uint32_t flags) {
|
||||
Identity(param, __func__)->hostFlags = flags;
|
||||
}
|
||||
|
||||
int APS5_VABI X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(LibreSslX509VerifyParam* param, const char* text) {
|
||||
if (!text) NotImplemented_nid_no_patch(__func__);
|
||||
unsigned char address[16];
|
||||
const std::size_t length = AddressFromText(address, text);
|
||||
if (length == 0) return 0;
|
||||
auto* id = Identity(param, __func__);
|
||||
auto* copy = static_cast<unsigned char*>(malloc_nid_postfix(length));
|
||||
if (!copy) return 0;
|
||||
std::memcpy(copy, address, length);
|
||||
free_nid_postfix(id->ip);
|
||||
id->ip = copy;
|
||||
id->ipLength = length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "prx/libSceLibreSsl/libSceLibreSsl.hpp"
|
||||
#include "prx/libc/include/Api.hpp"
|
||||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
struct Stack {
|
||||
std::int32_t num;
|
||||
char** data;
|
||||
std::int32_t sorted;
|
||||
std::int32_t numAlloc;
|
||||
int (APS5_VABI* comp)(const void*, const void*);
|
||||
};
|
||||
|
||||
using LookupControl = int (APS5_VABI*)(LibreSslX509Lookup*, int, const char*, std::int64_t, char**);
|
||||
|
||||
void Require(bool condition, const char* message) {
|
||||
if (condition) return;
|
||||
std::fprintf(stderr, "failed: %s\n", message);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
template<typename TAction>
|
||||
void RequireThrows(TAction action, const char* message) {
|
||||
try {
|
||||
action();
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
}
|
||||
Require(false, message);
|
||||
}
|
||||
|
||||
Stack* Lookups(LibreSslX509Store* store) {
|
||||
return static_cast<Stack*>(store->lookupMethods);
|
||||
}
|
||||
|
||||
void FileMethod() {
|
||||
auto* method = X509_LOOKUP_file_nid_postfix();
|
||||
Require(method && method == X509_LOOKUP_file_nid_postfix(), "the file method is one static object");
|
||||
Require(std::strcmp(method->name, "Load file into cache") == 0, "file method name");
|
||||
Require(!method->newItem && !method->free && !method->init && !method->shutdown, "the file method has no lifecycle callbacks");
|
||||
Require(!method->getBySubject && !method->getByIssuerSerial && !method->getByFingerprint && !method->getByAlias,
|
||||
"the file method has no lookup callbacks");
|
||||
Require(method->ctrl, "the file method has a control callback");
|
||||
auto control = reinterpret_cast<LookupControl>(method->ctrl);
|
||||
RequireThrows([&] { control(nullptr, 1, "certs.pem", 1, nullptr); }, "loading a file needs the certificate model");
|
||||
}
|
||||
|
||||
void AddLookup() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* method = X509_LOOKUP_file_nid_postfix();
|
||||
auto* lookup = X509_STORE_add_lookup_nid_postfix(store, method);
|
||||
Require(lookup && lookup->init == 0 && lookup->skip == 0 && lookup->method == method && lookup->methodData == nullptr
|
||||
&& lookup->storeContext == store, "a new lookup starts as X509_LOOKUP_new leaves it, owned by the store");
|
||||
Require(Lookups(store)->num == 1 && Lookups(store)->data[0] == reinterpret_cast<char*>(lookup) && Lookups(store)->sorted == 0,
|
||||
"the lookup is pushed on the store's methods");
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, method) == lookup && Lookups(store)->num == 1, "the same method returns the same lookup");
|
||||
lookup->init = 1;
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, method) == lookup && lookup->init == 1, "an existing lookup is returned unchanged");
|
||||
|
||||
std::array<LibreSslX509LookupMethod, 5> methods{};
|
||||
std::array<LibreSslX509Lookup*, 5> added{};
|
||||
for (std::size_t index = 0; index < methods.size(); ++index) {
|
||||
added[index] = X509_STORE_add_lookup_nid_postfix(store, &methods[index]);
|
||||
Require(added[index] && added[index]->method == &methods[index], "each method gets its own lookup");
|
||||
}
|
||||
Require(Lookups(store)->num == 6 && Lookups(store)->numAlloc == 8, "the stack doubles once four slots are not enough");
|
||||
for (std::size_t index = 0; index < methods.size(); ++index)
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, &methods[index]) == added[index], "lookups are found after growth");
|
||||
Require(Lookups(store)->num == 6, "finding a lookup adds nothing");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
void Unsupported() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
RequireThrows([] { X509_STORE_add_lookup_nid_postfix(nullptr, X509_LOOKUP_file_nid_postfix()); }, "null store");
|
||||
RequireThrows([&] { X509_STORE_add_lookup_nid_postfix(store, nullptr); }, "null method");
|
||||
LibreSslX509LookupMethod withNewItem{};
|
||||
withNewItem.newItem = reinterpret_cast<void*>(&Require);
|
||||
RequireThrows([&] { X509_STORE_add_lookup_nid_postfix(store, &withNewItem); }, "a guest new_item callback");
|
||||
Require(Lookups(store)->num == 0, "a refused method adds no lookup");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
LibreSslX509LookupMethod withShutdown{};
|
||||
withShutdown.shutdown = reinterpret_cast<void*>(&Require);
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, &withShutdown) != nullptr, "a method with only a shutdown callback is added");
|
||||
RequireThrows([&] { X509_STORE_free_nid_postfix(store); }, "a guest shutdown callback");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
LibreSslX509LookupMethod withFree{};
|
||||
withFree.free = reinterpret_cast<void*>(&Require);
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, &withFree) != nullptr, "a method with only a free callback is added");
|
||||
RequireThrows([&] { X509_STORE_free_nid_postfix(store); }, "a guest free callback");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
Lookups(store)->num = 1;
|
||||
RequireThrows([&] { X509_STORE_add_lookup_nid_postfix(store, X509_LOOKUP_file_nid_postfix()); }, "a null listed lookup");
|
||||
}
|
||||
|
||||
int allocations = 0;
|
||||
int frees = 0;
|
||||
int reallocations = 0;
|
||||
bool failRealloc = false;
|
||||
|
||||
void* APS5_VABI Allocate_nid_no_patch(std::size_t size) {
|
||||
++allocations;
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
void APS5_VABI Free_nid_no_patch(void* pointer) {
|
||||
if (pointer) ++frees;
|
||||
std::free(pointer);
|
||||
}
|
||||
|
||||
void* APS5_VABI Reallocate_nid_no_patch(void* pointer, std::size_t size) {
|
||||
++reallocations;
|
||||
if (failRealloc) return nullptr;
|
||||
return std::realloc(pointer, size);
|
||||
}
|
||||
|
||||
void* APS5_VABI Calloc_nid_no_patch(std::size_t count, std::size_t size) { return std::calloc(count, size); }
|
||||
void* APS5_VABI Align_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned allocation"); }
|
||||
void* APS5_VABI Realign_nid_no_patch(void*, std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned reallocation"); }
|
||||
int APS5_VABI PosixAlign_nid_no_patch(void**, std::size_t, std::size_t) { throw std::runtime_error("unexpected posix_memalign"); }
|
||||
|
||||
void Allocator() {
|
||||
std::array<void*, 10> api{
|
||||
reinterpret_cast<void*>(Allocate_nid_no_patch), reinterpret_cast<void*>(Free_nid_no_patch), reinterpret_cast<void*>(Calloc_nid_no_patch),
|
||||
reinterpret_cast<void*>(Reallocate_nid_no_patch), reinterpret_cast<void*>(Align_nid_no_patch), reinterpret_cast<void*>(Realign_nid_no_patch),
|
||||
reinterpret_cast<void*>(PosixAlign_nid_no_patch)};
|
||||
ApplicationHeapRegister_nid_no_patch(api.data());
|
||||
std::array<LibreSslX509LookupMethod, 4> methods{};
|
||||
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
allocations = frees = reallocations = 0;
|
||||
for (auto& method : methods) X509_STORE_add_lookup_nid_postfix(store, &method);
|
||||
Require(allocations == 4 && reallocations == 1 && frees == 0, "four lookups are malloc'd and the fourth push grows the array");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
Require(frees == 4 + 7, "freeing the store frees its lookups");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
for (std::size_t index = 0; index < 3; ++index) X509_STORE_add_lookup_nid_postfix(store, &methods[index]);
|
||||
allocations = frees = 0;
|
||||
failRealloc = true;
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, &methods[3]) == nullptr, "a failed growth fails the call");
|
||||
Require(allocations == 1 && frees == 1 && Lookups(store)->num == 3 && Lookups(store)->numAlloc == 4, "a failed growth frees the new lookup and keeps the stack");
|
||||
failRealloc = false;
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
LibreSslX509LookupMethod withNewItem{};
|
||||
withNewItem.newItem = reinterpret_cast<void*>(&Require);
|
||||
allocations = frees = 0;
|
||||
RequireThrows([&] { X509_STORE_add_lookup_nid_postfix(store, nullptr); }, "null method");
|
||||
RequireThrows([&] { X509_STORE_add_lookup_nid_postfix(store, &withNewItem); }, "a guest new_item callback");
|
||||
Require(allocations == 0 && frees == 0 && Lookups(store)->num == 0, "a refused method allocates nothing");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
auto* lookupMethods = Lookups(store);
|
||||
store->lookupMethods = nullptr;
|
||||
allocations = frees = 0;
|
||||
Require(X509_STORE_add_lookup_nid_postfix(store, &methods[0]) == nullptr && allocations == 1 && frees == 1,
|
||||
"a store without a method stack frees the new lookup");
|
||||
store->lookupMethods = lookupMethods;
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char**) {
|
||||
if (argc > 1) {
|
||||
Allocator();
|
||||
return 0;
|
||||
}
|
||||
std::array<void*, 10> api{};
|
||||
ApplicationHeapRegister_nid_no_patch(api.data());
|
||||
FileMethod();
|
||||
AddLookup();
|
||||
Unsupported();
|
||||
}
|
||||
@@ -61,8 +61,6 @@ void NewStore() {
|
||||
const auto* id = param->id;
|
||||
Require(id && id->hosts == nullptr && id->hostFlags == 0 && id->peerName == nullptr && id->email == nullptr
|
||||
&& id->emailLength == 0 && id->ip == nullptr && id->ipLength == 0, "verify parameter identity starts zeroed");
|
||||
const auto* objects = static_cast<const Stack*>(store->objects);
|
||||
RequireThrows([&] { objects->comp(nullptr, nullptr); }, "object comparison needs the certificate model");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
@@ -118,29 +116,9 @@ void Identity() {
|
||||
|
||||
void Unsupported() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* objects = static_cast<Stack*>(store->objects);
|
||||
int entry = 0;
|
||||
objects->data[0] = reinterpret_cast<char*>(&entry);
|
||||
objects->num = 1;
|
||||
RequireThrows([&] { X509_STORE_free_nid_postfix(store); }, "stored objects need X509_OBJECT_free");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
objects = static_cast<Stack*>(store->objects);
|
||||
objects->num = 2;
|
||||
static_cast<Stack*>(store->objects)->num = 2;
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
static_cast<Stack*>(store->lookupMethods)->num = 1;
|
||||
RequireThrows([&] { X509_STORE_free_nid_postfix(store); }, "lookup methods need X509_LOOKUP_free");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
auto* policies = static_cast<Stack*>(malloc_nid_postfix(sizeof(Stack)));
|
||||
policies->data = static_cast<char**>(malloc_nid_postfix(sizeof(char*) * 4));
|
||||
policies->data[0] = reinterpret_cast<char*>(&entry);
|
||||
policies->num = 1;
|
||||
store->param->policies = policies;
|
||||
RequireThrows([&] { X509_STORE_free_nid_postfix(store); }, "policy objects need ASN1_OBJECT_free");
|
||||
|
||||
store = X509_STORE_new_nid_postfix();
|
||||
static_cast<Stack*>(store->objects)->data = nullptr;
|
||||
static_cast<Stack*>(store->objects)->num = 1;
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
#include "prx/libSceLibreSsl/libSceLibreSsl.hpp"
|
||||
#include "prx/libc/include/Api.hpp"
|
||||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
void Require(bool condition, const char* message) {
|
||||
if (condition) return;
|
||||
std::fprintf(stderr, "failed: %s\n", message);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
template<typename TAction>
|
||||
void RequireThrows(TAction action, const char* message) {
|
||||
try {
|
||||
action();
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
}
|
||||
Require(false, message);
|
||||
}
|
||||
|
||||
void RequireAddress(LibreSslX509VerifyParam* param, const char* text, std::initializer_list<unsigned char> expected) {
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(param, text) == 1, text);
|
||||
Require(param->id->ipLength == expected.size() && std::memcmp(param->id->ip, expected.begin(), expected.size()) == 0, text);
|
||||
}
|
||||
|
||||
void RequireRejected(LibreSslX509VerifyParam* param, const char* text) {
|
||||
const unsigned char* before = param->id->ip;
|
||||
const std::uint64_t length = param->id->ipLength;
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(param, text) == 0, text);
|
||||
Require(param->id->ip == before && param->id->ipLength == length, "a rejected address keeps the previous one");
|
||||
}
|
||||
|
||||
void HostFlags() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* param = store->param;
|
||||
X509_VERIFY_PARAM_set_hostflags_nid_postfix(param, 0x4);
|
||||
Require(param->id->hostFlags == 0x4, "host flags are stored");
|
||||
X509_VERIFY_PARAM_set_hostflags_nid_postfix(param, 0xffffffffu);
|
||||
Require(param->id->hostFlags == 0xffffffffu, "host flags are replaced, not ORed");
|
||||
X509_VERIFY_PARAM_set_hostflags_nid_postfix(param, 0);
|
||||
Require(param->id->hostFlags == 0 && param->flags == 0 && param->inheritanceFlags == 0, "only the host flags change");
|
||||
RequireThrows([] { X509_VERIFY_PARAM_set_hostflags_nid_postfix(nullptr, 1); }, "null verify parameters");
|
||||
auto* id = param->id;
|
||||
param->id = nullptr;
|
||||
RequireThrows([&] { X509_VERIFY_PARAM_set_hostflags_nid_postfix(param, 1); }, "verify parameters without an identity");
|
||||
param->id = id;
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
void Ipv4() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* param = store->param;
|
||||
RequireAddress(param, "192.168.0.1", {192, 168, 0, 1});
|
||||
RequireAddress(param, "0.0.0.0", {0, 0, 0, 0});
|
||||
RequireAddress(param, "255.255.255.255", {255, 255, 255, 255});
|
||||
RequireAddress(param, " 1. 2.3.4", {1, 2, 3, 4});
|
||||
RequireAddress(param, "+1.2.3.4x", {1, 2, 3, 4});
|
||||
RequireAddress(param, "010.1.1.1", {10, 1, 1, 1});
|
||||
for (const char* text : {"", "1.2.3", "256.0.0.0", "1.2.3.256", "-1.0.0.0", "1..2.3", "a.b.c.d", "1 .2.3.4"})
|
||||
RequireRejected(param, text);
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
void Ipv6() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* param = store->param;
|
||||
RequireAddress(param, "::", {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
RequireAddress(param, "::1", {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1});
|
||||
RequireAddress(param, "1::", {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
RequireAddress(param, "fe80::aB:1", {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xab, 0, 1});
|
||||
RequireAddress(param, "1:2:3:4:5:6:7:8", {0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8});
|
||||
RequireAddress(param, "::ffff:192.0.2.1", {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 1});
|
||||
RequireAddress(param, "1:2:3:4:5:6:10.0.0.1", {0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 10, 0, 0, 1});
|
||||
for (const char* text : {":::", "1:::2", "1::2::3", ":1", "1:", "::1:", "1:2:3:4:5:6:7", "1:2:3:4:5:6:7:8:9",
|
||||
"1::2:3:4:5:6:7:8", "12345::", "g::", "1.2.3.4::", "1:2:3:4:5:6:7:1.2.3.4", "::1.2.3"})
|
||||
RequireRejected(param, text);
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
void Unsupported() {
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
RequireThrows([&] { X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(store->param, nullptr); }, "null address text");
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(nullptr, "bad") == 0, "a rejected address does not read the verify parameters");
|
||||
RequireThrows([] { X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(nullptr, "1.2.3.4"); }, "null verify parameters");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
int allocations = 0;
|
||||
int frees = 0;
|
||||
bool failNext = false;
|
||||
|
||||
void* APS5_VABI Allocate_nid_no_patch(std::size_t size) {
|
||||
if (failNext) {
|
||||
failNext = false;
|
||||
return nullptr;
|
||||
}
|
||||
++allocations;
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
void APS5_VABI Free_nid_no_patch(void* pointer) {
|
||||
if (pointer) ++frees;
|
||||
std::free(pointer);
|
||||
}
|
||||
|
||||
void* APS5_VABI Calloc_nid_no_patch(std::size_t count, std::size_t size) { return std::calloc(count, size); }
|
||||
void* APS5_VABI Reallocate_nid_no_patch(void*, std::size_t) { throw std::runtime_error("unexpected realloc"); }
|
||||
void* APS5_VABI Align_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned allocation"); }
|
||||
void* APS5_VABI Realign_nid_no_patch(void*, std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned reallocation"); }
|
||||
int APS5_VABI PosixAlign_nid_no_patch(void**, std::size_t, std::size_t) { throw std::runtime_error("unexpected posix_memalign"); }
|
||||
|
||||
void Allocator() {
|
||||
std::array<void*, 10> api{
|
||||
reinterpret_cast<void*>(Allocate_nid_no_patch), reinterpret_cast<void*>(Free_nid_no_patch), reinterpret_cast<void*>(Calloc_nid_no_patch),
|
||||
reinterpret_cast<void*>(Reallocate_nid_no_patch), reinterpret_cast<void*>(Align_nid_no_patch), reinterpret_cast<void*>(Realign_nid_no_patch),
|
||||
reinterpret_cast<void*>(PosixAlign_nid_no_patch)};
|
||||
ApplicationHeapRegister_nid_no_patch(api.data());
|
||||
auto* store = X509_STORE_new_nid_postfix();
|
||||
auto* param = store->param;
|
||||
allocations = frees = 0;
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(param, "10.0.0.1") == 1 && allocations == 1 && frees == 0, "the address is copied into a malloc'd block");
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(param, "::1") == 1 && allocations == 2 && frees == 1, "a new address frees the previous one");
|
||||
unsigned char* kept = param->id->ip;
|
||||
failNext = true;
|
||||
Require(X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(param, "10.0.0.2") == 0, "a failed copy fails the call");
|
||||
Require(param->id->ip == kept && param->id->ipLength == 16 && frees == 1, "a failed copy keeps the previous address");
|
||||
X509_STORE_free_nid_postfix(store);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char**) {
|
||||
if (argc > 1) {
|
||||
Allocator();
|
||||
return 0;
|
||||
}
|
||||
std::array<void*, 10> api{};
|
||||
ApplicationHeapRegister_nid_no_patch(api.data());
|
||||
HostFlags();
|
||||
Ipv4();
|
||||
Ipv6();
|
||||
Unsupported();
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Unknown function info
|
||||
|
||||
- [libSceLibreSsl pending exports](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - 338 named callable exports are listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl.c) and were cross-checked against the same module in PS5 firmware 13.60. Their signatures and behaviour are unverified; the declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`.
|
||||
- [libSceLibreSsl pending exports](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - 334 named callable exports are listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl.c) and were cross-checked against the same module in PS5 firmware 13.60. Their signatures and behaviour are unverified; the declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`.
|
||||
- [MD4, MD5, SHA1, SHA224, SHA256, SHA384 and SHA512 Init/Update/Final and SHA256](../../../core/libs/prx/libSceLibreSsl/src/Digest.cpp) (libSceLibreSsl) - signatures and context layouts follow the [LibreSSL headers](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/sha/sha.h), and buffering and `Final` follow its [sources](https://github.com/libressl/openbsd/tree/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/sha); nothing is checked on the console. Null contexts, null input with a nonzero length, null digest buffers in the 32-bit `Final` functions and a buffered byte count that is not below the block size, which LibreSSL does not check, throw
|
||||
- [DES_set_key, DES_ecb_encrypt, DES_set_odd_parity](../../../core/libs/prx/libSceLibreSsl/Export.cpp) (libSceLibreSsl) - the 128-byte `DES_key_schedule` holds the 8-byte key followed by zeros instead of LibreSSL's precomputed subkeys, so a title reading its contents sees different bytes; `DES_ecb_encrypt` derives the subkeys through mbedtls on each call. Not compared with the console. Results follow LibreSSL [des_key.c](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/des/des_key.c) and [des.c](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/des/des.c): `DES_set_key` skips the parity and weak-key checks and returns 0, as it does while `DES_check_key` is 0 (that variable is not in the PS5 export inventory), a nonzero `enc` encrypts, and `DES_set_odd_parity` sets each byte's low bit for odd parity. Null pointers throw where LibreSSL faults
|
||||
- [X509_verify_cert_error_string](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - no console call is verified. The 64-bit argument, low-32-bit lookup, messages and shared numeric fallback follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509/x509_txt.c), the version identified in [published firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). Console modifications and other firmware versions remain unverified. Unknown-code results share an overwritten static buffer and are not safe for concurrent use, as in that release; code 1 and codes above 54 use the numeric fallback.
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
- [ASN1_INTEGER_get and ASN1_STRING_data/length/type/to_UTF8](../../../core/libs/prx/libSceLibreSsl/src/Asn1.cpp) are unverified on PS5. Signatures, the 24-byte guest string layout and conversions follow [LibreSSL 2.5.4's ASN.1 sources](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/asn1), the version reported for firmware 13.40 in [discussion #8981](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). Null accessor inputs, null conversion outputs, missing nonempty data, oversized converted output and unrepresentable signed integer values throw where the source has undefined behaviour. Malformed encodings and allocation failure throw until ASN.1 error-queue reporting is implemented. Conversion buffers use the guest libc allocator and can be released with guest `free`.
|
||||
|
||||
- [X509_STORE_new, X509_STORE_free and X509_STORE_set_flags](../../../core/libs/prx/libSceLibreSsl/src/X509Store.cpp) are unverified on PS5. The 136-byte store, 64-byte verify parameters, 56-byte parameter identity, 32-byte stacks and the results follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509) `x509_lu.c` and `x509_vpm.c`, the version in [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export adds a certificate, CRL, lookup method or policy object, so `X509_STORE_free` throws instead of freeing one and the object cache's comparator throws. A null store or verify parameters, and a null element array behind a positive count, throw where LibreSSL faults
|
||||
- [X509_STORE_new, X509_STORE_free and X509_STORE_set_flags](../../../core/libs/prx/libSceLibreSsl/src/X509Store.cpp) are unverified on PS5. The 136-byte store, 64-byte verify parameters, 56-byte parameter identity, 32-byte stacks and the results follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509) `x509_lu.c` and `x509_vpm.c`, the version in [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export adds a certificate, CRL or policy object, so `X509_STORE_free` throws instead of freeing one and the object cache's comparator throws. A null store or verify parameters, and a null element array behind a positive count, throw where LibreSSL faults
|
||||
|
||||
- [X509_VERIFY_PARAM_set_hostflags and X509_VERIFY_PARAM_set1_ip_asc](../../../core/libs/prx/libSceLibreSsl/src/X509VerifyParam.cpp) are unverified on PS5. They follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509/x509_vpm.c) `x509_vpm.c` and the `a2i_ipadd` parser of its [`v3_utl.c`](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509v3/v3_utl.c), unchanged in 2.7, the first release whose symbols include `X509_VERIFY_PARAM_set1_host`, which the module also exports; IPv4 parts are read with the guest `sscanf` as the module would. LibreSSL 2.8 appends a `poisoned` field to the parameter identity, which these layouts lack. A null address text, and null verify parameters or identity once an address is accepted, throw where LibreSSL faults
|
||||
|
||||
- [X509_LOOKUP_file and X509_STORE_add_lookup](../../../core/libs/prx/libSceLibreSsl/src/X509Store.cpp) are unverified on PS5. The 80-byte method, the 32-byte lookup, the stack growth and the results follow LibreSSL 2.5.4 [`by_file.c`, `x509_lu.c`](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509) and `stack.c`, unchanged in 2.7. The file method's `ctrl`, which loads PEM certificates and CRLs, throws: there is no certificate model. Callbacks of a guest-supplied method (`new_item`, `shutdown`, `free`) throw instead of being called, and a null store, method or listed lookup throws where LibreSSL faults
|
||||
|
||||
- [X509_VERIFY_PARAM_set1_host](../../../core/libs/prx/libSceLibreSsl/src/X509Store.cpp) is unverified on PS5. It follows `int_x509_param_set_hosts` of [LibreSSL 2.7](https://github.com/libressl/openbsd/blob/OPENBSD_6_3/src/lib/libcrypto/x509/x509_vpm.c), the first release with this export, and copies the name with the guest `strndup`. LibreSSL 2.8 also marks the parameters as poisoned when the call fails, through a field the 2.5.4 to 2.7 layout lacks, so a failed call leaves no mark. Null verify parameters or identity throw where LibreSSL faults
|
||||
Reference in new issue
Block a user