ct_util.h (4361B)
1 /* 2 * ct_util.h - Constant-Time Utility Functions 3 * 4 * Provides constant-time operations to prevent timing side-channel attacks. 5 * All functions execute in time independent of secret data values. 6 */ 7 8 #ifndef CT_UTIL_H 9 #define CT_UTIL_H 10 11 #include <stdint.h> 12 #include <stddef.h> 13 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 /* ============================================================================ 19 * Constant-Time Comparison 20 * ========================================================================= */ 21 22 /** 23 * Constant-time byte comparison 24 * @return 0 if equal, non-zero otherwise (timing-safe) 25 */ 26 static inline int ct_memcmp(const void *a, const void *b, size_t len) { 27 const uint8_t *aa = (const uint8_t*)a; 28 const uint8_t *bb = (const uint8_t*)b; 29 uint8_t diff = 0; 30 31 for (size_t i = 0; i < len; i++) { 32 diff |= aa[i] ^ bb[i]; 33 } 34 35 return diff; 36 } 37 38 /** 39 * Constant-time equality check 40 * @return 1 if equal, 0 otherwise (timing-safe) 41 */ 42 static inline int ct_eq(const void *a, const void *b, size_t len) { 43 return ct_memcmp(a, b, len) == 0 ? 1 : 0; 44 } 45 46 /* ============================================================================ 47 * Constant-Time Selection 48 * ========================================================================= */ 49 50 /** 51 * Constant-time conditional select (byte) 52 * @param condition - 0 or 1 53 * @return condition ? if_true : if_false (timing-safe) 54 */ 55 static inline uint8_t ct_select_u8(uint8_t condition, uint8_t if_true, uint8_t if_false) { 56 uint8_t mask = -(uint8_t)(condition & 1); 57 return (mask & if_true) | (~mask & if_false); 58 } 59 60 /** 61 * Constant-time conditional select (32-bit) 62 */ 63 static inline uint32_t ct_select_u32(uint32_t condition, uint32_t if_true, uint32_t if_false) { 64 uint32_t mask = -(uint32_t)(condition & 1); 65 return (mask & if_true) | (~mask & if_false); 66 } 67 68 /** 69 * Constant-time conditional select (64-bit) 70 */ 71 static inline uint64_t ct_select_u64(uint64_t condition, uint64_t if_true, uint64_t if_false) { 72 uint64_t mask = -(uint64_t)(condition & 1); 73 return (mask & if_true) | (~mask & if_false); 74 } 75 76 /** 77 * Constant-time conditional copy 78 * @param condition - if 1, copy from src to dst; if 0, leave dst unchanged 79 */ 80 static inline void ct_copy(uint8_t *dst, const uint8_t *src, size_t len, uint8_t condition) { 81 uint8_t mask = -(uint8_t)(condition & 1); 82 for (size_t i = 0; i < len; i++) { 83 uint8_t tmp = dst[i]; 84 dst[i] = (mask & src[i]) | (~mask & tmp); 85 } 86 } 87 88 /* ============================================================================ 89 * Constant-Time Arithmetic 90 * ========================================================================= */ 91 92 /** 93 * Constant-time less than comparison 94 * @return 1 if a < b, 0 otherwise (timing-safe) 95 */ 96 static inline uint32_t ct_lt_u32(uint32_t a, uint32_t b) { 97 return (a ^ ((a ^ b) | ((a - b) ^ b))) >> 31; 98 } 99 100 /** 101 * Constant-time greater than or equal comparison 102 * @return 1 if a >= b, 0 otherwise (timing-safe) 103 */ 104 static inline uint32_t ct_ge_u32(uint32_t a, uint32_t b) { 105 return 1 - ct_lt_u32(a, b); 106 } 107 108 /** 109 * Constant-time check if value is zero 110 * @return 1 if zero, 0 otherwise (timing-safe) 111 */ 112 static inline uint32_t ct_is_zero_u32(uint32_t a) { 113 return 1 - ((a | (0 - a)) >> 31); 114 } 115 116 /** 117 * Constant-time absolute value (for signed 32-bit) 118 * @return |a| (timing-safe) 119 */ 120 static inline int32_t ct_abs_i32(int32_t a) { 121 int32_t mask = a >> 31; 122 return (a + mask) ^ mask; 123 } 124 125 /* ============================================================================ 126 * Secure Memory Operations 127 * ========================================================================= */ 128 129 /** 130 * Secure memory clear - prevents compiler optimization 131 * Use this instead of memset for clearing sensitive data 132 */ 133 static inline void secure_zero(void *ptr, size_t len) { 134 volatile uint8_t *p = (volatile uint8_t*)ptr; 135 while (len--) { 136 *p++ = 0; 137 } 138 } 139 140 /** 141 * Constant-time conditional swap 142 * If swap is 1, swap contents of a and b 143 * If swap is 0, leave unchanged 144 */ 145 static inline void ct_swap(uint8_t *a, uint8_t *b, size_t len, uint8_t swap) { 146 uint8_t mask = -(uint8_t)(swap & 1); 147 for (size_t i = 0; i < len; i++) { 148 uint8_t tmp = mask & (a[i] ^ b[i]); 149 a[i] ^= tmp; 150 b[i] ^= tmp; 151 } 152 } 153 154 #ifdef __cplusplus 155 } 156 #endif 157 158 #endif /* CT_UTIL_H */