utils icon indicating copy to clipboard operation
utils copied to clipboard

[WIP] ctutils: constant-time selection and equality testing

Open tarcieri opened this issue 4 months ago • 2 comments

(for lack of a better name)

This is woefully incomplete but I'm pushing it up anyway since several people have asked about const fn support for subtle.

This is effectively a rewrite of subtle using the cmov crate for both constant-time selection/predication as well as equality comparisons. The cmov crate uses architecture-specific predication instructions on x86(_64) and ARM, with a portable "best effort" fallback.

It uses core::hint::black_box on-access as an optimization barrier, however this is a belt-and-suspenders defense paired with the use of intrinsics where available. This is a bit different than subtle which uses a similar black box optimization barrier at initialization time. There are a couple problems with this approach:

  1. The optimizer can assume the value is unchanged after repeat accesses to the same Choice, which means it could potentially insert a branch to e.g. shortcut-on-zero
  2. black_box is (rather annoyingly) only const fn in Rust 1.86. This is targeting an initial MSRV of 1.85, as well as supporting const fn constructors for Choice which are a big missing piece in subtle right now

I'm not intending to replace our usages of subtle with this yet (I'd much rather ship everything), but would like to have a testbed for using cmov for constant-time operations which can perhaps inform a potential subtle v3.0 (if I can make that happen).

To be useful, this still needs an equivalent of CtOption (ideally with much more const fn support), which I was hoping to implement before pushing this up.

One thing we could consider is trying to get this complete enough to use in crypto-bigint to replace ConstChoice/ConstCtOption, though it would likely need all of the methods on Choice to be const fn, which would probably involve shipping Choice without black_box (i.e. what crypto-bigint is already doing), and then adding a subtle integration for converting ctutil::Choice -> subtle::Choice and a prospective ctutil::CtOption -> subtle::CtOption.

cc @andrewwhitehead @fjarri @ycscaly

tarcieri avatar Oct 28 '25 18:10 tarcieri

So why not just bump the MSRV to 1.86?

fjarri avatar Oct 28 '25 18:10 fjarri

@fjarri we're trying to ship everything as 1.85 so it can be packaged on Debian stable, then bumping MSRV after that (now that there's an MSRV-aware resolver)


That said, there are several places post-1.85 features would be nice in crypto-bigint, particularly inference for const-generic trait parameters.

tarcieri avatar Oct 28 '25 18:10 tarcieri

Ugh, cast_unsigned was stabilized in 1.87. I might start with that MSRV and then open a PR to downgrade the MSRV back to 1.85 so we can just revert that when we bump MSRV.

tarcieri avatar Dec 20 '25 00:12 tarcieri

I'd like to finally push this one past the draft PR it's been sitting in for ages and land it and iterate on new features/functionality.

I'm going to go ahead and merge but I'd appreciate any retroactive review.

tarcieri avatar Dec 20 '25 00:12 tarcieri