Repository navigation
feat(libSceSsl): apply the verify options, run the verify callback, add ALPN, non-blocking sockets and sceSslClose - #7626
Conversation
…dd ALPN, non-blocking sockets and sceSslClose sceSslConnect verifies the server's chain under MBEDTLS_SSL_VERIFY_OPTIONAL and returns the first failure the connection's verify options select, with the SSL_ERROR_* codes KytyPS5 lists. The initial options are all five checks, so a connection whose title never sets them fails closed: with no CA loaded it returns SSL_ERROR_UNKNOWN_CA instead of throwing. The result is final for the connection: a failure sends close_notify, later sceSslConnect calls return the same code, and sceSslRead and sceSslWrite throw. A verify callback runs once after the handshake, outside the session lock, with the connection id, that code, handles to a copy of the peer chain that the context's certificate readers accept, the chain length and the user argument; a negative return fails the connect with SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK. The ALPN list set with sceSslSetAlpn is split on commas and offered, sceSslGetAlpnSelected returns the protocol the server chose, and the minimum version floors the handshake at TLS 1.2. A socket that would block returns SSL_ERROR_WANT_POLLIN or WANT_POLLOUT from connect, read and write and the next sceSslConnect resumes the handshake; the BIO maps a reset to MBEDTLS_ERR_NET_CONN_RESET, which returns SSL_ERROR_SOCKET_CLOSED, and tells a blocking socket's expired receive timeout, which returns SSL_ERROR_READ_TIMEOUT, apart from a non-blocking would-block. sceSslClose sends close_notify once and marks the connection closed. The debt entry records the default options and the situation-to-code choices as unverified and drops the title IDs.
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Linux CI (run 39151593422) fails The server resets the socket ( Could the server wait until the client has finished its handshake before resetting? For example: after |
…is done The Serve::Reset case closed with linger 0 as soon as the server's handshake returned, while the client could still be reading the last flight; on Linux the RST discards unread data, so sceSslConnect reported the closed socket instead of 0. The server now reads one byte the client writes after its sceSslConnect and resets after it.
|
@oneandonlydean that reading is right, thanks. The server reset as soon as its own handshake returned, while the client could still be reading the last flight, and the RST discarding that unread data is a Linux behaviour the Windows run did not show. 51d0cb9 does what you describe: after On the 4090 box (Windows 11, WinLibs GCC 15.2.0, Release): AI-assisted: yes (Claude Code). |
What
The follow-up oneandonlydean asked for on #7319 and loyalburrito reviewed on loyalburrito#3, on top of #6828's
Sessiondesign, with that review's four points taken:MBEDTLS_SSL_VERIFY_OPTIONALandsceSslConnectreturns the first failure the connection's verify options select, with SharpProspero'sSceSslVerifyOptionbits and the codes KytyPS5's errno list gives:SSL_ERROR_UNKNOWN_CA0x8095F00C,CN_CHECK0x8095F00B,NOT_AFTER_CHECK0x8095F00D,NOT_BEFORE_CHECK0x8095F00E,INVALID_CERT0x8095F00A for any other X.509 fault. The initial options are all five checks (0x3D), so a title that never callssceSslEnableVerifyOptionfails closed: with no CA loaded a default connection returnsSSL_ERROR_UNKNOWN_CAinstead of throwing. The result is final for the connection: a failure sends close_notify, a repeatedsceSslConnectreturns the same code,sceSslRead/sceSslWritethrow; a repeatedsceSslConnectafter success returns 0.sceSslGetSubjectNameand the other readers on the connection's context accept, the chain length and the user argument. A negative return fails the connect withSSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK(0x8095F0FD); any other return accepts the connection. The callback can use the connection (sceSslGetAlpnSelected,sceSslClose,sceSslDeleteConnection); asceSslConnectfrom inside it, or from another thread while it runs, throws.sceSslSetAlpn's string is split on commas and offered;sceSslGetAlpnSelectedreturns the server's choice, null before the handshake or when nothing was selected. Every acceptedSceSslVersionfloors the handshake at TLS 1.2, all this build speaks.MBEDTLS_ERR_SSL_WANT_READ/WANT_WRITEreturnSSL_ERROR_WANT_POLLIN/WANT_POLLOUT(0x8095F013/14) from connect, read and write; the nextsceSslConnectresumes the handshake; a write that blocks after sending part of the buffer returns the part sent.Send/ReceivemapECONNRESET/EPIPEandWSAECONNRESET/WSAECONNABORTED/WSAENETRESETtoMBEDTLS_ERR_NET_CONN_RESET, which with a stream that ends without close_notify returnsSSL_ERROR_SOCKET_CLOSED(0x8095170D). A blocking socket's expired receive timeout (EAGAINon a socket withoutO_NONBLOCK,WSAETIMEDOUTon Windows) is told apart from a non-blocking would-block and returnsSSL_ERROR_READ_TIMEOUT(0x80951710) from connect and read; the call can be repeated. An expired send timeout throws, as no write timeout code is known. A fatal alert returnsSSL_ERROR_FATAL_ALERT(0x8095F010). When one of these ends the handshake the session is dropped and the nextsceSslConnectstarts over.sceSslClose. Sends close_notify once if the handshake completed, marks the connection closed (later connect, read and write throw) and leaves the socket to the title; returns 0 on a connection that never connected, already failed verification or was already closed.ssl_flags0xA7); the situation-to-code choices are listed as inferred from KytyPS5's names:WANT_POLLIN/WANT_POLLOUTrather thanSSL_ERROR_EAGAIN,SOCKET_CLOSEDrather thanSSL_ERROR_EOFfor a stream cut short,READ_TIMEOUT,FATAL_ALERT,INVALID_CERTas the catch-all, a repeatedsceSslConnectreturning the first result; and the callback's unknowns (which id, code or failed bits, element type, when it runs, whether a non-negative return overrides). The two title IDs the verify option entry named are removed; the entry text is otherwise rewritten around what the code now does.Unchanged from #6828: the
Sessionstruct and its locks, the pool allocator,KernelLookupSocketNative_nid_no_patch,sceSslDeleteConnection(no close_notify, socket stays open), the throws for unknown flags, null buffers, descriptors that are not sockets and other handshake failures.Tested
Windows 11 26200, WinLibs MinGW-w64 GCC 15.2.0 posix-seh ucrt r7, Release,
BUILD_TESTING=ON, on f03a2da + this commit:guest_ssl_transport_kernelandguest_ssl_transport_netrewritten around the new behaviour, 5 runs each, all passing: a connection on a context with no CA and untouched options returnsSSL_ERROR_UNKNOWN_CAtwice, read throws,sceSslClosereturns 0; withSERVER_VERIFYdisabled the same connection returns 0 and reads to the server's close_notify; a verify callback on that context receives the connection id,SSL_ERROR_UNKNOWN_CA, one peer handle whose subject readsCN=localhostthroughsceSslGetSubjectName/sceSslGetNameEntryInfo, returns 0 and the connection becomes readable, and the peer handle throws once the connection is deleted; a certificate for another host returnsSSL_ERROR_CN_CHECKtwice, 0 withCN_CHECKdisabled; a callback returning -1 on a passing chain gets code 0 and the connect returnsSSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECKtwice;SetMinSslVersion(TLS 1.2)+SetAlpn("h2,http/1.1")handshakes,GetAlpnSelectedishttp/1.1after and null before, a second connect returns 0,sceSslClosereturns 0 after the exchange, read and connect throw after it, a second close returns 0, pool memory returns and the socket stays open; a guest socket made non-blocking (SO_NBIOon libSceNet, the libkernel equivalent) handshakes throughWANT_POLLIN/WANT_POLLOUTrounds, read with nothing pending returnsWANT_POLLIN, then ping/pong and the close_notify arrive; a server that closes without close_notify ends the read with 0; a server that resets (linger 0) returnsSSL_ERROR_SOCKET_CLOSED; on the libSceNet table a 200 msSO_RCVTIMEOreturnsSSL_ERROR_READ_TIMEOUTfrom a read with nothing pending and the connection then exchanges ping/pong normally;sceSslCloseon a connection that never connected returns 0; four parallel connections unchanged.guest_ssl,guest_ssl_load,guest_memory_pool_statspass.python3 tools/check_conventions.py --base mainpasses.HostReset/HostTimedOutand the test'sclose/fcntlpaths are compiled only there), a send timeout, and a title.Checklist
main; no other open PR implements the same functions (feat(ssl): implement context-scoped PS5 certificate PEM reading #6511 addssceSslGetPemin the same file and does not touch these calls)NotImplemented_nid_no_patch); silent stubs are listed in the technical debt file.mdfiles or images added to the repositoryr14+0x48) while the title's video-out/flip frame-pacing loop runs #6350 (the libSceSsl configuration calls GT7 makes beforesceSslConnect)