static void udpInterface(Dict* config, struct Context* ctx) { Dict* udp = Dict_getDict(config, String_CONST("UDPInterface")); Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo")); if (connectTo) { struct Dict_Entry* entry = *connectTo; while (entry != NULL) { String* key = (String*) entry->key; if (entry->val->type != Object_DICT) { Log_critical1(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] " "is not a dictionary type.", key->bytes); exit(-1); } Dict* value = entry->val->as.dictionary; Log_keys1(ctx->logger, "Attempting to connect to node [%s].", key->bytes); struct Allocator* perCallAlloc = ctx->alloc->child(ctx->alloc); Dict_putString(value, String_CONST("address"), key, perCallAlloc); rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc); perCallAlloc->free(perCallAlloc); entry = entry->next; } } }
static void showMsg(struct AdminClient_Result* res, struct Context* ctx) { Log_keys1(ctx->logger, "message bytes = [%s]", res->messageBytes); #ifndef Log_KEYS Log_critical(ctx->logger, "enable Log_LEVEL=KEYS to see message content."); #endif }
static uint8_t decryptHandshake(struct Wrapper* wrapper, const uint32_t nonce, struct Message* message, union Headers_CryptoAuth* header) { if (message->length < sizeof(union Headers_CryptoAuth)) { Log_debug(wrapper->context->logger, "Dropped runt packet\n"); return Error_UNDERSIZE_MESSAGE; } // handshake // nextNonce 0: recieving hello. // nextNonce 1: recieving key, we sent hello. // nextNonce 2: recieving first data packet or duplicate hello. // nextNonce 3: recieving first data packet. // nextNonce >3: handshake complete if (wrapper->nextNonce < 2 && nonce == UINT32_MAX && !wrapper->requireAuth) { // Reset without knowing key is allowed until state reaches 2. // this is because we don't know that the other end knows our key until we // have received a valid packet from them. // We can't allow the upper layer to see this message because it's not authenticated. if (!knowHerKey(wrapper)) { memcpy(wrapper->herPerminentPubKey, header->handshake.publicKey, 32); } Message_shift(message, -Headers_CryptoAuth_SIZE); message->length = 0; wrapper->nextNonce = 0; wrapper->user = NULL; // Send an empty response (to initiate the connection). encryptHandshake(message, wrapper); return Error_NONE; } void* user = NULL; uint8_t passwordHashStore[32]; uint8_t* passwordHash = tryAuth(header, passwordHashStore, wrapper, &user); if (wrapper->requireAuth && !user) { Log_debug(wrapper->context->logger, "Dropping message because auth was not given and is required.\n"); return Error_AUTHENTICATION; } if (passwordHash == NULL && header->handshake.auth.challenge.type != 0) { Log_debug(wrapper->context->logger, "Dropping message because it contans an authenticator which is unrecognized.\n"); return Error_AUTHENTICATION; } // What the nextNonce will become if this packet is valid. uint32_t nextNonce; // The secret for decrypting this message. uint8_t sharedSecret[32]; uint8_t* herPermKey = NULL; if (nonce < 2) { if (nonce == 0) { Log_debug1(wrapper->context->logger, "Received a hello packet, using auth: %d\n", (passwordHash != NULL)); } else { Log_debug(wrapper->context->logger, "Received a repeat hello packet\n"); } // Decrypt message with perminent keys. if (!knowHerKey(wrapper) || wrapper->nextNonce == 0) { herPermKey = header->handshake.publicKey; #ifdef Log_DEBUG if (Bits_isZero(header->handshake.publicKey, 32)) { Log_debug(wrapper->context->logger, "Node sent public key of ZERO!\n"); } #endif } else { herPermKey = wrapper->herPerminentPubKey; if (memcmp(header->handshake.publicKey, herPermKey, 32)) { Log_debug(wrapper->context->logger, "Packet contains different perminent key.\n"); return Error_AUTHENTICATION; } } getSharedSecret(sharedSecret, wrapper->context->privateKey, herPermKey, passwordHash, wrapper->context->logger); nextNonce = 2; } else { if (nonce == 2) { Log_debug(wrapper->context->logger, "Received a key packet\n"); } else if (nonce == 3) { Log_debug(wrapper->context->logger, "Received a repeat key packet\n"); } else { Log_debug1(wrapper->context->logger, "Received a packet of unknown type! nonce=%u\n", nonce); } if (memcmp(header->handshake.publicKey, wrapper->herPerminentPubKey, 32)) { Log_debug(wrapper->context->logger, "Packet contains different perminent key.\n"); return Error_AUTHENTICATION; } // We sent the hello, this is a key getSharedSecret(sharedSecret, wrapper->secret, wrapper->herPerminentPubKey, passwordHash, wrapper->context->logger); nextNonce = 4; } // Shift it on top of the authenticator before the encrypted public key Message_shift(message, 48 - Headers_CryptoAuth_SIZE); Log_debug1(wrapper->context->logger, "Message length: %u\n", message->length); #ifdef Log_KEYS uint8_t sharedSecretHex[65]; printHexKey(sharedSecretHex, sharedSecret); uint8_t nonceHex[49]; Hex_encode(nonceHex, 49, header->handshake.nonce, 24); uint8_t cipherHex[65]; printHexKey(cipherHex, message->bytes); Log_keys3(wrapper->context->logger, "Decrypting message with:\n" " nonce: %s\n" " secret: %s\n" " cipher: %s\n", nonceHex, sharedSecretHex, cipherHex); #endif // Decrypt her temp public key and the message. if (decryptRndNonce(header->handshake.nonce, message, sharedSecret) != 0) { // just in case memset(header, 0, Headers_CryptoAuth_SIZE); Log_debug(wrapper->context->logger, "Dropped message because authenticated decryption failed.\n"); return Error_AUTHENTICATION; } wrapper->user = user; memcpy(wrapper->tempKey, header->handshake.encryptedTempKey, 32); #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); #endif #ifdef Log_KEYS uint8_t tempKeyHex[65]; Hex_encode(tempKeyHex, 65, wrapper->tempKey, 32); Log_keys1(wrapper->context->logger, "Unwrapping temp public key:\n" " %s\n", tempKeyHex); #endif Message_shift(message, -32); wrapper->nextNonce = nextNonce; if (nextNonce == 2) { wrapper->isInitiator = false; } if (herPermKey && herPermKey != wrapper->herPerminentPubKey) { memcpy(wrapper->herPerminentPubKey, herPermKey, 32); } // If this is a handshake which was initiated in reverse because we // didn't know the other node's key, now send what we were going to send. if (wrapper->hasBufferedMessage && message->length == 0) { Log_debug(wrapper->context->logger, "Sending buffered message.\n"); sendMessage(wrapper->bufferedMessage, &wrapper->externalInterface); wrapper->hasBufferedMessage = false; return Error_NONE; } else if (wrapper->hasBufferedMessage) { Log_debug(wrapper->context->logger, "There is a buffered message.\n"); } memset(&wrapper->replayProtector, 0, sizeof(struct ReplayProtector)); setRequiredPadding(wrapper); return callReceivedMessage(wrapper, message); }
static uint8_t encryptHandshake(struct Message* message, struct Wrapper* wrapper) { assert(message->padding >= sizeof(union Headers_CryptoAuth) || !"not enough padding"); Message_shift(message, sizeof(union Headers_CryptoAuth)); union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) message->bytes; // garbage the auth field to frustrate DPI and set the nonce (next 24 bytes after the auth) randombytes((uint8_t*) &header->handshake.auth, sizeof(union Headers_AuthChallenge) + 24); memcpy(&header->handshake.publicKey, wrapper->context->publicKey, 32); if (!knowHerKey(wrapper)) { return genReverseHandshake(message, wrapper, header); } // Password auth uint8_t* passwordHash = NULL; if (wrapper->password != NULL) { struct Auth auth; passwordHash = hashPassword(&auth, wrapper->password, wrapper->authType); memcpy(header->handshake.auth.bytes, &auth.challenge, sizeof(union Headers_AuthChallenge)); } header->handshake.auth.challenge.type = wrapper->authType; Headers_setPacketAuthRequired(&header->handshake.auth, wrapper->authenticatePackets); // set the session state uint32_t sessionState_be = Endian_hostToBigEndian32(wrapper->nextNonce); header->nonce = sessionState_be; if (wrapper->nextNonce == 0 || wrapper->nextNonce == 2) { // If we're sending a hello or a key crypto_box_curve25519xsalsa20poly1305_keypair(header->handshake.encryptedTempKey, wrapper->secret); if (wrapper->nextNonce == 0) { memcpy(wrapper->tempKey, header->handshake.encryptedTempKey, 32); } #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); assert(!Bits_isZero(wrapper->secret, 32)); #endif } else if (wrapper->nextNonce == 3) { // Dupe key // If nextNonce is 1 then we have our pubkey stored in wrapper->tempKey, // If nextNonce is 3 we need to recalculate it each time // because tempKey the final secret. crypto_scalarmult_curve25519_base(header->handshake.encryptedTempKey, wrapper->secret); } else { // Dupe hello // wrapper->nextNonce == 1 // Our public key is cached in wrapper->tempKey so lets copy it out. memcpy(header->handshake.encryptedTempKey, wrapper->tempKey, 32); } uint8_t sharedSecret[32]; if (wrapper->nextNonce < 2) { if (wrapper->nextNonce == 0) { Log_debug(wrapper->context->logger, "Sending hello packet\n"); } else { Log_debug(wrapper->context->logger, "Sending repeat hello packet\n"); } getSharedSecret(sharedSecret, wrapper->context->privateKey, wrapper->herPerminentPubKey, passwordHash, wrapper->context->logger); wrapper->isInitiator = true; wrapper->nextNonce = 1; #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); uint8_t myTempPubKey[32]; crypto_scalarmult_curve25519_base(myTempPubKey, wrapper->secret); assert(!memcmp(header->handshake.encryptedTempKey, myTempPubKey, 32)); #endif #ifdef Log_KEYS uint8_t tempKeyHex[65]; Hex_encode(tempKeyHex, 65, header->handshake.encryptedTempKey, 32); Log_keys1(wrapper->context->logger, "Wrapping temp public key:\n" " %s\n", tempKeyHex); #endif } else { if (wrapper->nextNonce == 2) { Log_debug(wrapper->context->logger, "Sending key packet\n"); } else { Log_debug(wrapper->context->logger, "Sending repeat key packet\n"); } // Handshake2 wrapper->tempKey holds her public temp key. // it was put there by receiveMessage() getSharedSecret(sharedSecret, wrapper->context->privateKey, wrapper->tempKey, passwordHash, wrapper->context->logger); wrapper->nextNonce = 3; #ifdef Log_KEYS uint8_t tempKeyHex[65]; Hex_encode(tempKeyHex, 65, wrapper->tempKey, 32); Log_keys1(wrapper->context->logger, "Using their temp public key:\n" " %s\n", tempKeyHex); #endif } // Shift message over the encryptedTempKey field. Message_shift(message, 32 - Headers_CryptoAuth_SIZE); encryptRndNonce(header->handshake.nonce, message, sharedSecret); Log_debug1(wrapper->context->logger, "Message length: %u\n", message->length); #ifdef Log_KEYS uint8_t sharedSecretHex[65]; printHexKey(sharedSecretHex, sharedSecret); uint8_t nonceHex[49]; Hex_encode(nonceHex, 49, header->handshake.nonce, 24); uint8_t cipherHex[65]; printHexKey(cipherHex, message->bytes); Log_keys3(wrapper->context->logger, "Encrypting message with:\n" " nonce: %s\n" " secret: %s\n" " cipher: %s\n", nonceHex, sharedSecretHex, cipherHex); #endif #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); #endif // Shift it back -- encryptRndNonce adds 16 bytes of authenticator. Message_shift(message, Headers_CryptoAuth_SIZE - 32 - 16); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }