Skip to content

Add an experimental TLS FFI module with a policy handle - #5941

Merged
randombit merged 1 commit into
randombit:masterfrom
moritzschmitt:ffi-tls
Sep 22, 2026
Merged

randombit merged 1 commit into
randombit:masterfrom
moritzschmitt:ffi-tls

Conversation

@moritzschmitt

Copy link
Copy Markdown
Contributor

This is the first, deliberately small step towards a C API for TLS (#2492), following the outline discussed there. It settles the conventions that the later parts (credentials, session managers, channels) will build on, without any of them yet.

  • New module ffi_tls (src/lib/ffi/ffi_tls) with its own public header botan/ffi_tls.h and version stamp FFI_TLS, laid out like jack/ffi-tls. The module has lifecycle -> "Experimental" as agreed on the issue, so it is only built with --enable-modules=ffi_tls or --enable-experimental-features (the CI script passes the latter on every target, so CI covers it) and its functions may still change. As far as I can tell it is the first module using that lifecycle value.
  • botan_ffi_tls_api_version() and botan_ffi_tls_supports_api() in ffi.h, as in jack/ffi-tls, so applications can detect the module at runtime; they return 0 resp. -1 when it is not built. The existing FFI version stamp is not bumped (per the remark on Expose SAN/IAN otherName entries via the FFI GeneralName API #5903 that this is better left to release time).
  • botan_tls_policy_t, an opaque handle wrapping a shared_ptr<const TLS::Policy> (via a small wrapper struct as ffi_tpm2.cpp does), so that channels can later co-own the policy and the handle may be destroyed right after use. Four functions: botan_tls_policy_init(policy, name) with the stock policies "default", "strict" and "bsi_tr_02102_2" (NULL selects the default, an unknown name returns BAD_PARAMETER; Suite B left out as suggested), botan_tls_policy_init_from_text() for Text_Policy (malformed text returns INVALID_INPUT; values are checked by Text_Policy only when consulted, which the header documents), botan_tls_policy_view_text() (Policy::to_string() through a view function) and botan_tls_policy_destroy().
  • Tests in src/tests/test_ffi_tls.cpp: ffi_tls_version runs in every FFI build and checks the version functions against BOTAN_HAS_FFI_TLS; ffi_tls_policy covers the stock policies, text policies and the error paths.
  • Python: TLSPolicy and ffi_tls_api_version() in botan3.py (the latter returns 0 for libraries without the module or predating it), a test that skips when the module is absent, and a section in python.rst.
  • Docs: a "TLS (Experimental)" section at the end of ffi.rst.

Checked locally on macOS (Apple clang) with the full test suite and the Python tests, with gcc 13 -std=c89 on the header, clang-tidy, clang-format, pylint and ruff, and a Sphinx build with -W. No news.rst entry yet; happy to add one now or with the first PR that makes TLS usable, whichever you prefer.

@reneme reneme left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good start to me. Thanks. Some inline comments for discussion.

Comment thread src/lib/ffi/ffi_tls/ffi_tls.cpp Outdated
Comment thread src/lib/ffi/ffi_tls/ffi_tls.cpp Outdated
Comment thread src/python/botan3.py
Comment thread src/python/botan3.py
Comment on lines +4175 to +4179
def __copy__(self):
raise TypeError('TLSPolicy objects cannot be copied')

def __deepcopy__(self, _memo):
raise TypeError('TLSPolicy objects cannot be copied')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, they could be copied because, internally, they are just a shared pointer after all. We'd need to provide a botan_tls_policy_dup() FFI binding for that, I guess. That might be useful when trying to juggle multiple TLS handles in the future.

At the moment, I'd suggest to just keep it in mind and revisit it later as needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and noted for later. Since the handle is a shared_ptr internally, a botan_tls_policy_dup() would be cheap, and the same would apply to the credentials and session manager handles. I will leave the Python objects non-copyable for now and add duplication when there is a concrete need for it.

Comment thread src/python/botan3.py Outdated
@moritzschmitt
moritzschmitt marked this pull request as ready for review September 18, 2026 05:24
@moritzschmitt

Copy link
Copy Markdown
Contributor Author

@randombit Would you like to take a look at this one as well, or is reneme's approval enough to merge it? The next PR (the credentials and session manager handles) is ready locally (well, almost) and is stacked on this branch. I would open it once this one is merged, or earlier as a draft if you prefer to see it now.

@randombit

Copy link
Copy Markdown
Owner

Looks good but re shared_ptr let's fix this now - see #5959

So I'd suggest merging 5959 first, rebase this to use the new native shared_ptr support, then continue

@moritzschmitt

Copy link
Copy Markdown
Contributor Author

Sounds good. I will rebase onto #5959 once it is merged and switch the policy handle to the new shared_ptr struct. The follow-up PRs will use it from the start.

@randombit

Copy link
Copy Markdown
Owner

5959 merged now

@randombit

Copy link
Copy Markdown
Owner

@moritzschmitt lgtm but please squash the commits

@moritzschmitt

Copy link
Copy Markdown
Contributor Author

Squashed into one commit; the tree is unchanged from the version CI ran on.

@moritzschmitt

Copy link
Copy Markdown
Contributor Author

The two failures are the windows-11-arm MSVC runners, and I have no idea what's going on, because both jobs passed on the identical tree a couple of hours earlier. The only thing I've noticed is that MSVC 19.51 was picked up in the meantime (before, it was 19.44). I just love software engineering.

First step towards a C API for TLS (GH randombit#2492): the ffi_tls module
skeleton with lifecycle Experimental, runtime version functions in
ffi.h, the botan_tls_policy_t handle, tests, Python binding and docs.
@moritzschmitt

Copy link
Copy Markdown
Contributor Author

@randombit Squashed and rebased onto current master; CI is green now. The earlier arm64 failures were the runner-image change (#5960 and #5962 took care of them). Ready from my side.

@randombit
randombit merged commit 9021748 into randombit:master Sep 22, 2026
51 checks passed
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.

3 participants