Exemple #1
0
/* Create a new onion path.
 *
 * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
 *
 * new_path must be an empty memory location of atleast Onion_Path size.
 *
 * return -1 on failure.
 * return 0 on success.
 */
int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes)
{
    if (!new_path || !nodes)
        return -1;

    encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1);
    memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);

    uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
    uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];

    crypto_box_keypair(random_public_key, random_secret_key);
    encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
    memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES);

    crypto_box_keypair(random_public_key, random_secret_key);
    encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
    memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES);

    new_path->ip_port1 = nodes[0].ip_port;
    new_path->ip_port2 = nodes[1].ip_port;
    new_path->ip_port3 = nodes[2].ip_port;

    memcpy(new_path->node_public_key1, nodes[0].public_key, crypto_box_PUBLICKEYBYTES);
    memcpy(new_path->node_public_key2, nodes[1].public_key, crypto_box_PUBLICKEYBYTES);
    memcpy(new_path->node_public_key3, nodes[2].public_key, crypto_box_PUBLICKEYBYTES);

    return 0;
}
Exemple #2
0
/* handle received packets for not yet established crypto connections. */
static void receive_crypto(void)
{
    uint32_t i;
    for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
        if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
            uint8_t temp_data[MAX_DATA_SIZE];
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            uint16_t len;
            if (id_packet(crypto_connections[i].number) == 1)
                /* if the packet is a friend request drop it (because we are already friends) */
                len = read_packet(crypto_connections[i].number, temp_data);
            if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */
                len = read_packet(crypto_connections[i].number, temp_data);
                if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
                    if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
                        memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
                        memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
                        increment_nonce(crypto_connections[i].sent_nonce);
                        uint32_t zero = 0;
                        encrypt_precompute(crypto_connections[i].peersessionpublic_key, 
                                           crypto_connections[i].sessionsecret_key, 
                                           crypto_connections[i].shared_key);
                        crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
                        write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
                        crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
                    }
                }
            } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
                crypto_kill(crypto_connections[i].number);

        }
        if (crypto_connections[i].status == CONN_NOT_CONFIRMED) {
            if (id_packet(crypto_connections[i].number) == 3) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint8_t data[MAX_DATA_SIZE];
                int length = read_packet(crypto_connections[i].number, temp_data);
                int len = decrypt_data(crypto_connections[i].peersessionpublic_key,
                                       crypto_connections[i].sessionsecret_key,
                                       crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
                uint32_t zero = 0;
                if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
                    increment_nonce(crypto_connections[i].recv_nonce);
                    encrypt_precompute(crypto_connections[i].peersessionpublic_key, 
                                       crypto_connections[i].sessionsecret_key, 
                                       crypto_connections[i].shared_key);
                    crypto_connections[i].status = CONN_ESTABLISHED;

                    /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
                    kill_connection_in(crypto_connections[i].number, 3000000);
                } else
                    crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does
            } else if(id_packet(crypto_connections[i].number) != -1)
                /* This should not happen
                   kill the connection if it does */
                crypto_kill(crypto_connections[i].number);
        }
    }
}
Exemple #3
0
END_TEST

START_TEST(test_fast_known)
{
    unsigned char k[CRYPTO_SHARED_KEY_SIZE];
    unsigned char c[147];
    unsigned char m[131];
    int clen, mlen;

    encrypt_precompute(bobpk, alicesk, k);

    ck_assert_msg(sizeof(c) == sizeof(m) + CRYPTO_MAC_SIZE * sizeof(unsigned char),
                  "cyphertext should be CRYPTO_MAC_SIZE bytes longer than plaintext");
    ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed");
    ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed");

    clen = encrypt_data_symmetric(k, test_nonce, test_m, sizeof(test_m) / sizeof(unsigned char), c);

    ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector");
    ck_assert_msg(clen == sizeof(c) / sizeof(unsigned char), "wrong ciphertext length");

    mlen = decrypt_data_symmetric(k, test_nonce, test_c, sizeof(test_c) / sizeof(unsigned char), m);

    ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector");
    ck_assert_msg(mlen == sizeof(m) / sizeof(unsigned char), "wrong plaintext length");
}
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
                 uint8_t *encrypted, uint32_t length, uint8_t *plain)
{
    uint8_t k[crypto_box_BEFORENMBYTES];
    encrypt_precompute(public_key, secret_key, k);
    return decrypt_data_fast(k, nonce, encrypted, length, plain);
}
Exemple #5
0
/* return 1 if everything went well.
 * return -1 if the connection must be killed.
 */
