Identity.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. /*
  2. * Copyright (c)2013-2020 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: 2024-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. #include <cstring>
  14. #include <cstdint>
  15. #include "Constants.hpp"
  16. #include "Identity.hpp"
  17. #include "SHA512.hpp"
  18. #include "Salsa20.hpp"
  19. #include "Utils.hpp"
  20. namespace ZeroTier {
  21. namespace {
  22. // These can't be changed without a new identity type. They define the
  23. // parameters of the hashcash hashing/searching algorithm for type 0
  24. // identities.
  25. #define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 17
  26. #define ZT_IDENTITY_GEN_MEMORY 2097152
  27. // A memory-hard composition of SHA-512 and Salsa20 for hashcash hashing
  28. static void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem)
  29. {
  30. // Digest publicKey[] to obtain initial digest
  31. SHA512(digest,publicKey,publicKeyBytes);
  32. // Initialize genmem[] using Salsa20 in a CBC-like configuration since
  33. // ordinary Salsa20 is randomly seek-able. This is good for a cipher
  34. // but is not what we want for sequential memory-hardness.
  35. memset(genmem,0,ZT_IDENTITY_GEN_MEMORY);
  36. Salsa20 s20(digest,(char *)digest + 32);
  37. s20.crypt20((char *)genmem,(char *)genmem,64);
  38. for(unsigned long i=64;i<ZT_IDENTITY_GEN_MEMORY;i+=64) {
  39. unsigned long k = i - 64;
  40. *((uint64_t *)((char *)genmem + i)) = *((uint64_t *)((char *)genmem + k));
  41. *((uint64_t *)((char *)genmem + i + 8)) = *((uint64_t *)((char *)genmem + k + 8));
  42. *((uint64_t *)((char *)genmem + i + 16)) = *((uint64_t *)((char *)genmem + k + 16));
  43. *((uint64_t *)((char *)genmem + i + 24)) = *((uint64_t *)((char *)genmem + k + 24));
  44. *((uint64_t *)((char *)genmem + i + 32)) = *((uint64_t *)((char *)genmem + k + 32));
  45. *((uint64_t *)((char *)genmem + i + 40)) = *((uint64_t *)((char *)genmem + k + 40));
  46. *((uint64_t *)((char *)genmem + i + 48)) = *((uint64_t *)((char *)genmem + k + 48));
  47. *((uint64_t *)((char *)genmem + i + 56)) = *((uint64_t *)((char *)genmem + k + 56));
  48. s20.crypt20((char *)genmem + i,(char *)genmem + i,64);
  49. }
  50. // Render final digest using genmem as a lookup table
  51. for(unsigned long i=0;i<(ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
  52. unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (64 / sizeof(uint64_t)));
  53. unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (ZT_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
  54. uint64_t tmp = ((uint64_t *)genmem)[idx2];
  55. ((uint64_t *)genmem)[idx2] = ((uint64_t *)digest)[idx1];
  56. ((uint64_t *)digest)[idx1] = tmp;
  57. s20.crypt20(digest,digest,64);
  58. }
  59. }
  60. // Hashcash generation halting condition -- halt when first byte is less than
  61. // threshold value.
  62. struct _Identity_generate_cond
  63. {
  64. inline _Identity_generate_cond() {}
  65. inline _Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {}
  66. inline bool operator()(const uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN]) const
  67. {
  68. _computeMemoryHardHash(pub,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
  69. return (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN);
  70. }
  71. unsigned char *digest;
  72. char *genmem;
  73. };
  74. } // anonymous namespace
  75. void Identity::generate(const Type t)
  76. {
  77. uint8_t digest[64];
  78. _type = t;
  79. _hasPrivate = true;
  80. _hash[0] = 0; // force hash recompute
  81. char *const genmem = new char[ZT_IDENTITY_GEN_MEMORY];
  82. do {
  83. C25519::generateSatisfying(_Identity_generate_cond(digest,genmem),_pub.c25519,_priv.c25519);
  84. _address.setTo(digest + 59); // last 5 bytes are address
  85. } while (_address.isReserved());
  86. delete [] genmem;
  87. if (t == P384) {
  88. // We sign with both because in pure FIPS environments we might have to say
  89. // that we do not rely on any non-FIPS algorithms, or may even have to disable
  90. // them.
  91. ECC384GenerateKey(_pub.p384,_priv.p384);
  92. C25519::sign(_priv.c25519,_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.c25519s);
  93. SHA384(digest,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE);
  94. ECC384ECDSASign(_priv.p384,digest,_pub.p384s);
  95. }
  96. }
  97. bool Identity::locallyValidate() const
  98. {
  99. uint8_t digest[64];
  100. if (_address.isReserved())
  101. return false;
  102. switch(_type) {
  103. case C25519:
  104. break;
  105. case P384:
  106. if (!C25519::verify(_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.c25519s,ZT_C25519_SIGNATURE_LEN))
  107. return false;
  108. SHA384(digest,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE);
  109. if (!ECC384ECDSAVerify(_pub.p384,digest,_pub.p384s))
  110. return false;
  111. break;
  112. default:
  113. return false;
  114. }
  115. char *genmem = nullptr;
  116. try {
  117. genmem = new char[ZT_IDENTITY_GEN_MEMORY];
  118. _computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
  119. delete [] genmem;
  120. return ((_address == Address(digest + 59,ZT_ADDRESS_LENGTH))&&(!_address.isReserved())&&(digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN));
  121. } catch ( ... ) {
  122. if (genmem) delete [] genmem;
  123. }
  124. return false;
  125. }
  126. void Identity::hashWithPrivate(uint8_t h[48]) const
  127. {
  128. switch(_type) {
  129. case C25519: SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN); break;
  130. case P384: SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv)); break;
  131. default: memset(h,0,48);
  132. }
  133. }
  134. unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
  135. {
  136. if (_hasPrivate) {
  137. switch(_type) {
  138. case C25519:
  139. if (siglen >= ZT_C25519_SIGNATURE_LEN) {
  140. C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
  141. return ZT_C25519_SIGNATURE_LEN;
  142. }
  143. case P384:
  144. if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
  145. // When signing with P384 we also hash the C25519 public key as an
  146. // extra measure to ensure that only this identity can verify.
  147. uint8_t h[48];
  148. SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
  149. ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
  150. return ZT_ECC384_SIGNATURE_SIZE;
  151. }
  152. }
  153. }
  154. return 0;
  155. }
  156. bool Identity::verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
  157. {
  158. switch(_type) {
  159. case C25519:
  160. return C25519::verify(_pub.c25519,data,len,sig,siglen);
  161. case P384:
  162. if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
  163. uint8_t h[48];
  164. SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
  165. return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
  166. }
  167. break;
  168. }
  169. return false;
  170. }
  171. bool Identity::agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const
  172. {
  173. uint8_t rawkey[128];
  174. uint8_t h[64];
  175. if (_hasPrivate) {
  176. if (_type == C25519) {
  177. if ((id._type == C25519)||(id._type == P384)) {
  178. // If we are a C25519 key we can agree with another C25519 key or with only the
  179. // C25519 portion of a type 1 P-384 key.
  180. C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
  181. SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
  182. memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
  183. return true;
  184. }
  185. } else if (_type == P384) {
  186. if (id._type == P384) {
  187. C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
  188. ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
  189. SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
  190. memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
  191. return true;
  192. } else if (id._type == C25519) {
  193. // If the other identity is a C25519 identity we can agree using only that type.
  194. C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
  195. SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
  196. memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
  197. return true;
  198. }
  199. }
  200. }
  201. return false;
  202. }
  203. char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
  204. {
  205. switch(_type) {
  206. case C25519: {
  207. char *p = buf;
  208. Utils::hex10(_address.toInt(),p);
  209. p += 10;
  210. *(p++) = ':';
  211. *(p++) = '0';
  212. *(p++) = ':';
  213. Utils::hex(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,p);
  214. p += ZT_C25519_PUBLIC_KEY_LEN * 2;
  215. if ((_hasPrivate)&&(includePrivate)) {
  216. *(p++) = ':';
  217. Utils::hex(_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN,p);
  218. p += ZT_C25519_PRIVATE_KEY_LEN * 2;
  219. }
  220. *p = (char)0;
  221. return buf;
  222. }
  223. case P384: {
  224. char *p = buf;
  225. Utils::hex10(_address.toInt(),p);
  226. p += 10;
  227. *(p++) = ':';
  228. *(p++) = '1';
  229. *(p++) = ':';
  230. int el = Utils::b32e((const uint8_t *)(&_pub),sizeof(_pub),p,(unsigned int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
  231. if (el <= 0) return nullptr;
  232. p += el;
  233. if ((_hasPrivate)&&(includePrivate)) {
  234. *(p++) = ':';
  235. el = Utils::b32e((const uint8_t *)(&_priv),sizeof(_priv),p,(unsigned int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
  236. if (el <= 0) return nullptr;
  237. p += el;
  238. }
  239. *p = (char)0;
  240. return buf;
  241. }
  242. }
  243. return nullptr;
  244. }
  245. bool Identity::fromString(const char *str)
  246. {
  247. _hasPrivate = false;
  248. _hash[0] = 0; // force hash recompute
  249. if (!str) {
  250. _address.zero();
  251. return false;
  252. }
  253. char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
  254. if (!Utils::scopy(tmp,sizeof(tmp),str)) {
  255. _address.zero();
  256. return false;
  257. }
  258. int fno = 0;
  259. char *saveptr = (char *)0;
  260. for(char *f=Utils::stok(tmp,":",&saveptr);((f)&&(fno < 4));f=Utils::stok((char *)0,":",&saveptr)) {
  261. switch(fno++) {
  262. case 0:
  263. _address = Address(Utils::hexStrToU64(f));
  264. if (_address.isReserved()) {
  265. _address.zero();
  266. return false;
  267. }
  268. break;
  269. case 1:
  270. if ((f[0] == '0')&&(!f[1])) {
  271. _type = C25519;
  272. } else if ((f[0] == '1')&&(!f[1])) {
  273. _type = P384;
  274. } else {
  275. _address.zero();
  276. return false;
  277. }
  278. break;
  279. case 2:
  280. switch(_type) {
  281. case C25519:
  282. if (Utils::unhex(f,strlen(f),_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
  283. _address.zero();
  284. return false;
  285. }
  286. break;
  287. case P384:
  288. if (Utils::b32d(f,(uint8_t *)(&_pub),sizeof(_pub)) != sizeof(_pub)) {
  289. _address.zero();
  290. return false;
  291. }
  292. break;
  293. }
  294. break;
  295. case 3:
  296. if (strlen(f) > 1) {
  297. switch(_type) {
  298. case C25519:
  299. if (Utils::unhex(f,strlen(f),_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
  300. _address.zero();
  301. return false;
  302. } else {
  303. _hasPrivate = true;
  304. }
  305. break;
  306. case P384:
  307. if (Utils::b32d(f,(uint8_t *)(&_priv),sizeof(_priv)) != sizeof(_priv)) {
  308. _address.zero();
  309. return false;
  310. } else {
  311. _hasPrivate = true;
  312. }
  313. break;
  314. }
  315. break;
  316. }
  317. }
  318. }
  319. if (fno < 3) {
  320. _address.zero();
  321. return false;
  322. }
  323. return true;
  324. }
  325. int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate) const
  326. {
  327. _address.copyTo(data);
  328. switch(_type) {
  329. case C25519:
  330. data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
  331. memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
  332. if ((includePrivate)&&(_hasPrivate)) {
  333. data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
  334. memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
  335. return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
  336. }
  337. data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = 0;
  338. return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
  339. case P384:
  340. data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
  341. memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
  342. if ((includePrivate)&&(_hasPrivate)) {
  343. data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE;
  344. memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
  345. data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE] = 0;
  346. return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1);
  347. }
  348. data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
  349. data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1] = 0;
  350. return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
  351. }
  352. return -1;
  353. }
  354. int Identity::unmarshal(const uint8_t *data,const int len)
  355. {
  356. if (len < (ZT_ADDRESS_LENGTH + 1))
  357. return -1;
  358. _hash[0] = 0; // force hash recompute
  359. unsigned int privlen;
  360. switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
  361. case C25519:
  362. if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1))
  363. return -1;
  364. memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
  365. privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
  366. if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
  367. if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
  368. return -1;
  369. _hasPrivate = true;
  370. memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
  371. return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
  372. } else if (privlen == 0) {
  373. _hasPrivate = false;
  374. return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
  375. }
  376. break;
  377. case P384:
  378. if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2))
  379. return -1;
  380. memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
  381. privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
  382. if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
  383. if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1))
  384. return -1;
  385. _hasPrivate = true;
  386. memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
  387. privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE];
  388. if (len < (int)(privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1)))
  389. return -1;
  390. return (int)(privlen + (unsigned int)(ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
  391. } else if (privlen == 0) {
  392. _hasPrivate = false;
  393. return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
  394. }
  395. break;
  396. }
  397. return -1;
  398. }
  399. void Identity::_computeHash()
  400. {
  401. switch(_type) {
  402. case C25519: SHA384(_hash,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN); break;
  403. case P384: SHA384(_hash,&_pub,sizeof(_pub)); break;
  404. default: memset(_hash,0,48);
  405. }
  406. }
  407. } // namespace ZeroTier
  408. extern "C" {
  409. ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type)
  410. {
  411. if ((type != ZT_IDENTITY_TYPE_C25519)&&(type != ZT_IDENTITY_TYPE_P384))
  412. return nullptr;
  413. try {
  414. ZeroTier::Identity *id = new ZeroTier::Identity();
  415. id->generate((ZeroTier::Identity::Type)type);
  416. return reinterpret_cast<ZT_Identity *>(id);
  417. } catch ( ... ) {
  418. return nullptr;
  419. }
  420. }
  421. ZT_Identity *ZT_Identity_fromString(const char *idStr)
  422. {
  423. if (!idStr)
  424. return nullptr;
  425. try {
  426. ZeroTier::Identity *id = new ZeroTier::Identity();
  427. if (!id->fromString(idStr)) {
  428. delete id;
  429. return nullptr;
  430. }
  431. return reinterpret_cast<ZT_Identity *>(id);
  432. } catch ( ... ) {
  433. return nullptr;
  434. }
  435. }
  436. int ZT_Identity_validate(const ZT_Identity *id)
  437. {
  438. if (!id)
  439. return 0;
  440. return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
  441. }
  442. unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength)
  443. {
  444. if (!id)
  445. return 0;
  446. if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE)
  447. return 0;
  448. return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data,len,signature,signatureBufferLength);
  449. }
  450. int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen)
  451. {
  452. if ((!id)||(!signature)||(!sigLen))
  453. return 0;
  454. return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data,len,signature,sigLen) ? 1 : 0;
  455. }
  456. enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id)
  457. {
  458. if (!id)
  459. return (ZT_Identity_Type)0;
  460. return (enum ZT_Identity_Type)reinterpret_cast<const ZeroTier::Identity *>(id)->type();
  461. }
  462. char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate)
  463. {
  464. if ((!id)||(!buf)||(capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
  465. return nullptr;
  466. reinterpret_cast<const ZeroTier::Identity *>(id)->toString(includePrivate != 0,buf);
  467. return buf;
  468. }
  469. int ZT_Identity_hasPrivate(const ZT_Identity *id)
  470. {
  471. if (!id)
  472. return 0;
  473. return reinterpret_cast<const ZeroTier::Identity *>(id)->hasPrivate() ? 1 : 0;
  474. }
  475. uint64_t ZT_Identity_address(const ZT_Identity *id)
  476. {
  477. if (!id)
  478. return 0;
  479. return reinterpret_cast<const ZeroTier::Identity *>(id)->address().toInt();
  480. }
  481. void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate)
  482. {
  483. if (includePrivate)
  484. reinterpret_cast<const ZeroTier::Identity *>(id)->hashWithPrivate(h);
  485. else memcpy(h,reinterpret_cast<const ZeroTier::Identity *>(id)->hash(),48);
  486. }
  487. ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)
  488. {
  489. if (id)
  490. delete reinterpret_cast<ZeroTier::Identity *>(id);
  491. }
  492. }