static void sendMsg(struct MsgCore_pvt* mcp, Dict* msgDict, struct Address* addr, struct Allocator* allocator) { struct Allocator* alloc = Allocator_child(allocator); // Send the encoding scheme definition Dict_putString(msgDict, CJDHTConstants_ENC_SCHEME, mcp->schemeDefinition, allocator); // And tell the asker which interface the message came from int encIdx = EncodingScheme_getFormNum(mcp->scheme, addr->path); Assert_true(encIdx != EncodingScheme_getFormNum_INVALID); Dict_putInt(msgDict, CJDHTConstants_ENC_INDEX, encIdx, allocator); // send the protocol version Dict_putInt(msgDict, CJDHTConstants_PROTOCOL, Version_CURRENT_PROTOCOL, allocator); if (!Defined(SUBNODE)) { String* q = Dict_getStringC(msgDict, "q"); String* sq = Dict_getStringC(msgDict, "sq"); if (q || sq) { Log_debug(mcp->log, "Send query [%s] to [%s]", ((q) ? q->bytes : sq->bytes), Address_toString(addr, alloc)->bytes); String* txid = Dict_getStringC(msgDict, "txid"); Assert_true(txid); String* newTxid = String_newBinary(NULL, txid->len + 1, alloc); Bits_memcpy(&newTxid->bytes[1], txid->bytes, txid->len); newTxid->bytes[0] = '1'; Dict_putStringC(msgDict, "txid", newTxid, alloc); } } struct Message* msg = Message_new(0, 2048, alloc); BencMessageWriter_write(msgDict, msg, NULL); //Log_debug(mcp->log, "Sending msg [%s]", Escape_getEscaped(msg->bytes, msg->length, alloc)); // Sanity check (make sure the addr was actually calculated) Assert_true(addr->ip6.bytes[0] == 0xfc); struct DataHeader data; Bits_memset(&data, 0, sizeof(struct DataHeader)); DataHeader_setVersion(&data, DataHeader_CURRENT_VERSION); DataHeader_setContentType(&data, ContentType_CJDHT); Message_push(msg, &data, sizeof(struct DataHeader), NULL); struct RouteHeader route; Bits_memset(&route, 0, sizeof(struct RouteHeader)); Bits_memcpy(route.ip6, addr->ip6.bytes, 16); route.version_be = Endian_hostToBigEndian32(addr->protocolVersion); route.sh.label_be = Endian_hostToBigEndian64(addr->path); Bits_memcpy(route.publicKey, addr->key, 32); Message_push(msg, &route, sizeof(struct RouteHeader), NULL); Iface_send(&mcp->pub.interRouterIf, msg); }
static void reset(struct CryptoAuth_Wrapper* wrapper) { wrapper->nextNonce = 0; wrapper->isInitiator = false; Bits_memset(wrapper->ourTempPrivKey, 0, 32); Bits_memset(wrapper->ourTempPubKey, 0, 32); Bits_memset(wrapper->herTempPubKey, 0, 32); Bits_memset(wrapper->sharedSecret, 0, 32); wrapper->established = false; Bits_memset(&wrapper->replayProtector, 0, sizeof(struct ReplayProtector)); }
static void reset(struct CryptoAuth_Session_pvt* session) { session->nextNonce = 0; session->isInitiator = false; Bits_memset(session->ourTempPrivKey, 0, 32); Bits_memset(session->ourTempPubKey, 0, 32); Bits_memset(session->herTempPubKey, 0, 32); Bits_memset(session->sharedSecret, 0, 32); session->established = false; Bits_memset(&session->pub.replayProtector, 0, sizeof(struct ReplayProtector)); }
static void encryptRndNonceTest() { uint8_t buff[44]; Bits_memset(buff, 0, 44); uint8_t nonce[24]; Bits_memset(nonce, 0, 24); uint8_t secret[32]; Bits_memset(secret, 0, 32); struct Message m = { .bytes=&buff[32], .length=12, .padding=32}; CString_strcpy((char*) m.bytes, "hello world"); CryptoAuth_encryptRndNonce(nonce, &m, secret); uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc"; uint8_t output[57]; Hex_encode(output, 57, m.bytes, m.length); //printf("\n%s\n%s\n", (char*) expected, (char*) output); Assert_true(!Bits_memcmp(expected, output, 56)); Assert_true(!CryptoAuth_decryptRndNonce(nonce, &m, secret)); Assert_true(m.length == 12 && !Bits_memcmp(m.bytes, "hello world", m.length)); } static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger) { struct RandomSeed* evilSeed = DeterminentRandomSeed_new(alloc); return Random_newWithSeed(alloc, logger, evilSeed, NULL); } static void createNew() { struct Allocator* allocator = MallocAllocator_new(BUFFER_SIZE); struct CryptoAuth* ca = CryptoAuth_new(allocator, privateKey, eventBase, NULL, evilRandom(allocator, NULL)); /*for (int i = 0; i < 32; i++) { printf("%.2x", ca->publicKey[i]); }*/ Assert_true(Bits_memcmp(ca->publicKey, publicKey, 32) == 0); Allocator_free(allocator); } static uint8_t receiveMessage(struct Message* message, struct Interface* iface) { Message_pop(message, NULL, 4, NULL); *((struct Message**)iface->receiverContext) = message; return Error_NONE; }
static void checkBytes(struct Random* rand, int alignment, int length) { Assert_true(length < 128 && alignment < 8); uint64_t buff64[20] = {0}; uint8_t* buff = (uint8_t*) (&buff64[1]); buff += alignment; // Check for bytes which are always the same, a few \0s are ok // but if every cycle they are always zero then there's a bug. uint8_t oldBuff[128] = {0}; // Preload into the output buff so alignment is same. Random_bytes(rand, buff, length); Bits_memcpy(oldBuff, buff, length); uint8_t sameAsOld[128]; Bits_memset(sameAsOld, 0xff, 128); // Check for bytes which are the same as other bytes every time. // if buff[3] always equals buff[8] then there's a bug. uint8_t sameBytes[128+128]; Bits_memset(sameBytes, 0xff, 128+128); for (int i = 0; i < 100; i++) { Random_bytes(rand, buff, length); for (int j = 0; j < length; j++) { for (int jj = j; jj < length; jj++) { sameBytes[j+jj] &= (jj != j && buff[j] == buff[jj]); } } for (int j = 0; j < length; j++) { sameAsOld[j] &= (oldBuff[i] == buff[i]); } // Check that the function did not write after or before the buffer. uint8_t* origBuff = (uint8_t*) (buff64); Assert_true(Bits_isZero(origBuff, 8+alignment)); Assert_true(Bits_isZero(buff+length, 8)); } for (int i = 0; i < length+length-1; i++) { Assert_true(!sameBytes[i]); } for (int i = 0; i < length; i++) { Assert_true(!sameAsOld[i]); } }
static int get(struct RandomSeed* randomSeed, uint64_t output[8]) { int mib[] = { CTL_KERN, KERN_ARND }; Bits_memset(output, 0, 64); size_t len = 64; if (sysctl(mib, 2, output, &len, NULL, 0) == -1) { // TOR/Libevent retry this 4 bytes at a time if it fails initially. size_t four = 4; int tries = 0; union { uint64_t longs[8]; uint32_t ints[16]; } num; for (int i = 0; i < 16; i++) { if (sysctl(mib, 2, &num.ints[i], &four, NULL, 0) == -1) { return -1; } if (num.ints[i] == 0) { i--; if (++tries > MAX_TRIES) { return -1; } } } } return Bits_isZero(output, 64) ? -1 : 0; }
static inline uint8_t incomingDHT(struct Message* message, struct Address* addr, struct Ducttape_pvt* context) { struct DHTMessage dht; Bits_memset(&dht, 0, sizeof(struct DHTMessage)); // TODO: These copies are not necessary at all. const uint32_t length = (message->length < DHTMessage_MAX_SIZE) ? message->length : DHTMessage_MAX_SIZE; Bits_memcpy(dht.bytes, message->bytes, length); dht.address = addr; uint8_t buffer[PER_MESSAGE_BUF_SZ]; dht.allocator = BufferAllocator_new(buffer, PER_MESSAGE_BUF_SZ); struct Jmp j; Jmp_try(j) { BufferAllocator_onOOM(dht.allocator, &j.handler); DHTModuleRegistry_handleIncoming(&dht, context->registry); } Jmp_catch { uint8_t printed[60]; Address_print(printed, addr); Log_warn(context->logger, "Parsing message from [%s] failed; out of memory.", printed); } // TODO: return something meaningful. return Error_NONE; }
static void onPingResponse(enum SwitchPinger_Result result, uint64_t label, String* data, uint32_t millisecondsLag, uint32_t version, void* onResponseContext) { if (SwitchPinger_Result_OK != result) { return; } struct IFCPeer* ep = Identity_cast((struct IFCPeer*) onResponseContext); struct Context* ic = ifcontrollerForPeer(ep); struct Address addr; Bits_memset(&addr, 0, sizeof(struct Address)); Bits_memcpyConst(addr.key, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); addr.path = ep->switchLabel; Log_debug(ic->logger, "got switch pong from node with version [%d]", version); RouterModule_addNode(ic->routerModule, &addr, version); #ifdef Log_DEBUG // This will be false if it times out. //Assert_true(label == ep->switchLabel); uint8_t path[20]; AddrTools_printPath(path, label); uint8_t sl[20]; AddrTools_printPath(sl, ep->switchLabel); Log_debug(ic->logger, "Received [%s] from lazy endpoint [%s] [%s]", SwitchPinger_resultString(result)->bytes, path, sl); #endif }
static Iface_DEFUN incomingFromUpperDistributorIf(struct Message* msg, struct Iface* upperDistributorIf) { struct TUNAdapter_pvt* ud = Identity_containerOf(upperDistributorIf, struct TUNAdapter_pvt, pub.upperDistributorIf); Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE); struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes; struct DataHeader* dh = (struct DataHeader*) &hdr[1]; enum ContentType type = DataHeader_getContentType(dh); Assert_true(type <= ContentType_IP6_RAW); // Shift ip address into destination slot. Bits_memmoveConst(&hdr->ip6[DataHeader_SIZE - 16], hdr->ip6, 16); // put my address as destination. Bits_memcpyConst(&hdr->ip6[DataHeader_SIZE], ud->myIp6, 16); Message_shift(msg, Headers_IP6Header_SIZE - DataHeader_SIZE - RouteHeader_SIZE, NULL); struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes; Bits_memset(ip6, 0, Headers_IP6Header_SIZE - 32); Headers_setIpVersion(ip6); ip6->payloadLength_be = Endian_bigEndianToHost16(msg->length - Headers_IP6Header_SIZE); ip6->nextHeader = type; ip6->hopLimit = 42; TUNMessageType_push(msg, Ethernet_TYPE_IP6, NULL); return sendToTunIf(msg, ud); }
static inline uint8_t incomingDHT(struct Message* message, struct Address* addr, struct Ducttape_pvt* context) { struct DHTMessage dht = { .address = addr, .binMessage = message, .allocator = message->alloc }; DHTModuleRegistry_handleIncoming(&dht, context->registry); // TODO(cjd): return something meaningful. return Error_NONE; } /** Header must not be encrypted and must be aligned on the beginning of the ipv6 header. */ static inline uint8_t sendToRouter(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { int safeDistance = SwitchHeader_SIZE; CryptoAuth_resetIfTimeout(session->internal); if (CryptoAuth_getState(session->internal) < CryptoAuth_HANDSHAKE3) { // Put the handle into the message so that it's authenticated. // see: sendToSwitch() //Log_debug(context->logger, "Sending receive handle under CryptoAuth"); Message_push(message, &session->receiveHandle_be, 4, NULL); safeDistance += CryptoHeader_SIZE; } else { // 16 for the authenticator, 4 for the nonce and 4 for the handle safeDistance += 24; } Message_shift(message, safeDistance, NULL); if (dtHeader->switchHeader) { if (message->bytes != (uint8_t*)dtHeader->switchHeader) { Bits_memmoveConst(message->bytes, dtHeader->switchHeader, SwitchHeader_SIZE); dtHeader->switchHeader = (struct SwitchHeader*) message->bytes; } } else { dtHeader->switchHeader = (struct SwitchHeader*) message->bytes; Bits_memset(dtHeader->switchHeader, 0, SwitchHeader_SIZE); } Message_shift(message, -safeDistance, NULL); SwitchHeader_setVersion(dtHeader->switchHeader, SwitchHeader_CURRENT_VERSION); SwitchHeader_setLabelShift(dtHeader->switchHeader, 0); dtHeader->switchHeader->label_be = Endian_hostToBigEndian64(dtHeader->switchLabel); // This comes out in outgoingFromCryptoAuth() then sendToSwitch() dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be); dtHeader->layer = Ducttape_SessionLayer_OUTER; return Interface_sendMessage(session->internal, message); }
static void nodeForAddress(struct PFChan_Node* nodeOut, struct Address* addr, uint32_t metric) { Bits_memset(nodeOut, 0, PFChan_Node_SIZE); nodeOut->version_be = Endian_hostToBigEndian32(addr->protocolVersion); nodeOut->metric_be = Endian_hostToBigEndian32(metric | 0xffff0000); nodeOut->path_be = Endian_hostToBigEndian64(addr->path); Bits_memcpy(nodeOut->publicKey, addr->key, 32); Bits_memcpy(nodeOut->ip6, addr->ip6.bytes, 16); }
static void onPingResponse(struct SwitchPinger_Response* resp, void* onResponseContext) { if (SwitchPinger_Result_OK != resp->res) { return; } struct InterfaceController_Peer* ep = Identity_check((struct InterfaceController_Peer*) onResponseContext); struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep); struct Address addr; Bits_memset(&addr, 0, sizeof(struct Address)); Bits_memcpyConst(addr.key, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); addr.path = ep->switchLabel; addr.protocolVersion = resp->version; #ifdef Log_DEBUG uint8_t addrStr[60]; Address_print(addrStr, &addr); uint8_t key[56]; Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32); #endif if (!Version_isCompatible(Version_CURRENT_PROTOCOL, resp->version)) { Log_debug(ic->logger, "got switch pong from node [%s] with incompatible version [%d]", key, resp->version); } else { Log_debug(ic->logger, "got switch pong from node [%s] with version [%d]", key, resp->version); } if (!ep->timeOfLastPing) { // We've never heard from this machine before (or we've since forgotten about it) // This is here because we want the tests to function without the janitor present. // Other than that, it just makes a slightly more synchronous/guaranteed setup. Router_sendGetPeers(ic->router, &addr, 0, 0, ic->allocator); } struct Node_Link* link = Router_linkForPath(ic->router, resp->label); if (!link || !Node_getBestParent(link->child)) { RumorMill_addNode(ic->rumorMill, &addr); } else { Log_debug(ic->logger, "link exists"); } ep->timeOfLastPing = Time_currentTimeMilliseconds(ic->eventBase); #ifdef Log_DEBUG // This will be false if it times out. //Assert_true(label == ep->switchLabel); uint8_t path[20]; AddrTools_printPath(path, resp->label); uint8_t sl[20]; AddrTools_printPath(sl, ep->switchLabel); Log_debug(ic->logger, "Received [%s] from lazy endpoint [%s] [%s]", SwitchPinger_resultString(resp->res)->bytes, path, sl); #endif }
/** @see BencSerializer.h */ static int32_t serializeint64_t(const struct Writer* writer, int64_t integer) { char buffer[32]; Bits_memset(buffer, 0, 32); snprintf(buffer, 32, "%" PRId64, integer); return writer->write(buffer, strlen(buffer), writer); }
static void pushRouteDataHeaders(struct Context* ctx, struct Message* message) { Message_shift(message, RouteHeader_SIZE + DataHeader_SIZE, NULL); struct RouteHeader* rh = (struct RouteHeader*) message->bytes; struct DataHeader* dh = (struct DataHeader*) &rh[1]; Bits_memset(rh, 0, RouteHeader_SIZE + DataHeader_SIZE); Bits_memcpy(rh->ip6, ctx->ipv6, 16); Bits_memcpy(rh->publicKey, ctx->pubKey, 32); DataHeader_setContentType(dh, ContentType_IPTUN); }
void* Allocator__calloc(struct Allocator* alloc, unsigned long length, unsigned long count, const char* fileName, int lineNum) { void* pointer = Allocator__malloc(alloc, length * count, fileName, lineNum); Bits_memset(pointer, 0, length * count); return pointer; }
static int getUUID(uint64_t output[2]) { int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; size_t sixteen = 16; Bits_memset(output, 0, 16); if (sysctl(mib, 3, output, &sixteen, NULL, 0) || Bits_isZero(output, 16)) { return -1; } return 0; }
static uint8_t receiveMessage(struct Message* msg, struct Interface* iface) { struct Context* ctx = Identity_cast((struct Context*) iface->receiverContext); struct Sockaddr_storage source; Message_pop(msg, &source, ctx->targetAddr->addrLen, NULL); if (Bits_memcmp(&source, ctx->targetAddr, ctx->targetAddr->addrLen)) { Log_info(ctx->logger, "Got spurious message from [%s], expecting messages from [%s]", Sockaddr_print(&source.addr, msg->alloc), Sockaddr_print(ctx->targetAddr, msg->alloc)); return 0; } // we don't yet know with which message this data belongs, // the message alloc lives the length of the message reception. struct Allocator* alloc = Allocator_child(msg->alloc); struct Reader* reader = ArrayReader_new(msg->bytes, msg->length, alloc); Dict* d = Dict_new(alloc); if (StandardBencSerializer_get()->parseDictionary(reader, alloc, d)) { return 0; } String* txid = Dict_getString(d, String_CONST("txid")); if (!txid || txid->len != 8) { return 0; } // look up the result uint32_t handle = ~0u; Hex_decode((uint8_t*)&handle, 4, txid->bytes, 8); int idx = Map_OfRequestByHandle_indexForHandle(handle, &ctx->outstandingRequests); if (idx < 0) { return 0; } struct Request* req = ctx->outstandingRequests.values[idx]; // now this data will outlive the life of the message. Allocator_adopt(req->promise->alloc, alloc); req->res.responseDict = d; int len = (msg->length > AdminClient_MAX_MESSAGE_SIZE) ? AdminClient_MAX_MESSAGE_SIZE : msg->length; Bits_memset(req->res.messageBytes, 0, AdminClient_MAX_MESSAGE_SIZE); Bits_memcpy(req->res.messageBytes, msg->bytes, len); done(req, AdminClient_Error_NONE); return 0; }
static uint8_t sendMessage(struct Message* message, struct Interface* ethIf) { struct ETHInterface* context = Identity_cast((struct ETHInterface*) ethIf); struct sockaddr_ll addr; Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll)); Message_pop(message, addr.sll_addr, 8); /* Cut down on the noise uint8_t buff[sizeof(addr) * 2 + 1] = {0}; Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr)); Log_debug(context->logger, "Sending ethernet frame to [%s]", buff); */ // Check if we will have to pad the message and pad if necessary. int pad = 0; for (int length = message->length; length+2 < MIN_PACKET_SIZE; length += 8) { pad++; } if (pad > 0) { int length = message->length; Message_shift(message, pad*8); Bits_memset(message->bytes, 0, pad*8); Bits_memmove(message->bytes, &message->bytes[pad*8], length); } Assert_true(pad < 8); uint16_t padAndId_be = Endian_hostToBigEndian16((context->id << 3) | pad); Message_push(message, &padAndId_be, 2); if (sendto(context->socket, message->bytes, message->length, 0, (struct sockaddr*) &addr, sizeof(struct sockaddr_ll)) < 0) { switch (errno) { case EMSGSIZE: return Error_OVERSIZE_MESSAGE; case ENOBUFS: case EAGAIN: return Error_LINK_LIMIT_EXCEEDED; default:; Log_info(context->logger, "Got error sending to socket [%s]", strerror(errno)); } } return 0; }
void encryptRndNonceTest() { uint8_t buff[44]; Bits_memset(buff, 0, 44); uint8_t nonce[24]; Bits_memset(nonce, 0, 24); uint8_t secret[32]; Bits_memset(secret, 0, 32); struct Message m = { .bytes=&buff[32], .length=12, .padding=32}; strcpy((char*) m.bytes, "hello world"); Exports_encryptRndNonce(nonce, &m, secret); uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc"; uint8_t output[57]; Hex_encode(output, 57, m.bytes, m.length); //printf("\n%s\n%s\n", (char*) expected, (char*) output); Assert_always(!Bits_memcmp(expected, output, 56)); Assert_always(!Exports_decryptRndNonce(nonce, &m, secret)); Assert_always(m.length == 12 && !Bits_memcmp(m.bytes, "hello world", m.length)); } void createNew() { uint8_t buff[BUFFER_SIZE]; struct Allocator* allocator = CanaryAllocator_new(BufferAllocator_new(buff, BUFFER_SIZE), NULL); struct CryptoAuth* ca = CryptoAuth_new(allocator, privateKey, eventBase, NULL, NULL); /*for (int i = 0; i < 32; i++) { printf("%.2x", ca->publicKey[i]); }*/ Assert_always(Bits_memcmp(ca->publicKey, publicKey, 32) == 0); }
/** Header must not be encrypted and must be aligned on the beginning of the ipv6 header. */ static inline uint8_t sendToRouter(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { int safeDistance = Headers_SwitchHeader_SIZE; if (CryptoAuth_getState(&session->iface) < CryptoAuth_HANDSHAKE3) { // Bug 104, see Version.h #ifdef Version_2_COMPAT if (session->version >= 3) { #endif // Put the handle into the message so that it's authenticated. // see: sendToSwitch() Log_debug(context->logger, "Sending receive handle under CryptoAuth"); Message_push(message, &session->receiveHandle_be, 4); #ifdef Version_2_COMPAT } else { // Otherwise it will be added on the other side. safeDistance += 4; } #endif safeDistance += Headers_CryptoAuth_SIZE; } else { // 16 for the authenticator, 4 for the nonce and 4 for the handle safeDistance += 24; } Message_shift(message, safeDistance); if (dtHeader->switchHeader) { if (message->bytes != (uint8_t*)dtHeader->switchHeader) { Bits_memmoveConst(message->bytes, dtHeader->switchHeader, Headers_SwitchHeader_SIZE); dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes; } } else { dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes; Bits_memset(dtHeader->switchHeader, 0, Headers_SwitchHeader_SIZE); } Message_shift(message, -safeDistance); dtHeader->switchHeader->label_be = Endian_hostToBigEndian64(dtHeader->switchLabel); // This comes out in outgoingFromCryptoAuth() then sendToSwitch() dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be); dtHeader->layer = Ducttape_SessionLayer_OUTER; return session->iface.sendMessage(message, &session->iface); }
static struct Ducttape_MessageHeader* getDtHeader(struct Message* message, bool init) { int padding = message->padding; Assert_true(padding > Ducttape_MessageHeader_SIZE); Message_shift(message, padding); struct Ducttape_MessageHeader* dtHeader = (struct Ducttape_MessageHeader*) message->bytes; Message_shift(message, -padding); if (init) { Bits_memset(dtHeader, 0, Ducttape_MessageHeader_SIZE); Identity_set(dtHeader); } else { Identity_check(dtHeader); } return dtHeader; }
/** * Encrypt and authenticate. * Shifts the message by 16 bytes. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. */ static inline void encryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { Assert_true(msg->padding >= 32); uint8_t* startAt = msg->bytes - 32; // This function trashes 16 bytes of the padding so we will put it back uint8_t paddingSpace[16]; Bits_memcpyConst(paddingSpace, startAt, 16); Bits_memset(startAt, 0, 32); crypto_box_curve25519xsalsa20poly1305_afternm( startAt, startAt, msg->length + 32, nonce, secret); Bits_memcpyConst(startAt, paddingSpace, 16); Message_shift(msg, 16, NULL); }
static int incomingFromDHT(struct DHTMessage* dmessage, void* vpf) { struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vpf); struct Message* msg = dmessage->binMessage; struct Address* addr = dmessage->address; if (addr->path == 1) { // Message to myself, can't handle this later because encrypting a message to yourself // causes problems. DHTModuleRegistry_handleIncoming(dmessage, pf->registry); return 0; } // Sanity check (make sure the addr was actually calculated) Assert_true(AddressCalc_validAddress(addr->ip6.bytes)); Message_shift(msg, PFChan_Msg_MIN_SIZE, NULL); struct PFChan_Msg* emsg = (struct PFChan_Msg*) msg->bytes; Bits_memset(emsg, 0, PFChan_Msg_MIN_SIZE); DataHeader_setVersion(&emsg->data, DataHeader_CURRENT_VERSION); DataHeader_setContentType(&emsg->data, ContentType_CJDHT); Bits_memcpy(emsg->route.ip6, addr->ip6.bytes, 16); emsg->route.version_be = Endian_hostToBigEndian32(addr->protocolVersion); emsg->route.sh.label_be = Endian_hostToBigEndian64(addr->path); emsg->route.flags |= RouteHeader_flags_PATHFINDER; SwitchHeader_setVersion(&emsg->route.sh, SwitchHeader_CURRENT_VERSION); Bits_memcpy(emsg->route.publicKey, addr->key, 32); Assert_true(!Bits_isZero(emsg->route.publicKey, 32)); Assert_true(emsg->route.sh.label_be); Assert_true(emsg->route.version_be); Message_push32(msg, PFChan_Pathfinder_SENDMSG, NULL); if (dmessage->replyTo) { // see incomingMsg dmessage->replyTo->pleaseRespond = true; //Log_debug(pf->log, "send DHT reply"); return 0; } //Log_debug(pf->log, "send DHT request"); Iface_send(&pf->pub.eventIf, msg); return 0; }
static void releaseAllocation(struct Allocator_pvt* context, struct Allocator_Allocation_pvt* allocation, Allocator_Provider provider, Allocator_Provider_CONTEXT_TYPE* providerCtx) { checkCanaries(allocation, context); // TODO(cjd): make this optional. Bits_memset(&(&allocation->pub)[1], 0xee, allocation->pub.size - sizeof(struct Allocator_Allocation)); provider(providerCtx, &allocation->pub, 0, ((char*)context != (char*)allocation) ? &context->pub : NULL); }
static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* addrIface) { struct Context* ctx = Identity_containerOf(addrIface, struct Context, addrIface); struct Sockaddr_storage source; Message_pop(msg, &source, ctx->targetAddr->addrLen, NULL); if (Bits_memcmp(&source, ctx->targetAddr, ctx->targetAddr->addrLen)) { Log_info(ctx->logger, "Got spurious message from [%s], expecting messages from [%s]", Sockaddr_print(&source.addr, msg->alloc), Sockaddr_print(ctx->targetAddr, msg->alloc)); return NULL; } // we don't yet know with which message this data belongs, // the message alloc lives the length of the message reception. struct Allocator* alloc = Allocator_child(msg->alloc); int origLen = msg->length; Dict* d = NULL; char* err = BencMessageReader_readNoExcept(msg, alloc, &d); if (err) { return NULL; } Message_shift(msg, origLen, NULL); String* txid = Dict_getString(d, String_CONST("txid")); if (!txid || txid->len != 8) { return NULL; } // look up the result uint32_t handle = ~0u; Hex_decode((uint8_t*)&handle, 4, txid->bytes, 8); int idx = Map_OfRequestByHandle_indexForHandle(handle, &ctx->outstandingRequests); if (idx < 0) { return NULL; } struct Request* req = ctx->outstandingRequests.values[idx]; // now this data will outlive the life of the message. Allocator_adopt(req->promise->alloc, alloc); req->res.responseDict = d; int len = (msg->length > AdminClient_MAX_MESSAGE_SIZE) ? AdminClient_MAX_MESSAGE_SIZE : msg->length; Bits_memset(req->res.messageBytes, 0, AdminClient_MAX_MESSAGE_SIZE); Bits_memcpy(req->res.messageBytes, msg->bytes, len); done(req, AdminClient_Error_NONE); return NULL; }
static int get(struct RandomSeed* randomSeed, uint64_t output[8]) { #ifdef SYS_getrandom // Try using getrandom instead sysctl as with systems with getrandom // sysctl is probably alrady deprecated and possibly disabled. Bits_memset(output, 0, 64); // Just make sure that it is zero all along. long ret = syscall(SYS_getrandom, output, 64, 0); if (ret == 64 && !Bits_isZero(output, 64)) { return 0; } #endif if (getUUID(output) || getUUID(output+2) || getUUID(output+4) || getUUID(output+6)) { return -1; } return 0; }
int main() { struct Allocator* alloc; BufferAllocator_STACK(alloc, 512); struct Random* rand = Random_new(alloc, NULL); uint8_t bytes[32]; Random_bytes(rand, bytes, 32); uint8_t base32[64]; Bits_memset(base32, 0, 64); Assert_always(Base32_encode(base32, 64, bytes, 32) == 52); //printf("base32 encoded: %s\n", base32); uint8_t bytes2[32]; Assert_always(Base32_decode(bytes2, 32, base32, 52) == 32); Assert_always(Bits_memcmp(bytes, bytes2, 32) == 0); }
/** * Decrypt and authenticate. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. * @return 0 if decryption is succeddful, otherwise -1. */ static inline int decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { if (msg->length < 16) { return -1; } Assert_true(msg->padding >= 16); uint8_t* startAt = msg->bytes - 16; uint8_t paddingSpace[16]; Bits_memcpyConst(paddingSpace, startAt, 16); Bits_memset(startAt, 0, 16); if (crypto_box_curve25519xsalsa20poly1305_open_afternm( startAt, startAt, msg->length + 16, nonce, secret) != 0) { return -1; } Bits_memcpyConst(startAt, paddingSpace, 16); Message_shift(msg, -16, NULL); return 0; }
int main() { struct Allocator* alloc = MallocAllocator_new(20000); struct Random* rand = Random_new(alloc, NULL, NULL); uint8_t bytes[32]; Random_bytes(rand, bytes, 32); uint8_t base32[64]; Bits_memset(base32, 0, 64); Assert_always(Base32_encode(base32, 64, bytes, 32) == 52); //printf("base32 encoded: %s\n", base32); uint8_t bytes2[32]; Assert_always(Base32_decode(bytes2, 32, base32, 52) == 32); Assert_always(Bits_memcmp(bytes, bytes2, 32) == 0); Allocator_free(alloc); return 0; }
/** @see Allocator->calloc() */ static void* allocatorCalloc(size_t length, size_t count, const struct Allocator* allocator) { void* pointer = allocator->malloc(length * count, allocator); Bits_memset(pointer, 0, length * count); return pointer; }