Closed fscoto closed 4 years ago
MSVC is not free and requires subscription, right? What about Intel compiler, XL C from IBM?
Monocypher tested on big number of platforms and compilers, even IRIX works and latest tcc from git and gcc 3.x.x. If so i would like to test, asap, on Sun Oracle studio version i have, worked several years ago.
Since Monocypher passed TIS, compcert and SANs I am calm. Wellcome to hell of compilers compatibility.
MSVC is free with the Community edition of Visual Studio Community. VS Community will ask you to register (i.e. give up personal information) after 30 days though; the for-profit editions won't do that (and instead ask you for money).
Also this is MSVC, I'm absolutely not ruling out a compiler bug here.
Weather update: 3.0.0 doesn't exhibit the issue, so it's some change between 3.0.0 and 3.1.0 that caused MSVC to have a bad hair day.
git bisect
narrows it down to commit 6411aa4.
Replacing line 1379 COPY(trimmed, scalar, 32);
with memcpy(trimmed, scalar, 32);
makes the tests pass again. This is obviously a non-starter because it introduces a dependency on the C standard library, but this is either an optimization bug or some kind of really non-intuitive interpretation of... something.
It's also partially not a heisenbug: If I add debug printf() that print both e
and your_secret_key
in crypto_x25519
, the issue doesn't vanish. But it is a heisenbug in the function itself: If I add something that prints every element as it's being copied or that prints every byte of trimmed
right before the function returns, the tests pass again.
If I move the COPY()
out of trim_scalar()
and do the trimming immediately at the calling sites, then it works (which is essentially the same as before 6411aa4).
Is there any way to read either the C or C++ standard that the compiler is allowed to somehow break a copy operation between two pointers (i.e. iterating through two arrays and setting every element) except if using memcpy?
Monocypher 3.1.0 passed tests on Oracle SPARC under Sun Studio 12.5
cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2018/09/21
Monocypher 3.1.0 passed tests on IBM POWER under XL C
IBM XL C/C++ for AIX, V12.0
Version: 12.00.0000.0000
It appears that the compiler assumes the two pointers cannot alias, and triggers UB on that ground.
I'll revert the patch: it has dubious value: we save like one line of code, at the cost of a copy in some cases, and now this MSVC… oddity.
In any case, I'm not worried about security: the test suite fails fairly loudly, I expect the failures will manifest as clean breaks (the programs will simply fail).
It appears that the compiler assumes the two pointers cannot alias, and triggers UB on that ground.
The funniest part is that it's breaking on two pointers that don't alias. your_secret_key
comes from an outside context and e
is on the local stack of crypto_x25519
. They never, ever alias, and thus nothing should break. I have no idea why this is happening and I'm about 30% sure it's a compiler bug.
Okay, that's creepy. I'd personally bet at 90% compiler bug: our test suite is really thorough, @tankf33der tests this on a gazillion machines… Perhaps we should test this (before my latest patch) with older versions of MSVC?
If someone can find the energy to report a bug, that would be great. Thought I wouldn't hold my breath about them responding favourably.
This is like, worst possible news, but... Apparently nobody's been testing Windows for a while and 3.1.0 fails tests for X25519 (but not EdDSA!) and some related functions. This issue manifests only at
/O2
, but not/O1
.My crude test methodology missing make(1) goes like this:
Giving this output:
I'll try to hunt down what the cause might be, but this is important enough that I wanted an issue up now and figure out the details later.