std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh_agree( const std::string& curve_name, const std::vector<uint8_t>& peer_public_value, const Policy& policy, RandomNumberGenerator& rng, bool compressed) { secure_vector<uint8_t> ecdh_secret; std::vector<uint8_t> our_public_value; if(curve_name == "x25519") { #if defined(BOTAN_HAS_CURVE_25519) if(peer_public_value.size() != 32) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size"); } Curve25519_PublicKey peer_key(peer_public_value); policy.check_peer_key_acceptable(peer_key); Curve25519_PrivateKey priv_key(rng); PK_Key_Agreement ka(priv_key, rng, "Raw"); ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); // X25519 is always compressed but sent as "uncompressed" in TLS our_public_value = priv_key.public_value(); #else throw Internal_Error("Negotiated X25519 somehow, but it is disabled"); #endif } else { EC_Group group(OIDS::lookup(curve_name)); ECDH_PublicKey peer_key(group, group.OS2ECP(peer_public_value)); policy.check_peer_key_acceptable(peer_key); ECDH_PrivateKey priv_key(rng, group); PK_Key_Agreement ka(priv_key, rng, "Raw"); ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); our_public_value = priv_key.public_value(compressed ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED); } return std::make_pair(ecdh_secret, our_public_value); }
std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_dh_agree( const std::vector<uint8_t>& modulus, const std::vector<uint8_t>& generator, const std::vector<uint8_t>& peer_public_value, const Policy& policy, RandomNumberGenerator& rng) { BigInt p = BigInt::decode(modulus); BigInt g = BigInt::decode(generator); BigInt Y = BigInt::decode(peer_public_value); /* * A basic check for key validity. As we do not know q here we * cannot check that Y is in the right subgroup. However since * our key is ephemeral there does not seem to be any * advantage to bogus keys anyway. */ if(Y <= 1 || Y >= p - 1) throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Server sent bad DH key for DHE exchange"); DL_Group group(p, g); if(!group.verify_group(rng, false)) throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, "DH group validation failed"); DH_PublicKey peer_key(group, Y); policy.check_peer_key_acceptable(peer_key); DH_PrivateKey priv_key(rng, group); PK_Key_Agreement ka(priv_key, rng, "Raw"); secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros( ka.derive_key(0, peer_key.public_value()).bits_of()); return std::make_pair(dh_secret, priv_key.public_value()); }
std::string srv_insert_peer(const Ctracker_input& v, bool udp, t_user* user) { if (m_use_sql && m_config.m_log_announce) { m_announce_log_buffer += Csql_query(m_database, "(?,?,?,?,?,?,?,?,?,?),") (ntohl(v.m_ipa)) (ntohs(v.m_port)) (v.m_event) (v.m_info_hash) (v.m_peer_id) (v.m_downloaded) (v.m_left) (v.m_uploaded) (user ? user->uid : 0) (srv_time()) .read(); } if (!m_config.m_offline_message.empty()) return m_config.m_offline_message; if (0) return bts_banned_client; if (!m_config.m_anonymous_announce && !user) return bts_unregistered_torrent_pass; if (!m_config.m_auto_register && !find_torrent(v.m_info_hash)) return bts_unregistered_torrent; if (v.m_left && user && !user->can_leech) return bts_can_not_leech; t_torrent& file = m_torrents[to_array<char, 20>(v.m_info_hash)]; if (!file.ctime) file.ctime = srv_time(); if (v.m_left && user && user->wait_time && file.ctime + user->wait_time > srv_time()) return bts_wait_time; peer_key_c peer_key(v.m_ipa, user ? user->uid : 0); t_peer* i = find_ptr(file.peers, peer_key); if (i) (i->left ? file.leechers : file.seeders)--; else if (v.m_left && user && user->peers_limit) { int c = 0; for (auto& j : file.peers) c += j.second.left && j.second.uid == user->uid; if (c >= user->peers_limit) return bts_peers_limit_reached; } if (m_use_sql && user && file.fid) { long long downloaded = 0; long long uploaded = 0; if (i && i->uid == user->uid && boost::equals(i->peer_id, v.m_peer_id) && v.m_downloaded >= i->downloaded && v.m_uploaded >= i->uploaded) { downloaded = v.m_downloaded - i->downloaded; uploaded = v.m_uploaded - i->uploaded; } m_torrents_users_updates_buffer += Csql_query(m_database, "(?,1,?,?,?,?,?,?,?),") (v.m_event != Ctracker_input::e_stopped) (v.m_event == Ctracker_input::e_completed) (downloaded) (v.m_left) (uploaded) (srv_time()) (file.fid) (user->uid) .read(); if (downloaded || uploaded) m_users_updates_buffer += Csql_query(m_database, "(?,?,?),")(downloaded)(uploaded)(user->uid).read(); if (m_torrents_users_updates_buffer.size() > 255 << 10) write_db_users(); } if (v.m_event == Ctracker_input::e_stopped) file.peers.erase(peer_key); else { t_peer& peer = i ? *i : file.peers[peer_key]; peer.downloaded = v.m_downloaded; peer.left = v.m_left; peer.peer_id = v.m_peer_id; peer.port = v.m_port; peer.uid = user ? user->uid : 0; peer.uploaded = v.m_uploaded; (peer.left ? file.leechers : file.seeders)++; peer.mtime = srv_time(); } if (v.m_event == Ctracker_input::e_completed) file.completed++; (udp ? m_stats.announced_udp : m_stats.announced_http)++; file.dirty = true; return std::string(); }