Example #1
0
File: ping.c Project: Dmdv/toxcore
static int handle_ping_response(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length)
{
    DHT      *dht = _dht;
    int       rc;

    if (length != DHT_PING_SIZE)
        return 1;

    PING *ping = dht->ping;

    if (id_equal(packet + 1, ping->dht->self_public_key))
        return 1;

    uint8_t shared_key[crypto_box_BEFORENMBYTES];

    // generate key to encrypt ping_id with recipient privkey
    DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);

    uint8_t ping_plain[PING_PLAIN_SIZE];
    // Decrypt ping_id
    rc = decrypt_data_symmetric(shared_key,
                                packet + 1 + crypto_box_PUBLICKEYBYTES,
                                packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
                                PING_PLAIN_SIZE + crypto_box_MACBYTES,
                                ping_plain);

    if (rc != sizeof(ping_plain))
        return 1;

    if (ping_plain[0] != NET_PACKET_PING_RESPONSE)
        return 1;

    uint64_t   ping_id;
    memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
    uint8_t data[PING_DATA_SIZE];

    if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data))
        return 1;

    if (!id_equal(packet + 1, data))
        return 1;

    IP_Port ipp;
    memcpy(&ipp, data + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));

    if (!ipport_equal(&ipp, &source))
        return 1;

    addto_lists(dht, source, packet + 1);
    return 0;
}
Example #2
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;
}
Example #3
0
static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length)
{
    Onion *onion = object;

    if (length > ONION_MAX_PACKET_SIZE)
        return 1;

    if (length <= 1 + SEND_2)
        return 1;

    change_symmetric_key(onion);

    uint8_t plain[ONION_MAX_PACKET_SIZE];
    uint8_t shared_key[crypto_box_BEFORENMBYTES];
    get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES);
    int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
                                     length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain);

    if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES))
        return 1;

    IP_Port send_to;

    if (ipport_unpack(&send_to, plain, len, 0) == -1)
        return 1;

    uint8_t data[ONION_MAX_PACKET_SIZE];
    data[0] = NET_PACKET_ONION_SEND_2;
    memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES);
    memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT);
    uint16_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT);
    uint8_t *ret_part = data + data_len;
    new_nonce(ret_part);
    uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
    ipport_pack(ret_data, &source);
    memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
    len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
                                 ret_part + crypto_box_NONCEBYTES);

    if (len != RETURN_2 - crypto_box_NONCEBYTES)
        return 1;

    data_len += crypto_box_NONCEBYTES + len;

    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len)
        return 1;

    return 0;
}
Example #4
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;
}
Example #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;
}
Example #6
0
static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
{
    DHT       *dht = (DHT *)object;
    int        rc;

    if (length != DHT_PING_SIZE) {
        return 1;
    }

    PING *ping = dht->ping;

    if (id_equal(packet + 1, ping->dht->self_public_key)) {
        return 1;
    }

    uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];

    uint8_t ping_plain[PING_PLAIN_SIZE];
    // Decrypt ping_id
    DHT_get_shared_key_recv(dht, shared_key, packet + 1);
    rc = decrypt_data_symmetric(shared_key,
                                packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
                                packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
                                PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
                                ping_plain);

    if (rc != sizeof(ping_plain)) {
        return 1;
    }

    if (ping_plain[0] != NET_PACKET_PING_REQUEST) {
        return 1;
    }

    uint64_t   ping_id;
    memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
    // Send response
    send_ping_response(ping, source, packet + 1, ping_id, shared_key);
    add_to_ping(ping, packet + 1, source);

    return 0;
}
Example #7
0
static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
{
    Onion *onion = (Onion *)object;

    if (length > ONION_MAX_PACKET_SIZE) {
        return 1;
    }

    if (length <= 1 + RETURN_1) {
        return 1;
    }

    change_symmetric_key(onion);

    uint8_t plain[SIZE_IPPORT];
    int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
                                     SIZE_IPPORT + crypto_box_MACBYTES, plain);

    if ((uint32_t)len != SIZE_IPPORT) {
        return 1;
    }

    IP_Port send_to;

    if (ipport_unpack(&send_to, plain, len, 1) == -1) {
        return 1;
    }

    uint16_t data_len = length - (1 + RETURN_1);

    if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) {
        return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len);
    }

    if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) {
        return 1;
    }

    return 0;
}
Example #8
0
static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
{
    Onion *onion = (Onion *)object;

    if (length > ONION_MAX_PACKET_SIZE) {
        return 1;
    }

    if (length <= 1 + RETURN_2) {
        return 1;
    }

    change_symmetric_key(onion);

    uint8_t plain[SIZE_IPPORT + RETURN_1];
    int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
                                     SIZE_IPPORT + RETURN_1 + crypto_box_MACBYTES, plain);

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

    IP_Port send_to;

    if (ipport_unpack(&send_to, plain, len, 0) == -1) {
        return 1;
    }

    uint8_t data[ONION_MAX_PACKET_SIZE];
    data[0] = NET_PACKET_ONION_RECV_1;
    memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);
    memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
    uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));

    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
        return 1;
    }

    return 0;
}
Example #9
0
/* return length of received packet on success.
 * return 0 if could not read any packet.
 * return -1 on failure (connection must be killed).
 */
