Beispiel #1
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);
        }
    }
}
Beispiel #2
0
/* return 1 on success.
 * return 0 if could not send packet.
 * return -1 on failure (connection must be killed).
 */
static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
        bool priority)
{
    if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) {
        return -1;
    }

    bool sendpriority = 1;

    if (send_pending_data(con) == -1) {
        if (priority) {
            sendpriority = 0;
        } else {
            return 0;
        }
    }

    uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];

    uint16_t c_length = htons(length + crypto_box_MACBYTES);
    memcpy(packet, &c_length, sizeof(uint16_t));
    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));

    if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) {
        return -1;
    }

    if (priority) {
        len = sendpriority ? send(con->sock, (const char *)packet, sizeof(packet), MSG_NOSIGNAL) : 0;

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

        increment_nonce(con->sent_nonce);

        if ((unsigned int)len == sizeof(packet)) {
            return 1;
        }

        return add_priority(con, packet, sizeof(packet), len);
    }

    len = send(con->sock, (const char *)packet, sizeof(packet), MSG_NOSIGNAL);

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

    increment_nonce(con->sent_nonce);

    if ((unsigned int)len == sizeof(packet)) {
        return 1;
    }

    memcpy(con->last_packet, packet, sizeof(packet));
    con->last_packet_length = sizeof(packet);
    con->last_packet_sent = len;
    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;
}
/*  return 0 if data could not be put in packet queue.
 *  return 1 if data was put into the queue.
 */
int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
{
    if (crypt_connection_id_not_valid(c, crypt_connection_id))
        return 0;

    if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
        return 0;

    if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED)
        return 0;

    uint8_t temp_data[MAX_DATA_SIZE];
    int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key,
                                c->crypto_connections[crypt_connection_id].sent_nonce,
                                data, length, temp_data + 1);

    if (len == -1)
        return 0;

    temp_data[0] = 3;

    if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
        return 0;

    increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce);
    return 1;
}
Beispiel #5
0
/* return 0 if data could not be put in packet queue
   return 1 if data was put into the queue */
int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length)
{
    if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
    {
        return 0;   
    }
    if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
    {
        return 0;
    }
    if(crypto_connections[crypt_connection_id].status != 3)
    {
        return 0;
    }
    uint8_t temp_data[MAX_DATA_SIZE];
    int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, 
                           crypto_connections[crypt_connection_id].sessionsecret_key,
                           crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1);
    if(len == -1)
    {
        return 0;
    }
    temp_data[0] = 3;
    if(write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
    {
        return 0;
    }
    increment_nonce(crypto_connections[crypt_connection_id].sent_nonce);
    return 1;
}
Beispiel #6
0
/* return 0 if there is no received data in the buffer 
   return -1  if the packet was discarded.
   return length of received data if successful */
int read_cryptpacket(int crypt_connection_id, uint8_t * data)
{
    if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
    {
        return 0;   
    }
    if(crypto_connections[crypt_connection_id].status != 3)
    {
        return 0;
    }
    uint8_t temp_data[MAX_DATA_SIZE];
    int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
    if(length == 0)
    {
        return 0;
    }
    if(temp_data[0] != 3)
    {
        return -1;
    }
    int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, 
                           crypto_connections[crypt_connection_id].sessionsecret_key,
                           crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data);
    if(len != -1)
    {
        increment_nonce(crypto_connections[crypt_connection_id].recv_nonce);
        return len;
    }
    return -1;
}
Beispiel #7
0
/* return 1 on success.
 * return 0 if could not send packet.
 * return -1 on failure (connection must be killed).
 */
static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t length)
{
    if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE)
        return -1;

    uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];

    length = htons(length);
    memcpy(packet, &length, sizeof(uint16_t));
    uint32_t len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));

    if (len != (sizeof(packet) - sizeof(uint16_t)))
        return -1;

    increment_nonce(con->sent_nonce);

    len = send(con->sock, packet, sizeof(packet), 0);

    if (len == sizeof(packet))
        return 1;

    if (len <= 0)
        return 0;

    return -1;
}
Beispiel #8
0
/* return length of recieved packet on success.
 * return 0 if could not read any packet.
 * return -1 on failure (connection must be killed).
 */
