Description
Hi there,
I'm the author of sidefuzz (https://github.com/phayes/sidefuzz) and I have found what appears to be variable-time behavior in the rsa::internals::encrypt()
function. Specifically, rsa::internals::encrypt()
appears to be variable-time in relation to the message. Note that I haven't worked this up into an actual exploit, but merely demonstrated that this function isn't constant-time in relation to the message inputed.
Specifically, the message 20d90c8af42aac9b1ee53dc9a0187201
takes 549894 instructions to encrypt, while the message 5a28cec68d47f6fe3b1df54c9f320f6d
takes 552427 instruction to encrypt. This is a difference of 2533 instructions, or about 0.5%. So it's a slight difference, but probably exploitable with sufficient sampling.
I have crated a fuzzing targets here: https://github.com/phayes/sidefuzz-targets
You can confirm this difference with the sidefuzz tool like so:
sidefuzz check ./target/wasm32-unknown-unknown/release/rsa_encrypt_message.wasm 5a28cec68d47f6fe3b1df54c9f320f6d 20d90c8af42aac9b1ee53dc9a0187201
samples: 20000, t-value: 219771.0790572351, confidence: 100%
Found timing difference of 2533 instructions between these two inputs with 100% confidence:
input 1: 5a28cec68d47f6fe3b1df54c9f320f6d (552427 instructions)
input 2: 20d90c8af42aac9b1ee53dc9a0187201 (549894 instructions)
My first suspicion was that this was due to num_bigint_dig::BigUint::from_bytes_be()
being variable-time, but fuzzing that function specifically results in what appears to be constant-time behavior. So I'm not actually sure where the problem is.