int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key,
                                      uint8_t *recv_nonce, uint8_t *data, uint16_t max_len)
{
    if (*next_packet_length == 0) {
        uint16_t len = read_TCP_length(sock);

        if (len == (uint16_t)~0) {
            return -1;
        }

        if (len == 0) {
            return 0;
        }

        *next_packet_length = len;
    }

    if (max_len + crypto_box_MACBYTES < *next_packet_length) {
        return -1;
    }

    uint8_t data_encrypted[*next_packet_length];
    int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length);

    if (len_packet != *next_packet_length) {
        return 0;
    }

    *next_packet_length = 0;

    int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);

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

    increment_nonce(recv_nonce);

    return len;
}
Example #10
0
static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length)
{
    Onion *onion = object;

    if (length > ONION_MAX_PACKET_SIZE)
        return 1;

    if (length <= 1 + RETURN_3)
        return 1;

    if (packet[1 + RETURN_3] != NET_PACKET_ANNOUNCE_RESPONSE &&
            packet[1 + RETURN_3] != NET_PACKET_ONION_DATA_RESPONSE) {
        return 1;
    }

    change_symmetric_key(onion);

    uint8_t plain[SIZE_IPPORT + RETURN_2];
    int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
                                     SIZE_IPPORT + RETURN_2 + crypto_box_MACBYTES, plain);

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

    IP_Port send_to;

    if (ipport_unpack(&send_to, plain, len, 0) == -1)
        return 1;

    uint8_t data[ONION_MAX_PACKET_SIZE];
    data[0] = NET_PACKET_ONION_RECV_2;
    memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);
    memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
    uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));

    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len)
        return 1;

    return 0;
}
/* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
 * ip contained in it in ret_ip_port
 *
 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
 * ret_pubkey must be at least crypto_box_PUBLICKEYBYTES big
 * ret_ip_port must be at least 1 big
 *
 * return ~0 on failure
 * return num (see new_sendback(...)) on success
 */
static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port)
{
    uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
    int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES,
                                     ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain);

    if ((uint32_t)len != sizeof(plain))
        return ~0;

    uint64_t timestamp;
    memcpy(&timestamp, plain + sizeof(uint32_t), sizeof(uint64_t));
    uint64_t temp_time = unix_time();

    if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp)
        return ~0;

    memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
    memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
    uint32_t num;
    memcpy(&num, plain, sizeof(uint32_t));
    return num;
}
Example #12
0
File: ping.c Project: Dmdv/toxcore
static int handle_ping_request(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length)
{
    DHT       *dht = _dht;
    int        rc;

    if (length != DHT_PING_SIZE)
        return 1;

    PING *ping = dht->ping;

    if (id_equal(packet + 1, ping->dht->self_public_key))
        return 1;

    uint8_t shared_key[crypto_box_BEFORENMBYTES];

    uint8_t ping_plain[PING_PLAIN_SIZE];
    // Decrypt ping_id
    DHT_get_shared_key_recv(dht, shared_key, packet + 1);
    rc = decrypt_data_symmetric(shared_key,
                                packet + 1 + crypto_box_PUBLICKEYBYTES,
                                packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
                                PING_PLAIN_SIZE + crypto_box_MACBYTES,
                                ping_plain );

    if (rc != sizeof(ping_plain))
        return 1;

    if (ping_plain[0] != NET_PACKET_PING_REQUEST)
        return 1;

    uint64_t   ping_id;
    memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
    // Send response
    send_ping_response(ping, source, packet + 1, ping_id, shared_key);
    add_to_ping(ping, packet + 1, source);

    return 0;
}
Example #13
0
static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length)
{
    Onion *onion = object;

    if (length > ONION_MAX_PACKET_SIZE)
        return 1;

    if (length <= 1 + SEND_1)
        return 1;

    change_symmetric_key(onion);

    uint8_t plain[ONION_MAX_PACKET_SIZE];
    uint8_t shared_key[crypto_box_BEFORENMBYTES];
    get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES);
    int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
                                     length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);

    if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES))
        return 1;

    return onion_send_1(onion, plain, len, source, packet + 1);
}
Example #14
0
END_TEST

