Skip to content

refactor: use package:boring for BoringSSL native assets and FFI bindings - #417

Draft
mosuem wants to merge 7 commits into
google:masterfrom
mosuem:use-package-boring
Draft

mosuem wants to merge 7 commits into
google:masterfrom
mosuem:use-package-boring

Conversation

@mosuem

@mosuem mosuem commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Switches package:webcrypto's native BoringSSL dependency and FFI bindings to package:boring ^0.4.0.

Key Changes

  • Build & C wrappers removed: Removes hook/build.dart and src/webcrypto.{c,h} in favor of package:boring's native asset build and link hooks (which fetch prebuilt binaries for desktop targets or build from source, and tree-shake unused BoringSSL symbols via @RecordUse() in AOT/release builds).
  • Bindings & symbol addresses: Replaces lib/src/boringssl/ with package:boring/bindings.dart, which exposes ssl.addresses.* (NativeFinalizerFunction pointers for all *_free / *_cleanup functions, annotated with @RecordUse() via SymbolAddresses).
  • NativeHandle<EVP_PKEY>: Replaces the custom _EvpPKey finalizer wrapper and its four .invoke reachability extensions with NativeHandle(pkey, ssl.addresses.EVP_PKEY_free) from package:boring.
  • BoringArena replaces _Scope: The internal _Scope arena, dataAsPointer, createCBS / createCBB, and CBB.copy() moved to package:boring as BoringArena (run, stream, using, move), copyBytes, cbs() / cbb(), and CBB.toBytes(). webcrypto keeps only a small create() extension that maps nullptr to OperationError. BoringArena.run releases after a returned Future completes; the old assert(T is! Future) guard in _Scope.sync / _Scope.async was a no-op.
  • opensslAllocator & extractBoringSslError(): Uses ssl.opensslAllocator (OPENSSL_malloc + OPENSSL_cleanse + OPENSSL_free) and ssl.extractBoringSslError() from package:boring/bindings.dart, including in the checkErrorStack test helper, so package:ffi is no longer a dependency.

CI

  • Removes .github/workflows/update-boringssl.yml: it ran tool/bump-boringssl-revision.sh and read tool/REVISION, both deleted here. BoringSSL revision bumps now happen weekly on CI in package:boring (same script), and the existing Dependabot pub config will pick up new boring releases.
  • Conformance testing lives in package:boring: its CI runs Project Wycheproof (32 vector files) and x509-limbo path validation directly against the raw bindings.

Replaces the internal `_Scope` arena with `BoringArena` from package:boring:

- `_Scope.sync` / `_Scope.async` -> `BoringArena.run`, which releases after a
  returned Future completes (the old `assert(T is! Future)` guard was a
  no-op), and `_Scope.stream` -> `BoringArena.stream`.
- `dataAsPointer` -> `copyBytes`, `createCBS` / `createCBB` -> `cbs` / `cbb`,
  `CBB.copy()` -> `CBB.toBytes()`, and `defer(() => X_free(p))` ->
  `using(p, X_free)`. `move` is unchanged.
- Keeps a small `create()` extension that maps `nullptr` to OperationError.
- `checkErrorStack` uses `extractBoringSslError()`, which removes the last
  use of package:ffi, so the dependency is dropped.
- Remove the update-boringssl workflow. It ran
  tool/bump-boringssl-revision.sh and read tool/REVISION, which this PR
  deletes along with the vendored BoringSSL. BoringSSL bumps now happen in
  package:boring, and Dependabot's pub config picks up boring releases.
- Declare boring as a hosted `^0.4.0` dependency and pin the unreleased
  commit with dependency_overrides, fixing the invalid_dependency warning
  that failed the lints job. The example app needs the same override
  because overrides don't propagate through its path dependency.
- Bump the pin to 60072877, whose CI runs the Wycheproof and x509-limbo
  conformance suites. lib/, hook/ and src/ are unchanged since 410fae8e.
The TODO in checkErrorStack proposed clearing BoringSSL errors in every
finally via BoringArena and asserting that none are left. That doesn't
work in Dart: the error queue is thread-local and an isolate may resume
on a different OS thread after an await, so a clear or assert at arena
release can miss errors or see another isolate's.

Errors are already consumed right after each failing call (_checkOp,
_checkData, and the explicit clear in _verifyStream), and checkErrorStack
already fails tests that leave errors behind. Replace both TODOs with
comments saying so, and state the rule once above _checkOp.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant