diff --git a/CMakeLists.txt b/CMakeLists.txt index 455bfe6cd..ff060c5a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,10 +219,13 @@ if(NOT PACKAGE_STATIC) if ( CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "amd64" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" + CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "X86_64" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "x64" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "X64" ) message("++ Adding flags for processor ${CMAKE_SYSTEM_PROCESSOR}") - add_compile_options(-maes -mrdrnd -mpclmul -msse -msse2 -mssse3 -msse4 -msse4.1 -msse4.2) + add_compile_options(-maes -mrdrnd -mpclmul -msse -msse2) endif() if ( diff --git a/core/Address.hpp b/core/Address.hpp index e999f353e..5690a467f 100644 --- a/core/Address.hpp +++ b/core/Address.hpp @@ -158,6 +158,8 @@ private: uint64_t _a; }; +static_assert(sizeof(Address) == sizeof(uint64_t),"Address has unnecessary extra padding"); + } // namespace ZeroTier #endif diff --git a/core/Blob.hpp b/core/Blob.hpp index 8f31de838..007df037b 100644 --- a/core/Blob.hpp +++ b/core/Blob.hpp @@ -112,6 +112,9 @@ struct UniqueID { return (memcmp(data, b.data, 16) >= 0); } }; +static_assert(sizeof(SHA384Hash) == 48,"SHA384Hash contains unnecessary padding"); +static_assert(sizeof(UniqueID) == 16,"UniqueID contains unnecessary padding"); + } // namespace ZeroTier #endif diff --git a/core/CAPI.cpp b/core/CAPI.cpp new file mode 100644 index 000000000..7649b63b2 --- /dev/null +++ b/core/CAPI.cpp @@ -0,0 +1,704 @@ +/* + * Copyright (c)2013-2020 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2025-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +#include "Constants.hpp" +#include "Node.hpp" +#include "Identity.hpp" +#include "Locator.hpp" +#include "Certificate.hpp" + +extern "C" { + +/********************************************************************************************************************/ + +// These macros make the idiom of passing buffers to outside code via the API work properly even +// if the first address of Buf does not overlap with its data field, since the C++ standard does +// not absolutely guarantee this. +#define _ZT_PTRTOBUF(p) ((ZeroTier::Buf *)( ((uintptr_t)(p)) - ((uintptr_t)&(((ZeroTier::Buf *)0)->unsafeData[0])) )) +#define _ZT_BUFTOPTR(b) ((void *)(&((b)->unsafeData[0]))) + +void *ZT_getBuffer() +{ + // When external code requests a Buf, grab one from the pool (or freshly allocated) + // and return it with its reference count left at zero. It's the responsibility of + // external code to bring it back via freeBuffer() or one of the processX() calls. + // When this occurs it's either sent back to the pool with Buf's delete operator or + // wrapped in a SharedPtr<> to be passed into the core. + try { + return _ZT_BUFTOPTR(new ZeroTier::Buf()); + } catch (...) { + return nullptr; // can only happen on out of memory condition + } +} + +void ZT_freeBuffer(void *b) +{ + if (b) + delete _ZT_PTRTOBUF(b); +} + +struct p_queryResultBase +{ + void (*freeFunction)(const void *); +}; + +void ZT_freeQueryResult(const void *qr) +{ + if ((qr) && (reinterpret_cast(qr)->freeFunction)) + reinterpret_cast(qr)->freeFunction(qr); +} + +void ZT_version(int *major, int *minor, int *revision, int *build) +{ + if (major) + *major = ZEROTIER_VERSION_MAJOR; + if (minor) + *minor = ZEROTIER_VERSION_MINOR; + if (revision) + *revision = ZEROTIER_VERSION_REVISION; + if (build) + *build = ZEROTIER_VERSION_BUILD; +} + +/********************************************************************************************************************/ + +enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const struct ZT_Node_Callbacks *callbacks, int64_t now) +{ + *node = (ZT_Node *)0; + try { + *node = reinterpret_cast(new ZeroTier::Node(uptr, tptr, callbacks, now)); + return ZT_RESULT_OK; + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (std::runtime_error &exc) { + return ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +void ZT_Node_delete(ZT_Node *node, void *tPtr) +{ + try { + reinterpret_cast(node)->shutdown(tPtr); + delete (reinterpret_cast(node)); + } catch (...) {} +} + +enum ZT_ResultCode ZT_Node_processWirePacket( + ZT_Node *node, + void *tptr, + int64_t now, + int64_t localSocket, + const struct sockaddr_storage *remoteAddress, + const void *packetData, + unsigned int packetLength, + int isZtBuffer, + volatile int64_t *nextBackgroundTaskDeadline) +{ + try { + ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? _ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK)); + return reinterpret_cast(node)->processWirePacket(tptr, now, localSocket, remoteAddress, buf, packetLength, nextBackgroundTaskDeadline); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + // "OK" since invalid packets are simply dropped, but the system is still up. + // We should never make it here, but if we did that would be the interpretation. + return ZT_RESULT_OK; + } +} + +enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( + ZT_Node *node, + void *tptr, + int64_t now, + uint64_t nwid, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void *frameData, + unsigned int frameLength, + int isZtBuffer, + volatile int64_t *nextBackgroundTaskDeadline) +{ + try { + ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? _ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK)); + return reinterpret_cast(node)->processVirtualNetworkFrame(tptr, now, nwid, sourceMac, destMac, etherType, vlanId, buf, frameLength, nextBackgroundTaskDeadline); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) +{ + try { + return reinterpret_cast(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, void *tptr) +{ + try { + return reinterpret_cast(node)->join(nwid, controllerFingerprint, uptr, tptr); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void *tptr) +{ + try { + return reinterpret_cast(node)->leave(nwid, uptr, tptr); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) +{ + try { + return reinterpret_cast(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) +{ + try { + return reinterpret_cast(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi); + } catch (std::bad_alloc &exc) { + return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +uint64_t ZT_Node_address(ZT_Node *node) +{ + return reinterpret_cast(node)->address(); +} + +const ZT_Identity *ZT_Node_identity(ZT_Node *node) +{ + return (const ZT_Identity *)(&(reinterpret_cast(node)->identity())); +} + +void ZT_Node_status(ZT_Node *node, ZT_NodeStatus *status) +{ + try { + reinterpret_cast(node)->status(status); + } catch (...) {} +} + +ZT_PeerList *ZT_Node_peers(ZT_Node *node) +{ + try { + return reinterpret_cast(node)->peers(); + } catch (...) { + return (ZT_PeerList *)0; + } +} + +ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid) +{ + try { + return reinterpret_cast(node)->networkConfig(nwid); + } catch (...) { + return (ZT_VirtualNetworkConfig *)0; + } +} + +ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) +{ + try { + return reinterpret_cast(node)->networks(); + } catch (...) { + return (ZT_VirtualNetworkList *)0; + } +} + +int ZT_Node_tryPeer( + ZT_Node *node, + void *tptr, + const ZT_Fingerprint *fp, + const ZT_Endpoint *endpoint, + int retries) +{ + try { + return reinterpret_cast(node)->tryPeer(tptr, fp, endpoint, retries); + } catch (...) { + return 0; + } +} + +enum ZT_CertificateError ZT_Node_addCertificate( + ZT_Node *node, + void *tptr, + int64_t now, + unsigned int localTrust, + const ZT_Certificate *cert, + const void *certData, + unsigned int certSize) +{ + try { + return reinterpret_cast(node)->addCertificate(tptr, now, localTrust, cert, certData, certSize); + } catch (...) { + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + } +} + +ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( + ZT_Node *node, + void *tptr, + const void *serialNo) +{ + try { + return reinterpret_cast(node)->deleteCertificate(tptr, serialNo); + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) +{ + try { + return reinterpret_cast(node)->listCertificates(); + } catch (...) { + return nullptr; + } +} + +void ZT_Node_setNetworkUserPtr(ZT_Node *node, uint64_t nwid, void *ptr) +{ + try { + reinterpret_cast(node)->setNetworkUserPtr(nwid, ptr); + } catch (...) {} +} + +void ZT_Node_setInterfaceAddresses(ZT_Node *node, const ZT_InterfaceAddress *addrs, unsigned int addrCount) +{ + try { + reinterpret_cast(node)->setInterfaceAddresses(addrs, addrCount); + } catch (...) {} +} + +enum ZT_ResultCode ZT_Node_addPeer( + ZT_Node *node, + void *tptr, + const ZT_Identity *id) +{ + try { + return reinterpret_cast(node)->addPeer(tptr, id); + } catch (...) { + return ZT_RESULT_ERROR_INTERNAL; + } +} + +int ZT_Node_sendUserMessage(ZT_Node *node, void *tptr, uint64_t dest, uint64_t typeId, const void *data, unsigned int len) +{ + try { + return reinterpret_cast(node)->sendUserMessage(tptr, dest, typeId, data, len); + } catch (...) { + return 0; + } +} + +void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance) +{ + try { + reinterpret_cast(node)->setController(networkControllerInstance); + } catch (...) {} +} + +/********************************************************************************************************************/ + +ZT_Locator *ZT_Locator_create( + int64_t ts, + const ZT_Endpoint *endpoints, + const ZT_EndpointAttributes *endpointAttributes, // TODO: not used yet + unsigned int endpointCount, + const ZT_Identity *signer) +{ + try { + if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer)) + return nullptr; + ZeroTier::Locator *loc = new ZeroTier::Locator(); + for (unsigned int i = 0;i < endpointCount;++i) + loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT); + if (!loc->sign(ts, *reinterpret_cast< const ZeroTier::Identity * >(signer))) { + delete loc; + return nullptr; + } + return reinterpret_cast(loc); + } catch (...) { + return nullptr; + } +} + +ZT_Locator *ZT_Locator_fromString(const char *str) +{ + try { + if (!str) + return nullptr; + ZeroTier::Locator *loc = new ZeroTier::Locator(); + if (!loc->fromString(str)) { + delete loc; + return nullptr; + } + return reinterpret_cast(loc); + } catch ( ... ) { + return nullptr; + } +} + +ZT_Locator *ZT_Locator_unmarshal( + const void *data, + unsigned int len) +{ + try { + if ((!data) || (len == 0)) + return nullptr; + ZeroTier::Locator *loc = new ZeroTier::Locator(); + if (loc->unmarshal(reinterpret_cast(data), (int) len) <= 0) { + delete loc; + return nullptr; + } + return reinterpret_cast(loc); + } catch (...) { + return nullptr; + } +} + +int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize) +{ + if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX)) + return -1; + return reinterpret_cast(loc)->marshal(reinterpret_cast(buf), (int) bufSize); +} + +char *ZT_Locator_toString( + const ZT_Locator *loc, + char *buf, + int capacity) +{ + if ((!loc) || (capacity < ZT_LOCATOR_STRING_SIZE_MAX)) + return nullptr; + return reinterpret_cast(loc)->toString(buf); +} + +const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc) +{ + if (!loc) + return nullptr; + return (ZT_Fingerprint *) (&(reinterpret_cast(loc)->signer())); +} + +int64_t ZT_Locator_timestamp(const ZT_Locator *loc) +{ + if (!loc) + return 0; + return reinterpret_cast(loc)->timestamp(); +} + +unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc) +{ + return (loc) ? (unsigned int) (reinterpret_cast(loc)->endpoints().size()) : 0; +} + +const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep) +{ + if (!loc) + return nullptr; + if (ep >= (unsigned int) (reinterpret_cast(loc)->endpoints().size())) + return nullptr; + return reinterpret_cast(&(reinterpret_cast(loc)->endpoints()[ep])); +} + +int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer) +{ + if ((!loc) || (!signer)) + return 0; + return reinterpret_cast(loc)->verify(*reinterpret_cast(signer)) ? 1 : 0; +} + +void ZT_Locator_delete(ZT_Locator *loc) +{ + if (loc) + delete reinterpret_cast(loc); +} + +/********************************************************************************************************************/ + +ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) +{ + if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384)) + return nullptr; + try { + ZeroTier::Identity *const id = new ZeroTier::Identity(); + id->generate((ZeroTier::Identity::Type)type); + return reinterpret_cast(id); + } catch (...) { + return nullptr; + } +} + +ZT_Identity *ZT_Identity_fromString(const char *idStr) +{ + if (!idStr) + return nullptr; + try { + ZeroTier::Identity *const id = new ZeroTier::Identity(); + if (!id->fromString(idStr)) { + delete id; + return nullptr; + } + return reinterpret_cast(id); + } catch (...) { + return nullptr; + } +} + +int ZT_Identity_validate(const ZT_Identity *id) +{ + if (!id) + return 0; + return reinterpret_cast(id)->locallyValidate() ? 1 : 0; +} + +unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength) +{ + if (!id) + return 0; + if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE) + return 0; + return reinterpret_cast(id)->sign(data, len, signature, signatureBufferLength); +} + +int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen) +{ + if ((!id) || (!signature) || (!sigLen)) + return 0; + return reinterpret_cast(id)->verify(data, len, signature, sigLen) ? 1 : 0; +} + +enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id) +{ + if (!id) + return (ZT_IdentityType)0; + return (enum ZT_IdentityType)reinterpret_cast(id)->type(); +} + +char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate) +{ + if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH)) + return nullptr; + reinterpret_cast(id)->toString(includePrivate != 0, buf); + return buf; +} + +int ZT_Identity_hasPrivate(const ZT_Identity *id) +{ + if (!id) + return 0; + return reinterpret_cast(id)->hasPrivate() ? 1 : 0; +} + +uint64_t ZT_Identity_address(const ZT_Identity *id) +{ + if (!id) + return 0; + return reinterpret_cast(id)->address(); +} + +const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) +{ + if (!id) + return nullptr; + return &(reinterpret_cast(id)->fingerprint()); +} + +void ZT_Identity_delete(ZT_Identity *id) +{ + if (id) + delete reinterpret_cast(id); +} + +/********************************************************************************************************************/ + +int ZT_Certificate_newSubjectUniqueId( + enum ZT_CertificateUniqueIdType type, + void *uniqueId, + int *uniqueIdSize, + void *uniqueIdPrivate, + int *uniqueIdPrivateSize) +{ + try { + switch (type) { + case ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384: + if ((*uniqueIdSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (*uniqueIdPrivateSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE)) + return ZT_RESULT_ERROR_BAD_PARAMETER; + *uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE; + *uniqueIdPrivateSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE; + ZeroTier::Certificate::createSubjectUniqueId(reinterpret_cast(uniqueId), reinterpret_cast(uniqueIdPrivate)); + return ZT_RESULT_OK; + } + return ZT_RESULT_ERROR_BAD_PARAMETER; + } catch (...) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +int ZT_Certificate_newCSR( + const ZT_Certificate_Subject *subject, + const void *uniqueId, + int uniqueIdSize, + const void *uniqueIdPrivate, + int uniqueIdPrivateSize, + void *csr, + int *csrSize) +{ + try { + if (!subject) + return ZT_RESULT_ERROR_BAD_PARAMETER; + const ZeroTier::Vector< uint8_t > csrV(ZeroTier::Certificate::createCSR(*subject, uniqueId, uniqueIdSize, uniqueIdPrivate, uniqueIdPrivateSize)); + if ((int)csrV.size() > *csrSize) + return ZT_RESULT_ERROR_BAD_PARAMETER; + ZeroTier::Utils::copy(csr, csrV.data(), (unsigned int)csrV.size()); + *csrSize = (int)csrV.size(); + return ZT_RESULT_OK; + } catch (...) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +int ZT_Certificate_sign( + const ZT_Certificate *cert, + const ZT_Identity *signer, + void *signedCert, + int *signedCertSize) +{ + try { + if (!cert) + return ZT_RESULT_ERROR_BAD_PARAMETER; + ZeroTier::Certificate c(*cert); + if (!c.sign(*reinterpret_cast(signer))) + return ZT_RESULT_ERROR_INTERNAL; + + const ZeroTier::Vector< uint8_t > enc(c.encode()); + if ((int)enc.size() > *signedCertSize) + return ZT_RESULT_ERROR_BAD_PARAMETER; + ZeroTier::Utils::copy(signedCert, enc.data(), (unsigned int)enc.size()); + *signedCertSize = (int)enc.size(); + + return ZT_RESULT_OK; + } catch (...) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +enum ZT_CertificateError ZT_Certificate_decode( + const ZT_Certificate **decodedCert, + const void *cert, + int certSize, + int verify) +{ + try { + if ((!decodedCert) || (!cert) || (certSize <= 0)) + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + *decodedCert = nullptr; + ZeroTier::Certificate *const c = new ZeroTier::Certificate(); + if (!c->decode(cert, certSize)) { + delete c; + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + } + if (verify) { + const ZT_CertificateError err = c->verify(); + if (err != ZT_CERTIFICATE_ERROR_NONE) { + delete c; + return err; + } + } + *decodedCert = c; + return ZT_CERTIFICATE_ERROR_NONE; + } catch (...) { + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + } +} + +int ZT_Certificate_encode( + const ZT_Certificate *cert, + void *encoded, + int *encodedSize) +{ + try { + if ((!cert) || (!encoded) || (!encodedSize)) + return ZT_RESULT_ERROR_BAD_PARAMETER; + ZeroTier::Certificate c(*cert); + ZeroTier::Vector< uint8_t > enc(c.encode()); + if ((int)enc.size() > *encodedSize) + return ZT_RESULT_ERROR_BAD_PARAMETER; + ZeroTier::Utils::copy(encoded, enc.data(), (unsigned int)enc.size()); + *encodedSize = (int)enc.size(); + return ZT_RESULT_OK; + } catch (...) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +enum ZT_CertificateError ZT_Certificate_verify(const ZT_Certificate *cert) +{ + try { + if (!cert) + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + return ZeroTier::Certificate(*cert).verify(); + } catch (...) { + return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; + } +} + +const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) +{ + try { + if (!cert) + return nullptr; + return (const ZT_Certificate *)(new ZeroTier::Certificate(*cert)); + } catch (...) { + return nullptr; + } +} + +void ZT_Certificate_delete(const ZT_Certificate *cert) +{ + try { + if (cert) + delete (const ZeroTier::Certificate *)(cert); + } catch (...) {} +} + +/********************************************************************************************************************/ + +} // extern "C" diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 51566c922..62bc64e7f 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -63,6 +63,7 @@ set(core_src AES.cpp Buf.cpp C25519.cpp + CAPI.cpp CapabilityCredential.cpp Certificate.cpp Defaults.cpp diff --git a/core/Certificate.cpp b/core/Certificate.cpp index ca5e90184..3dc0cc215 100644 --- a/core/Certificate.cpp +++ b/core/Certificate.cpp @@ -663,157 +663,3 @@ void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d } } // namespace ZeroTier - -extern "C" { - -int ZT_Certificate_newSubjectUniqueId( - enum ZT_CertificateUniqueIdType type, - void *uniqueId, - int *uniqueIdSize, - void *uniqueIdPrivate, - int *uniqueIdPrivateSize) -{ - try { - switch (type) { - case ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384: - if ((*uniqueIdSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (*uniqueIdPrivateSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE)) - return ZT_RESULT_ERROR_BAD_PARAMETER; - *uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE; - *uniqueIdPrivateSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE; - ZeroTier::Certificate::createSubjectUniqueId(reinterpret_cast(uniqueId), reinterpret_cast(uniqueIdPrivate)); - return ZT_RESULT_OK; - } - return ZT_RESULT_ERROR_BAD_PARAMETER; - } catch (...) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - -int ZT_Certificate_newCSR( - const ZT_Certificate_Subject *subject, - const void *uniqueId, - int uniqueIdSize, - const void *uniqueIdPrivate, - int uniqueIdPrivateSize, - void *csr, - int *csrSize) -{ - try { - if (!subject) - return ZT_RESULT_ERROR_BAD_PARAMETER; - const ZeroTier::Vector< uint8_t > csrV(ZeroTier::Certificate::createCSR(*subject, uniqueId, uniqueIdSize, uniqueIdPrivate, uniqueIdPrivateSize)); - if ((int)csrV.size() > *csrSize) - return ZT_RESULT_ERROR_BAD_PARAMETER; - ZeroTier::Utils::copy(csr, csrV.data(), (unsigned int)csrV.size()); - *csrSize = (int)csrV.size(); - return ZT_RESULT_OK; - } catch (...) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - -int ZT_Certificate_sign( - const ZT_Certificate *cert, - const ZT_Identity *signer, - void *signedCert, - int *signedCertSize) -{ - try { - if (!cert) - return ZT_RESULT_ERROR_BAD_PARAMETER; - ZeroTier::Certificate c(*cert); - if (!c.sign(*reinterpret_cast(signer))) - return ZT_RESULT_ERROR_INTERNAL; - - const ZeroTier::Vector< uint8_t > enc(c.encode()); - if ((int)enc.size() > *signedCertSize) - return ZT_RESULT_ERROR_BAD_PARAMETER; - ZeroTier::Utils::copy(signedCert, enc.data(), (unsigned int)enc.size()); - *signedCertSize = (int)enc.size(); - - return ZT_RESULT_OK; - } catch (...) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - -enum ZT_CertificateError ZT_Certificate_decode( - const ZT_Certificate **decodedCert, - const void *cert, - int certSize, - int verify) -{ - try { - if ((!decodedCert) || (!cert) || (certSize <= 0)) - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - *decodedCert = nullptr; - ZeroTier::Certificate *const c = new ZeroTier::Certificate(); - if (!c->decode(cert, certSize)) { - delete c; - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - } - if (verify) { - const ZT_CertificateError err = c->verify(); - if (err != ZT_CERTIFICATE_ERROR_NONE) { - delete c; - return err; - } - } - *decodedCert = c; - return ZT_CERTIFICATE_ERROR_NONE; - } catch (...) { - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - } -} - -int ZT_Certificate_encode( - const ZT_Certificate *cert, - void *encoded, - int *encodedSize) -{ - try { - if ((!cert) || (!encoded) || (!encodedSize)) - return ZT_RESULT_ERROR_BAD_PARAMETER; - ZeroTier::Certificate c(*cert); - ZeroTier::Vector< uint8_t > enc(c.encode()); - if ((int)enc.size() > *encodedSize) - return ZT_RESULT_ERROR_BAD_PARAMETER; - ZeroTier::Utils::copy(encoded, enc.data(), (unsigned int)enc.size()); - *encodedSize = (int)enc.size(); - return ZT_RESULT_OK; - } catch (...) { - return ZT_RESULT_FATAL_ERROR_INTERNAL; - } -} - -enum ZT_CertificateError ZT_Certificate_verify(const ZT_Certificate *cert) -{ - try { - if (!cert) - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - return ZeroTier::Certificate(*cert).verify(); - } catch (...) { - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - } -} - -const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) -{ - try { - if (!cert) - return nullptr; - return (const ZT_Certificate *)(new ZeroTier::Certificate(*cert)); - } catch (...) { - return nullptr; - } -} - -void ZT_Certificate_delete(const ZT_Certificate *cert) -{ - try { - if (cert) - delete (const ZeroTier::Certificate *)(cert); - } catch (...) {} -} - -} diff --git a/core/Identity.cpp b/core/Identity.cpp index bdbf98498..0ca0a16d9 100644 --- a/core/Identity.cpp +++ b/core/Identity.cpp @@ -542,101 +542,3 @@ void Identity::m_computeHash() } } // namespace ZeroTier - -extern "C" { - -ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) -{ - if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384)) - return nullptr; - try { - ZeroTier::Identity *const id = new ZeroTier::Identity(); - id->generate((ZeroTier::Identity::Type)type); - return reinterpret_cast(id); - } catch (...) { - return nullptr; - } -} - -ZT_Identity *ZT_Identity_fromString(const char *idStr) -{ - if (!idStr) - return nullptr; - try { - ZeroTier::Identity *const id = new ZeroTier::Identity(); - if (!id->fromString(idStr)) { - delete id; - return nullptr; - } - return reinterpret_cast(id); - } catch (...) { - return nullptr; - } -} - -int ZT_Identity_validate(const ZT_Identity *id) -{ - if (!id) - return 0; - return reinterpret_cast(id)->locallyValidate() ? 1 : 0; -} - -unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength) -{ - if (!id) - return 0; - if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE) - return 0; - return reinterpret_cast(id)->sign(data, len, signature, signatureBufferLength); -} - -int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen) -{ - if ((!id) || (!signature) || (!sigLen)) - return 0; - return reinterpret_cast(id)->verify(data, len, signature, sigLen) ? 1 : 0; -} - -enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id) -{ - if (!id) - return (ZT_IdentityType)0; - return (enum ZT_IdentityType)reinterpret_cast(id)->type(); -} - -char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate) -{ - if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH)) - return nullptr; - reinterpret_cast(id)->toString(includePrivate != 0, buf); - return buf; -} - -int ZT_Identity_hasPrivate(const ZT_Identity *id) -{ - if (!id) - return 0; - return reinterpret_cast(id)->hasPrivate() ? 1 : 0; -} - -uint64_t ZT_Identity_address(const ZT_Identity *id) -{ - if (!id) - return 0; - return reinterpret_cast(id)->address(); -} - -const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) -{ - if (!id) - return nullptr; - return &(reinterpret_cast(id)->fingerprint()); -} - -ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id) -{ - if (id) - delete reinterpret_cast(id); -} - -} diff --git a/core/Locator.cpp b/core/Locator.cpp index c713b9781..a1b32afcf 100644 --- a/core/Locator.cpp +++ b/core/Locator.cpp @@ -204,122 +204,3 @@ void Locator::m_sortEndpoints() noexcept { std::sort(m_endpoints.begin(), m_endpoints.end(), p_SortByEndpoint()); } } // namespace ZeroTier - -extern "C" { - -ZT_Locator *ZT_Locator_create( - int64_t ts, - const ZT_Endpoint *endpoints, - const ZT_EndpointAttributes *endpointAttributes, // TODO: not used yet - unsigned int endpointCount, - const ZT_Identity *signer) -{ - try { - if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer)) - return nullptr; - ZeroTier::Locator *loc = new ZeroTier::Locator(); - for (unsigned int i = 0;i < endpointCount;++i) - loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT); - if (!loc->sign(ts, *reinterpret_cast< const ZeroTier::Identity * >(signer))) { - delete loc; - return nullptr; - } - return reinterpret_cast(loc); - } catch (...) { - return nullptr; - } -} - -ZT_Locator *ZT_Locator_fromString(const char *str) -{ - try { - if (!str) - return nullptr; - ZeroTier::Locator *loc = new ZeroTier::Locator(); - if (!loc->fromString(str)) { - delete loc; - return nullptr; - } - return reinterpret_cast(loc); - } catch ( ... ) { - return nullptr; - } -} - -ZT_Locator *ZT_Locator_unmarshal( - const void *data, - unsigned int len) -{ - try { - if ((!data) || (len == 0)) - return nullptr; - ZeroTier::Locator *loc = new ZeroTier::Locator(); - if (loc->unmarshal(reinterpret_cast(data), (int) len) <= 0) { - delete loc; - return nullptr; - } - return reinterpret_cast(loc); - } catch (...) { - return nullptr; - } -} - -int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize) -{ - if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX)) - return -1; - return reinterpret_cast(loc)->marshal(reinterpret_cast(buf), (int) bufSize); -} - -char *ZT_Locator_toString( - const ZT_Locator *loc, - char *buf, - int capacity) -{ - if ((!loc) || (capacity < ZT_LOCATOR_STRING_SIZE_MAX)) - return nullptr; - return reinterpret_cast(loc)->toString(buf); -} - -const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc) -{ - if (!loc) - return nullptr; - return (ZT_Fingerprint *) (&(reinterpret_cast(loc)->signer())); -} - -int64_t ZT_Locator_timestamp(const ZT_Locator *loc) -{ - if (!loc) - return 0; - return reinterpret_cast(loc)->timestamp(); -} - -unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc) -{ - return (loc) ? (unsigned int) (reinterpret_cast(loc)->endpoints().size()) : 0; -} - -const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep) -{ - if (!loc) - return nullptr; - if (ep >= (unsigned int) (reinterpret_cast(loc)->endpoints().size())) - return nullptr; - return reinterpret_cast(&(reinterpret_cast(loc)->endpoints()[ep])); -} - -int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer) -{ - if ((!loc) || (!signer)) - return 0; - return reinterpret_cast(loc)->verify(*reinterpret_cast(signer)) ? 1 : 0; -} - -void ZT_Locator_delete(ZT_Locator *loc) -{ - if (loc) - delete reinterpret_cast(loc); -} - -} // C API functions diff --git a/core/MAC.hpp b/core/MAC.hpp index 982a0c71a..f3e0fbaf7 100644 --- a/core/MAC.hpp +++ b/core/MAC.hpp @@ -264,6 +264,8 @@ private: uint64_t m_mac; }; +static_assert(sizeof(MAC) == sizeof(uint64_t),"MAC contains unnecessary padding"); + } // namespace ZeroTier #endif diff --git a/core/Node.cpp b/core/Node.cpp index a5b7fd9e3..b4cfd786e 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -840,320 +840,3 @@ void Node::ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &d } } // namespace ZeroTier - -// C API -------------------------------------------------------------------------------------------------------------- - -extern "C" { - -// These macros make the idiom of passing buffers to outside code via the API work properly even -// if the first address of Buf does not overlap with its data field, since the C++ standard does -// not absolutely guarantee this. -#define _ZT_PTRTOBUF(p) ((ZeroTier::Buf *)( ((uintptr_t)(p)) - ((uintptr_t)&(((ZeroTier::Buf *)0)->unsafeData[0])) )) -#define _ZT_BUFTOPTR(b) ((void *)(&((b)->unsafeData[0]))) - -void *ZT_getBuffer() -{ - // When external code requests a Buf, grab one from the pool (or freshly allocated) - // and return it with its reference count left at zero. It's the responsibility of - // external code to bring it back via freeBuffer() or one of the processX() calls. - // When this occurs it's either sent back to the pool with Buf's delete operator or - // wrapped in a SharedPtr<> to be passed into the core. - try { - return _ZT_BUFTOPTR(new ZeroTier::Buf()); - } catch (...) { - return nullptr; // can only happen on out of memory condition - } -} - -void ZT_freeBuffer(void *b) -{ - if (b) - delete _ZT_PTRTOBUF(b); -} - -struct p_queryResultBase -{ - void (*freeFunction)(const void *); -}; - -void ZT_freeQueryResult(const void *qr) -{ - if ((qr) && (reinterpret_cast(qr)->freeFunction)) - reinterpret_cast(qr)->freeFunction(qr); -} - -enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const struct ZT_Node_Callbacks *callbacks, int64_t now) -{ - *node = (ZT_Node *)0; - try { - *node = reinterpret_cast(new ZeroTier::Node(uptr, tptr, callbacks, now)); - return ZT_RESULT_OK; - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (std::runtime_error &exc) { - return ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -void ZT_Node_delete(ZT_Node *node, void *tPtr) -{ - try { - reinterpret_cast(node)->shutdown(tPtr); - delete (reinterpret_cast(node)); - } catch (...) {} -} - -enum ZT_ResultCode ZT_Node_processWirePacket( - ZT_Node *node, - void *tptr, - int64_t now, - int64_t localSocket, - const struct sockaddr_storage *remoteAddress, - const void *packetData, - unsigned int packetLength, - int isZtBuffer, - volatile int64_t *nextBackgroundTaskDeadline) -{ - try { - ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? _ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK)); - return reinterpret_cast(node)->processWirePacket(tptr, now, localSocket, remoteAddress, buf, packetLength, nextBackgroundTaskDeadline); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - // "OK" since invalid packets are simply dropped, but the system is still up. - // We should never make it here, but if we did that would be the interpretation. - return ZT_RESULT_OK; - } -} - -enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( - ZT_Node *node, - void *tptr, - int64_t now, - uint64_t nwid, - uint64_t sourceMac, - uint64_t destMac, - unsigned int etherType, - unsigned int vlanId, - const void *frameData, - unsigned int frameLength, - int isZtBuffer, - volatile int64_t *nextBackgroundTaskDeadline) -{ - try { - ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? _ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK)); - return reinterpret_cast(node)->processVirtualNetworkFrame(tptr, now, nwid, sourceMac, destMac, etherType, vlanId, buf, frameLength, nextBackgroundTaskDeadline); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) -{ - try { - return reinterpret_cast(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, void *tptr) -{ - try { - return reinterpret_cast(node)->join(nwid, controllerFingerprint, uptr, tptr); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void *tptr) -{ - try { - return reinterpret_cast(node)->leave(nwid, uptr, tptr); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) -{ - try { - return reinterpret_cast(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) -{ - try { - return reinterpret_cast(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi); - } catch (std::bad_alloc &exc) { - return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -uint64_t ZT_Node_address(ZT_Node *node) -{ - return reinterpret_cast(node)->address(); -} - -const ZT_Identity *ZT_Node_identity(ZT_Node *node) -{ - return (const ZT_Identity *)(&(reinterpret_cast(node)->identity())); -} - -void ZT_Node_status(ZT_Node *node, ZT_NodeStatus *status) -{ - try { - reinterpret_cast(node)->status(status); - } catch (...) {} -} - -ZT_PeerList *ZT_Node_peers(ZT_Node *node) -{ - try { - return reinterpret_cast(node)->peers(); - } catch (...) { - return (ZT_PeerList *)0; - } -} - -ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid) -{ - try { - return reinterpret_cast(node)->networkConfig(nwid); - } catch (...) { - return (ZT_VirtualNetworkConfig *)0; - } -} - -ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) -{ - try { - return reinterpret_cast(node)->networks(); - } catch (...) { - return (ZT_VirtualNetworkList *)0; - } -} - -int ZT_Node_tryPeer( - ZT_Node *node, - void *tptr, - const ZT_Fingerprint *fp, - const ZT_Endpoint *endpoint, - int retries) -{ - try { - return reinterpret_cast(node)->tryPeer(tptr, fp, endpoint, retries); - } catch (...) { - return 0; - } -} - -enum ZT_CertificateError ZT_Node_addCertificate( - ZT_Node *node, - void *tptr, - int64_t now, - unsigned int localTrust, - const ZT_Certificate *cert, - const void *certData, - unsigned int certSize) -{ - try { - return reinterpret_cast(node)->addCertificate(tptr, now, localTrust, cert, certData, certSize); - } catch (...) { - return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; - } -} - -ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( - ZT_Node *node, - void *tptr, - const void *serialNo) -{ - try { - return reinterpret_cast(node)->deleteCertificate(tptr, serialNo); - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) -{ - try { - return reinterpret_cast(node)->listCertificates(); - } catch (...) { - return nullptr; - } -} - -void ZT_Node_setNetworkUserPtr(ZT_Node *node, uint64_t nwid, void *ptr) -{ - try { - reinterpret_cast(node)->setNetworkUserPtr(nwid, ptr); - } catch (...) {} -} - -void ZT_Node_setInterfaceAddresses(ZT_Node *node, const ZT_InterfaceAddress *addrs, unsigned int addrCount) -{ - try { - reinterpret_cast(node)->setInterfaceAddresses(addrs, addrCount); - } catch (...) {} -} - -enum ZT_ResultCode ZT_Node_addPeer( - ZT_Node *node, - void *tptr, - const ZT_Identity *id) -{ - try { - return reinterpret_cast(node)->addPeer(tptr, id); - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -int ZT_Node_sendUserMessage(ZT_Node *node, void *tptr, uint64_t dest, uint64_t typeId, const void *data, unsigned int len) -{ - try { - return reinterpret_cast(node)->sendUserMessage(tptr, dest, typeId, data, len); - } catch (...) { - return 0; - } -} - -void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance) -{ - try { - reinterpret_cast(node)->setController(networkControllerInstance); - } catch (...) {} -} - -void ZT_version(int *major, int *minor, int *revision, int *build) -{ - if (major) - *major = ZEROTIER_VERSION_MAJOR; - if (minor) - *minor = ZEROTIER_VERSION_MINOR; - if (revision) - *revision = ZEROTIER_VERSION_REVISION; - if (build) - *build = ZEROTIER_VERSION_BUILD; -} - -} // extern "C" diff --git a/core/OS.hpp b/core/OS.hpp index f4e83da78..79af8121c 100644 --- a/core/OS.hpp +++ b/core/OS.hpp @@ -115,14 +115,6 @@ #include #endif -#if (defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON)) -#ifndef ZT_ARCH_ARM_HAS_NEON -#define ZT_ARCH_ARM_HAS_NEON 1 -#endif -#include -/*#include */ -#endif - #if defined(ZT_ARCH_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386) #define ZT_ARCH_X86 1 #endif @@ -133,6 +125,20 @@ #endif #endif +#if (defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(ZT_ARCH_ARM_HAS_NEON)) +#if (defined(__APPLE__) && !defined(__LP64__)) || (defined(__ANDROID__) && defined(__arm__)) +#ifdef ZT_ARCH_ARM_HAS_NEON +#undef ZT_ARCH_ARM_HAS_NEON +#endif +#else +#ifndef ZT_ARCH_ARM_HAS_NEON +#define ZT_ARCH_ARM_HAS_NEON 1 +#endif +#include +/*#include */ +#endif +#endif + #if defined(__SIZEOF_INT128__) || ((defined(ZT_ARCH_X64) || defined(__aarch64__)) && defined(__GNUC__)) #ifdef __SIZEOF_INT128__ #define ZT_HAVE_UINT128 1 @@ -216,10 +222,9 @@ typedef unsigned uint128_t __attribute__((mode(TI))); #endif #endif -// Macro to print very verbose tracing information to standard error. -#define ZT_VA_ARGS(...) , ##__VA_ARGS__ #define ZT_DEBUG_SPEW #ifdef ZT_DEBUG_SPEW +#define ZT_VA_ARGS(...) , ##__VA_ARGS__ #define ZT_SPEW(f,...) fprintf(stderr,"%s:%d(%s): " f ZT_EOL_S,__FILE__,__LINE__,__FUNCTION__ ZT_VA_ARGS(__VA_ARGS__)) #else #define ZT_SPEW(f,...) diff --git a/core/Topology.hpp b/core/Topology.hpp index 7de6e13ab..c6b8053d5 100644 --- a/core/Topology.hpp +++ b/core/Topology.hpp @@ -194,7 +194,6 @@ private: SharedPtr< const Certificate > certificate; unsigned int localTrust; }; - Map< SHA384Hash, p_CertEntry > m_certs; Map< SHA384Hash, p_CertEntry > m_certsBySubjectUniqueID; Map< Fingerprint, Map< SharedPtr< const Certificate >, unsigned int > > m_certsBySubjectIdentity; diff --git a/core/Utils.cpp b/core/Utils.cpp index dd326ebe2..d7e3a0258 100644 --- a/core/Utils.cpp +++ b/core/Utils.cpp @@ -38,9 +38,21 @@ namespace ZeroTier { namespace Utils { -#ifdef ZT_ARCH_ARM_HAS_NEON +#ifdef ZT_ARCH_ARM_HAS_NEON /****************************************************************************************/ ARMCapabilities::ARMCapabilities() noexcept { + +#ifdef __APPLE__ + + this->aes = true; + this->crc32 = true; + this->pmull = true; + this->sha1 = true; + this->sha2 = true; + +#else + +#ifdef __LINUX__ #ifdef HWCAP2_AES if (sizeof(void *) == 4) { const long hwcaps2 = getauxval(AT_HWCAP2); @@ -60,13 +72,16 @@ ARMCapabilities::ARMCapabilities() noexcept #ifdef HWCAP2_AES } #endif +#endif + +#endif + } const ARMCapabilities ARMCAP; -#endif - -#ifdef ZT_ARCH_X64 +#endif /*************************************************************************************************************/ +#ifdef ZT_ARCH_X64 /*************************************************************************************************/ CPUIDRegisters::CPUIDRegisters() noexcept { uint32_t eax, ebx, ecx, edx; @@ -113,7 +128,7 @@ CPUIDRegisters::CPUIDRegisters() noexcept } const CPUIDRegisters CPUID; -#endif +#endif /*************************************************************************************************************/ const std::bad_alloc BadAllocException; const std::out_of_range OutOfRangeException("access out of range"); @@ -131,19 +146,18 @@ bool secureEq(const void *a, const void *b, unsigned int len) noexcept void burn(volatile void *ptr, unsigned int len) { + static volatile uintptr_t foo = 0; Utils::zero((void *)ptr, len); - // This line is present to force the compiler not to optimize out the memory - // zeroing operation above, as burn() is used to erase secrets and other - // sensitive data. - if ((reinterpret_cast(ptr)[0] | reinterpret_cast(ptr)[len-1]) != 0) - burn(ptr, len); + // Force compiler not to optimize this function out by taking a volatile + // parameter and also updating a volatile variable. + foo += (uintptr_t)len ^ (uintptr_t)reinterpret_cast(ptr)[0]; } -static unsigned long _Utils_itoa(unsigned long n, char *s) +static unsigned long s_decimalRecursive(unsigned long n, char *s) { if (n == 0) return 0; - unsigned long pos = _Utils_itoa(n / 10, s); + unsigned long pos = s_decimalRecursive(n / 10, s); if (pos >= 22) // sanity check,should be impossible pos = 22; s[pos] = (char)('0' + (n % 10)); @@ -157,7 +171,7 @@ char *decimal(unsigned long n, char s[24]) noexcept s[1] = (char)0; return s; } - s[_Utils_itoa(n, s)] = (char)0; + s[s_decimalRecursive(n, s)] = (char)0; return s; } @@ -353,7 +367,7 @@ void getSecureRandom(void *const buf, unsigned int bytes) noexcept uint64_t getSecureRandomU64() noexcept { - uint64_t tmp = 0; + uint64_t tmp; getSecureRandom(&tmp, sizeof(tmp)); return tmp; }