Utils.hpp 11 KB

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