Files
AnyPS5/docs/dev/debt/libSceSsl.md
T

13 KiB

libSceSsl technical debt

Unknown function info

  • sceSslCreateConnection, sceSslDeleteConnection, sceSslSetVerifyCallback, sceSslConnect, sceSslRead, sceSslWrite (libSceSsl) - imported by ffmpeg.prx. Signatures follow SharpProspero, which also says the socket stays open after sceSslDeleteConnection and that sceSslRead returns 0 at the end of the stream. An unknown context returns SSL_ERROR_INVALID_ID (0x8095F006), as sceSslGetMemoryPoolStats does on the console and as KytyPS5 and sharpemu return for other context calls; for an unknown connection, a connection whose context was terminated and a null host the console's codes are unknown, so these throw. sceSslConnect runs a TLS 1.2 client handshake with Mbed TLS 3.6.7 over the host socket that the guest number maps to in the libkernel or libSceNet socket table, and sceSslRead and sceSslWrite carry application data over it. TLS 1.3 is compiled out: SharpProspero's SceSslVersion ends at TLS 1.2, and Mbed TLS 1.3 needs PSA crypto state that is process-wide rather than allocated from a context's pool. Connection state is allocated from the context's pool and returned to it by sceSslDeleteConnection; a connection keeps the pool alive after sceSslTerm. The server's chain is checked against the CAs loaded with sceSslLoadCert, its validity dates and the host name the connection was created with, which is also sent as SNI, and sceSslConnect returns the first failure the connection's verify options select (the verify option entry below lists the bits and codes); no root bundle is shipped and the console's built-in roots are unknown, so with no CA loaded a connection with the initial options returns SSL_ERROR_UNKNOWN_CA (0x8095F00C). A client certificate loaded with sceSslLoadCert is sent when the server asks for one. The result of the first completed sceSslConnect is final for the connection: a failure sends close_notify, later sceSslConnect calls return the same code, and sceSslRead and sceSslWrite throw. With a verify callback set it is called once after the handshake, outside the connection's lock, with the connection id, that code (0 when the chain passed), handles to a copy of the peer chain that the certificate readers of the connection's context accept until the connection is deleted (the handles stay registered in the context until it is terminated), the chain length and the user argument; a negative return fails the connect with SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK (0x8095F0FD) and any other return accepts the connection whatever the code was, following SharpProspero's "a negative return fails the handshake" (https://github.com/SvenGDK/SharpProspero/blob/60977b29103452b9681ae10c7a9011d44965bf16/src/SharpProspero/Interop/Net/Http.cs#L195-L252). Whether the id is the context or the connection, whether the second argument is that code or the bits of the failed checks, the chain element type, when the console runs the callback and whether a non-negative return overrides a failed check are unknown. A sceSslConnect from inside the callback, or from another thread while it runs, throws. A non-blocking socket that would block returns SSL_ERROR_WANT_POLLIN (0x8095F013) or SSL_ERROR_WANT_POLLOUT (0x8095F014) from sceSslConnect, sceSslRead and sceSslWrite; the next sceSslConnect resumes the handshake, and sceSslWrite returns the part it sent before blocking. A blocking libSceNet socket whose SO_RCVTIMEO expires returns SSL_ERROR_READ_TIMEOUT (0x80951710) from sceSslConnect and sceSslRead, and the call can be repeated; one whose SO_SNDTIMEO expires throws, as no write timeout code is known. libkernel keeps its timeouts above the host socket, so they do not bound SSL reads and writes on a libkernel socket. A reset (ECONNRESET, EPIPE, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET) returns SSL_ERROR_SOCKET_CLOSED (0x8095170D), as does a transport that ends without close_notify during the handshake, and a fatal alert returns SSL_ERROR_FATAL_ALERT (0x8095F010); when one of these ends the handshake the session is dropped and the next sceSslConnect starts over. Which situation returns which code is inferred: KytyPS5 gives the names and values but not when the console returns them, so WANT_POLLIN and WANT_POLLOUT rather than SSL_ERROR_EAGAIN (0x8095F00F) for a socket that would block, SOCKET_CLOSED rather than SSL_ERROR_EOF (0x8095177C) for a handshake cut short, READ_TIMEOUT for an expired receive timeout, FATAL_ALERT for a fatal alert, INVALID_CERT (0x8095F00A) for a verification failure no option names, and a repeated sceSslConnect returning the first result, 0 included, rather than an error are all unverified on a console. Other handshake and socket failures, a read or write before the handshake, after a failed verification or after sceSslClose, a descriptor that is not a socket, a null buffer, write flags other than 0 and read flags other than 0 and MsgFlagPartialRead (1) throw, as their console codes are unknown; MsgFlagPeek (3) is not implemented. sceSslRead returns what one Mbed TLS read delivers, up to len, with flags 0 and with MsgFlagPartialRead alike; SharpProspero describes sceSslRead as reading up to len but MsgFlagPartialRead as returning before the buffer is full, so whether flags 0 waits to fill the buffer is unknown. It returns 0 after the server's close_notify and also when the transport ends without one, as Mbed TLS reports both as the end of the stream. sceSslWrite sends all of len, capped at INT_MAX, and returns the count. A connection serializes its reads and writes, so a read blocked in one thread holds back a write on the same connection from another. sceSslDeleteConnection sends no close_notify. The socket is not checked when the connection is created, sceSslTerm leaves the context's connections to sceSslDeleteConnection, and sceSslSetVerifyCallback accepts any callback, null included, and returns 0. None of this is verified on the console. SSL_ERROR_BEFORE_INIT (0x8095F001) is never returned, as the library keeps no state apart from its contexts
  • sceSslClose (libSceSsl) - takes the connection id, as in SharpProspero. It sends close_notify once if the handshake completed, marks the connection closed so later sceSslConnect, sceSslRead and sceSslWrite throw, and leaves the socket to the title; on a connection that never connected, already failed verification or was already closed it returns 0. Whether the console closes the socket, what it returns for a connection that was never connected, and what happens when a non-blocking socket cannot take the close_notify at once (it is not retried) are unknown
  • sceSslGetSerialNumber, sceSslGetSubjectName, sceSslGetIssuerName, sceSslGetNameEntryCount, sceSslGetNameEntryInfo, sceSslFreeSslCertName, sceSslGetNotBefore, sceSslGetNotAfter, sceSslGetFingerprint (libSceSsl) - signatures and context ownership follow SharpProspero, with hash types matching its SceSslFingerprintHashAlgorithm enum. Operations take a context handle as their first argument and operate on certificate and name handles scoped to that context. sceSslGetSerialNumber copies into a caller-allocated output buffer or queries the required length when the buffer is null or capacity is zero; a buffer smaller than the serial number returns SSL_ERROR_INVALID_ARG (0x8095177a). Mbed TLS parses the certificate's serial number, validity period (converted to microseconds since Gregorian year 0001 epoch), fingerprint digests and X.509 subject and issuer distinguished names, extracting OID attribute short names (or numeric strings) and value strings. An unknown context, unknown or expired certificate handle or invalid certificate name handle throws; null output pointers, unsupported hash types or out-of-range entry indices return SSL_ERROR_INVALID_ARG (0x8095177a). The error codes, the zero-capacity length query, the NUL-terminated truncation of name entry strings with the full value length in valueLen, and the lifetime of name handles (released only by sceSslFreeSslCertName or when the context is terminated) have not been measured on a PS5
  • sceSslLoadCert, sceSslGetCaList, sceSslFreeCaList, sceSslGetCaCerts, sceSslFreeCaCerts, sceSslUnloadCert (libSceSsl) - signatures and layouts follow SharpProspero. PPSA15508/01.002.000 calls sceSslLoadCert with one 1,408-byte PEM CA and null client certificate/key arguments; this confirms that call shape, not console error behavior. Mbed TLS 3.6.7 parses DER/PEM chains and checks an optional client certificate/key pair. Imports are retained per context and committed together; a failed import preserves existing credentials. CA queries return independently owned snapshots; unload clears active credentials while outstanding snapshots remain valid. Appending repeated CA imports, snapshot lifetime across unload, memory overhead and error precedence have not been measured on a PS5. Invalid loads, malformed material, exhausted pools and unsupported keys throw rather than inventing console error codes. No root bundle is shipped; an empty context still returns NOT_FOUND. The existing null-list error, unknown-context behavior and legacy clearing of foreign raw CA lists remain unchanged. Certificate reader queries reflect active certificates or outstanding snapshots. Loading credentials does not start a TLS connection; sceSslConnect verifies the server against the loaded CAs and offers the loaded client certificate
  • sceSslEnableVerifyOption, sceSslDisableVerifyOption, sceSslSetMinSslVersion, sceSslSetAlpn, sceSslGetAlpnSelected (libSceSsl) - signatures follow SharpProspero, the source of the other connection signatures. The verify options select which verification failures sceSslConnect reports (see the connection entry above), with the bit values SharpProspero's SceSslVerifyOption gives: SERVER_VERIFY 0x1, CN_CHECK 0x4, NOT_AFTER_CHECK 0x8, NOT_BEFORE_CHECK 0x10, KNOWN_CA_CHECK 0x20. The initial options are all five checks (0x3D), so a connection whose title never calls these fails closed; what the console starts with is unknown, and the one source, the HTTPS layer of KytyPS5, starts its libSceHttp connections with ssl_flags 0xA7 (SERVER_VERIFY, CLIENT_VERIFY, CN_CHECK, KNOWN_CA_CHECK, SNI), evidence that verification is on by default rather than for these bits. A check that is disabled is not reported, whatever the chain. sceSslSetMinSslVersion accepts the SceSslVersion values SharpProspero lists, 0 (none) to 5 (TLS 1.2), and throws for others; whether the console accepts a TLS 1.3 value is unknown. Every accepted value gives the same handshake, as Mbed TLS 3 speaks TLS 1.2 and nothing older and TLS 1.3 is compiled out. sceSslSetAlpn stores the string up to its terminator and throws for a null list; it is split on commas into the protocols offered in the handshake, as HTTP libraries write ALPN lists, and whether the console expects that or the TLS wire format is unknown. sceSslGetAlpnSelected returns the protocol the server selected, or null before the handshake and when none was selected; the pointer is owned by the connection. An unknown connection and a connection whose context was terminated throw, as for sceSslSetVerifyCallback
  • sceSslGetPem (libSceSsl) - static inspection of PPSA28002 confirms the context-first four-argument call with a caller-owned buffer and an in/out 64-bit length. Mbed TLS serializes PEM including its trailing NUL. Buffers smaller than the required encoding throw; an unknown context or foreign or expired certificate handle throws. The exact console PEM length policy, error precedence and truncation behavior have not been measured on a PS5. Existing serial/name, validity and fingerprint readers and their documented uncertainties remain unchanged