loader: use the real crypto/tls on hosted linux and darwin - #5635
Open
yohimik wants to merge 2 commits into
Open
loader: use the real crypto/tls on hosted linux and darwin#5635yohimik wants to merge 2 commits into
yohimik wants to merge 2 commits into
Conversation
This was referenced Aug 30, 2026
The runtime had weak.runtime_registerWeakPointer but not its counterpart, so a program that reads a weak pointer back did not link. crypto/tls does this in the certificate cache that it keeps behind a weak.Pointer. Weak pointers are not weak here. registerWeakPointer returns the pointer that it got, so the value it refers to stays and the way back to a strong pointer is the identity too. weak.Pointer.Value thus never reports a collected value, which the documented contract permits. testdata/weak.go does not link on the current dev branch and prints the expected value with this change.
TinyGo replaces crypto/tls with a stub whose handshake does nothing, so a program that dials https gets a plaintext connection behind the TLS API. That stub is correct for a target with no OS below it, which has neither the code size for a full TLS implementation nor usually a socket to speak it over. Hosted linux and macOS have both, and there the crypto/tls of the Go standard library compiles and runs. Make the override conditional. Without an entry in the map, crypto/tls falls under the "crypto/" merge, which links the package of the standard library into the synthetic GOROOT. GOOS alone cannot decide this, because a baremetal target reports GOOS=linux, so the build tags decide as well. The goroot cache key is a hash of the merge links, so the two variants get separate cache entries. testdata/hostcryptotls.go does a TLS handshake over an in-memory pipe with a certificate that it makes at run time. On the current dev branch it prints "negotiated an unexpected version: 0", because the stub does no handshake. With this change the handshake completes, the data goes through, and a client that does not trust the certificate refuses it. loader/goroot_test.go covers the targets that keep the stub, the baremetal one that reports GOOS=linux included.
yohimik
force-pushed
the
upstream-pr/hosted-crypto-tls
branch
from
September 2, 2026 08:50
2d41706 to
4b2c48c
Compare
Author
|
Rebased on dev after the 0.42.0 release. The change applies on top of v0.42.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
loader: use the real crypto/tls on hosted linux and darwin
Depends on
upstream-pr/weak-strong-from-weak.What this does
TinyGo replaces
crypto/tlswith a stub whose handshake does nothing, so aprogram that dials
https://gets a plaintext connection behind the TLS API.That stub is correct for a target with no OS below it, which has neither the
code size for a full TLS implementation nor usually a socket to speak it over.
Hosted linux and macOS have both, and there the
crypto/tlsof the Go standardlibrary compiles and runs.
The override becomes conditional. Without an entry in the map,
crypto/tlsfalls under the
"crypto/"merge, which links the package of the standardlibrary into the synthetic GOROOT. GOOS alone cannot decide this, because a
baremetal target reports GOOS=linux, so the build tags decide as well. The
goroot cache key is a hash of the merge links, so the two variants get separate
cache entries.
Evidence
testdata/hostcryptotls.gomakes an ECDSA key and a self-signed certificate atrun time, then does a TLS handshake over
net.Pipe. It needs no network and nonetdev.
TestHostCryptoTLSinmain_test.goruns it on the host, and skipswhere the host is not linux or darwin, in the same way as
TestTimerStopResetRace.Measured on macOS 26.6 arm64.
negotiated an unexpected version: 0got: pongandunknown certificate refusedThe first row shows what the stub does. It reports a completed handshake and a
version of zero, and it does not verify anything. The second row shows a real
TLS 1.3 handshake, data through the connection, and a client with an empty root
pool refusing the certificate.
loader/goroot_test.gocovers the decision itself, with the baremetal case thatreports GOOS=linux.
A downstream product ships binaries built with these changes in a production
release. dispat v1.4.0 is published and is not a prerelease. It carries
dispat-tiny-linux-amd64anddispat-tiny-linux-arm64, built by the forkrelease v0.42.0-net.4 from sha256-pinned tarballs and smoke-executed under
binfmt before upload, beside six binaries from the gc toolchain.
https://github.com/yohimik/dispat/releases/tag/services%2Fdispat%2Fv1.4.0
The acceptance record of that repository is committed at
packages/docs/docs/internals/tinygo.md. It reports the net.2 to net.4acceptance history, an integration suite of 694 rows that passes with 0 failures
and 1 documented skip on darwin, and a size table of 0.58x to 0.63x against the
gc equivalents with TinyGo
-opt=z -no-debugagainstgo build -trimpath -ldflags "-s -w". Those figures come from that document. They are not ameasurement of this branch.
The self-update path of that program runs over real TLS against a live host, and
its suite has negative rows as well. An unknown CA is refused, and a plaintext
server on a TLS port is refused.
Scope and known gaps
nintendoswitch and every baremetal target. Their behaviour does not change.
crypto/tlssees a size change, and such aprogram did not work before.
crypto/x509on darwin uses the platform verifier, andcrypto/x509/internal/macosin TinyGo is a stub, so a nilRootCAsfails ondarwin.
net/httpin tinygo-org/net handles this by giving the client a rootpool. A caller that dials
tls.Dialdirectly on darwin has to supplyRootCAs. See the tinygo-org/net PR "net/http: give the HTTPS client trustroots on darwin".
http.Client.Timeoutis inert in the tinygo-org/net client. It is notaddressed here.
crypto/tlsAPI gaps such astls.X509KeyPair. This change makesthe real package available on hosted targets, so those gaps disappear there,
but the stub keeps them on every other target.
Related
constants, LoadX509KeyPair stubbed"
This is a smaller change than the netdev reworks in #4187, #4273 and #4498. It
does not replace the
netpackage or add a netpoller. It only stops thesubstitution of the TLS stub where the standard library package works.
Enables
A command line program that needs an HTTPS client path. Self-update, an API
client, a webhook sender. Client side only. There is no server claim here beyond
what the tests show.
Related pull requests
This change is part of one body of work. Together the changes make programs that use the network and child processes work on hosted linux and macOS. A full CLI was tested end to end with all of them and ships binaries built this way, see dispat v1.4.0 in the evidence section.
In this repository
In tinygo-org/net
A merge order that works. The three bug fixes are independent. #5633 goes before #5635. HTTPS on linux needs only #5633 and #5635. Full darwin support also needs #5636, the net changes and a new src/net submodule pin.