static uint8_t receiveMessage(struct Message* received, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = Identity_cast((struct CryptoAuth_Wrapper*) interface->receiverContext); union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) received->bytes; if (received->length < (wrapper->authenticatePackets ? 20 : 4)) { cryptoAuthDebug0(wrapper, "Dropped runt"); return Error_UNDERSIZE_MESSAGE; } Assert_true(received->padding >= 12 || "need at least 12 bytes of padding in incoming message"); #ifdef Log_DEBUG Assert_true(!((uintptr_t)received->bytes % 4) || !"alignment fault"); #endif Message_shift(received, -4); uint32_t nonce = Endian_bigEndianToHost32(header->nonce); if (wrapper->nextNonce < 5) { if (nonce > 3 && nonce != UINT32_MAX && knowHerKey(wrapper)) { cryptoAuthDebug(wrapper, "Trying final handshake step, nonce=%u\n", nonce); uint8_t secret[32]; getSharedSecret(secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); // We'll optimistically advance the nextNonce value because decryptMessage() // passes the message on to the upper level and if this message causes a // response, we want the CA to be in ESTABLISHED state. // if the decryptMessage() call fails, we CryptoAuth_reset() it back. wrapper->nextNonce += 3; if (decryptMessage(wrapper, nonce, received, secret)) { cryptoAuthDebug0(wrapper, "Final handshake step succeeded"); Bits_memcpyConst(wrapper->secret, secret, 32); return callReceivedMessage(wrapper, received); } CryptoAuth_reset(&wrapper->externalInterface); cryptoAuthDebug0(wrapper, "Final handshake step failed"); return Error_UNDELIVERABLE; } } else if (nonce > 4) { if (decryptMessage(wrapper, nonce, received, wrapper->secret)) { return callReceivedMessage(wrapper, received); } else { cryptoAuthDebug0(wrapper, "Failed to decrypt message"); return Error_UNDELIVERABLE; } } else { cryptoAuthDebug0(wrapper, "Received handshake message during established connection"); } Message_shift(received, 4); return decryptHandshake(wrapper, nonce, received, header); }
static uint8_t sendMessage(struct Message* message, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = Identity_cast((struct CryptoAuth_Wrapper*) interface->senderContext); // If there has been no incoming traffic for a while, reset the connection to state 0. // This will prevent "connection in bad state" situations from lasting forever. uint64_t nowSecs = Time_currentTimeSeconds(wrapper->context->eventBase); if (nowSecs - wrapper->timeOfLastPacket > wrapper->context->pub.resetAfterInactivitySeconds) { Log_debug(wrapper->context->logger, "No traffic in [%d] seconds, resetting connection.", (int) (nowSecs - wrapper->timeOfLastPacket)); wrapper->timeOfLastPacket = nowSecs; CryptoAuth_reset(interface); return encryptHandshake(message, wrapper); } #ifdef Log_DEBUG Assert_true(!((uintptr_t)message->bytes % 4) || !"alignment fault"); #endif // nextNonce 0: sending hello, we are initiating connection. // nextNonce 1: sending another hello, nothing received yet. // nextNonce 2: sending key, hello received. // nextNonce 3: sending key again, no data packet recieved yet. // nextNonce >3: handshake complete // // if it's a blind handshake, every message will be empty and nextNonce will remain // zero until the first message is received back. if (wrapper->nextNonce < 5) { if (wrapper->nextNonce < 4) { return encryptHandshake(message, wrapper); } else { Log_debug(wrapper->context->logger, "@%p Doing final step to send message. nonce=4\n", (void*) wrapper); uint8_t secret[32]; getSharedSecret(secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); Bits_memcpyConst(wrapper->secret, secret, 32); } } return encryptMessage(message, wrapper); }
void InterfaceController_resetPeering(struct InterfaceController* ifController, uint8_t herPublicKey[32]) { struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifController); for (int j = 0; j < ic->icis->length; j++) { struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, j); for (int i = 0; i < (int)ici->peerMap.count; i++) { struct Peer* peer = ici->peerMap.values[i]; if (!herPublicKey || !Bits_memcmp(herPublicKey, peer->caSession->herPublicKey, 32)) { CryptoAuth_reset(peer->caSession); } } } }
static uint8_t receiveMessage(struct Message* received, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = (struct CryptoAuth_Wrapper*) interface->receiverContext; union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) received->bytes; if (received->length < (wrapper->authenticatePackets ? 20 : 4)) { Log_debug(wrapper->context->logger, "Dropped runt"); return Error_UNDERSIZE_MESSAGE; } Assert_true(received->padding >= 12 || "need at least 12 bytes of padding in incoming message"); #ifdef Log_DEBUG Assert_true(!((uintptr_t)received->bytes % 4) || !"alignment fault"); #endif Message_shift(received, -4); uint32_t nonce = Endian_bigEndianToHost32(header->nonce); if (wrapper->nextNonce < 5) { if (nonce > 3 && nonce != UINT32_MAX && knowHerKey(wrapper)) { Log_debug(wrapper->context->logger, "@%p Trying final handshake step, nonce=%u\n", (void*) wrapper, nonce); uint8_t secret[32]; getSharedSecret(secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); if (decryptMessage(wrapper, nonce, received, secret)) { Log_debug(wrapper->context->logger, "Final handshake step succeeded.\n"); wrapper->nextNonce += 3; Bits_memcpyConst(wrapper->secret, secret, 32); return Error_NONE; } CryptoAuth_reset(&wrapper->externalInterface); Log_debug(wrapper->context->logger, "Final handshake step failed.\n"); } } else if (nonce > 2 && decryptMessage(wrapper, nonce, received, wrapper->secret)) { // If decryptMessage returns false then we will try the packet as a handshake. return Error_NONE; } else { Log_debug(wrapper->context->logger, "Decryption failed, trying message as a handshake.\n"); } Message_shift(received, 4); return decryptHandshake(wrapper, nonce, received, header); }
static uint8_t sendMessage(struct Message* message, struct Interface* interface) { struct Wrapper* wrapper = (struct Wrapper*) interface->senderContext; // If there has been no incoming traffic for a while, reset the connection to state 0. // This will prevent "connection in bad state" situations from lasting forever. struct timeval now; event_base_gettimeofday_cached(wrapper->context->eventBase, &now); int64_t whenToReset = (int64_t) wrapper->timeOfLastPacket + wrapper->context->resetAfterInactivitySeconds; if (now.tv_sec > whenToReset) { Log_debug(wrapper->context->logger, "No traffic in a while, resetting connection.\n"); wrapper->timeOfLastPacket = now.tv_sec; CryptoAuth_reset(interface); return encryptHandshake(message, wrapper); } #ifdef Log_DEBUG assert(!((uintptr_t)message->bytes % 4) || !"alignment fault"); #endif // nextNonce 0: sending hello, we are initiating connection. // nextNonce 1: sending another hello, nothing received yet. // nextNonce 2: sending key, hello received. // nextNonce 3: sending key again, no data packet recieved yet. // nextNonce >3: handshake complete // // if it's a blind handshake, every message will be empty and nextNonce will remain // zero until the first message is received back. if (wrapper->nextNonce < 5) { if (wrapper->nextNonce < 4) { return encryptHandshake(message, wrapper); } else { Log_debug(wrapper->context->logger, "Doing final step to send message.\n"); getSharedSecret(wrapper->secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); } } return encryptMessage(message, wrapper); }
static uint8_t receiveMessage(struct Message* received, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = Identity_check((struct CryptoAuth_Wrapper*) interface->receiverContext); union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) received->bytes; if (received->length < 20) { cryptoAuthDebug0(wrapper, "DROP runt"); return Error_UNDERSIZE_MESSAGE; } Assert_true(received->padding >= 12 || "need at least 12 bytes of padding in incoming message"); Assert_true(!((uintptr_t)received->bytes % 4) || !"alignment fault"); Message_shift(received, -4, NULL); uint32_t nonce = Endian_bigEndianToHost32(header->nonce); if (!wrapper->established) { if (nonce > 3 && nonce != UINT32_MAX) { if (wrapper->nextNonce < 3) { // This is impossible because we have not exchanged hello and key messages. cryptoAuthDebug0(wrapper, "DROP Received a run message to an un-setup session"); return Error_UNDELIVERABLE; } cryptoAuthDebug(wrapper, "Trying final handshake step, nonce=%u\n", nonce); uint8_t secret[32]; Assert_ifParanoid(!Bits_isZero(wrapper->ourTempPrivKey, 32)); Assert_ifParanoid(!Bits_isZero(wrapper->herTempPubKey, 32)); getSharedSecret(secret, wrapper->ourTempPrivKey, wrapper->herTempPubKey, NULL, wrapper->context->logger); // We'll optimistically advance the nextNonce value because decryptMessage() // passes the message on to the upper level and if this message causes a // response, we want the CA to be in ESTABLISHED state. // if the decryptMessage() call fails, we CryptoAuth_reset() it back. wrapper->nextNonce += 3; if (decryptMessage(wrapper, nonce, received, secret)) { cryptoAuthDebug0(wrapper, "Final handshake step succeeded"); Bits_memcpyConst(wrapper->sharedSecret, secret, 32); // Now we're in run mode, no more handshake packets will be accepted Bits_memset(wrapper->ourTempPrivKey, 0, 32); Bits_memset(wrapper->ourTempPubKey, 0, 32); Bits_memset(wrapper->herTempPubKey, 0, 32); wrapper->established = true; return callReceivedMessage(wrapper, received); } CryptoAuth_reset(&wrapper->externalInterface); cryptoAuthDebug0(wrapper, "DROP Final handshake step failed"); return Error_UNDELIVERABLE; } Message_shift(received, 4, NULL); return decryptHandshake(wrapper, nonce, received, header); } else if (nonce > 3 && nonce != UINT32_MAX) { Assert_ifParanoid(!Bits_isZero(wrapper->sharedSecret, 32)); if (decryptMessage(wrapper, nonce, received, wrapper->sharedSecret)) { return callReceivedMessage(wrapper, received); } else { cryptoAuthDebug0(wrapper, "DROP Failed to decrypt message"); return Error_UNDELIVERABLE; } } else if (nonce < 2) { cryptoAuthDebug(wrapper, "hello packet during established session nonce=[%d]", nonce); Message_shift(received, 4, NULL); return decryptHandshake(wrapper, nonce, received, header); } else { // setup keys are already zeroed, not much we can do here. cryptoAuthDebug(wrapper, "DROP key packet during established session nonce=[%d]", nonce); return Error_UNDELIVERABLE; } Assert_true(0); }