Merge pull request #1367 from gilles-peskine-arm/aesni_has_support-volatile-3.6

Backport 3.6: Fix race condition in mbedtls_aesni_has_support
diff --git a/ChangeLog.d/aesni_has_support.txt b/ChangeLog.d/aesni_has_support.txt
new file mode 100644
index 0000000..26b7c2c
--- /dev/null
+++ b/ChangeLog.d/aesni_has_support.txt
@@ -0,0 +1,17 @@
+Bugfix
+   * Fix a race condition on x86/amd64 platforms in AESNI support detection
+     that could lead to using software AES in some threads at the very
+     beginning of a multithreaded program. Reported by Solar Designer.
+     Fixes #9840.
+
+Security
+   * On x86/amd64 platforms, with some compilers, when the library is
+     compiled with support for both AESNI and software AES and AESNI is
+     available in hardware, an adversary with fine control over which
+     threads make progress in a multithreaded program could force software
+     AES to be used for some time when the program starts. This could allow
+     the adversary to conduct timing attacks and potentially recover the
+     key. In particular, this attacker model may be possible against an SGX
+     enclave.
+     The same vulnerability affects GCM acceleration, which could allow
+     a similarly powerful adversary to craft GCM forgeries.
diff --git a/library/aesni.c b/library/aesni.c
index 4fc1cb9..2857068 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -48,8 +48,19 @@
  */
 int mbedtls_aesni_has_support(unsigned int what)
 {
-    static int done = 0;
-    static unsigned int c = 0;
+    /* To avoid a race condition, tell the compiler that the assignment
+     * `done = 1` and the assignment to `c` may not be reordered.
+     * https://github.com/Mbed-TLS/mbedtls/issues/9840
+     *
+     * Note that we may also be worried about memory access reordering,
+     * but fortunately the x86 memory model is not too wild: stores
+     * from the same thread are observed consistently by other threads.
+     * (See example 8-1 in Sewell et al., "x86-TSO: A Rigorous and Usable
+     * Programmer’s Model for x86 Multiprocessors", CACM, 2010,
+     * https://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf)
+     */
+    static volatile int done = 0;
+    static volatile unsigned int c = 0;
 
     if (!done) {
 #if MBEDTLS_AESNI_HAVE_CODE == 2