static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
                                const uint8_t *self_secret_key)
{
    if (length != TCP_CLIENT_HANDSHAKE_SIZE) {
        return -1;
    }

    if (con->status != TCP_STATUS_CONNECTED) {
        return -1;
    }

    uint8_t shared_key[crypto_box_BEFORENMBYTES];
    encrypt_precompute(data, self_secret_key, shared_key);
    uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
    int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES,
                                     data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain);

    if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
        return -1;
    }

    memcpy(con->public_key, data, crypto_box_PUBLICKEYBYTES);
    uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
    uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];
    crypto_box_keypair(resp_plain, temp_secret_key);
    random_nonce(con->sent_nonce);
    memcpy(resp_plain + crypto_box_PUBLICKEYBYTES, con->sent_nonce, crypto_box_NONCEBYTES);
    memcpy(con->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);

    uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
    random_nonce(response);

    len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
                                 response + crypto_box_NONCEBYTES);

    if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) {
        return -1;
    }

    if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, (const char *)response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL)) {
        return -1;
    }

    encrypt_precompute(plain, temp_secret_key, con->shared_key);
    con->status = TCP_STATUS_UNCONFIRMED;
    return 1;
}
/* Accept an incoming connection using the parameters provided by crypto_inbound.
 *
 *  return -1 if not successful.
 *  return the crypt_connection_id if successful.
 */
int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
                          uint8_t *session_key)
{
    uint32_t i;

    if (discard_packet(c->lossless_udp, connection_id) == -1)
        return -1;

    /*
     * if(getcryptconnection_id(public_key) != -1)
     * {
     *     return -1;
     * }
     */

    if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
            || c->crypto_connections == NULL)
        return -1;

    memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
    c->crypto_connections[c->crypto_connections_length].number = ~0;

    for (i = 0; i <= c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
            c->crypto_connections[i].number = connection_id;
            c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED;
            c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT;
            random_nonce(c->crypto_connections[i].recv_nonce);
            memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
            memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
            increment_nonce(c->crypto_connections[i].sent_nonce);
            memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);

            crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);

            if (c->crypto_connections_length == i)
                ++c->crypto_connections_length;

            if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce,
                                     c->crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(c->crypto_connections[i].recv_nonce);
                uint32_t zero = 0;
                encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                   c->crypto_connections[i].sessionsecret_key,
                                   c->crypto_connections[i].shared_key);
                c->crypto_connections[i].status =
                    CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
                write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
                c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
                return i;
            }

            return -1; /* This should never happen. */
        }
    }

    return -1;
}
Exemple #7
0
int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
                     const uint8_t *encrypted, size_t length, uint8_t *plain)
{
    if (!public_key || !secret_key) {
        return -1;
    }

    uint8_t k[crypto_box_BEFORENMBYTES];
    encrypt_precompute(public_key, secret_key, k);
    int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain);
    crypto_memzero(k, sizeof k);
    return ret;
}
Exemple #8
0
/* data must be of length TCP_SERVER_HANDSHAKE_SIZE
 *
 * return 0 on success.
 * return -1 on failure.
 */
static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
{
    uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
    int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES,
                                     TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain);

    if (len != sizeof(plain))
        return -1;

    memcpy(TCP_conn->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
    encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
    memset(TCP_conn->temp_secret_key, 0, crypto_box_SECRETKEYBYTES);
    return 0;
}
Exemple #9
0
/* data must be of length TCP_SERVER_HANDSHAKE_SIZE
 *
 * return 0 on success.
 * return -1 on failure.
 */
