endianess.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* ===================================================================
  2. *
  3. * Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. * ===================================================================
  30. */
  31. #ifndef ENDIANESS_H
  32. #define ENDIANESS_H
  33. #include "common.h"
  34. static inline void u32to8_little(uint8_t *p, const uint32_t *w)
  35. {
  36. #ifdef PYCRYPTO_LITTLE_ENDIAN
  37. memcpy(p, w, 4);
  38. #else
  39. p[0] = (uint8_t)*w;
  40. p[1] = (uint8_t)(*w >> 8);
  41. p[2] = (uint8_t)(*w >> 16);
  42. p[3] = (uint8_t)(*w >> 24);
  43. #endif
  44. }
  45. static inline void u8to32_little(uint32_t *w, const uint8_t *p)
  46. {
  47. #ifdef PYCRYPTO_LITTLE_ENDIAN
  48. memcpy(w, p, 4);
  49. #else
  50. *w = (uint32_t)p[0] | (uint32_t)p[1]<<8 | (uint32_t)p[2]<<16 | (uint32_t)p[3]<<24;
  51. #endif
  52. }
  53. static inline void u32to8_big(uint8_t *p, const uint32_t *w)
  54. {
  55. #ifdef PYCRYPTO_BIG_ENDIAN
  56. memcpy(p, w, 4);
  57. #else
  58. p[0] = (uint8_t)(*w >> 24);
  59. p[1] = (uint8_t)(*w >> 16);
  60. p[2] = (uint8_t)(*w >> 8);
  61. p[3] = (uint8_t)*w;
  62. #endif
  63. }
  64. static inline void u8to32_big(uint32_t *w, const uint8_t *p)
  65. {
  66. #ifdef PYCRYPTO_BIG_ENDIAN
  67. memcpy(w, p, 4);
  68. #else
  69. *w = (uint32_t)p[3] | (uint32_t)p[2]<<8 | (uint32_t)p[1]<<16 | (uint32_t)p[0]<<24;
  70. #endif
  71. }
  72. static inline uint32_t load_u8to32_little(const uint8_t *p)
  73. {
  74. uint32_t w;
  75. u8to32_little(&w, p);
  76. return w;
  77. }
  78. static inline uint32_t load_u8to32_big(const uint8_t *p)
  79. {
  80. uint32_t w;
  81. u8to32_big(&w, p);
  82. return w;
  83. }
  84. #define LOAD_U32_LITTLE(p) load_u8to32_little(p)
  85. #define LOAD_U32_BIG(p) load_u8to32_big(p)
  86. #define STORE_U32_LITTLE(p, w) u32to8_little((p), &(w))
  87. #define STORE_U32_BIG(p, w) u32to8_big((p), &(w))
  88. static inline void u64to8_little(uint8_t *p, const uint64_t *w)
  89. {
  90. #ifdef PYCRYPTO_LITTLE_ENDIAN
  91. memcpy(p, w, 8);
  92. #else
  93. p[0] = (uint8_t)*w;
  94. p[1] = (uint8_t)(*w >> 8);
  95. p[2] = (uint8_t)(*w >> 16);
  96. p[3] = (uint8_t)(*w >> 24);
  97. p[4] = (uint8_t)(*w >> 32);
  98. p[5] = (uint8_t)(*w >> 40);
  99. p[6] = (uint8_t)(*w >> 48);
  100. p[7] = (uint8_t)(*w >> 56);
  101. #endif
  102. }
  103. static inline void u8to64_little(uint64_t *w, const uint8_t *p)
  104. {
  105. #ifdef PYCRYPTO_LITTLE_ENDIAN
  106. memcpy(w, p, 8);
  107. #else
  108. *w = (uint64_t)p[0] |
  109. (uint64_t)p[1] << 8 |
  110. (uint64_t)p[2] << 16 |
  111. (uint64_t)p[3] << 24 |
  112. (uint64_t)p[4] << 32 |
  113. (uint64_t)p[5] << 40 |
  114. (uint64_t)p[6] << 48 |
  115. (uint64_t)p[7] << 56;
  116. #endif
  117. }
  118. static inline void u64to8_big(uint8_t *p, const uint64_t *w)
  119. {
  120. #ifdef PYCRYPTO_BIG_ENDIAN
  121. memcpy(p, w, 8);
  122. #else
  123. p[0] = (uint8_t)(*w >> 56);
  124. p[1] = (uint8_t)(*w >> 48);
  125. p[2] = (uint8_t)(*w >> 40);
  126. p[3] = (uint8_t)(*w >> 32);
  127. p[4] = (uint8_t)(*w >> 24);
  128. p[5] = (uint8_t)(*w >> 16);
  129. p[6] = (uint8_t)(*w >> 8);
  130. p[7] = (uint8_t)*w;
  131. #endif
  132. }
  133. static inline void u8to64_big(uint64_t *w, const uint8_t *p)
  134. {
  135. #ifdef PYCRYPTO_BIG_ENDIAN
  136. memcpy(w, p, 8);
  137. #else
  138. *w = (uint64_t)p[0] << 56 |
  139. (uint64_t)p[1] << 48 |
  140. (uint64_t)p[2] << 40 |
  141. (uint64_t)p[3] << 32 |
  142. (uint64_t)p[4] << 24 |
  143. (uint64_t)p[5] << 16 |
  144. (uint64_t)p[6] << 8 |
  145. (uint64_t)p[7];
  146. #endif
  147. }
  148. static inline uint64_t load_u8to64_little(const uint8_t *p)
  149. {
  150. uint64_t w;
  151. u8to64_little(&w, p);
  152. return w;
  153. }
  154. static inline uint64_t load_u8to64_big(const uint8_t *p)
  155. {
  156. uint64_t w;
  157. u8to64_big(&w, p);
  158. return w;
  159. }
  160. #define LOAD_U64_LITTLE(p) load_u8to64_little(p)
  161. #define LOAD_U64_BIG(p) load_u8to64_big(p)
  162. #define STORE_U64_LITTLE(p, w) u64to8_little((p), &(w))
  163. #define STORE_U64_BIG(p, w) u64to8_big((p), &(w))
  164. /**
  165. * Convert a big endian-encoded number in[] into a little-endian
  166. * 64-bit word array x[]. There must be enough words to contain the entire
  167. * number.
  168. */
  169. static inline int bytes_to_words(uint64_t *x, size_t words, const uint8_t *in, size_t len)
  170. {
  171. uint8_t buf8[8];
  172. size_t words_used, bytes_in_msw, i;
  173. uint64_t *xp;
  174. if (0 == words || 0 == len)
  175. return ERR_NOT_ENOUGH_DATA;
  176. if (NULL == x || NULL == in)
  177. return ERR_NULL;
  178. memset(x, 0, words*sizeof(uint64_t));
  179. /** Shorten the input **/
  180. for (; len > 0 && 0 == *in; in++, len--);
  181. if (0 == len)
  182. return 0;
  183. /** How many words we actually need **/
  184. words_used = (len + 7) / 8;
  185. if (words_used > words)
  186. return ERR_MAX_DATA;
  187. /** Not all bytes in the most-significant words are used **/
  188. bytes_in_msw = len % 8;
  189. if (bytes_in_msw == 0)
  190. bytes_in_msw = 8;
  191. /** Do most significant word **/
  192. memset(buf8, 0, 8);
  193. memcpy(buf8 + (8 - bytes_in_msw), in, bytes_in_msw);
  194. xp = &x[words_used-1];
  195. *xp = LOAD_U64_BIG(buf8);
  196. in += bytes_in_msw;
  197. /** Do the other words **/
  198. for (i=0; i<words_used-1; i++, in += 8) {
  199. xp--;
  200. *xp = LOAD_U64_BIG(in);
  201. }
  202. return 0;
  203. }
  204. /**
  205. * Convert a little-endian 64-bit word array x[] into a big endian-encoded
  206. * number out[]. The number is left-padded with zeroes if required.
  207. */
  208. static inline int words_to_bytes(uint8_t *out, size_t len, const uint64_t *x, size_t words)
  209. {
  210. size_t i;
  211. const uint64_t *msw;
  212. uint8_t buf8[8];
  213. size_t partial, real_len;
  214. if (0 == words || 0 == len)
  215. return ERR_NOT_ENOUGH_DATA;
  216. if (NULL == x || NULL == out)
  217. return ERR_NULL;
  218. memset(out, 0, len);
  219. /* Shorten the input, so that the rightmost word is
  220. * the most significant one (and non-zero)
  221. */
  222. for (; words>0 && x[words-1]==0; words--);
  223. if (words == 0)
  224. return 0;
  225. msw = &x[words-1];
  226. /* Find how many non-zero bytes there are in the most-significant word */
  227. STORE_U64_BIG(buf8, *msw);
  228. for (partial=8; partial>0 && buf8[8-partial] == 0; partial--);
  229. assert(partial > 0);
  230. /** Check if there is enough room **/
  231. real_len = partial + 8*(words-1);
  232. if (real_len > len)
  233. return ERR_MAX_DATA;
  234. /** Pad **/
  235. out += len - real_len;
  236. /** Most significant word **/
  237. memcpy(out, buf8+(8-partial), partial);
  238. out += partial;
  239. msw--;
  240. /** Any remaining full word **/
  241. for (i=0; i<words-1; i++, out += 8, msw--)
  242. STORE_U64_BIG(out, *msw);
  243. return 0;
  244. }
  245. #endif