bitops.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * cifra - embedded cryptography library
  3. * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
  4. *
  5. * To the extent possible under law, the author(s) have dedicated all
  6. * copyright and related and neighboring rights to this software to the
  7. * public domain worldwide. This software is distributed without any
  8. * warranty.
  9. *
  10. * You should have received a copy of the CC0 Public Domain Dedication
  11. * along with this software. If not, see
  12. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  13. */
  14. #ifndef BITOPS_H
  15. #define BITOPS_H
  16. #include <stdint.h>
  17. #include <stddef.h>
  18. /* Assorted bitwise and common operations used in ciphers. */
  19. /** Circularly rotate right x by n bits.
  20. * 0 > n > 32. */
  21. static inline uint32_t rotr32(uint32_t x, unsigned n)
  22. {
  23. return (x >> n) | (x << (32 - n));
  24. }
  25. /** Circularly rotate left x by n bits.
  26. * 0 > n > 32. */
  27. static inline uint32_t rotl32(uint32_t x, unsigned n)
  28. {
  29. return (x << n) | (x >> (32 - n));
  30. }
  31. /** Circularly rotate right x by n bits.
  32. * 0 > n > 64. */
  33. static inline uint64_t rotr64(uint64_t x, unsigned n)
  34. {
  35. return (x >> n) | (x << (64 - n));
  36. }
  37. /** Circularly rotate left x by n bits.
  38. * 0 > n > 64. */
  39. static inline uint64_t rotl64(uint64_t x, unsigned n)
  40. {
  41. return (x << n) | (x >> (64 - n));
  42. }
  43. /** Read 4 bytes from buf, as a 32-bit big endian quantity. */
  44. static inline uint32_t read32_be(const uint8_t buf[4])
  45. {
  46. return (buf[0] << 24) |
  47. (buf[1] << 16) |
  48. (buf[2] << 8) |
  49. (buf[3]);
  50. }
  51. /** Read 4 bytes from buf, as a 32-bit little endian quantity. */
  52. static inline uint32_t read32_le(const uint8_t buf[4])
  53. {
  54. return (buf[3] << 24) |
  55. (buf[2] << 16) |
  56. (buf[1] << 8) |
  57. (buf[0]);
  58. }
  59. /** Read 8 bytes from buf, as a 64-bit big endian quantity. */
  60. static inline uint64_t read64_be(const uint8_t buf[8])
  61. {
  62. uint32_t hi = read32_be(buf),
  63. lo = read32_be(buf + 4);
  64. return ((uint64_t)hi) << 32 |
  65. lo;
  66. }
  67. /** Read 8 bytes from buf, as a 64-bit little endian quantity. */
  68. static inline uint64_t read64_le(const uint8_t buf[8])
  69. {
  70. uint32_t hi = read32_le(buf + 4),
  71. lo = read32_le(buf);
  72. return ((uint64_t)hi) << 32 |
  73. lo;
  74. }
  75. /** Encode v as a 32-bit big endian quantity into buf. */
  76. static inline void write32_be(uint32_t v, uint8_t buf[4])
  77. {
  78. *buf++ = (v >> 24) & 0xff;
  79. *buf++ = (v >> 16) & 0xff;
  80. *buf++ = (v >> 8) & 0xff;
  81. *buf = v & 0xff;
  82. }
  83. /** Encode v as a 32-bit little endian quantity into buf. */
  84. static inline void write32_le(uint32_t v, uint8_t buf[4])
  85. {
  86. *buf++ = v & 0xff;
  87. *buf++ = (v >> 8) & 0xff;
  88. *buf++ = (v >> 16) & 0xff;
  89. *buf = (v >> 24) & 0xff;
  90. }
  91. /** Encode v as a 64-bit big endian quantity into buf. */
  92. static inline void write64_be(uint64_t v, uint8_t buf[8])
  93. {
  94. *buf++ = (v >> 56) & 0xff;
  95. *buf++ = (v >> 48) & 0xff;
  96. *buf++ = (v >> 40) & 0xff;
  97. *buf++ = (v >> 32) & 0xff;
  98. *buf++ = (v >> 24) & 0xff;
  99. *buf++ = (v >> 16) & 0xff;
  100. *buf++ = (v >> 8) & 0xff;
  101. *buf = v & 0xff;
  102. }
  103. /** Encode v as a 64-bit little endian quantity into buf. */
  104. static inline void write64_le(uint64_t v, uint8_t buf[8])
  105. {
  106. *buf++ = v & 0xff;
  107. *buf++ = (v >> 8) & 0xff;
  108. *buf++ = (v >> 16) & 0xff;
  109. *buf++ = (v >> 24) & 0xff;
  110. *buf++ = (v >> 32) & 0xff;
  111. *buf++ = (v >> 40) & 0xff;
  112. *buf++ = (v >> 48) & 0xff;
  113. *buf = (v >> 56) & 0xff;
  114. }
  115. /** out = in ^ b8.
  116. * out and in may alias. */
  117. static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len)
  118. {
  119. for (size_t i = 0; i < len; i++)
  120. out[i] = in[i] ^ b8;
  121. }
  122. /** out = x ^ y.
  123. * out, x and y may alias. */
  124. static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len)
  125. {
  126. for (size_t i = 0; i < len; i++)
  127. out[i] = x[i] ^ y[i];
  128. }
  129. /* out ^= x
  130. * out and x may alias. */
  131. static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords)
  132. {
  133. for (size_t i = 0; i < nwords; i++)
  134. out[i] ^= x[i];
  135. }
  136. /** Produce 0xffffffff if x == y, zero otherwise, without branching. */
  137. static inline uint32_t mask_u32(uint32_t x, uint32_t y)
  138. {
  139. uint32_t diff = x ^ y;
  140. uint32_t diff_is_zero = ~diff & (diff - 1);
  141. return - (diff_is_zero >> 31);
  142. }
  143. /** Product 0xff if x == y, zero otherwise, without branching. */
  144. static inline uint8_t mask_u8(uint32_t x, uint32_t y)
  145. {
  146. uint32_t diff = x ^ y;
  147. uint8_t diff_is_zero = ~diff & (diff - 1);
  148. return - (diff_is_zero >> 7);
  149. }
  150. /** Select the ith entry from the given table of n values, in a side channel-silent
  151. * way. */
  152. static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n)
  153. {
  154. uint32_t r = 0;
  155. for (uint32_t ii = 0; ii < n; ii++)
  156. {
  157. uint32_t mask = mask_u32(i, ii);
  158. r = (r & ~mask) | (tab[ii] & mask);
  159. }
  160. return r;
  161. }
  162. /** Select the ith entry from the given table of n values, in a side channel-silent
  163. * way. */
  164. static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n)
  165. {
  166. uint8_t r = 0;
  167. for (uint32_t ii = 0; ii < n; ii++)
  168. {
  169. uint8_t mask = mask_u8(i, ii);
  170. r = (r & ~mask) | (tab[ii] & mask);
  171. }
  172. return r;
  173. }
  174. /** Select the ath, bth, cth and dth entries from the given table of n values,
  175. * placing the results into a, b, c and d. */
  176. static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
  177. volatile const uint8_t *tab, uint32_t n)
  178. {
  179. uint8_t ra = 0,
  180. rb = 0,
  181. rc = 0,
  182. rd = 0;
  183. uint8_t mask;
  184. for (uint32_t i = 0; i < n; i++)
  185. {
  186. uint8_t item = tab[i];
  187. mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask);
  188. mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask);
  189. mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask);
  190. mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask);
  191. }
  192. *a = ra;
  193. *b = rb;
  194. *c = rc;
  195. *d = rd;
  196. }
  197. /** out ^= if0 or if1, depending on the value of bit. */
  198. static inline void select_xor128(uint32_t out[4],
  199. const uint32_t if0[4],
  200. const uint32_t if1[4],
  201. uint8_t bit)
  202. {
  203. uint32_t mask1 = mask_u32(bit, 1);
  204. uint32_t mask0 = ~mask1;
  205. out[0] ^= (if0[0] & mask0) | (if1[0] & mask1);
  206. out[1] ^= (if0[1] & mask0) | (if1[1] & mask1);
  207. out[2] ^= (if0[2] & mask0) | (if1[2] & mask1);
  208. out[3] ^= (if0[3] & mask0) | (if1[3] & mask1);
  209. }
  210. /** Increments the integer stored at v (of non-zero length len)
  211. * with the least significant byte first. */
  212. static inline void incr_le(uint8_t *v, size_t len)
  213. {
  214. size_t i = 0;
  215. while (1)
  216. {
  217. if (++v[i] != 0)
  218. return;
  219. i++;
  220. if (i == len)
  221. return;
  222. }
  223. }
  224. /** Increments the integer stored at v (of non-zero length len)
  225. * with the most significant byte last. */
  226. static inline void incr_be(uint8_t *v, size_t len)
  227. {
  228. len--;
  229. while (1)
  230. {
  231. if (++v[len] != 0)
  232. return;
  233. if (len == 0)
  234. return;
  235. len--;
  236. }
  237. }
  238. /** Copies len bytes from in to out, with in shifted left by offset bits
  239. * to the right. */
  240. static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset)
  241. {
  242. uint8_t byte_off = offset / 8;
  243. uint8_t bit_off = offset & 7;
  244. uint8_t rmask = (1 << bit_off) - 1;
  245. uint8_t lmask = ~rmask;
  246. for (size_t i = 0; i < len; i++)
  247. {
  248. out[i] = (in[i + byte_off] << bit_off) & lmask;
  249. out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask;
  250. }
  251. }
  252. #endif