mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-08 13:50:20 +00:00
Merge pull request #15045 from atharvjairath/feat/libressl3-tls-protocol-parser
feat(libSceLibreSsl3): implement TLS protocol list parsing
This commit is contained in:
6 files changed
+280
-8
No files matched your search
@@ -634,10 +634,6 @@ int APS5_VABI ASN1_OCTET_STRING_free_nid_postfix() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI tls_config_parse_protocols_nid_postfix() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SSL_CTX_set_post_handshake_auth_nid_postfix() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
@@ -236,6 +236,20 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL "Linux" AND EXISTS "${LIBS_INCLU
|
||||
set_tests_properties(guest_libressl3_mixed_evp PROPERTIES TIMEOUT 20)
|
||||
endif()
|
||||
|
||||
target_sources(libSceLibreSsl3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/TlsProtocols.cpp)
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_libressl3_tls_protocols_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/TlsProtocols.cpp)
|
||||
target_include_directories(guest_libressl3_tls_protocols_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_libressl3_tls_protocols_tests PRIVATE libSceLibreSsl3 libc)
|
||||
configure_windows_unwind(guest_libressl3_tls_protocols_tests)
|
||||
add_test(NAME guest_libressl3_tls_protocols COMMAND guest_libressl3_tls_protocols_tests)
|
||||
set_tests_properties(guest_libressl3_tls_protocols PROPERTIES TIMEOUT 20)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_libressl3_tls_protocols PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceLibreSsl3>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_sources(libSceLibreSsl3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/RsaSetters.cpp)
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_libressl3_rsa_setters_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/RsaSetters.cpp)
|
||||
|
||||
@@ -376,7 +376,7 @@ int APS5_VABI EVP_PKEY_cmp_nid_postfix(const LibreSsl3EvpPkey* first, const Libr
|
||||
int APS5_VABI d2i_ASN1_SEQUENCE_ANY_nid_postfix();
|
||||
int APS5_VABI PKCS5_PBKDF2_HMAC_nid_postfix();
|
||||
int APS5_VABI ASN1_OCTET_STRING_free_nid_postfix();
|
||||
int APS5_VABI tls_config_parse_protocols_nid_postfix();
|
||||
int APS5_VABI tls_config_parse_protocols_nid_postfix(std::uint32_t* protocols, const char* text);
|
||||
int APS5_VABI SSL_CTX_set_post_handshake_auth_nid_postfix();
|
||||
int APS5_VABI tls_config_insecure_noverifyname_nid_postfix();
|
||||
int APS5_VABI ASN1_TYPE_free_nid_postfix();
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "prx/libSceLibreSsl3/libSceLibreSsl3.hpp"
|
||||
#include "prx/libc/libc.hpp"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::uint32_t SupportedProtocols = 0x18;
|
||||
constexpr std::array<std::pair<std::string_view, std::uint32_t>, 9> ProtocolNames{{
|
||||
{"all", SupportedProtocols}, {"legacy", SupportedProtocols},
|
||||
{"default", SupportedProtocols}, {"secure", SupportedProtocols},
|
||||
{"tlsv1", SupportedProtocols}, {"tlsv1.0", 0x02},
|
||||
{"tlsv1.1", 0x04}, {"tlsv1.2", 0x08}, {"tlsv1.3", 0x10}
|
||||
}};
|
||||
|
||||
bool EqualName(std::string_view text, std::string_view name) {
|
||||
if (text.size() != name.size()) return false;
|
||||
for (std::size_t index = 0; index < text.size(); ++index) {
|
||||
const unsigned char byte = static_cast<unsigned char>(text[index]);
|
||||
const unsigned char folded = byte >= 'A' && byte <= 'Z' ? byte + ('a' - 'A') : byte;
|
||||
if (folded != static_cast<unsigned char>(name[index])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" int APS5_VABI tls_config_parse_protocols_nid_postfix(std::uint32_t* protocols, const char* text) {
|
||||
if (!protocols) throw std::invalid_argument("tls_config_parse_protocols: null output");
|
||||
if (!text) {
|
||||
*protocols = SupportedProtocols;
|
||||
return 0;
|
||||
}
|
||||
char* const copy = strdup_nid_postfix(text);
|
||||
if (!copy) return -1;
|
||||
std::string_view remaining(copy);
|
||||
std::uint32_t result = 0;
|
||||
for (;;) {
|
||||
const std::size_t separator = remaining.find_first_of(",:");
|
||||
std::string_view token = remaining.substr(0, separator);
|
||||
while (!token.empty() && (token.front() == ' ' || token.front() == '\t')) token.remove_prefix(1);
|
||||
const bool exclude = !token.empty() && token.front() == '!';
|
||||
if (exclude) token.remove_prefix(1);
|
||||
std::uint32_t selected = 0;
|
||||
for (const auto& [name, mask] : ProtocolNames) {
|
||||
if (EqualName(token, name)) {
|
||||
selected = mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!selected) {
|
||||
free_nid_postfix(copy);
|
||||
return -1;
|
||||
}
|
||||
if (exclude) {
|
||||
if (!result) result = SupportedProtocols;
|
||||
result &= ~selected;
|
||||
} else {
|
||||
result |= selected;
|
||||
}
|
||||
if (separator == std::string_view::npos) break;
|
||||
remaining.remove_prefix(separator + 1);
|
||||
}
|
||||
*protocols = result;
|
||||
free_nid_postfix(copy);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "prx/libSceLibreSsl3/libSceLibreSsl3.hpp"
|
||||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <source_location>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace {
|
||||
|
||||
std::size_t checks = 0;
|
||||
std::size_t cases = 0;
|
||||
std::size_t attempts = 0;
|
||||
std::size_t releases = 0;
|
||||
void* live = nullptr;
|
||||
std::size_t liveSize = 0;
|
||||
bool failAllocation = false;
|
||||
const std::uint32_t* observedOutput = nullptr;
|
||||
std::uint32_t expectedAtRelease = 0;
|
||||
|
||||
void Require(bool condition, std::source_location location = std::source_location::current()) {
|
||||
++checks;
|
||||
if (condition) return;
|
||||
std::fprintf(stderr, "TLS protocol check failed at line %u, case %zu\n", location.line(), cases);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
void* APS5_VABI Allocate_nid_no_patch(std::size_t size) {
|
||||
++attempts;
|
||||
Require(live == nullptr);
|
||||
if (failAllocation) return nullptr;
|
||||
auto* raw = static_cast<unsigned char*>(std::malloc(size + 32));
|
||||
Require(raw != nullptr);
|
||||
std::memset(raw, 0xa5, size + 32);
|
||||
live = raw + 16;
|
||||
liveSize = size;
|
||||
return live;
|
||||
}
|
||||
|
||||
void APS5_VABI Release_nid_no_patch(void* pointer) {
|
||||
if (!pointer) return;
|
||||
Require(pointer == live);
|
||||
if (observedOutput) Require(*observedOutput == expectedAtRelease);
|
||||
auto* raw = static_cast<unsigned char*>(pointer) - 16;
|
||||
for (std::size_t i = 0; i < 16; ++i) Require(raw[i] == 0xa5 && raw[16 + liveSize + i] == 0xa5);
|
||||
std::free(raw);
|
||||
live = nullptr;
|
||||
++releases;
|
||||
}
|
||||
|
||||
void* APS5_VABI UnexpectedCalloc_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected calloc"); }
|
||||
void* APS5_VABI UnexpectedRealloc_nid_no_patch(void*, std::size_t) { throw std::runtime_error("unexpected realloc"); }
|
||||
void* APS5_VABI UnexpectedAlign_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected align"); }
|
||||
void* APS5_VABI UnexpectedRealign_nid_no_patch(void*, std::size_t, std::size_t) { throw std::runtime_error("unexpected realign"); }
|
||||
int APS5_VABI UnexpectedPosixAlign_nid_no_patch(void**, std::size_t, std::size_t) { throw std::runtime_error("unexpected posix align"); }
|
||||
|
||||
void Check(const char* input, int status, std::uint32_t expected) {
|
||||
++cases;
|
||||
struct Output { std::uint32_t before; std::uint32_t value; std::uint32_t after; } output{0x12345678, 0xcafebeef, 0x87654321};
|
||||
const std::string saved = input ? input : "";
|
||||
const std::size_t oldAttempts = attempts;
|
||||
const std::size_t oldReleases = releases;
|
||||
observedOutput = &output.value;
|
||||
expectedAtRelease = status == 0 ? expected : 0xcafebeef;
|
||||
Require(tls_config_parse_protocols_nid_postfix(&output.value, input) == status);
|
||||
observedOutput = nullptr;
|
||||
Require(output.value == (status == 0 ? expected : 0xcafebeef));
|
||||
Require(output.before == 0x12345678 && output.after == 0x87654321);
|
||||
Require(!input || saved == input);
|
||||
Require(attempts == oldAttempts + (input ? 1 : 0));
|
||||
Require(releases == oldReleases + (input && !failAllocation ? 1 : 0));
|
||||
Require(live == nullptr);
|
||||
if (input && !failAllocation) Require(liveSize == saved.size() + 1);
|
||||
}
|
||||
|
||||
void KnownCases() {
|
||||
Check(nullptr, 0, 0x18);
|
||||
const std::array<std::pair<const char*, std::uint32_t>, 24> good{{
|
||||
{"all", 0x18}, {"legacy", 0x18}, {"default", 0x18}, {"secure", 0x18}, {"tlsv1", 0x18},
|
||||
{"tlsv1.0", 2}, {"tlsv1.1", 4}, {"tlsv1.2", 8}, {"tlsv1.3", 16},
|
||||
{" \tTlSv1.2", 8}, {"!tlsv1.3", 8}, {"!tlsv1.2", 16}, {"!all", 0},
|
||||
{"tlsv1.0,tlsv1.1:tlsv1.2,tlsv1.3", 30}, {"all:!tlsv1.2", 16},
|
||||
{"all:!tlsv1.3", 8}, {"all,!all", 0}, {"!all,!tlsv1.2", 16},
|
||||
{"tlsv1.0,!tlsv1.0,!tlsv1.3", 8}, {"!all,!all", 0},
|
||||
{"tlsv1.0:!secure", 2}, {"!tlsv1.0", 24}, {"tlsv1.2,tlsv1.2", 8},
|
||||
{"\t!default:TLSV1.1", 4}
|
||||
}};
|
||||
for (const auto& [input, expected] : good) Check(input, 0, expected);
|
||||
const std::array bad{"", " ", "\t", "!", "!!all", "! all", "!\tall", "all ", "all\t", "all\n", "\nall", "\rall", "\vall", "\fall", "tlsv1.4", "tlsv1.20", "tlsv1.2x", "TLSv2", "sslv3", "none", "0x18", "*", ",all", "all,", "all::tlsv1.2", "all,,tlsv1.3", "all: \t", "all:bad", "tlsv1.2;tlsv1.3", "tlsv1.2 tlsv1.3", "all:!tlsv1.2:bad", "\xc2\xa0" "all"};
|
||||
for (const auto* input : bad) Check(input, -1, 0);
|
||||
failAllocation = true;
|
||||
Check(nullptr, 0, 0x18);
|
||||
for (const auto& [input, expected] : good) Check(input, -1, 0);
|
||||
for (const auto* input : bad) Check(input, -1, 0);
|
||||
failAllocation = false;
|
||||
}
|
||||
|
||||
struct Term { std::string_view text; std::uint32_t bits; bool remove; };
|
||||
constexpr std::array<Term, 18> Terms{{
|
||||
{"all",24,false},{"legacy",24,false},{"default",24,false},{"secure",24,false},{"tlsv1",24,false},
|
||||
{"tlsv1.0",2,false},{"tlsv1.1",4,false},{"tlsv1.2",8,false},{"tlsv1.3",16,false},
|
||||
{"!all",24,true},{"!legacy",24,true},{"!default",24,true},{"!secure",24,true},{"!tlsv1",24,true},
|
||||
{"!tlsv1.0",2,true},{"!tlsv1.1",4,true},{"!tlsv1.2",8,true},{"!tlsv1.3",16,true}
|
||||
}};
|
||||
|
||||
std::uint32_t Expected(const std::array<Term, 3>& terms) {
|
||||
std::array<bool, 4> enabled{};
|
||||
for (const auto& term : terms) {
|
||||
if (term.remove && enabled == std::array<bool, 4>{}) enabled = {false, false, true, true};
|
||||
for (std::size_t bit = 0; bit < enabled.size(); ++bit) {
|
||||
if (term.bits & (2u << bit)) enabled[bit] = !term.remove;
|
||||
}
|
||||
}
|
||||
std::uint32_t mask = 0;
|
||||
for (std::size_t bit = 0; bit < enabled.size(); ++bit) if (enabled[bit]) mask += 2u << bit;
|
||||
return mask;
|
||||
}
|
||||
|
||||
void Combinations() {
|
||||
for (const auto& first : Terms) for (const auto& second : Terms) for (const auto& third : Terms) {
|
||||
std::string input = std::string(first.text) + ", \t" + std::string(second.text) + ":\t" + std::string(third.text);
|
||||
for (std::size_t i = 0; i < input.size(); ++i) if ((i & 1) && input[i] >= 'a' && input[i] <= 'z') input[i] -= 'a' - 'A';
|
||||
Check(input.c_str(), 0, Expected({first, second, third}));
|
||||
}
|
||||
}
|
||||
|
||||
void CasePermutations() {
|
||||
for (std::size_t term = 0; term < 9; ++term) {
|
||||
std::string word(Terms[term].text);
|
||||
for (unsigned mask = 0; mask < (1u << word.size()); ++mask) {
|
||||
std::string input(word);
|
||||
for (std::size_t index = 0; index < word.size(); ++index) if ((mask & (1u << index)) && word[index] >= 'a' && word[index] <= 'z') input[index] -= 'a' - 'A';
|
||||
Check(input.c_str(), 0, Terms[term].bits);
|
||||
}
|
||||
}
|
||||
for (unsigned byte = 1; byte < 256; ++byte) {
|
||||
std::string input(1, static_cast<char>(byte));
|
||||
input += "all";
|
||||
if (byte == ' ' || byte == '\t') Check(input.c_str(), 0, 24);
|
||||
else if (byte == '!') Check(input.c_str(), 0, 0);
|
||||
else Check(input.c_str(), -1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Boundaries() {
|
||||
std::string longList;
|
||||
for (int index = 0; index < 1024; ++index) longList += "tlsv1.0,!tlsv1.0,";
|
||||
longList += "!tlsv1.2";
|
||||
Check(longList.c_str(), 0, 16);
|
||||
longList += ",bad";
|
||||
Check(longList.c_str(), -1, 0);
|
||||
const std::array<char, 10> embedded{'a','l','l','\0',',','b','a','d','\0','x'};
|
||||
Check(embedded.data(), 0, 24);
|
||||
std::array<std::uint32_t, 8> alias{};
|
||||
auto* text = reinterpret_cast<char*>(alias.data());
|
||||
std::memcpy(text, "tlsv1.0,!tlsv1.0,!tlsv1.2", sizeof("tlsv1.0,!tlsv1.0,!tlsv1.2"));
|
||||
const auto before = alias;
|
||||
Require(tls_config_parse_protocols_nid_postfix(&alias[1], text) == 0);
|
||||
Require(alias[1] == 16);
|
||||
for (std::size_t i = 0; i < alias.size(); ++i) if (i != 1) Require(alias[i] == before[i]);
|
||||
for (const auto* input : std::array<const char*, 3>{nullptr, "all", "bad"}) {
|
||||
const auto oldAttempts = attempts;
|
||||
bool caught = false;
|
||||
try { tls_config_parse_protocols_nid_postfix(nullptr, input); }
|
||||
catch (const std::invalid_argument&) { caught = true; }
|
||||
Require(caught && attempts == oldAttempts && live == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::array<void*, 10> api{
|
||||
reinterpret_cast<void*>(Allocate_nid_no_patch), reinterpret_cast<void*>(Release_nid_no_patch), reinterpret_cast<void*>(UnexpectedCalloc_nid_no_patch),
|
||||
reinterpret_cast<void*>(UnexpectedRealloc_nid_no_patch), reinterpret_cast<void*>(UnexpectedAlign_nid_no_patch), reinterpret_cast<void*>(UnexpectedRealign_nid_no_patch),
|
||||
reinterpret_cast<void*>(UnexpectedPosixAlign_nid_no_patch)};
|
||||
ApplicationHeapRegister_nid_no_patch(api.data());
|
||||
KnownCases();
|
||||
Combinations();
|
||||
CasePermutations();
|
||||
Boundaries();
|
||||
Require(live == nullptr);
|
||||
std::printf("TLS protocol parser: %zu cases, %zu checks, %zu releases, zero live allocations\n", cases, checks, releases);
|
||||
}
|
||||
@@ -38,11 +38,15 @@
|
||||
|
||||
- [ASN1_TIME_diff](../../../core/libs/prx/libSceLibreSsl3/src/Time.cpp) has no console ABI or behavior verification. Its signature and date rules follow LibreSSL 4.0.0 [a_time.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time.c), [a_time_tm.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time_tm.c) and [a_time_posix.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time_posix.c), using the existing 24-byte string layout. Null inputs use the host wall clock; the console clock relationship is unverified. Null output pointers throw after valid input parsing, where the reference dereferences them. Closes when: measured on a PS5.
|
||||
|
||||
- [tls_config_parse_protocols](../../../core/libs/prx/libSceLibreSsl3/src/TlsProtocols.cpp) has no independent console execution or TLS configuration interoperability verification. Parsing follows [LibreSSL 4.0.0](https://github.com/libressl/openbsd/tree/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libtls). A null output pointer throws instead of an upstream fault. Tests use caller-owned text/output and guest-heap allocation failure; other TLS configuration and handshake exports remain unimplemented. Closes when: console grammar and TLS configuration interoperability are measured.
|
||||
|
||||
- [Reported firmware 13.42 parser masks](../../../core/libs/prx/libSceLibreSsl3/src/TlsProtocols.cpp) come from a [contributor's disassembly](https://github.com/boykopovar/AnyPS5/pull/15045#pullrequestreview-5736573950) of `libSceLibreSsl3.sprx` (SHA-256 `ee2c529c87fe21b7ef1e5f13d10c47ee90944f52a1f848fe0995e031817c2c3a`), not independent execution here. The report identifies default/aggregate/negation-base mask `0x18` and explicit TLS 1.0/1.1/1.2/1.3 bits `2`/`4`/`8`/`16`, matching this implementation. Other firmware revisions, complete grammar and real TLS configuration use remain unverified.
|
||||
|
||||
- [EVP_PKEY_size, EVP_PKEY_security_bits and EVP_PKEY_cmp](../../../core/libs/prx/libSceLibreSsl3/src/PkeyQueries.cpp) have no console ABI or behavior verification. Dispatch follows [LibreSSL 4.0.0](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/evp/p_lib.c) using the existing 32-byte key and the LP64 method slots in that revision's `evp_local.h`: public comparison at 56, size at 96, security bits at 112 and parameter comparison at 160. Tests use caller-owned keys and callbacks; real key-constructor and algorithm-method interoperability remains unverified. Null comparison operands, undefined upstream, throw; null size/security queries and missing callbacks keep upstream's distinct results. Malformed method pointers remain unverified. Closes when: layouts and complete key lifetimes are measured on a console.
|
||||
|
||||
### Additional callable export inventory
|
||||
|
||||
- [Additional exports](../../../core/libs/prx/libSceLibreSsl3/AdditionalExports.cpp) declare 166 remaining callable exports: 156 named and 10 known only by NID. Every entry throws. Parameterless `int` declarations are unknown-signature placeholders, not verified ABI contracts. Names/NIDs match the 13.60 export table. No functional implementation or title unblock is claimed.
|
||||
- [Additional exports](../../../core/libs/prx/libSceLibreSsl3/AdditionalExports.cpp) declare 165 remaining callable exports: 155 named and 10 known only by NID. Every entry throws. Parameterless `int` declarations are unknown-signature placeholders, not verified ABI contracts. Names/NIDs match the 13.60 export table. No functional implementation or title unblock is claimed.
|
||||
|
||||
| Name | NID |
|
||||
| --- | --- |
|
||||
@@ -199,7 +203,6 @@
|
||||
| `d2i_ASN1_SEQUENCE_ANY` | `vR0po3nBkBs` |
|
||||
| `PKCS5_PBKDF2_HMAC` | `vnwZHU5FvBQ` |
|
||||
| `ASN1_OCTET_STRING_free` | `vo-cv5gnPUA` |
|
||||
| `tls_config_parse_protocols` | `vu4FgwGayHY` |
|
||||
| `SSL_CTX_set_post_handshake_auth` | `wHdymWL7CbE` |
|
||||
| `tls_config_insecure_noverifyname` | `wNQT6Zn4UG4` |
|
||||
| `X509_EXTENSION_free` | `wbJDMMsje6s` |
|
||||
@@ -213,7 +216,7 @@
|
||||
| `ECDSA_SIG_get0` | `z8fsXF8JuL0` |
|
||||
| `EVP_MD_block_size` | `zCa75KLWWn4` |
|
||||
|
||||
- 107 of the 126 exports the 13.60 table lists only by NID carry, in the table above and in [Additional exports](../../../core/libs/prx/libSceLibreSsl3/AdditionalExports.cpp), the LibreSSL names whose `tools/nid_names.py` hash equals the NID; the names were taken from the identifiers of the LibreSSL 3.8.4 and 4.0.0 `include`, `crypto`, `ssl` and `tls` sources. A name match does not show that the console function has LibreSSL's prototype or behavior; each keeps the no-parameter import-resolution convention and throws through `NotImplemented_nid_no_patch`. `AES_wrap_key`, `ECDSA_SIG_free`, `ECDSA_do_verify`, `ERR_load_ERR_strings`, `ERR_print_errors_fp` and `i2d_PUBKEY` also hash to the NIDs of six `unknown` rows, which keep their NID names; `PBYz0kpXwg8` hashes to no identifier of those sources.
|
||||
- 106 of the 126 exports the 13.60 table lists only by NID carry, in the table above and in [Additional exports](../../../core/libs/prx/libSceLibreSsl3/AdditionalExports.cpp), the LibreSSL names whose `tools/nid_names.py` hash equals the NID; the names were taken from the identifiers of the LibreSSL 3.8.4 and 4.0.0 `include`, `crypto`, `ssl` and `tls` sources. A name match does not show that the console function has LibreSSL's prototype or behavior; each keeps the no-parameter import-resolution convention and throws through `NotImplemented_nid_no_patch`. `AES_wrap_key`, `ECDSA_SIG_free`, `ECDSA_do_verify`, `ERR_load_ERR_strings`, `ERR_print_errors_fp` and `i2d_PUBKEY` also hash to the NIDs of six `unknown` rows, which keep their NID names; `PBYz0kpXwg8` hashes to no identifier of those sources.
|
||||
|
||||
### Functional
|
||||
|
||||
|
||||
Reference in new issue
Block a user