tls: the peer's certificate from a TlsStream #116
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Channel binding and certificate pinning. Listed among what
stdis missing for the first-party packages.Source
Acceptance criteria
Dependencies
None known.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), source FIRST-PARTY.md gap 18, not a duplicate. No dependencies. next: waiting (refine queued, ready buffer full) until 2026-10-10T04:00:00Z
[loop:torbscript] claim refine by session:loop-torbscript-20261024 until 2026-10-24T07:39:00Z
Refinement: scope narrowed to step 1 of 2 (the runtime function and its natives row)
FIRST-PARTY.md gap 18 needs a new native,
tlsPeerCertificate.CLAUDE.md"Seed and breaking changes": a new native takes two commits, the second only after a published seed knows the first (the pattern of #362 / #363). So this issue is commit 1: the runtime function, the header, the natives row. Thestd/tlsdeclaration, theTlsStreammethod, its tests and the docs are #463, ordered after this issue and the next published seed.[loop:torbscript] decided by the loop: native shape
int64_t torb_tls_peer_certificate(int64_t session, torb_list *into)appends the DER and answers the length (0 = none), the same shape astorb_tls_take_outgoing/torb_tls_read(the list is the caller's, no new ownership rule). The bytes come frommbedtls_ssl_get_peer_cert;MBEDTLS_SSL_KEEP_PEER_CERTIFICATEis on in the vendoredmbedtls_config.h, so no config change. Leaf certificate only (whattls-server-end-pointand pinning use); the chain is not needed. Naming follows thetls*natives. No owner question: internal technical design, no published contract changes.Requirements
runtime/include/torb_tls.h:int64_t torb_tls_peer_certificate(int64_t session, torb_list *into);with a doc comment (DER of the certificate the peer sent, leaf, appended to*intoa list ofUInt8; the number of bytes, 0 where the session is unknown, the handshake is not done, or the peer sent none).runtime/tls/tls.c: the body undertorb_tls_lockliketorb_tls_protocol: look up the session,mbedtls_ssl_is_handshake_over,mbedtls_ssl_get_peer_cert,torb_list_add_plain(into, cert->raw.p, cert->raw.len). Works with the platform verifier on Windows too (the certificate is parsed by mbedTLS either way).compiler/src/backend/c/natives.trb: atlsRuntimeOf("tlsPeerCertificate", ...)entry intlsEntrieswith the prototype of the header; the VM thunk comes from the same manifest.docs/design/NATIVES.md: a rowtlsPeerCertificate | Runtime | keep | tls | - | - | -and the counts of the table updated (the audit test checks that every manifest entry has a row and the counts match).std/(a declaration there would break the seed's bootstrap), nothing underseed/,tests/conformance/.Acceptance criteria
compiler/tests/natives.test.trb(the audit) passes with the new row and counts.runtime/tests/tls_test.c(it hastls_certificates.h): after a loopback handshake of a client and a server session, the client'storb_tls_peer_certificatereturns the length of the server's leaf and the bytes equal the DER of the first block of the test chain (decode in the test); the server's returns 0 (no client certificate); a session before the handshake and an unknown handle return 0.runtime/touched).seedworkflow or the nightly). Not part of this PR; #463 stays notreadyuntilseeds.txtlists a seed at or after the merge commit.Seed impact
Yes: a new native. This is commit 1 of the two-commit rule; the declaration is #463.
Size
One PR, about 1 h: one Conventional Commit
feat(tls): the peer certificate of a session, and its natives row(two if the test file is split out). Source: gap 18; design record NETWORK.md section 5 (TLS as a state machine over bytes), ROADMAP std/tls. No conflict with #117 (client certificates) or #118 (ALPN): different natives.[loop:torbscript] refine: split by the two-commit rule: #116 is step 1 (runtime function, header, natives row; requirements and acceptance above), step 2 is #463 (std/tls declaration,
TlsStream.peerCertificate(), tests, docs, gap 18 done) and waits for a published seed after #116's merge; labelreadyset on #116. Tokens: ~0.2M. next: implement[loop:torbscript] claim implement by session:loop-torbscript-20261024 until 2026-10-24T07:48:27Z
[loop:torbscript] implement: PR 464 (
57ea45b2), next: waiting (forge CI of57ea45b2)Buffer.holdsClose(step 2 of #55, commit 1 of 2) #468Buffer.holdsClose(step 2 of #55, commit 1 of 2) #468