static int handle_recv_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 + 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; }
static int handle_recv_2(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_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; }
static int handle_send_initial(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 + 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); }
static int handle_send_2(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_3) 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_3, 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_2), plain); if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) return 1; if (len <= SIZE_IPPORT) { return 1; } if (plain[SIZE_IPPORT] != NET_PACKET_ANNOUNCE_REQUEST && plain[SIZE_IPPORT] != NET_PACKET_ONION_DATA_REQUEST) { return 1; } IP_Port send_to; if (ipport_unpack(&send_to, plain, len, 0) == -1) return 1; uint8_t data[ONION_MAX_PACKET_SIZE]; memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT); uint16_t data_len = (len - SIZE_IPPORT); uint8_t *ret_part = data + (len - SIZE_IPPORT); new_nonce(ret_part); uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; ipport_pack(ret_data, &source); memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), ret_part + crypto_box_NONCEBYTES); if (len != RETURN_3 - crypto_box_NONCEBYTES) return 1; data_len += RETURN_3; if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) return 1; return 0; }
static int handle_send_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 + 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; }