Utils.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2023-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_UTILS_HPP
  14. #define ZT_UTILS_HPP
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <stdint.h>
  18. #include <string.h>
  19. #include <time.h>
  20. #include <string>
  21. #include <stdexcept>
  22. #include <vector>
  23. #include <map>
  24. #include "Constants.hpp"
  25. namespace ZeroTier {
  26. /**
  27. * Miscellaneous utility functions and global constants
  28. */
  29. class Utils
  30. {
  31. public:
  32. /**
  33. * Hexadecimal characters 0-f
  34. */
  35. static const char HEXCHARS[16];
  36. /**
  37. * Perform a time-invariant binary comparison
  38. *
  39. * @param a First binary string
  40. * @param b Second binary string
  41. * @param len Length of strings
  42. * @return True if strings are equal
  43. */
  44. static ZT_ALWAYS_INLINE bool secureEq(const void *a,const void *b,unsigned int len)
  45. {
  46. uint8_t diff = 0;
  47. for(unsigned int i=0;i<len;++i)
  48. diff |= ( (reinterpret_cast<const uint8_t *>(a))[i] ^ (reinterpret_cast<const uint8_t *>(b))[i] );
  49. return (diff == 0);
  50. }
  51. /**
  52. * Zero memory, ensuring to avoid any compiler optimizations or other things that may stop this.
  53. */
  54. static void burn(void *ptr,unsigned int len);
  55. /**
  56. * @param n Number to convert
  57. * @param s Buffer, at least 24 bytes in size
  58. * @return String containing 'n' in base 10 form
  59. */
  60. static char *decimal(unsigned long n,char s[24]);
  61. /**
  62. * Compute CRC16-CCITT
  63. */
  64. static uint16_t crc16(const void *buf,unsigned int len);
  65. /**
  66. * Convert an unsigned integer into hex
  67. *
  68. * @param i Any unsigned integer
  69. * @param s Buffer to receive hex, must be at least (2*sizeof(i))+1 in size or overflow will occur.
  70. * @return Pointer to s containing hex string with trailing zero byte
  71. */
  72. template<typename I>
  73. static ZT_ALWAYS_INLINE char *hex(I x,char *s)
  74. {
  75. char *const r = s;
  76. for(unsigned int i=0,b=(sizeof(x)*8);i<sizeof(x);++i) {
  77. *(s++) = HEXCHARS[(x >> (b -= 4)) & 0xf];
  78. *(s++) = HEXCHARS[(x >> (b -= 4)) & 0xf];
  79. }
  80. *s = (char)0;
  81. return r;
  82. }
  83. /**
  84. * Convert the least significant 40 bits of a uint64_t to hex
  85. *
  86. * @param i Unsigned 64-bit int
  87. * @param s Buffer of size [11] to receive 10 hex characters
  88. * @return Pointer to buffer
  89. */
  90. static ZT_ALWAYS_INLINE char *hex10(uint64_t i,char s[11])
  91. {
  92. s[0] = HEXCHARS[(i >> 36) & 0xf];
  93. s[1] = HEXCHARS[(i >> 32) & 0xf];
  94. s[2] = HEXCHARS[(i >> 28) & 0xf];
  95. s[3] = HEXCHARS[(i >> 24) & 0xf];
  96. s[4] = HEXCHARS[(i >> 20) & 0xf];
  97. s[5] = HEXCHARS[(i >> 16) & 0xf];
  98. s[6] = HEXCHARS[(i >> 12) & 0xf];
  99. s[7] = HEXCHARS[(i >> 8) & 0xf];
  100. s[8] = HEXCHARS[(i >> 4) & 0xf];
  101. s[9] = HEXCHARS[i & 0xf];
  102. s[10] = (char)0;
  103. return s;
  104. }
  105. /**
  106. * Convert a byte array into hex
  107. *
  108. * @param d Bytes
  109. * @param l Length of bytes
  110. * @param s String buffer, must be at least (l*2)+1 in size or overflow will occur
  111. * @return Pointer to filled string buffer
  112. */
  113. static ZT_ALWAYS_INLINE char *hex(const void *d,unsigned int l,char *s)
  114. {
  115. char *const save = s;
  116. for(unsigned int i=0;i<l;++i) {
  117. const unsigned int b = reinterpret_cast<const uint8_t *>(d)[i];
  118. *(s++) = HEXCHARS[b >> 4];
  119. *(s++) = HEXCHARS[b & 0xf];
  120. }
  121. *s = (char)0;
  122. return save;
  123. }
  124. static unsigned int unhex(const char *h,void *buf,unsigned int buflen);
  125. static unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen);
  126. /**
  127. * Generate secure random bytes
  128. *
  129. * This will try to use whatever OS sources of entropy are available. It's
  130. * guarded by an internal mutex so it's thread-safe.
  131. *
  132. * @param buf Buffer to fill
  133. * @param bytes Number of random bytes to generate
  134. */
  135. static void getSecureRandom(void *buf,unsigned int bytes);
  136. /**
  137. * Get a 64-bit unsigned secure random number
  138. */
  139. static ZT_ALWAYS_INLINE uint64_t getSecureRandom64()
  140. {
  141. uint64_t x;
  142. getSecureRandom(&x,sizeof(x));
  143. return x;
  144. }
  145. static int b32e(const uint8_t *data,int length,char *result,int bufSize);
  146. static int b32d(const char *encoded, uint8_t *result, int bufSize);
  147. static ZT_ALWAYS_INLINE unsigned int b64MaxEncodedSize(const unsigned int s) { return ((((s + 2) / 3) * 4) + 1); }
  148. static unsigned int b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen);
  149. static unsigned int b64d(const char *in,uint8_t *out,unsigned int outlen);
  150. /**
  151. * Get a non-cryptographic random integer
  152. */
  153. static uint64_t random();
  154. static ZT_ALWAYS_INLINE float normalize(float value, int64_t bigMin, int64_t bigMax, int32_t targetMin, int32_t targetMax)
  155. {
  156. int64_t bigSpan = bigMax - bigMin;
  157. int64_t smallSpan = targetMax - targetMin;
  158. float valueScaled = (value - (float)bigMin) / (float)bigSpan;
  159. return (float)targetMin + valueScaled * (float)smallSpan;
  160. }
  161. /**
  162. * Tokenize a string (alias for strtok_r or strtok_s depending on platform)
  163. *
  164. * @param str String to split
  165. * @param delim Delimiters
  166. * @param saveptr Pointer to a char * for temporary reentrant storage
  167. */
  168. static ZT_ALWAYS_INLINE char *stok(char *str,const char *delim,char **saveptr)
  169. {
  170. #ifdef __WINDOWS__
  171. return strtok_s(str,delim,saveptr);
  172. #else
  173. return strtok_r(str,delim,saveptr);
  174. #endif
  175. }
  176. static ZT_ALWAYS_INLINE unsigned int strToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,10); }
  177. static ZT_ALWAYS_INLINE int strToInt(const char *s) { return (int)strtol(s,(char **)0,10); }
  178. static ZT_ALWAYS_INLINE unsigned long strToULong(const char *s) { return strtoul(s,(char **)0,10); }
  179. static ZT_ALWAYS_INLINE long strToLong(const char *s) { return strtol(s,(char **)0,10); }
  180. static ZT_ALWAYS_INLINE unsigned long long strToU64(const char *s)
  181. {
  182. #ifdef __WINDOWS__
  183. return (unsigned long long)_strtoui64(s,(char **)0,10);
  184. #else
  185. return strtoull(s,(char **)0,10);
  186. #endif
  187. }
  188. static ZT_ALWAYS_INLINE long long strTo64(const char *s)
  189. {
  190. #ifdef __WINDOWS__
  191. return (long long)_strtoi64(s,(char **)0,10);
  192. #else
  193. return strtoll(s,(char **)0,10);
  194. #endif
  195. }
  196. static ZT_ALWAYS_INLINE unsigned int hexStrToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,16); }
  197. static ZT_ALWAYS_INLINE int hexStrToInt(const char *s) { return (int)strtol(s,(char **)0,16); }
  198. static ZT_ALWAYS_INLINE unsigned long hexStrToULong(const char *s) { return strtoul(s,(char **)0,16); }
  199. static ZT_ALWAYS_INLINE long hexStrToLong(const char *s) { return strtol(s,(char **)0,16); }
  200. static ZT_ALWAYS_INLINE unsigned long long hexStrToU64(const char *s)
  201. {
  202. #ifdef __WINDOWS__
  203. return (unsigned long long)_strtoui64(s,(char **)0,16);
  204. #else
  205. return strtoull(s,(char **)0,16);
  206. #endif
  207. }
  208. static ZT_ALWAYS_INLINE long long hexStrTo64(const char *s)
  209. {
  210. #ifdef __WINDOWS__
  211. return (long long)_strtoi64(s,(char **)0,16);
  212. #else
  213. return strtoll(s,(char **)0,16);
  214. #endif
  215. }
  216. /**
  217. * Perform a safe C string copy, ALWAYS null-terminating the result
  218. *
  219. * This will never ever EVER result in dest[] not being null-terminated
  220. * regardless of any input parameter (other than len==0 which is invalid).
  221. *
  222. * @param dest Destination buffer (must not be NULL)
  223. * @param len Length of dest[] (if zero, false is returned and nothing happens)
  224. * @param src Source string (if NULL, dest will receive a zero-length string and true is returned)
  225. * @return True on success, false on overflow (buffer will still be 0-terminated)
  226. */
  227. static ZT_ALWAYS_INLINE bool scopy(char *dest,unsigned int len,const char *src)
  228. {
  229. if (!len)
  230. return false; // sanity check
  231. if (!src) {
  232. *dest = (char)0;
  233. return true;
  234. }
  235. char *const end = dest + len;
  236. while ((*dest++ = *src++)) {
  237. if (dest == end) {
  238. *(--dest) = (char)0;
  239. return false;
  240. }
  241. }
  242. return true;
  243. }
  244. #ifdef __GNUC__
  245. static ZT_ALWAYS_INLINE unsigned int countBits(const uint8_t v) { return (unsigned int)__builtin_popcount((unsigned int)v); }
  246. static ZT_ALWAYS_INLINE unsigned int countBits(const uint16_t v) { return (unsigned int)__builtin_popcount((unsigned int)v); }
  247. static ZT_ALWAYS_INLINE unsigned int countBits(const uint32_t v) { return (unsigned int)__builtin_popcountl((unsigned long)v); }
  248. static ZT_ALWAYS_INLINE unsigned int countBits(const uint64_t v) { return (unsigned int)__builtin_popcountll((unsigned long long)v); }
  249. #else
  250. /**
  251. * Count the number of bits set in an integer
  252. *
  253. * @param v Unsigned integer
  254. * @return Number of bits set in this integer (0-bits in integer)
  255. */
  256. template<typename T>
  257. static ZT_ALWAYS_INLINE unsigned int countBits(T v)
  258. {
  259. v = v - ((v >> 1) & (T)~(T)0/3);
  260. v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
  261. v = (v + (v >> 4)) & (T)~(T)0/255*15;
  262. return (unsigned int)((v * ((~((T)0))/((T)255))) >> ((sizeof(T) - 1) * 8));
  263. }
  264. #endif
  265. // Byte swappers for big/little endian conversion
  266. #if __BYTE_ORDER == __LITTLE_ENDIAN
  267. static ZT_ALWAYS_INLINE uint8_t hton(uint8_t n) { return n; }
  268. static ZT_ALWAYS_INLINE int8_t hton(int8_t n) { return n; }
  269. static ZT_ALWAYS_INLINE uint16_t hton(uint16_t n) { return htons(n); }
  270. static ZT_ALWAYS_INLINE int16_t hton(int16_t n) { return (int16_t)Utils::hton((uint16_t)n); }
  271. static ZT_ALWAYS_INLINE uint32_t hton(uint32_t n)
  272. {
  273. #if defined(__GNUC__)
  274. #if defined(__FreeBSD__)
  275. return htonl(n);
  276. #elif (!defined(__OpenBSD__))
  277. return __builtin_bswap32(n);
  278. #endif
  279. #else
  280. return htonl(n);
  281. #endif
  282. }
  283. static ZT_ALWAYS_INLINE int32_t hton(int32_t n) { return (int32_t)Utils::hton((uint32_t)n); }
  284. static ZT_ALWAYS_INLINE uint64_t hton(uint64_t n)
  285. {
  286. #if defined(__GNUC__)
  287. #if defined(__FreeBSD__)
  288. return bswap64(n);
  289. #elif (!defined(__OpenBSD__))
  290. return __builtin_bswap64(n);
  291. #endif
  292. #else
  293. return (
  294. ((n & 0x00000000000000FFULL) << 56) |
  295. ((n & 0x000000000000FF00ULL) << 40) |
  296. ((n & 0x0000000000FF0000ULL) << 24) |
  297. ((n & 0x00000000FF000000ULL) << 8) |
  298. ((n & 0x000000FF00000000ULL) >> 8) |
  299. ((n & 0x0000FF0000000000ULL) >> 24) |
  300. ((n & 0x00FF000000000000ULL) >> 40) |
  301. ((n & 0xFF00000000000000ULL) >> 56)
  302. );
  303. #endif
  304. }
  305. static ZT_ALWAYS_INLINE int64_t hton(int64_t n) { return (int64_t)hton((uint64_t)n); }
  306. #else
  307. template<typename T>
  308. static ZT_ALWAYS_INLINE T hton(T n) { return n; }
  309. #endif
  310. #if __BYTE_ORDER == __LITTLE_ENDIAN
  311. static ZT_ALWAYS_INLINE uint8_t ntoh(uint8_t n) { return n; }
  312. static ZT_ALWAYS_INLINE int8_t ntoh(int8_t n) { return n; }
  313. static ZT_ALWAYS_INLINE uint16_t ntoh(uint16_t n) { return ntohs(n); }
  314. static ZT_ALWAYS_INLINE int16_t ntoh(int16_t n) { return (int16_t)Utils::ntoh((uint16_t)n); }
  315. static ZT_ALWAYS_INLINE uint32_t ntoh(uint32_t n)
  316. {
  317. #if defined(__GNUC__)
  318. #if defined(__FreeBSD__)
  319. return ntohl(n);
  320. #elif (!defined(__OpenBSD__))
  321. return __builtin_bswap32(n);
  322. #endif
  323. #else
  324. return ntohl(n);
  325. #endif
  326. }
  327. static ZT_ALWAYS_INLINE int32_t ntoh(int32_t n) { return (int32_t)Utils::ntoh((uint32_t)n); }
  328. static ZT_ALWAYS_INLINE uint64_t ntoh(uint64_t n)
  329. {
  330. #if defined(__GNUC__)
  331. #if defined(__FreeBSD__)
  332. return bswap64(n);
  333. #elif (!defined(__OpenBSD__))
  334. return __builtin_bswap64(n);
  335. #endif
  336. #else
  337. return (
  338. ((n & 0x00000000000000FFULL) << 56) |
  339. ((n & 0x000000000000FF00ULL) << 40) |
  340. ((n & 0x0000000000FF0000ULL) << 24) |
  341. ((n & 0x00000000FF000000ULL) << 8) |
  342. ((n & 0x000000FF00000000ULL) >> 8) |
  343. ((n & 0x0000FF0000000000ULL) >> 24) |
  344. ((n & 0x00FF000000000000ULL) >> 40) |
  345. ((n & 0xFF00000000000000ULL) >> 56)
  346. );
  347. #endif
  348. }
  349. static ZT_ALWAYS_INLINE int64_t ntoh(int64_t n) { return (int64_t)ntoh((uint64_t)n); }
  350. #else
  351. template<typename T>
  352. static ZT_ALWAYS_INLINE T ntoh(T n) { return n; }
  353. #endif
  354. };
  355. } // namespace ZeroTier
  356. #endif