static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
{
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
    int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + CRYPTO_NONCE_SIZE,
                                     TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);

    if (len != sizeof(plain)) {
        return -1;
    }

    memcpy(TCP_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
    encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
    crypto_memzero(TCP_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
    return 0;
}
Exemple #10
0
/* return 0 on success.
 * return -1 on failure.
 */
static int generate_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *self_public_key,
                              const uint8_t *self_secret_key)
{
    uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
    crypto_box_keypair(plain, TCP_conn->temp_secret_key);
    encrypt_precompute(TCP_conn->public_key, self_secret_key, TCP_conn->shared_key);
    random_nonce(TCP_conn->sent_nonce);
    memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES);
    memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES);
    new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES);
    int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain,
                                     sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);

    if (len != sizeof(plain) + crypto_box_MACBYTES)
        return -1;

    TCP_conn->last_packet_length = crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(plain) + crypto_box_MACBYTES;
    TCP_conn->last_packet_sent = 0;
    return 0;
}
Exemple #11
0
/* accept an incoming connection using the parameters provided by crypto_inbound
   return -1 if not successful
   returns the crypt_connection_id if successful */
int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
{
    uint32_t i;
    if (connection_id == -1)
        return -1;
    /*
    if(getcryptconnection_id(public_key) != -1)
    {
        return -1;
    }*/
    for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
        if(crypto_connections[i].status == CONN_NO_CONNECTION) {
            crypto_connections[i].number = connection_id;
            crypto_connections[i].status = CONN_NOT_CONFIRMED;
            random_nonce(crypto_connections[i].recv_nonce);
            memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
            memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
            increment_nonce(crypto_connections[i].sent_nonce);
            memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);

            crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);

            if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce,
                                     crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(crypto_connections[i].recv_nonce);
                uint32_t zero = 0;
                encrypt_precompute(crypto_connections[i].peersessionpublic_key, 
                                   crypto_connections[i].sessionsecret_key, 
                                   crypto_connections[i].shared_key);
                crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
                write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
                crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
                return i;
            }
            return -1; /* this should never happen. */
        }
    }
    return -1;
}
Exemple #12
0
END_TEST

