[Python-checkins] bpo-40791: Make compare_digest more constant-time. (GH-23438) (GH-23767)

ned-deily webhook-mailer at python.org
Mon Dec 14 12:05:10 EST 2020


https://github.com/python/cpython/commit/8bef9ebb1b88cfa4b2a38b93fe4ea22015d8254a
commit: 8bef9ebb1b88cfa4b2a38b93fe4ea22015d8254a
branch: 3.6
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ned-deily <nad at python.org>
date: 2020-12-14T12:04:57-05:00
summary:

bpo-40791: Make compare_digest more constant-time. (GH-23438) (GH-23767)

The existing volatile `left`/`right` pointers guarantee that the reads will all occur, but does not guarantee that they will be _used_. So a compiler can still short-circuit the loop, saving e.g. the overhead of doing the xors and especially the overhead of the data dependency between `result` and the reads. That would change performance depending on where the first unequal byte occurs. This change removes that optimization.

(This is change GH-1 from https://bugs.python.org/issue40791 .)
(cherry picked from commit 31729366e2bc09632e78f3896dbce0ae64914f28)

Co-authored-by: Devin Jeanpierre <jeanpierreda at google.com>

files:
A Misc/NEWS.d/next/Security/2020-05-28-06-06-47.bpo-40791.QGZClX.rst
M Modules/_operator.c

diff --git a/Misc/NEWS.d/next/Security/2020-05-28-06-06-47.bpo-40791.QGZClX.rst b/Misc/NEWS.d/next/Security/2020-05-28-06-06-47.bpo-40791.QGZClX.rst
new file mode 100644
index 0000000000000..69b9de1beae0d
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2020-05-28-06-06-47.bpo-40791.QGZClX.rst
@@ -0,0 +1 @@
+Add ``volatile`` to the accumulator variable in ``hmac.compare_digest``, making constant-time-defeating optimizations less likely.
\ No newline at end of file
diff --git a/Modules/_operator.c b/Modules/_operator.c
index af05f1c296bdb..25654440d2a75 100644
--- a/Modules/_operator.c
+++ b/Modules/_operator.c
@@ -184,7 +184,7 @@ _tscmp(const unsigned char *a, const unsigned char *b,
     volatile const unsigned char *left;
     volatile const unsigned char *right;
     Py_ssize_t i;
-    unsigned char result;
+    volatile unsigned char result;
 
     /* loop count depends on length of b */
     length = len_b;



More information about the Python-checkins mailing list