On Sat, 22 Aug 2026 20:23:22 GMT, Andrew Haley <[email protected]> wrote:

>> The existing arbitrary `conditionalSet()` benchmark is not necessarily 
>> indicative of susceptibility to a side-channel attack in production code due 
>> to a number reasons, including the use of non-constant input arguments and 
>> the dependencies of intermediate operations due to adding between successive 
>> `lookup()` calls when calculating point multiplication, as an example.  As a 
>> result, the problem being addressed is a benchmark issue, as the current 
>> conditional set benchmark is nothing like what is utilized in EC production 
>> operations.  This is why I lifted the existing `lookup()` logic as a form of 
>> measuring conditional set performance, which better emulates a production 
>> state.
>> 
>> The above code uses flag arguments that are incorrect which would generate 
>> invalid bit masks, subsequently corrupting the associated limbs during 
>> conditional sets.  Even with non-binary flags, because the pair-wise 
>> assignments use the same input, C2 could perform a bitwise OR of the two 
>> masks and use the resulting mask only once for the conditional assignment.  
>> As a result C2 may i) not need to reload registers for the second call, ii) 
>> not need to store the result to memory from the first call when the second 
>> call would overwrite the first, and iii) keep the intermediate limbs in 
>> registers.  Correcting the flag arguments to binary would make it even 
>> easier for inlining as it could eliminate the the first call if the second 
>> call has a 1 flag.  In aggregate, this likely contributes to the 18% drop in 
>> performance with intrinsics when using the above code, compared to a 52% 
>> performance gain when using intrinsics with the originally proposed 
>> solution.  The goal is to try to reproduce
 the same shape that we see in production EC operations.
>
>> The goal is to try to reproduce the same shape that we see in production EC 
>> operations.
> 
> Maybe I'm misunderstanding something, but here's what I think is problematic:
> 
> We have an implementation that executes in constant time, but only if a 
> compiler cannot predict a flag. It would take a little improvement in an 
> optimizing compiler to generate two versions of the code, calling either one 
> or the other depending on that flag. If it did,even with a non-constant flag 
> the supposed constant-time implementation would be no such thing. Am I wrong?

I guess what @theRealAph is referring to is the following. Looking at the spec 
of `MutableIntegerModuloP::conditionalSet`, it only accepts the second argument 
being 0 or 1. If, we do profiling for `int` parameters, and see that they are 
the only possible values of `set`, the compiler may emit code like this:

    void conditionalSet(IntegerModuloP b, int set) {
        if (set == 0) {
            return conditionalSet(b, 0);
        } else if (set == 1) {
            return conditionalSet(b, 1);
        } else {
            trap();
        }
    }

Then, there is a risk of time-based speculation.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/32047#discussion_r3841730953

Reply via email to