static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len)
{
    if (con->next_packet_length == 0) {
        uint16_t len = read_length(con->sock);

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

        if (len == 0)
            return 0;

        con->next_packet_length = len;
    }

    if (max_len + crypto_box_MACBYTES < con->next_packet_length)
        return -1;

    uint8_t data_encrypted[con->next_packet_length];
    int len_packet = read_TCP_packet(con->sock, data_encrypted, con->next_packet_length);

    if (len_packet != con->next_packet_length)
        return 0;

    con->next_packet_length = 0;

    int len = decrypt_data_fast(con->shared_key, con->recv_nonce, data_encrypted, len_packet, data);

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

    increment_nonce(con->recv_nonce);

    return len;
}
Beispiel #9
0
void increment_and_send_nonce(struct network_status *net_stat)
  /*@ requires [?f0]world(?pub, ?key_clsfy) &*&
               proof_obligations(pub) &*&
               network_status(net_stat) &*&
               principal(?principal, ?count1) &*&
               true == bad(principal); @*/
  /*@ ensures  [f0]world(pub, key_clsfy) &*&
               proof_obligations(pub) &*&
               network_status(net_stat) &*&
               principal(principal, ?count2); @*/
{
  struct item *nonce = network_receive(net_stat);
  //@ assert item(nonce, ?n, pub);
  if (is_nonce(nonce))
  {
    increment_nonce(nonce);
    //@ assert item(nonce, ?n_inc, pub);
    //@ open proof_obligations(pub);
    /*@ if (col)
        {
          assert is_public_collision(?proof, pub);
          proof(n_inc);
        }
        else
        {
          assert is_public_incremented_nonce(?proof, pub);
          proof(n, n_inc);
        }
    @*/
    //@ close proof_obligations(pub);
    network_send(net_stat, nonce);
  }
  item_free(nonce);
}
Beispiel #10
0
/* Start a secure connection with other peer who has public_key and ip_port
   returns -1 if failure
   returns crypt_connection_id of the initialized connection if everything went well. */
int crypto_connect(uint8_t *public_key, IP_Port ip_port)
{
    uint32_t i;
    int id = getcryptconnection_id(public_key);
    if (id != -1) {
        IP_Port c_ip = connection_ip(crypto_connections[id].number);
        if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port)
            return -1;
    }
    for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
        if (crypto_connections[i].status == CONN_NO_CONNECTION) {
            int id = new_connection(ip_port);
            if (id == -1)
                return -1;
            crypto_connections[i].number = id;
            crypto_connections[i].status = CONN_HANDSHAKE_SENT;
            random_nonce(crypto_connections[i].recv_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(id, public_key, crypto_connections[i].recv_nonce,
                                     crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(crypto_connections[i].recv_nonce);
                return i;
            }
            return -1; /* this should never happen. */
        }
    }
    return -1;
}
Beispiel #11
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;
}
Beispiel #12
0
/*  return 0 if there is no received data in the buffer.
 *  return -1  if the packet was discarded.
 *  return length of received data if successful.
 */
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
{
    if (crypt_connection_id_not_valid(c, crypt_connection_id))
        return 0;

    if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED)
        return 0;

    uint8_t temp_data[MAX_DATA_SIZE];
    int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data);

    if (length == 0)
        return 0;

    if (temp_data[0] != 3)
        return -1;

    int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key,
                                c->crypto_connections[crypt_connection_id].recv_nonce,
                                temp_data + 1, length - 1, data);

    if (len != -1) {
        increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce);
        return len;
    }

    return -1;
}
Beispiel #13
0
/* return 1 on success.
 * return 0 if could not send packet.
 * return -1 on failure (connection must be killed).
 */
