constant time programming in fact
play

Constant-time programming in FaCT Sunjay Cauligi , UC San Diego - PowerPoint PPT Presentation

Constant-time programming in FaCT Sunjay Cauligi , UC San Diego Fraser Brown, Ranjit Jhala, Brian Johannesmeyer, John Renner, Gary Soeller, Deian Stefan, Riad Wahby Timing side channels Crypto Constant-time programming with FaCT Strange Loop


  1. Padding removal: 1st try int32_t remove_padding( int32_t remove_padding2( uint8_t* buf, uint8_t* buf, uint32_t buflen) { uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint8_t padlen = buf[buflen-1]; uint32_t i; uint32_t i; for (i = 0; i < padlen; i++) { for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) if (buf[buflen-i-1] != padlen) return -1; ok = 0; buf[buflen-i-1] = 0; buf[buflen-i-1] = 0; } } return padlen; return ok ? padlen : -1; } } 10μs 10μs 53 74 ... 4c 6f 6f 70 05 05 07 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  2. Padding removal: 1st try int32_t remove_padding( int32_t remove_padding2( uint8_t* buf, uint8_t* buf, uint32_t buflen) { uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint8_t padlen = buf[buflen-1]; uint32_t i; uint32_t i; for (i = 0; i < padlen; i++) { for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) if (buf[buflen-i-1] != padlen) return -1; ok = 0; buf[buflen-i-1] = 0; buf[buflen-i-1] = 0; } } return padlen; return ok ? padlen : -1; } } 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 00 00 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  3. Padding removal: 2nd try int32_t remove_padding2( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) ok = 0; buf[buflen-i-1] = 0; } return ok ? padlen : -1; } 53 74 ... 4c 6f 6f 70 05 05 05 05 05 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  4. Padding removal: 2nd try int32_t remove_padding2( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) ok = 0; buf[buflen-i-1] = 0; } return ok ? padlen : -1; } 53 74 ... 4c 6f 6f 70 05 05 05 05 05 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  5. Padding removal: 2nd try int32_t remove_padding2( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) ok = 0; buf[buflen-i-1] = 0; } return ok ? padlen : -1; } 53 74 ... 4c 6f 6f 70 31 38 03 03 03 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  6. Padding removal: 2nd try int32_t remove_padding2( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) ok = 0; buf[buflen-i-1] = 0; } return ok ? padlen : -1; } 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  7. Padding removal: 2nd try int32_t remove_padding2( uint8_t* buf, It’s dangerous to uint32_t buflen) { bound loops with secrets! uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for ( i = 0; i < padlen; i++) { if (buf[buflen-i-1] != padlen) ok = 0; buf[buflen-i-1] = 0; Use this instead. } return ok ? padlen : -1; } 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  8. Padding removal: 2nd try int32_t remove_padding3( uint8_t* buf, int32_t remove_padding2( uint32_t buflen) { uint8_t* buf, uint8_t ok = 1; uint32_t buflen) { uint8_t padlen = buf[buflen-1]; uint8_t ok = 1; uint32_t i; for ( i = buflen-255; i < buflen; i++) { uint8_t padlen = buf[buflen-1]; uint8_t b = buf[i]; uint32_t i; if (i >= buflen - padlen) { for (i = 0; i < padlen; i++) { if (b != padlen) if (buf[buflen-i-1] != padlen) ok = 0; ok = 0; b = 0; buf[buflen-i-1] = 0; } } buf[i] = b; return ok ? padlen : -1; } } return ok ? padlen : -1; } 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  9. Padding removal: 2nd try int32_t remove_padding3( uint8_t* buf, int32_t remove_padding2( uint32_t buflen) { uint8_t* buf, uint8_t ok = 1; uint32_t buflen) { uint8_t padlen = buf[buflen-1]; uint8_t ok = 1; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t padlen = buf[buflen-1]; uint8_t b = buf[i]; uint32_t i; if (i >= buflen - padlen) { for (i = 0; i < padlen; i++) { if (b != padlen) if (buf[buflen-i-1] != padlen) ok = 0; ok = 0; b = 0; buf[buflen-i-1] = 0; } } buf[i] = b; return ok ? padlen : -1; } } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  10. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  11. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  12. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  13. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  14. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 10μs 10μs 10μs 10μs 10μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  15. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } buf[i] = b; } return ok ? padlen : -1; } 9μs 9μs 9μs 9μs 9μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  16. Padding removal: 3rd try int32_t remove_padding3( uint8_t* buf, uint32_t buflen) { It’s dangerous to uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; have branching code! uint32_t i; for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; if (i >= buflen - padlen) { if (b != padlen) ok = 0; b = 0; } Use this instead. buf[i] = b; } return ok ? padlen : -1; } 9μs 9μs 9μs 9μs 9μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  17. Padding removal: 3rd try int32_t remove_padding4( int32_t remove_padding3( uint8_t* buf, uint8_t* buf, uint32_t buflen) { uint32_t buflen) { uint32_t ok = -1; uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint8_t padlen = buf[buflen-1]; uint32_t i; uint32_t i; for (i = buflen-255; i < buflen; i++) { for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint8_t b = buf[i]; uint32_t improper_index = if (i >= buflen - padlen) { -(i - (buflen - padlen) >> 31); if (b != padlen) uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok = 0; ok &= matches_pad | improper_index; b = 0; b = improper_index & b; } buf[i] = b; buf[i] = b; } } return (ok & padlen) | ~ok; return ok ? padlen : -1; } } 9μs 9μs 9μs 9μs 9μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  18. Padding removal: 3rd try int32_t remove_padding4( int32_t remove_padding3( uint8_t* buf, uint8_t* buf, uint32_t buflen) { uint32_t buflen) { uint32_t ok = -1; uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint8_t padlen = buf[buflen-1]; uint32_t i; Ugly! Do not read! uint32_t i; for (i = buflen-255; i < buflen; i++) { for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint8_t b = buf[i]; uint32_t improper_index = if (i >= buflen - padlen) { -(i - (buflen - padlen) >> 31); if (b != padlen) uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok = 0; ok &= matches_pad | improper_index; b = 0; b = improper_index & b; } buf[i] = b; buf[i] = b; } } return (ok & padlen) | ~ok; return ok ? padlen : -1; } } 9μs 9μs 9μs 9μs 9μs 10μs 10μs 10μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  19. Padding removal: 3rd try int32_t remove_padding4( int32_t remove_padding3( uint8_t* buf, uint8_t* buf, uint32_t buflen) { uint32_t buflen) { uint32_t ok = -1; uint8_t ok = 1; uint8_t padlen = buf[buflen-1]; uint8_t padlen = buf[buflen-1]; uint32_t i; Ugly! Do not read! uint32_t i; for (i = buflen-255; i < buflen; i++) { for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint8_t b = buf[i]; uint32_t improper_index = if (i >= buflen - padlen) { -(i - (buflen - padlen) >> 31); if (b != padlen) uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok = 0; ok &= matches_pad | improper_index; b = 0; b = improper_index & b; } buf[i] = b; buf[i] = b; } } return (ok & padlen) | ~ok; return ok ? padlen : -1; } } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  20. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  21. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); ??? uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  22. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  23. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); random_sleep(); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  24. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); random_sleep(); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  25. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); sleep_til_max(); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  26. Padding removal: 4th try int32_t remove_padding4( uint8_t* buf, uint32_t buflen) { uint32_t ok = -1; ! d a uint8_t padlen = buf[buflen-1]; e r t o n o uint32_t i; D ! y l g U for (i = buflen-255; i < buflen; i++) { uint8_t b = buf[i]; uint32_t improper_index = -(i - (buflen - padlen) >> 31); uint32_t matches_pad = -((b ^ padlen) - 1 >> 31); sleep_til_max(); ok &= matches_pad | improper_index; b = improper_index & b; buf[i] = b; } return (ok & padlen) | ~ok; } 12μs 12μs 12μs 12μs 12μs 12μs 12μs 12μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  27. Writing constant-time code is hard ● Challenge : manually ensuring code is CT Manually keep track of secret vs. public ○ Standard programming constructs introduce timing leaks ○ Can’t simply pad/randomize ○ Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  28. Writing constant-time code is hard ● Challenge : manually ensuring code is CT Manually keep track of secret vs. public ○ Standard programming constructs introduce timing leaks ○ Can’t simply pad/randomize ○ ● Consequence : vulnerabilities! Difficult to write correct code ○ Hard to understand what CT code is doing ○ Hard to maintain CT code ○ Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  29. Error-prone in practice OpenSSL padding oracle attack Canvel, et al. “Password Interception in a SSL/TLS Channel.” Crypto, Vol. 2729. 2003. Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  30. Error-prone in practice Lucky 13 timing attack Al Fardan and Paterson. “Lucky thirteen: Breaking the TLS and DTLS record protocols.” Oakland 2013. Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  31. Error-prone in practice Further refinements Decryption path has no more measurable timing differences Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  32. Error-prone in practice Further refinements Decryption path has no more measurable timing differences Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  33. Error-prone in practice CVE-2016-2107 Somorovsky. “Curious padding oracle in OpenSSL.” Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  34. This is what DSLs are for! ● Explicitly distinguish secret vs. public values ● Type system to prevent writing leaky code ● Compiler to transform high-level constructs to CT Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  35. FaCT .c cc -c ld Final binary .o .h Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  36. FaCT .fact .c cc -c ld Final binary .o .h Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  37. FaCT FaCT .fact .c cc -c ld Final binary .o .h Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  38. FaCT FaCT .fact .h .o .c cc -c ld Final binary .o .h Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  39. FaCT FaCT .fact .h .o .c .c cc -c ld Final binary .o .h .h Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  40. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  41. What does FaCT look like? secret int32 remove_padding( secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  42. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  43. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume (len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  44. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  45. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  46. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { uint8_t b = buf[i]; if (buf[i] != padlen) { uint32_t improper_index = return -1; -(i - (buflen - padlen) >> 31); } uint32_t matches_pad = buf[i] = 0; -((b ^ padlen) - 1 >> 31); } ok &= matches_pad | improper_index; } b = improper_index & b; return int32(padlen); buf[i] = b; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  47. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { uint8_t b = buf[i]; if (buf[i] != padlen) { uint32_t improper_index = return -1; -(i - (buflen - padlen) >> 31); } uint32_t matches_pad = buf[i] = 0; -((b ^ padlen) - 1 >> 31); } ok &= matches_pad | improper_index; } b = improper_index & b; return int32(padlen); buf[i] = b; } 11μs 11μs 11μs 11μs 11μs 11μs 11μs 11μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  48. What does FaCT look like? secret int32 remove_padding( secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } 11μs 11μs 11μs 11μs 11μs 11μs 11μs 11μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  49. What does FaCT look like? secret int32 remove_padding(secret mut uint8[] buf) { assume(len buf >= 255); secret uint8 padlen = buf[len buf - 1]; for (uint64 i from len buf - 255 to len buf) { if (i >= len buf - padlen) { if (buf[i] != padlen) { return -1; } buf[i] = 0; } } return int32(padlen); } 11μs 11μs 11μs 11μs 11μs 11μs 11μs 11μs 53 74 ... 4c 6f 6f 70 31 38 00 00 00 Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  50. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  51. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ for (uint32 i from 0 to secret_value ) { do_operation(); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  52. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ for (uint32 i from 0 to public_value ) { if (i < secret_value ) { do_operation(); } } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  53. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Cache lines x = sensitive_buffer[ secret_value ]; Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  54. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Cache lines for (uint32 i from public_lo to public_hi ) { if (i == secret_value ) { x = sensitive_buffer[ i ]; } } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  55. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Variable-time instructions ○ x = public_value / secret_value2 ; Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  56. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Variable-time instructions ○ x = public_value / public_value2 ; OR x = ct_div( public_value, secret_value2 ) ; Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  57. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Variable-time instructions ○ Recursive calls ○ secret uint32 fact(secret uint32 n) { if (n > 1) { return n * fact(n - 1); } return 1; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  58. Labels ensure no leakage ● No assignment from secret to public ● Type system tracks control flow label Only transform secret control flow ○ ● Prevent secret expressions that leak: Loop bounds ○ Array indices ○ Variable-time instructions ○ Recursive calls ○ secret uint32 fact(secret uint32 n) { if (n > 1) { return n * fact(n - 1); } return 1; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  59. Automatically transform code Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  60. Automatically transform code FaCT Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  61. Automatically transform code ● Transform secret branches ● Keep track of static control flow if (s) { if (s2) { x = 42; } else { x = 17; } y = x + 2; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  62. Automatically transform code ● Transform secret branches ● Keep track of static control flow if (s) { if (s2) { x = 42; x = ct_select(s & s2, 42, x); } else { x = ct_select(s & ~s2, 17, x); x = 17; y = ct_select(s, x + 2, y); } y = x + 2; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  63. Automatically transform code ● Transform away early returns ● Keep track of current return state if (s) { return 42; } return 17; Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  64. Automatically transform code ● Transform away early returns ● Keep track of current return state rval = ct_select(s & ~returned, 42, rval); if (s) { returned |= s; return 42; } rval = ct_select(~returned, 17, rval); return 17; returned |= true; ... return rval; Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  65. Automatically transform code ● Transform function side effects Depends on control flow state of caller ○ ● Pass the current control flow as an extra parameter if (s) { foo(ref x); } void foo(mut x) { x = 42; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  66. Automatically transform code ● Transform function side effects Depends on control flow state of caller ○ ● Pass the current control flow as an extra parameter if (s) { foo(ref x); foo(ref x, s); } void foo(mut x) { void foo(mut x, bool state) { x = 42; x = ct_select(state, 42, x); } } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  67. Transformations are tricky if (i < secret_index) { buf[i] = 0; } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  68. Transformations are tricky if (i < secret_index) { m = (i < secret_index); buf[i] = 0; buf[i] = ct_select(m, 0, buf[i]); } Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  69. Transformations are tricky if (i < secret_index) { m = (i < secret_index); buf[i] = 0; buf[i] = ct_select(m, 0, buf[i] ); } ● Problem: secret if-statements always perform branches Does not guard execution ○ Similar problem for secret early return ○ Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

  70. Transformations are tricky if (i < secret_index) { m = (i < secret_index); buf[i] = 0; buf[i] = ct_select(m, 0, buf[i]); } ● Problem: secret if-statements always perform branches Does not guard execution ○ Similar problem for secret early return ○ ● Solution: disallow these programs! FaCT Z3 .fact Constant-time programming with FaCT Strange Loop 2018 Sunjay Cauligi

Recommend


More recommend