Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
            }
        }
    }
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}