static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length)
{
    if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE)
        return -1;

    if (send_pending_data(con) == -1)
        return 0;

    uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];

    uint16_t c_length = htons(length + crypto_box_MACBYTES);
    memcpy(packet, &c_length, sizeof(uint16_t));
    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));

    if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t)))
        return -1;

    increment_nonce(con->sent_nonce);

    len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL);

    if ((unsigned int)len == sizeof(packet))
        return 1;

    if (len <= 0)
        return 0;

    memcpy(con->last_packet, packet, length);
    con->last_packet_length = sizeof(packet);
    con->last_packet_sent = len;
    return 1;
}
Beispiel #14
0
/* Gives a nonce guaranteed to be different from previous ones.*/
void new_nonce(uint8_t *nonce)
{
    if (nonce_set == 0) {
        random_nonce(base_nonce);
        nonce_set = 1;
    }

    increment_nonce(base_nonce);
    memcpy(nonce, base_nonce, crypto_box_NONCEBYTES);
}
Beispiel #15
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 == 0)
        {
            crypto_connections[i].number = connection_id;
            crypto_connections[i].status = 2;
            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;
                crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */
                write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
                crypto_connections[i].status = 2; /* set it to its proper value right after. */
                return i;
            }
            return -1; /* this should never happen. */
        }
    }
    return -1;    
}
Beispiel #16
0
/* Start a secure connection with other peer who has public_key and ip_port.
 *
 *  return -1 if failure.
 *  return crypt_connection_id of the initialized connection if everything went well.
 */
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
{
    uint32_t i;
    int id_existing = getcryptconnection_id(c, public_key);

    if (id_existing != -1) {
        IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number);

        if (ipport_equal(&c_ip, &ip_port))
            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) {
            int id_new = new_connection(c->lossless_udp, ip_port);

            if (id_new == -1)
                return -1;

            c->crypto_connections[i].number = id_new;
            c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT;
            random_nonce(c->crypto_connections[i].recv_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);
            c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT;

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

            if (send_cryptohandshake(c, id_new, public_key,  c->crypto_connections[i].recv_nonce,
                                     c->crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(c->crypto_connections[i].recv_nonce);
                return i;
            }

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

    return -1;
}
Beispiel #17
0
/* Start a secure connection with other peer who has public_key and ip_port.
 *
 *  return -1 if failure.
 *  return crypt_connection_id of the initialized connection if everything went well.
 */
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
{
    uint32_t i;
    int id = getcryptconnection_id(c, public_key);

    if (id != -1) {
        IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number);

        if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port)
            return -1;
    }

    if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1)
        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 == CONN_NO_CONNECTION) {
            int id = new_connection(c->lossless_udp, ip_port);

            if (id == -1)
                return -1;

            c->crypto_connections[i].number = id;
            c->crypto_connections[i].status = CONN_HANDSHAKE_SENT;
            random_nonce(c->crypto_connections[i].recv_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, id, public_key,  c->crypto_connections[i].recv_nonce,
                                     c->crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(c->crypto_connections[i].recv_nonce);
                return i;
            }

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

    return -1;
}
Beispiel #18
0
/* return 0 if data could not be put in packet queue
   return 1 if data was put into the queue */
int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
{
    if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
        return 0;
    if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
        return 0;
    if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
        return 0;
    uint8_t temp_data[MAX_DATA_SIZE];
    int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key,
                                crypto_connections[crypt_connection_id].sent_nonce, 
                                data, length, temp_data + 1);
    if (len == -1)
        return 0;
    temp_data[0] = 3;
    if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
        return 0;
    increment_nonce(crypto_connections[crypt_connection_id].sent_nonce);
    return 1;
}
Beispiel #19
0
/* return 0 if there is no received data in the buffer
   return -1  if the packet was discarded.
   return length of received data if successful */
int read_cryptpacket(int crypt_connection_id, uint8_t *data)
{
    if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
        return 0;
    if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
        return 0;
    uint8_t temp_data[MAX_DATA_SIZE];
    int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
    if (length == 0)
        return 0;
    if (temp_data[0] != 3)
        return -1;
    int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key,
                                crypto_connections[crypt_connection_id].recv_nonce, 
                                temp_data + 1, length - 1, data);
    if (len != -1) {
        increment_nonce(crypto_connections[crypt_connection_id].recv_nonce);
        return len;
    }
    return -1;
}
Beispiel #20
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(Socket 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_MAC_SIZE < *next_packet_length) {
        return -1;
    }

    VLA(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_MAC_SIZE != len_packet) {
        return -1;
    }

    increment_nonce(recv_nonce);

    return len;
}
Beispiel #21
0
/* 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;
        }
    }
}
Beispiel #22
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;
        }
    }
}