START_TEST(test_endtoend)
{
    unsigned char pk1[CRYPTO_PUBLIC_KEY_SIZE];
    unsigned char sk1[CRYPTO_SECRET_KEY_SIZE];
    unsigned char pk2[CRYPTO_PUBLIC_KEY_SIZE];
    unsigned char sk2[CRYPTO_SECRET_KEY_SIZE];
    unsigned char k1[CRYPTO_SHARED_KEY_SIZE];
    unsigned char k2[CRYPTO_SHARED_KEY_SIZE];

    unsigned char n[CRYPTO_NONCE_SIZE];

    unsigned char m[500];
    unsigned char c1[sizeof(m) + CRYPTO_MAC_SIZE];
    unsigned char c2[sizeof(m) + CRYPTO_MAC_SIZE];
    unsigned char c3[sizeof(m) + CRYPTO_MAC_SIZE];
    unsigned char c4[sizeof(m) + CRYPTO_MAC_SIZE];
    unsigned char m1[sizeof(m)];
    unsigned char m2[sizeof(m)];
    unsigned char m3[sizeof(m)];
    unsigned char m4[sizeof(m)];

    int mlen;
    int c1len, c2len, c3len, c4len;
    int m1len, m2len, m3len, m4len;

    int testno;

    // Test 100 random messages and keypairs
    for (testno = 0; testno < 100; testno++) {
        //Generate random message (random length from 100 to 500)
        mlen = (random_u32() % 400) + 100;
        rand_bytes(m, mlen);
        rand_bytes(n, CRYPTO_NONCE_SIZE);

        //Generate keypairs
        crypto_new_keypair(pk1, sk1);
        crypto_new_keypair(pk2, sk2);

        //Precompute shared keys
        encrypt_precompute(pk2, sk1, k1);
        encrypt_precompute(pk1, sk2, k2);

        ck_assert_msg(memcmp(k1, k2, CRYPTO_SHARED_KEY_SIZE) == 0, "encrypt_precompute: bad");

        //Encrypt all four ways
        c1len = encrypt_data(pk2, sk1, n, m, mlen, c1);
        c2len = encrypt_data(pk1, sk2, n, m, mlen, c2);
        c3len = encrypt_data_symmetric(k1, n, m, mlen, c3);
        c4len = encrypt_data_symmetric(k2, n, m, mlen, c4);

        ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ");
        ck_assert_msg(c1len == mlen + (int)CRYPTO_MAC_SIZE, "wrong cyphertext length");
        ck_assert_msg(memcmp(c1, c2, c1len) == 0 && memcmp(c1, c3, c1len) == 0
                      && memcmp(c1, c4, c1len) == 0, "crypertexts differ");

        //Decrypt all four ways
        m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1);
        m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2);
        m3len = decrypt_data_symmetric(k1, n, c1, c1len, m3);
        m4len = decrypt_data_symmetric(k2, n, c1, c1len, m4);

        ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ");
        ck_assert_msg(m1len == mlen, "wrong decrypted text length");
        ck_assert_msg(memcmp(m1, m2, mlen) == 0 && memcmp(m1, m3, mlen) == 0
                      && memcmp(m1, m4, mlen) == 0, "decrypted texts differ");
        ck_assert_msg(memcmp(m1, m, mlen) == 0, "wrong decrypted text");
    }
}
/* Handle received packets for not yet established crypto connections. */
static void receive_crypto(Net_Crypto *c)
{
    uint32_t i;
    uint64_t temp_time = unix_time();

    for (i = 0; i < c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION)
            continue;

        if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) {
            uint8_t temp_data[MAX_DATA_SIZE];
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            uint16_t len;

            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */
                len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);

                if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
                    if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
                        memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
                        memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
                        increment_nonce(c->crypto_connections[i].sent_nonce);
                        uint32_t zero = 0;
                        encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                           c->crypto_connections[i].sessionsecret_key,
                                           c->crypto_connections[i].shared_key);
                        c->crypto_connections[i].status =
                            CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
                        write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
                        c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
                    } else {
                        /* This should not happen, timeout the connection if it does. */
                        c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
                    }
                } else {
                    /* This should not happen, timeout the connection if it does. */
                    c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
                }
            } else if (id_packet(c->lossless_udp,
                                 c->crypto_connections[i].number) != -1) {
                /* This should not happen, timeout the connection if it does. */
                c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
            }
        }

        if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) {
            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint8_t data[MAX_DATA_SIZE];
                int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
                int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
                uint32_t zero = 0;

                if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
                    increment_nonce(c->crypto_connections[i].recv_nonce);
                    encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].shared_key);
                    c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED;
                    c->crypto_connections[i].timeout = ~0;
                    /* Connection is accepted. */
                    confirm_connection(c->lossless_udp, c->crypto_connections[i].number);
                } else {
                    /* This should not happen, timeout the connection if it does. */
                    c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
                }
            } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1) {
                /* This should not happen, timeout the connection if it does. */
                c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
            }
        }

        if (temp_time > c->crypto_connections[i].timeout) {
            c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
        }
    }
}
int main(int argc, char *argv[])
{
    const int numtrials = 10000;

    unsigned char pk1[crypto_box_PUBLICKEYBYTES];
    unsigned char sk1[crypto_box_SECRETKEYBYTES];
    unsigned char pk2[crypto_box_PUBLICKEYBYTES];
    unsigned char sk2[crypto_box_SECRETKEYBYTES];
    unsigned char k1[crypto_box_BEFORENMBYTES];
    unsigned char k2[crypto_box_BEFORENMBYTES];

    unsigned char n[crypto_box_NONCEBYTES];

    unsigned char m[500];
    unsigned char c[sizeof(m) + crypto_box_MACBYTES];

    unsigned char k[crypto_box_BEFORENMBYTES];

    int trialno;

    double starttime;
    double endtime;
    double slow_time;
    double fast_time;
    double keygen_time;
    double precompute_time;

    // Pregenerate
    crypto_box_keypair(pk1, sk1);
    crypto_box_keypair(pk2, sk2);
    encrypt_precompute(pk1, sk2, k1);
    encrypt_precompute(pk2, sk1, k2);
    rand_bytes(m, sizeof(m));
    rand_bytes(n, sizeof(n));

    printf("starting slow...\n");
    starttime = get_time();

    for (trialno = 0; trialno < numtrials; trialno++) {
        encrypt_data(pk1, sk2, n, m, sizeof(m), c);
        decrypt_data(pk2, sk1, n, c, sizeof(c), m);
    }

    endtime = get_time();
    slow_time = endtime - starttime;

    printf("starting fast...\n");
    starttime = get_time();

    for (trialno = 0; trialno < numtrials; trialno++) {
        encrypt_data_symmetric(k1, n, m, sizeof(m), c);
        decrypt_data_symmetric(k2, n, c, sizeof(c), m);
    }

    endtime = get_time();
    fast_time = endtime - starttime;

    printf("starting keygen...\n");
    starttime = get_time();

    for (trialno = 0; trialno < numtrials; trialno++) {
        crypto_box_keypair(pk1, sk1);
        crypto_box_keypair(pk2, sk2);
    }

    endtime = get_time();
    keygen_time = endtime - starttime;

    printf("starting precompute...\n");
    starttime = get_time();

    for (trialno = 0; trialno < numtrials; trialno++) {
        encrypt_precompute(pk1, sk2, k);
        encrypt_precompute(pk2, sk1, k);
    }

    endtime = get_time();
    precompute_time = endtime - starttime;

    printf("\n");
    printf("trials: %i\n", 2 * numtrials);
    printf("\n");
    printf("slow time: %f sec\n", slow_time);
    printf("fast time: %f sec\n", fast_time);
    printf("keygen time: %f sec\n", keygen_time);
    printf("precompute time: %f sec\n", precompute_time);
    printf("\n");
    printf("Speed boost: %.1f%%\n", slow_time * 100 / fast_time);
    printf("\n");
    printf("slow: %.1f per second\n", 2 * numtrials / slow_time);
    printf("fast: %.1f per second\n", 2 * numtrials / fast_time);

    return 0;
}
Exemple #15
0
/* Handle received packets for not yet established crypto connections. */
static void receive_crypto(Net_Crypto *c)
{
    uint32_t i;

    for (i = 0; i < c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
            uint8_t temp_data[MAX_DATA_SIZE];
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            uint16_t len;

            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */
                len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);

                if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
                    if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
                        memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
                        memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
                        increment_nonce(c->crypto_connections[i].sent_nonce);
                        uint32_t zero = 0;
                        encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                           c->crypto_connections[i].sessionsecret_key,
                                           c->crypto_connections[i].shared_key);
                        c->crypto_connections[i].status =
                            CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
                        write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
                        c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
                    }
                }
            } else if (id_packet(c->lossless_udp,
                                 c->crypto_connections[i].number) != -1) { // This should not happen, kill the connection if it does.
                crypto_kill(c, i);
                return;
            }
        }

        if (c->crypto_connections[i].status == CONN_NOT_CONFIRMED) {
            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint8_t data[MAX_DATA_SIZE];
                int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
                int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
                uint32_t zero = 0;

                if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
                    increment_nonce(c->crypto_connections[i].recv_nonce);
                    encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].shared_key);
                    c->crypto_connections[i].status = CONN_ESTABLISHED;

                    /* Connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
                    kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000);
                } else {
                    /* This should not happen, kill the connection if it does. */
                    crypto_kill(c, i);
                    return;
                }
            } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1)
                /* This should not happen, kill the connection if it does. */
                crypto_kill(c, i);

            return;
        }
    }
}
Exemple #16
0
/* Create new TCP connection to ip_port/public_key
 */
TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
        const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
{
    if (networking_at_startup() != 0) {
        return NULL;
    }

    if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) {
        return NULL;
    }

    uint8_t family = ip_port.ip.family;

    TCP_Proxy_Info default_proxyinfo;

    if (proxy_info == NULL) {
        default_proxyinfo.proxy_type = TCP_PROXY_NONE;
        proxy_info = &default_proxyinfo;
    }

    if (proxy_info->proxy_type != TCP_PROXY_NONE) {
        family = proxy_info->ip_port.ip.family;
    }

    Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);

    if (!sock_valid(sock)) {
        return NULL;
    }

    if (!set_socket_nosigpipe(sock)) {
        kill_sock(sock);
        return 0;
    }

    if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
        kill_sock(sock);
        return NULL;
    }

    TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1);

    if (temp == NULL) {
        kill_sock(sock);
        return NULL;
    }

    temp->sock = sock;
    memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
    memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
    encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
    temp->ip_port = ip_port;
    temp->proxy_info = *proxy_info;

    switch (proxy_info->proxy_type) {
        case TCP_PROXY_HTTP:
            temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
            proxy_http_generate_connection_request(temp);
            break;

        case TCP_PROXY_SOCKS5:
            temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
            proxy_socks5_generate_handshake(temp);
            break;

        case TCP_PROXY_NONE:
            temp->status = TCP_CLIENT_CONNECTING;

            if (generate_handshake(temp) == -1) {
                kill_sock(sock);
                free(temp);
                return NULL;
            }

            break;
    }

    temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;

    return temp;
}