SLIDE 1 1
Cryptographic software engineering, part 1 Daniel J. Bernstein This is easy, right?
- 1. Take general principles
- f software engineering.
- 2. Apply principles to crypto.
Let’s try some examples : : :
2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change.
SLIDE 2 1
Cryptographic re engineering,
easy, right? e general principles software engineering. Apply principles to crypto. try some examples : : :
2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change. Another
Make the and the
SLIDE 3 1
engineering, Bernstein right? principles engineering. rinciples to crypto. examples : : :
2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change. Another general principle
Make the right thing and the wrong thing
SLIDE 4 1
engineering. crypto. : :
2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change. Another general principle
Make the right thing simple and the wrong thing complex.
SLIDE 5 2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change.
3
Another general principle
Make the right thing simple and the wrong thing complex.
SLIDE 6 2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change.
3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators.
SLIDE 7 2
1972 Parnas “On the criteria to be used in decomposing systems into modules”: “We propose instead that
difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” e.g. If number of cipher rounds is properly modularized as
#define ROUNDS 20
then it is easy to change.
3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ”
SLIDE 8 2
arnas “On the criteria used in decomposing systems into modules”: ropose instead that egins with a list of difficult design decisions or decisions which are to change. Each module designed to hide such decision from the others.” number of cipher rounds erly modularized as
ROUNDS 20
is easy to change.
3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ” Not so easy: 1970s: TENEX compares against secret
stopping
SLIDE 9 2
“On the criteria decomposing dules”: instead that a list of decisions or which are Each module to hide such the others.”
dularized as
20
change.
3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ” Not so easy: Timing 1970s: TENEX op compares user-supplied against secret passw
stopping at first difference:
- AAAAAA vs. FRIEND
- FAAAAA vs. FRIEND
- FRAAAA vs. FRIEND
SLIDE 10 2
criteria r dule such
rounds
3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ” Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at
- FAAAAA vs. FRIEND: stop at
- FRAAAA vs. FRIEND: stop at
SLIDE 11 3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ”
4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
SLIDE 12 3
Another general principle
Make the right thing simple and the wrong thing complex. e.g. Make it difficult to ignore invalid authenticators. Do not design APIs like this: “The sample code used in this manual omits the checking
- f status values for clarity, but
when using cryptlib you should check return values, particularly for critical functions : : : ”
4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password.
SLIDE 13 3
Another general principle ware engineering: the right thing simple the wrong thing complex. Make it difficult to invalid authenticators. not design APIs like this: sample code used in manual omits the checking status values for clarity, but using cryptlib you should return values, particularly tical functions : : : ”
4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password. How typical 16-byte authenticato
for (i if (x[i] return
SLIDE 14 3
principle engineering: thing simple thing complex. difficult to authenticators. APIs like this: de used in
for clarity, but cryptlib you should values, particularly functions : : : ”
4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password. How typical softwa 16-byte authenticato
for (i = 0;i < if (x[i] != y[i]) return 1;
SLIDE 15 3
simple complex. rs. this: checking but should rticularly
4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password. How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return return 1;
SLIDE 16 4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password.
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
SLIDE 17 4
Not so easy: Timing attacks 1970s: TENEX operating system compares user-supplied string against secret password
stopping at first difference:
- AAAAAA vs. FRIEND: stop at 1.
- FAAAAA vs. FRIEND: stop at 2.
- FRAAAA vs. FRIEND: stop at 3.
Attacker sees comparison time, deduces position of difference. A few hundred tries reveal secret password.
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex.
SLIDE 18
4
easy: Timing attacks TENEX operating system res user-supplied string against secret password character at a time, stopping at first difference: AAAAAA vs. FRIEND: stop at 1. FAAAAA vs. FRIEND: stop at 2. FRAAAA vs. FRIEND: stop at 3. er sees comparison time, deduces position of difference. hundred tries secret password.
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex. Language “right” is So mistak
SLIDE 19 4
Timing attacks
user-supplied string password a time, difference: FRIEND: stop at 1. FRIEND: stop at 2. FRIEND: stop at 3. comparison time,
tries password.
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex. Language designer’s “right” is too weak So mistakes continue
SLIDE 20
4
attacks system string difference: stop at 1. stop at 2. stop at 3. time, difference.
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex. Language designer’s notion of “right” is too weak for securit So mistakes continue to happ
SLIDE 21
5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex.
6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen.
SLIDE 22 5
How typical software checks 16-byte authenticator:
for (i = 0;i < 16;++i) if (x[i] != y[i]) return 0; return 1;
Fix, eliminating information flow from secrets to timings:
diff = 0; for (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
Notice that the language makes the wrong thing simple and the right thing complex.
6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
SLIDE 23 5
ypical software checks yte authenticator:
(i = 0;i < 16;++i) (x[i] != y[i]) return 0; return 1;
eliminating information flow secrets to timings:
= 0; (i = 0;i < 16;++i) diff |= x[i] ^ y[i]; return 1 & ((diff-1) >> 8);
that the language the wrong thing simple the right thing complex.
6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
Do timing Objection:
SLIDE 24 5
ware checks authenticator:
16;++i) y[i]) return 0;
information flow timings:
16;++i) ^ y[i]; ((diff-1) >> 8);
language wrong thing simple thing complex.
6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
Do timing attacks Objection: “Timings
SLIDE 25 5
checks
return 0;
rmation flow
>> 8);
imple complex.
6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
Do timing attacks really work? Objection: “Timings are noisy!
SLIDE 26 6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!”
SLIDE 27 6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow.
SLIDE 28 6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise.
SLIDE 29 6
Language designer’s notion of “right” is too weak for security. So mistakes continue to happen. One of many examples, part of the reference software for
- ne of the CAESAR candidates:
/* compare the tag */ int i; for(i = 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; } return RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise. Answer #3, what the 1970s attackers actually did: Cross page boundary, inducing page faults, to amplify timing signal.
SLIDE 30 6
Language designer’s notion of “right” is too weak for security. mistakes continue to happen.
- f many examples,
- f the reference software for
the CAESAR candidates:
compare the tag */ 0;i < CRYPTO_ABYTES;i++) if(tag[i] != c[(*mlen) + i]){ return RETURN_TAG_NO_MATCH; RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise. Answer #3, what the 1970s attackers actually did: Cross page boundary, inducing page faults, to amplify timing signal. Defenders Some of 1996 Ko attacks on Briefly mentioned Kocher and Schneier–W secret arra affect timing 2002 Page, Suzaki–Shigeri–Miy timing attacks
SLIDE 31
6
designer’s notion of eak for security. continue to happen. examples, reference software for CAESAR candidates:
tag */ CRYPTO_ABYTES;i++) c[(*mlen) + i]){ RETURN_TAG_NO_MATCH; RETURN_SUCCESS;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise. Answer #3, what the 1970s attackers actually did: Cross page boundary, inducing page faults, to amplify timing signal. Defenders don’t lea Some of the literature: 1996 Kocher pointed attacks on cryptographi Briefly mentioned Kocher and by 1998 Schneier–Wagner–Hall: secret array indices affect timing via cache 2002 Page, 2003 Tsuno Suzaki–Shigeri–Miy timing attacks on
SLIDE 32
6
notion of security. happen. are for candidates:
CRYPTO_ABYTES;i++) + i]){ RETURN_TAG_NO_MATCH;
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise. Answer #3, what the 1970s attackers actually did: Cross page boundary, inducing page faults, to amplify timing signal. Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misse 2002 Page, 2003 Tsunoo–Sa Suzaki–Shigeri–Miyauchi: timing attacks on DES.
SLIDE 33
7
Do timing attacks really work? Objection: “Timings are noisy!” Answer #1: Does noise stop all attacks? To guarantee security, defender must block all information flow. Answer #2: Attacker uses statistics to eliminate noise. Answer #3, what the 1970s attackers actually did: Cross page boundary, inducing page faults, to amplify timing signal.
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES.
SLIDE 34
7
timing attacks really work? Objection: “Timings are noisy!” er #1: noise stop all attacks? guarantee security, defender block all information flow. er #2: Attacker uses statistics to eliminate noise. er #3, what the attackers actually did: page boundary, inducing page faults, amplify timing signal.
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES. “Guaranteed” load entire
SLIDE 35 7
attacks really work? Timings are noisy!” all attacks? security, defender information flow. ttacker uses eliminate noise. what the actually did:
aults, timing signal.
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES. “Guaranteed” counterme load entire table into
SLIDE 36 7
noisy!” attacks? defender flow. noise. did:
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES. “Guaranteed” countermeasur load entire table into cache.
SLIDE 37
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES.
9
“Guaranteed” countermeasure: load entire table into cache.
SLIDE 38
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES.
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices.
SLIDE 39
8
Defenders don’t learn Some of the literature: 1996 Kocher pointed out timing attacks on cryptographic key bits. Briefly mentioned by Kocher and by 1998 Kelsey– Schneier–Wagner–Hall: secret array indices can affect timing via cache misses. 2002 Page, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: timing attacks on DES.
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption.
SLIDE 40 8
Defenders don’t learn
Kocher pointed out timing attacks on cryptographic key bits. mentioned by cher and by 1998 Kelsey– Schneier–Wagner–Hall: array indices can timing via cache misses. age, 2003 Tsunoo–Saito– Suzaki–Shigeri–Miyauchi: attacks on DES.
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption. Intel recomme OpenSSL countermeasure: from kno
SLIDE 41 8
learn literature:
cryptographic key bits. mentioned by 1998 Kelsey– agner–Hall: indices can cache misses. Tsunoo–Saito– Suzaki–Shigeri–Miyauchi:
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption. Intel recommends, OpenSSL integrates, countermeasure: alw from known lines of
SLIDE 42 8
timing ey bits. Kelsey– misses.
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption. Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache.
SLIDE 43
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache.
SLIDE 44
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004.
SLIDE 45
9
“Guaranteed” countermeasure: load entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; e.g., secret array indices can affect timing via cache-bank collisions. What is safe: kill all data flow from secrets to array indices. 2005 Tromer–Osvik–Shamir: 65ms to steal Linux AES key used for hard-disk encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL.
SLIDE 46 9
ranteed” countermeasure: entire table into cache. 2004.11/2005.04 Bernstein: Timing attacks on AES. Countermeasure isn’t safe; secret array indices can affect via cache-bank collisions. is safe: kill all data flow secrets to array indices. romer–Osvik–Shamir: to steal Linux AES key for hard-disk encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL. 2008 RF Layer Securit Version 1.2”: small timing performance extent on fragment, be large due to the existing MA
SLIDE 47 9
countermeasure: into cache. Bernstein:
isn’t safe; indices can affect cache-bank collisions. kill all data flow array indices. romer–Osvik–Shamir: Linux AES key rd-disk encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL. 2008 RFC 5246 “The Layer Security (TLS) Version 1.2”: “This small timing channel, performance depends extent on the size fragment, but it is be large enough to due to the large blo existing MACs and
SLIDE 48 9
asure: cache. Bernstein: safe; can affect collisions. flow indices. romer–Osvik–Shamir: ey encryption.
10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL. 2008 RFC 5246 “The Transp Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MA performance depends to some extent on the size of the data fragment, but it is not believed be large enough to be exploitable due to the large block size of existing MACs and the small
SLIDE 49 10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL.
11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
SLIDE 50 10
Intel recommends, and OpenSSL integrates, cheaper countermeasure: always loading from known lines of cache. 2013 Bernstein–Schwabe “A word of warning”: This countermeasure isn’t safe. Variable-time lab experiment. Same issues described in 2004. 2016 Yarom–Genkin–Heninger “CacheBleed” steals RSA secret key via timings of OpenSSL.
11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
2013 AlFardan–Paterson “Lucky Thirteen: breaking the TLS and DTLS record protocols”: exploit these timings; steal plaintext.
SLIDE 51 10
recommends, and enSSL integrates, cheaper countermeasure: always loading known lines of cache. Bernstein–Schwabe rd of warning”: countermeasure isn’t safe. riable-time lab experiment. issues described in 2004. arom–Genkin–Heninger “CacheBleed” steals RSA secret timings of OpenSSL.
11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
2013 AlFardan–Paterson “Lucky Thirteen: breaking the TLS and DTLS record protocols”: exploit these timings; steal plaintext. How to write If possible, to control Look for identifying “Division when the completes, cycles re values of Measure trusting
SLIDE 52 10
s, and integrates, cheaper always loading lines of cache. Bernstein–Schwabe rning”: countermeasure isn’t safe. lab experiment. described in 2004. rom–Genkin–Heninger steals RSA secret
11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
2013 AlFardan–Paterson “Lucky Thirteen: breaking the TLS and DTLS record protocols”: exploit these timings; steal plaintext. How to write constant-time If possible, write co to control instruction Look for documentation identifying variabilit “Division operations when the divide op completes, with the cycles required dep values of the input Measure cycles rather trusting CPU documentation.
SLIDE 53 10
cheaper loading cache. safe. eriment. 2004. rom–Genkin–Heninger secret enSSL.
11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
2013 AlFardan–Paterson “Lucky Thirteen: breaking the TLS and DTLS record protocols”: exploit these timings; steal plaintext. How to write constant-time If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number cycles required dependent on values of the input operands.” Measure cycles rather than trusting CPU documentation.
SLIDE 54 11
2008 RFC 5246 “The Transport Layer Security (TLS) Protocol, Version 1.2”: “This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size
2013 AlFardan–Paterson “Lucky Thirteen: breaking the TLS and DTLS record protocols”: exploit these timings; steal plaintext.
12
How to write constant-time code If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number of cycles required dependent on the values of the input operands.” Measure cycles rather than trusting CPU documentation.
SLIDE 55 11
RFC 5246 “The Transport Security (TLS) Protocol, ersion 1.2”: “This leaves a timing channel, since MAC rmance depends to some
fragment, but it is not believed to rge enough to be exploitable, the large block size of existing MACs and the small size timing signal.” AlFardan–Paterson “Lucky Thirteen: breaking the TLS and record protocols”: exploit timings; steal plaintext.
12
How to write constant-time code If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number of cycles required dependent on the values of the input operands.” Measure cycles rather than trusting CPU documentation. Cut off all secrets to Cut off all secrets to Cut off all secrets to Prefer logic Prefer vecto Watch o variable-time Cortex-M3
SLIDE 56
11
“The Transport (TLS) Protocol, his leaves a channel, since MAC ends to some size of the data is not believed to to be exploitable, block size of and the small size signal.” rdan–Paterson “Lucky reaking the TLS and rotocols”: exploit steal plaintext.
12
How to write constant-time code If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number of cycles required dependent on the values of the input operands.” Measure cycles rather than trusting CPU documentation. Cut off all data flo secrets to branch conditions. Cut off all data flo secrets to array indices. Cut off all data flo secrets to shift/rotate Prefer logic instructions. Prefer vector instructions. Watch out for CPUs variable-time multipliers: Cortex-M3 and most
SLIDE 57 11
ransport Protocol, a since MAC some data elieved to exploitable,
all size “Lucky TLS and exploit plaintext.
12
How to write constant-time code If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number of cycles required dependent on the values of the input operands.” Measure cycles rather than trusting CPU documentation. Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs.
SLIDE 58
12
How to write constant-time code If possible, write code in asm to control instruction selection. Look for documentation identifying variability: e.g., “Division operations terminate when the divide operation completes, with the number of cycles required dependent on the values of the input operands.” Measure cycles rather than trusting CPU documentation.
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs.
SLIDE 59 12
to write constant-time code
- ssible, write code in asm
control instruction selection. for documentation identifying variability: e.g., “Division operations terminate the divide operation completes, with the number of required dependent on the
Measure cycles rather than trusting CPU documentation.
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs. Suppose const-time Suppose has “secret Easy for that secret by const-time Proofs of (uninitialized ctgrind,
SLIDE 60 12
constant-time code code in asm instruction selection. cumentation riability: e.g., erations terminate
the number of dependent on the input operands.” rather than cumentation.
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs. Suppose we know const-time machine Suppose programming has “secret” types. Easy for compiler to that secret types by const-time instructions. Proofs of concept: (uninitialized data ctgrind, ct-verif, Flo
SLIDE 61 12
constant-time code asm selection. e.g., terminate er of
erands.” than cumentation.
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs. Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret ctgrind, ct-verif, FlowTracker.
SLIDE 62
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs.
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker.
SLIDE 63
13
Cut off all data flow from secrets to branch conditions. Cut off all data flow from secrets to array indices. Cut off all data flow from secrets to shift/rotate distances. Prefer logic instructions. Prefer vector instructions. Watch out for CPUs with variable-time multipliers: e.g., Cortex-M3 and most PowerPCs.
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array?
SLIDE 64 13
all data flow from to branch conditions. all data flow from to array indices. all data flow from to shift/rotate distances. logic instructions. vector instructions.
riable-time multipliers: e.g., rtex-M3 and most PowerPCs.
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array? Eliminating Let’s try Assume
SLIDE 65
13
flow from ranch conditions. flow from indices. flow from shift/rotate distances. instructions. instructions. CPUs with multipliers: e.g., most PowerPCs.
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array? Eliminating branches Let’s try sorting 2 Assume int32 is secret
SLIDE 66
13
conditions. distances. e.g., erPCs.
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array? Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
SLIDE 67
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array?
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
SLIDE 68
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array?
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
SLIDE 69
14
Suppose we know (some) const-time machine instructions. Suppose programming language has “secret” types. Easy for compiler to guarantee that secret types are used only by const-time instructions. Proofs of concept: Valgrind (uninitialized data as secret), ctgrind, ct-verif, FlowTracker. How can we implement, e.g., sorting of a secret array?
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
SLIDE 70 14
const-time machine instructions.
secret” types. for compiler to guarantee secret types are used only const-time instructions.
(uninitialized data as secret), ctgrind, ct-verif, FlowTracker. can we implement, e.g.,
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
void sort2(int32 { int32 int32 if (x1 x[0] x[1] } else x[0] x[1] } }
SLIDE 71
14
w (some) machine instructions. rogramming language ypes. compiler to guarantee es are used only instructions. concept: Valgrind data as secret), FlowTracker. implement, e.g., secret array?
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
void sort2(int32 { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
SLIDE 72
14
instructions. nguage rantee used only instructions. d secret), ker. e.g.,
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
SLIDE 73
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
SLIDE 74
15
Eliminating branches Let’s try sorting 2 integers. Assume int32 is secret.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } }
Unacceptable: not constant-time.
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
SLIDE 75
15
Eliminating branches try sorting 2 integers. Assume int32 is secret.
sort2(int32 *x) x0 = x[0]; x1 = x[1]; (x1 < x0) { x[0] = x1; x[1] = x0;
Unacceptable: not constant-time.
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
void sort2(int32 { int32 int32 int32 x[0] = x[1] = }
SLIDE 76
15
ranches 2 integers. is secret.
*x) x[0]; x[1];
not constant-time.
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
void sort2(int32 { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x[0] = (c ? x1 x[1] = (c ? x0 }
SLIDE 77
15
rs. constant-time.
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
SLIDE 78
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
SLIDE 79
16
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; if (x1 < x0) { x[0] = x1; x[1] = x0; } else { x[0] = x0; x[1] = x1; } }
Safe compiler won’t allow this. Branch timing leaks secrets.
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1;
SLIDE 80
16
sort2(int32 *x) x0 = x[0]; x1 = x[1]; (x1 < x0) { x[0] = x1; x[1] = x0; else { x[0] = x0; x[1] = x1;
compiler won’t allow this. Branch timing leaks secrets.
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1; void sort2(int32 { int32 int32 int32 x[c] = x[1 - }
SLIDE 81 16
*x) x[0]; x[1];
leaks secrets.
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1; void sort2(int32 { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x[c] = x0; x[1 - c] = x1; }
SLIDE 82
16
this. secrets.
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1; void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
SLIDE 83
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1;
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
SLIDE 84
17
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[0] = (c ? x1 : x0); x[1] = (c ? x0 : x1); }
Syntax is different but “?:” is a branch by definition:
if (x1 < x0) x[0] = x1; else x[0] = x0; if (x1 < x0) x[1] = x0; else x[1] = x1;
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
SLIDE 85
17
sort2(int32 *x) x0 = x[0]; x1 = x[1]; c = (x1 < x0); = (c ? x1 : x0); = (c ? x0 : x1);
is different but “?:” ranch by definition:
(x1 < x0) x[0] = x1; x[0] = x0; (x1 < x0) x[1] = x0; x[1] = x1;
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
void sort2(int32 { int32 int32 int32 c *= x1 x[0] = x[1] = }
SLIDE 86
17
*x) x[0]; x[1]; < x0); : x0); : x1);
different but “?:” efinition:
x[0] = x1; x0; x[1] = x0; x1;
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
void sort2(int32 { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
SLIDE 87
17
”
x1; x0;
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
SLIDE 88
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
SLIDE 89
18
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); x[c] = x0; x[1 - c] = x1; }
Safe compiler won’t allow this: won’t allow secret data to be used as an array index. Cache timing is not constant: see earlier attack examples.
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
Does safe compiler allow multiplication of secrets? Recall that multiplication takes variable time on, e.g., Cortex-M3 and most PowerPCs.
SLIDE 90
18
sort2(int32 *x) x0 = x[0]; x1 = x[1]; c = (x1 < x0); = x0; c] = x1;
compiler won’t allow this: allow secret data used as an array index. timing is not constant: rlier attack examples.
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
Does safe compiler allow multiplication of secrets? Recall that multiplication takes variable time on, e.g., Cortex-M3 and most PowerPCs. Will want for fast p but let’s for this so
void sort2(int32 { int32 int32 int32 c &= x1 x[0] = x[1] = }
SLIDE 91 18
*x) x[0]; x[1]; < x0);
secret data array index. not constant: examples.
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
Does safe compiler allow multiplication of secrets? Recall that multiplication takes variable time on, e.g., Cortex-M3 and most PowerPCs. Will want to handle for fast prime-field but let’s dodge the for this sorting code:
void sort2(int32 { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
SLIDE 92
18
this: index. constant: examples.
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
Does safe compiler allow multiplication of secrets? Recall that multiplication takes variable time on, e.g., Cortex-M3 and most PowerPCs. Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
SLIDE 93
19
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = (x1 < x0); c *= x1 - x0; x[0] = x0 + c; x[1] = x1 - c; }
Does safe compiler allow multiplication of secrets? Recall that multiplication takes variable time on, e.g., Cortex-M3 and most PowerPCs.
20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
SLIDE 94 19
sort2(int32 *x) x0 = x[0]; x1 = x[1]; c = (x1 < x0); x1 - x0; = x0 + c; = x1 - c;
safe compiler allow multiplication of secrets? that multiplication variable time on, e.g., rtex-M3 and most PowerPCs.
20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
(also for C standa int32 as “undefined” Real CPU but C compiler
SLIDE 95 19
*x) x[0]; x[1]; < x0);
compiler allow secrets? multiplication time on, e.g., most PowerPCs.
20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
(also for previous co C standard does not int32 as twos-complement; “undefined” behavio Real CPU uses twos-complement but C compiler can
SLIDE 96 19
e.g., erPCs.
20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
- 1. Possible correctness problem
(also for previous code): C standard does not define int32 as twos-complement; “undefined” behavior on overflo Real CPU uses twos-complement but C compiler can screw this
SLIDE 97 20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up.
SLIDE 98 20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
SLIDE 99 20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t?
SLIDE 100 20
Will want to handle this issue for fast prime-field ECC etc., but let’s dodge the issue for this sorting code:
void sort2(int32 *x) { int32 x0 = x[0]; int32 x1 = x[1]; int32 c = -(x1 < x0); c &= x1 ^ x0; x[0] = x0 ^ c; x[1] = x1 ^ c; }
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this.
SLIDE 101 20
ant to handle this issue fast prime-field ECC etc., let’s dodge the issue is sorting code:
sort2(int32 *x) x0 = x[0]; x1 = x[1]; c = -(x1 < x0); x1 ^ x0; = x0 ^ c; = x1 ^ c;
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this. Constant-time
int32 isnegative(int32 { return
Returns
SLIDE 102 20
handle this issue rime-field ECC etc., the issue code:
*x) x[0]; x[1]; < x0);
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this. Constant-time com
int32 isnegative(int32 { return x >> 31;
Returns -1 if x < 0
SLIDE 103 20
issue etc.,
21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this. Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise
SLIDE 104 21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this.
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0.
SLIDE 105 21
- 1. Possible correctness problems
(also for previous code): C standard does not define int32 as twos-complement; says “undefined” behavior on overflow. Real CPU uses twos-complement but C compiler can screw this up. Fix: use gcc -fwrapv.
- 2. Does safe compiler allow
“x1 < x0” for secrets? What do we do if it doesn’t? C compilers sometimes use constant-time instructions for this.
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
SLIDE 106 21
- ssible correctness problems
for previous code): standard does not define as twos-complement; says “undefined” behavior on overflow. CPU uses twos-complement compiler can screw this up. use gcc -fwrapv. es safe compiler allow
x0” for secrets?
do we do if it doesn’t? compilers sometimes use constant-time instructions for this.
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
int32 ispositive(int32 { return
SLIDE 107 21
rrectness problems revious code): not define
ehavior on overflow. wos-complement can screw this up.
compiler allow secrets? if it doesn’t? sometimes use instructions for this.
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
int32 ispositive(int32 { return isnegative(-x);
SLIDE 108 21
roblems define
- s-complement; says
- verflow.
- s-complement
this up. w esn’t? use for this.
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
int32 ispositive(int32 x) { return isnegative(-x);
SLIDE 109
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
23
int32 ispositive(int32 x) { return isnegative(-x); }
SLIDE 110
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231.
SLIDE 111
22
Constant-time comparisons
int32 isnegative(int32 x) { return x >> 31; }
Returns -1 if x < 0, otherwise 0. Why this works: the bits (b31; b30; : : : ; b2; b1; b0) represent the integer b0 + 2b1 + 4b2 + · · · + 230b30 − 231b31. “1-bit signed right shift”: (b31; b31; : : : ; b3; b2; b1). “31-bit signed right shift”: (b31; b31; : : : ; b31; b31; b31).
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
SLIDE 112
22
Constant-time comparisons
isnegative(int32 x) return x >> 31; }
Returns -1 if x < 0, otherwise 0. this works: the bits
30; : : : ; b2; b1; b0)
resent the integer b0 + 2b1 + · · · + 230b30 − 231b31. signed right shift”:
31; : : : ; b3; b2; b1).
“31-bit signed right shift”:
31; : : : ; b31; b31; b31).
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
Side note
int32 ispositive(int32 { if (x return
SLIDE 113
22
comparisons
isnegative(int32 x) 31; }
0, otherwise 0. the bits ; b1; b0) integer b0 + 2b1 +
30 − 231b31.
right shift”: ; b2; b1). right shift”: ; b31; b31).
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
Side note illustrating
int32 ispositive(int32 { if (x == -x) return return isnegative(-x);
SLIDE 114 22
risons
x)
2b1 +
31.
shift”: ).
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
Side note illustrating -fwrapv
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x);
SLIDE 115
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
SLIDE 116
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time.
SLIDE 117
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code.
SLIDE 118
23
int32 ispositive(int32 x) { return isnegative(-x); }
This code is incorrect! Fails for input −231, because “-x” produces −231. Can catch this bug by testing:
int64 x; int32 c; for (x = INT32_MIN; x <= INT32_MAX;++x) { c = ispositive(x); assert(c == -(x > 0)); }
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
SLIDE 119
23
ispositive(int32 x) return isnegative(-x); }
code is incorrect! for input −231, ecause “-x” produces −231. catch this bug by testing:
x; int32 c; = INT32_MIN; <= INT32_MAX;++x) { ispositive(x); assert(c == -(x > 0));
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
int32 isnonzero(int32 { return || isnegative(-x);
SLIDE 120 23
ispositive(int32 x) isnegative(-x); }
rrect! 231, roduces −231. bug by testing:
c; INT32_MIN; INT32_MAX;++x) { ispositive(x);
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
int32 isnonzero(int32 { return isnegative(x) || isnegative(-x);
SLIDE 121
23
x) }
231. testing:
{
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
SLIDE 122
24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
SLIDE 123 24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
SLIDE 124 24
Side note illustrating -fwrapv:
int32 ispositive(int32 x) { if (x == -x) return 0; return isnegative(-x); }
Not constant-time. Even worse: without -fwrapv, current gcc can remove the x == -x test, breaking this code. Incompetent gcc engineering: source of many security holes. Incompetent language standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
SLIDE 125 24
note illustrating -fwrapv:
ispositive(int32 x) == -x) return 0; return isnegative(-x); }
constant-time.
current gcc can remove the test, breaking this code. Incompetent gcc engineering:
Incompetent language standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
int32 issmaller(int32 { return
SLIDE 126 24
illustrating -fwrapv:
ispositive(int32 x) return 0; isnegative(-x); }
constant-time. without -fwrapv, remove the reaking this code. engineering: security holes. language standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
int32 issmaller(int32 { return isnegative(x
SLIDE 127 24
x) }
the this code. engineering: holes. standard.
25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
int32 issmaller(int32 x,int32 { return isnegative(x - y);
SLIDE 128 25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
SLIDE 129 25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231).
SLIDE 130 25
int32 isnonzero(int32 x) { return isnegative(x) || isnegative(-x); }
Not constant-time. Second part is evaluated
- nly if first part is zero.
int32 isnonzero(int32 x) { return isnegative(x) | isnegative(-x); }
Constant-time logic instructions. Safe compiler will allow this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); }
SLIDE 131
25
isnonzero(int32 x) return isnegative(x) isnegative(-x); }
constant-time. Second part is evaluated first part is zero.
isnonzero(int32 x) return isnegative(x) isnegative(-x); }
Constant-time logic instructions. compiler will allow this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); } int32 issmaller(int32 { int32 int32 c ^= xy return }
SLIDE 132
25
isnonzero(int32 x) isnegative(x) isnegative(-x); }
constant-time. evaluated is zero.
isnonzero(int32 x) isnegative(x) isnegative(-x); }
logic instructions. will allow this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); } int32 issmaller(int32 { int32 xy = x ^ int32 c = x - y; c ^= xy & (c ^ return isnegative(c); }
SLIDE 133
25
instructions. this.
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); } int32 issmaller(int32 x,int32 { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
SLIDE 134
26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); }
27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
SLIDE 135 26
int32 issmaller(int32 x,int32 y) { return isnegative(x - y); }
This code is incorrect! Generalization of ispositive. Wrong for inputs (0; −231). Wrong for many more inputs. Caught quickly by random tests:
for (j = 0;j < 10000000;++j) { x += random(); y += random(); c = issmaller(x,y); assert(c == -(x < y)); }
27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
Some verification strategies:
- Think this through.
- Write a proof.
- Formally verify proof.
- Automate proof construction.
- Test many random inputs.
- A bit painful: test all inputs.
- Faster: test int16 version.
SLIDE 136 26
issmaller(int32 x,int32 y) return isnegative(x - y); }
code is incorrect! Generalization of ispositive. for inputs (0; −231). for many more inputs. Caught quickly by random tests:
= 0;j < 10000000;++j) { random(); y += random(); issmaller(x,y); assert(c == -(x < y));
27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
Some verification strategies:
- Think this through.
- Write a proof.
- Formally verify proof.
- Automate proof construction.
- Test many random inputs.
- A bit painful: test all inputs.
- Faster: test int16 version.
void minmax(int32 { int32 int32 int32 int32 c ^= ab c >>= c &= ab; *x = a *y = b } void sort2(int32 { minmax(x,x
SLIDE 137 26
issmaller(int32 x,int32 y) isnegative(x - y); }
rrect!
inputs (0; −231). more inputs. by random tests:
10000000;++j) { y += random(); issmaller(x,y);
27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
Some verification strategies:
- Think this through.
- Write a proof.
- Formally verify proof.
- Automate proof construction.
- Test many random inputs.
- A bit painful: test all inputs.
- Faster: test int16 version.
void minmax(int32 { int32 a = *x; int32 b = *y; int32 ab = b ^ int32 c = b - a; c ^= ab & (c ^ c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 { minmax(x,x + 1);
SLIDE 138 26
x,int32 y) y); }
ispositive. ). inputs. tests:
10000000;++j) { random();
27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
Some verification strategies:
- Think this through.
- Write a proof.
- Formally verify proof.
- Automate proof construction.
- Test many random inputs.
- A bit painful: test all inputs.
- Faster: test int16 version.
void minmax(int32 *x,int32 { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); }
SLIDE 139 27
int32 issmaller(int32 x,int32 y) { int32 xy = x ^ y; int32 c = x - y; c ^= xy & (c ^ x); return isnegative(c); }
Some verification strategies:
- Think this through.
- Write a proof.
- Formally verify proof.
- Automate proof construction.
- Test many random inputs.
- A bit painful: test all inputs.
- Faster: test int16 version.
28
void minmax(int32 *x,int32 *y) { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); }
SLIDE 140
27
issmaller(int32 x,int32 y) xy = x ^ y; c = x - y; xy & (c ^ x); return isnegative(c);
verification strategies: Think this through. rite a proof. ally verify proof. Automate proof construction. many random inputs. bit painful: test all inputs. aster: test int16 version.
28
void minmax(int32 *x,int32 *y) { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); } int32 ispositive(int32 { int32 c ^= x return } void sort(int32 { long long for (j for minmax(x }
Safe compiler if array length
SLIDE 141 27
issmaller(int32 x,int32 y) y; y; x); isnegative(c);
verification strategies: rough. proof.
random inputs. test all inputs. int16 version.
28
void minmax(int32 *x,int32 *y) { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); } int32 ispositive(int32 { int32 c = -x; c ^= x & c; return isnegative(c); } void sort(int32 *x,long { long long i,j; for (j = 0;j < for (i = j - minmax(x + }
Safe compiler will if array length n is
SLIDE 142
27
x,int32 y)
strategies: construction. puts. inputs. version.
28
void minmax(int32 *x,int32 *y) { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); } int32 ispositive(int32 x) { int32 c = -x; c ^= x & c; return isnegative(c); } void sort(int32 *x,long long { long long i,j; for (j = 0;j < n;++j) for (i = j - 1;i >= 0;--i) minmax(x + i,x + i }
Safe compiler will allow this if array length n is not secret
SLIDE 143
28
void minmax(int32 *x,int32 *y) { int32 a = *x; int32 b = *y; int32 ab = b ^ a; int32 c = b - a; c ^= ab & (c ^ b); c >>= 31; c &= ab; *x = a ^ c; *y = b ^ c; } void sort2(int32 *x) { minmax(x,x + 1); }
29
int32 ispositive(int32 x) { int32 c = -x; c ^= x & c; return isnegative(c); } void sort(int32 *x,long long n) { long long i,j; for (j = 0;j < n;++j) for (i = j - 1;i >= 0;--i) minmax(x + i,x + i + 1); }
Safe compiler will allow this if array length n is not secret.