Ejemplo n.º 1
0
/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
 *
 * public_key is the real public key of the node which we want to send the data of length length to.
 * encrypt_public_key is the public key used to encrypt the data packet.
 *
 * nonce is the nonce to encrypt this packet with
 *
 * return -1 on failure.
 * return 0 on success.
 */
int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
                        const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
{
    if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
        return -1;
    }

    if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) {
        return -1;
    }

    packet[0] = NET_PACKET_ONION_DATA_REQUEST;
    memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);

    uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
    uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
    crypto_new_keypair(random_public_key, random_secret_key);

    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);

    int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
                           packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);

    if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
            length) {
        return -1;
    }

    return DATA_REQUEST_MIN_SIZE + length;
}
Ejemplo n.º 2
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_SHARED_KEY_SIZE];
    encrypt_precompute(data, self_secret_key, shared_key);
    uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
    int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
                                     data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);

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

    memcpy(con->public_key, data, CRYPTO_PUBLIC_KEY_SIZE);
    uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
    uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];
    crypto_new_keypair(resp_plain, temp_secret_key);
    random_nonce(con->sent_nonce);
    memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE);
    memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);

    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_NONCE_SIZE);

    if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
        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;
}
Ejemplo n.º 3
0
/* return 0 on success.
 * return -1 on failure.
 */
static int generate_handshake(TCP_Client_Connection *TCP_conn)
{
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
    crypto_new_keypair(plain, TCP_conn->temp_secret_key);
    random_nonce(TCP_conn->sent_nonce);
    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, TCP_conn->sent_nonce, CRYPTO_NONCE_SIZE);
    memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
    random_nonce(TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE);
    int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
                                     sizeof(plain), TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);

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

    TCP_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
    TCP_conn->last_packet_sent = 0;
    return 0;
}
Ejemplo n.º 4
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");
    }
}