aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/ct_utils.h
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-10-16 17:39:43 -0400
committerJack Lloyd <[email protected]>2015-10-16 17:39:43 -0400
commitea07110c86c7ae2601e71dd3c1134873ccfd721f (patch)
tree1ccbb775a624d8a977f21a37b2d60a619fc0824f /src/lib/utils/ct_utils.h
parentf257cb324614adb5f9266ca185ab2bfeb64b1dd4 (diff)
Make PKCS #1 and OAEP decoding constant time to avoid oracle attacks
via timing channels. Add annotations for checking constant-time code using ctgrind to PKCS #1 and OAEP, as well as IDEA and Curve25519 which were already written as constant time code.
Diffstat (limited to 'src/lib/utils/ct_utils.h')
-rw-r--r--src/lib/utils/ct_utils.h207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/lib/utils/ct_utils.h b/src/lib/utils/ct_utils.h
new file mode 100644
index 000000000..02148001e
--- /dev/null
+++ b/src/lib/utils/ct_utils.h
@@ -0,0 +1,207 @@
+/*
+* Functions for constant time operations on data and testing of
+* constant time annotations using ctgrind.
+*
+* For more information about constant time programming see
+* Wagner, Molnar, et al "The Program Counter Security Model"
+*
+* (C) 2010 Falko Strenzke
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_TIMING_ATTACK_CM_H__
+#define BOTAN_TIMING_ATTACK_CM_H__
+
+#include <botan/types.h>
+#include <vector>
+
+#if defined(BOTAN_USE_CTGRIND)
+
+// These are external symbols from libctgrind.so
+extern "C" void ct_poison(const void* address, size_t length);
+extern "C" void ct_unpoison(const void* address, size_t length);
+
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_USE_CTGRIND)
+
+#define BOTAN_CONST_TIME_POISON(p, l) ct_poison(p, l)
+#define BOTAN_CONST_TIME_UNPOISON(p, l) ct_unpoison(p, l)
+
+#else
+
+#define BOTAN_CONST_TIME_POISON(p, l)
+#define BOTAN_CONST_TIME_UNPOISON(p, l)
+
+#endif
+
+/*
+* Constant time operations for 32 bit values:
+* mask, select, zero, equals, min, max
+*/
+
+/*
+* Expand to a mask used for other operations
+* @param in an integer
+* @return 0 if in == 0 else 0xFFFFFFFF
+*/
+
+inline uint32_t ct_expand_mask_32(uint32_t x)
+ {
+ uint32_t r = x;
+ r |= r >> 1;
+ r |= r >> 2;
+ r |= r >> 4;
+ r |= r >> 8;
+ r |= r >> 16;
+ r &= 1;
+ r = ~(r - 1);
+ return r;
+ }
+
+inline uint32_t ct_select_mask_32(uint32_t mask, uint32_t a, uint32_t b)
+ {
+ return (a & mask) | (b & ~mask);
+ }
+
+inline uint32_t ct_select_cond_32(bool cond, uint32_t a, uint32_t b)
+ {
+ return ct_select_mask_32(ct_expand_mask_32(static_cast<uint32_t>(cond)), a, b);
+ }
+
+inline uint32_t ct_get_high_bit_32(uint32_t x)
+ {
+ return (x >> (8 * sizeof(x) - 1));
+ }
+
+/*
+* If x is zero, return 0xFFFF...
+* Otherwise returns zero
+*/
+inline uint32_t ct_is_zero_32(uint32_t x)
+ {
+ return ct_expand_mask_32(ct_get_high_bit_32(~x & (x-1)));
+ }
+
+inline uint32_t ct_is_equal_32(uint32_t x, uint32_t y)
+ {
+ return ct_is_zero_32(x ^ y);
+ }
+
+/**
+* Branch-free maximum
+* Note: assumes twos-complement signed representation
+* @param a an integer
+* @param b an integer
+* @return max(a,b)
+*/
+inline uint32_t ct_max_32(uint32_t a, uint32_t b)
+ {
+ const uint32_t s = b - a;
+ return ct_select_cond_32(ct_get_high_bit_32(s), a, b);
+ }
+
+/**
+* Branch-free minimum
+* Note: assumes twos-complement signed representation
+* @param a an integer
+* @param b an integer
+* @return min(a,b)
+*/
+inline uint32_t ct_min_32(uint32_t a, uint32_t b)
+ {
+ const uint32_t s = b - a;
+ return ct_select_cond_32(ct_get_high_bit_32(s), b, a);
+ }
+
+/*
+* Constant time operations for 16 bit values:
+* mask, select, zero, equals
+*/
+inline uint16_t ct_expand_mask_16(uint16_t x)
+ {
+ uint16_t r = x;
+ r |= r >> 1;
+ r |= r >> 2;
+ r |= r >> 4;
+ r |= r >> 8;
+ r &= 1;
+ r = ~(r - 1);
+ return r;
+ }
+
+inline uint16_t ct_select_mask_16(uint16_t mask, uint16_t a, uint16_t b)
+ {
+ return (a & mask) | (b & ~mask);
+ }
+
+inline uint16_t ct_select_cond_16(bool cond, uint16_t a, uint16_t b)
+ {
+ return ct_select_mask_16(ct_expand_mask_16(static_cast<uint16_t>(cond)), a, b);
+ }
+
+inline uint16_t ct_get_high_bit_16(uint16_t x)
+ {
+ return (x >> (8 * sizeof(x) - 1));
+ }
+
+inline uint16_t ct_is_zero_16(uint16_t x)
+ {
+ //uint16_t z = x & (x - 1)
+ //return ct_expand_mask_16((~x & (x-1))
+ return ct_expand_mask_16(ct_get_high_bit_16(~x & (x-1)));
+ }
+
+inline uint16_t ct_is_equal_16(uint16_t x, uint16_t y)
+ {
+ return ct_is_zero_16(x ^ y);
+ }
+
+/*
+* Constant time operations for 8 bit values:
+* mask, select, zero, equals
+*/
+
+inline uint8_t ct_expand_mask_8(uint8_t x)
+ {
+ uint8_t r = x;
+ r |= r >> 4;
+ r |= r >> 2;
+ r |= r >> 1;
+ r &= 1;
+ r = ~(r - 1);
+ return r;
+ }
+
+inline uint8_t ct_select_mask_8(uint8_t mask, uint8_t a, uint8_t b)
+ {
+ return (a & mask) | (b & ~mask);
+ }
+
+inline uint8_t ct_select_cond_8(bool cond, uint8_t a, uint8_t b)
+ {
+ return ct_select_mask_8(ct_expand_mask_8(static_cast<uint8_t>(cond)), a, b);
+ }
+
+inline uint8_t ct_get_high_bit_8(uint8_t x)
+ {
+ return (x >> (8 * sizeof(x) - 1));
+ }
+
+inline uint8_t ct_is_zero_8(uint8_t x)
+ {
+ return ct_expand_mask_8(ct_get_high_bit_8(~x & (x-1)));
+ }
+
+inline uint8_t ct_is_equal_8(uint8_t x, uint8_t y)
+ {
+ return ct_is_zero_8(x ^ y);
+ }
+
+}
+
+#endif