START_TEST(test_large_data)
{
    unsigned char k[CRYPTO_SHARED_KEY_SIZE];

    unsigned char n[CRYPTO_NONCE_SIZE];

    unsigned char m1[MAX_CRYPTO_PACKET_SIZE - CRYPTO_MAC_SIZE];
    unsigned char c1[sizeof(m1) + CRYPTO_MAC_SIZE];
    unsigned char m1prime[sizeof(m1)];

    unsigned char m2[MAX_CRYPTO_PACKET_SIZE];
    unsigned char c2[sizeof(m2) + CRYPTO_MAC_SIZE];

    int c1len, c2len;
    int m1plen;

    //Generate random messages
    rand_bytes(m1, sizeof(m1));
    rand_bytes(m2, sizeof(m2));
    rand_bytes(n, CRYPTO_NONCE_SIZE);

    //Generate key
    rand_bytes(k, CRYPTO_SHARED_KEY_SIZE);

    c1len = encrypt_data_symmetric(k, n, m1, sizeof(m1), c1);
    c2len = encrypt_data_symmetric(k, n, m2, sizeof(m2), c2);

    ck_assert_msg(c1len == sizeof(m1) + CRYPTO_MAC_SIZE, "could not encrypt");
    ck_assert_msg(c2len == sizeof(m2) + CRYPTO_MAC_SIZE, "could not encrypt");

    m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime);

    ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ");
    ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ");
}
Example #15
0
/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
 * tox_derive_key.
 *
 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
 *
 * returns true on success
 */
bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out,
                          TOX_ERR_DECRYPTION *error)
{
    if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
        return 0;
    }

    if (!data || !key || !out) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
        return 0;
    }

    if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
        return 0;
    }

    data += TOX_ENC_SAVE_MAGIC_LENGTH;
    data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation

    size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;

    uint8_t nonce[crypto_box_NONCEBYTES];
    memcpy(nonce, data, crypto_box_NONCEBYTES);
    data += crypto_box_NONCEBYTES;

    /* decrypt the data */
    if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
            != decrypt_length) {
        SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED);
        return 0;
    }

    SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK);
    return 1;
}
Example #16
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");
    }
}
Example #17
0
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;
}
Example #18
0
static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
{
    Onion_Announce *onion_a = (Onion_Announce *)object;

    if (length != ANNOUNCE_REQUEST_SIZE_RECV) {
        return 1;
    }

    const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;
    uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
    get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key);

    uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
                  ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
    int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
                                     ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
                                     CRYPTO_MAC_SIZE, plain);

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

    uint8_t ping_id1[ONION_PING_ID_SIZE];
    generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1);

    uint8_t ping_id2[ONION_PING_ID_SIZE];
    generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);

    int index = -1;

    uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;

    if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0
            || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
        index = add_to_entries(onion_a, source, packet_public_key, data_public_key,
                               packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
    } else {
        index = in_entries(onion_a, plain + ONION_PING_ID_SIZE);
    }

    /*Respond with a announce response packet*/
    Node_format nodes_list[MAX_SENT_NODES];
    unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0,
                             LAN_ip(source.ip) == 0, 1);
    uint8_t nonce[CRYPTO_NONCE_SIZE];
    random_nonce(nonce);

    uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];

    if (index == -1) {
        pl[0] = 0;
        memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
    } else {
        if (public_key_cmp(onion_a->entries[index].public_key, packet_public_key) == 0) {
            if (public_key_cmp(onion_a->entries[index].data_public_key, data_public_key) != 0) {
                pl[0] = 0;
                memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
            } else {
                pl[0] = 2;
                memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
            }
        } else {
            pl[0] = 1;
            memcpy(pl + 1, onion_a->entries[index].data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
        }
    }

    int nodes_length = 0;

    if (num_nodes != 0) {
        nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);

        if (nodes_length <= 0) {
            return 1;
        }
    }

    uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
    len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
                                 data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);

    if (len != 1 + ONION_PING_ID_SIZE + nodes_length + CRYPTO_MAC_SIZE) {
        return 1;
    }

    data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
    memcpy(data + 1, plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
           ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
    memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE);

    if (send_onion_response(onion_a->net, source, data,
                            1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len,
                            packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) {
        return 1;
    }

    return 0;
}