From 2b7bf64cf5aa013f9a540551cc438118f7c28da1 Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 22:30:29 +0200 Subject: [PATCH 01/30] rename encryption and move option out of constructor (just use the set_...) Fix comp unit test --- executables/benchmark.cpp | 6 ++++-- executables/unit_test.cpp | 8 +++++--- src/Encryption.hpp | 21 +++++++++------------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/executables/benchmark.cpp b/executables/benchmark.cpp index 8e611216..9f803e6a 100644 --- a/executables/benchmark.cpp +++ b/executables/benchmark.cpp @@ -98,8 +98,10 @@ void benchmark_fec_encode(const Options &options, bool printBlockTime = false) { void benchmark_crypt(const Options &options,const bool packet_validation_only) { assert(options.benchmarkType == BENCHMARK_ENCRYPT || options.benchmarkType == BENCHMARK_DECRYPT); const bool encrypt=options.benchmarkType==BENCHMARK_ENCRYPT; - Encryptor encryptor{std::nullopt,packet_validation_only}; - Decryptor decryptor{std::nullopt,packet_validation_only}; + Encryptor encryptor{std::nullopt}; + encryptor.set_encryption_enabled(!packet_validation_only); + Decryptor decryptor{std::nullopt}; + encryptor.set_encryption_enabled(!packet_validation_only); std::array sessionKeyNonce{}; std::array sessionKeyData{}; encryptor.makeNewSessionKey(sessionKeyNonce, sessionKeyData); diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index 5a1aa380..7ffcf73a 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -111,7 +111,7 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){ static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool message_signing_only) { std::cout << "Using generated keypair (default seed otherwise):" << (useGeneratedFiles ? "y" : "n") << "\n"; const std::string filename_gs="gs.key"; //"../example_keys/gs.key" - const std::string filename_drone="drone.key" //"../example_keys/drone.key" + const std::string filename_drone="drone.key"; //"../example_keys/drone.key" std::optional encKey = useGeneratedFiles ? std::optional(filename_gs) : std::nullopt; std::optional decKey = useGeneratedFiles ? std::optional(filename_drone) : std::nullopt; if(message_signing_only){ @@ -120,8 +120,10 @@ static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool mess std::cout<<"Testing encryption & signing\n"; } - Encryptor encryptor{encKey,message_signing_only}; - Decryptor decryptor{decKey,message_signing_only}; + Encryptor encryptor{encKey}; + encryptor.set_encryption_enabled(!message_signing_only); + Decryptor decryptor{decKey}; + encryptor.set_encryption_enabled(!message_signing_only); struct SessionStuff{ std::array sessionKeyNonce{}; // random data std::array sessionKeyData{}; diff --git a/src/Encryption.hpp b/src/Encryption.hpp index 795817a7..d829cf73 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -46,8 +46,7 @@ class Encryptor { * @param keypair encryption key, otherwise enable a default deterministic encryption key by using std::nullopt * @param DISABLE_ENCRYPTION_FOR_PERFORMANCE only validate, do not encrypt (less CPU usage) */ - explicit Encryptor(std::optional keypair, const bool DISABLE_ENCRYPTION_FOR_PERFORMANCE = false) - : DISABLE_ENCRYPTION_FOR_PERFORMANCE(DISABLE_ENCRYPTION_FOR_PERFORMANCE) { + explicit Encryptor(std::optional keypair){ if (keypair == std::nullopt) { // use default encryption keys crypto_box_seed_keypair(rx_publickey.data(), tx_secretkey.data(), DEFAULT_ENCRYPTION_SEED.data()); @@ -93,7 +92,7 @@ class Encryptor { * Returns written data size (msg payload plus sign data) */ int authenticate_and_encrypt(const uint64_t nonce,const uint8_t *src,std::size_t src_len,uint8_t* dest){ - if(DISABLE_ENCRYPTION_FOR_PERFORMANCE){ + if(!m_encrypt_data){ memcpy(dest,src, src_len); uint8_t* sign=dest+src_len; const auto sub_key=create_onetimeauth_subkey(nonce,session_key); @@ -120,7 +119,7 @@ class Encryptor { * @param encryption_enabled */ void set_encryption_enabled(bool encryption_enabled){ - DISABLE_ENCRYPTION_FOR_PERFORMANCE=!encryption_enabled; + m_encrypt_data =encryption_enabled; } private: // tx->rx keypair @@ -128,16 +127,14 @@ class Encryptor { std::array rx_publickey{}; std::array session_key{}; // use this one if you are worried about CPU usage when using encryption - bool DISABLE_ENCRYPTION_FOR_PERFORMANCE; - //static_assert(crypto_onetimeauth_BYTES); + bool m_encrypt_data= true; }; class Decryptor { public: // enable a default deterministic encryption key by using std::nullopt // else, pass path to file with encryption keys - explicit Decryptor(std::optional keypair, const bool DISABLE_ENCRYPTION_FOR_PERFORMANCE = false) - : DISABLE_ENCRYPTION_FOR_PERFORMANCE(DISABLE_ENCRYPTION_FOR_PERFORMANCE) { + explicit Decryptor(std::optional keypair){ if (keypair == std::nullopt) { crypto_box_seed_keypair(tx_publickey.data(), rx_secretkey.data(), DEFAULT_ENCRYPTION_SEED.data()); wifibroadcast::log::get_default()->debug("Using default keys"); @@ -160,7 +157,7 @@ class Decryptor { } private: // use this one if you are worried about CPU usage when using encryption - bool DISABLE_ENCRYPTION_FOR_PERFORMANCE; + bool m_encrypt_data= true; public: std::array rx_secretkey{}; public: @@ -202,7 +199,7 @@ class Decryptor { * @param dest needs to be at least @param encrypted - 16 bytes big. */ bool authenticate_and_decrypt(const uint64_t& nonce,const uint8_t* encrypted,int encrypted_size,uint8_t* dest){ - if(DISABLE_ENCRYPTION_FOR_PERFORMANCE){ + if(!m_encrypt_data){ const auto payload_size=encrypted_size-crypto_onetimeauth_BYTES; assert(payload_size>0); const uint8_t* sign=encrypted+payload_size; @@ -233,7 +230,7 @@ class Decryptor { return nullptr; } int get_additional_payload_size() const{ - if(DISABLE_ENCRYPTION_FOR_PERFORMANCE){ + if(m_encrypt_data){ return crypto_onetimeauth_BYTES; } return crypto_aead_chacha20poly1305_ABYTES; @@ -243,7 +240,7 @@ class Decryptor { * @param encryption_enabled */ void set_encryption_enabled(bool encryption_enabled){ - DISABLE_ENCRYPTION_FOR_PERFORMANCE=!encryption_enabled; + m_encrypt_data =encryption_enabled; } }; From 877fba3e565abb5887c553fc80e8a1fd7e7f64bd Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 22:31:03 +0200 Subject: [PATCH 02/30] rename encryption and move option out of constructor (just use the set_...) Fix comp unit test --- src/WBTxRx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WBTxRx.h b/src/WBTxRx.h index a1276c25..b1f5b911 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -48,7 +48,7 @@ * (To give the user time to register all the receive handlers) * * NOTE2: You won't find any FEC or similar here - this class intentionally - * represents a lowe level where FEC or similar can be added on top + * represents a lower level where FEC or similar can be added on top */ class WBTxRx { public: From 58e19c6a68d7a4332b8df7c2755e84c577307505 Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 22:32:24 +0200 Subject: [PATCH 03/30] encryption in WBTx - default to true --- src/WBStreamTx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WBStreamTx.h b/src/WBStreamTx.h index e3282965..0a8cbfbe 100644 --- a/src/WBStreamTx.h +++ b/src/WBStreamTx.h @@ -138,7 +138,7 @@ class WBStreamTx { void process_enqueued_packet(const EnqueuedPacket& packet); void process_enqueued_block(const EnqueuedBlock& block); void send_packet(const uint8_t* packet,int packet_len); - std::atomic m_enable_encryption=false; + std::atomic m_enable_encryption=true; }; #endif // WIFIBROADCAST_WBSTREAMTX_H From 7cb621f66560f62eca87500ce7e4a5521c1ea70d Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 22:49:43 +0200 Subject: [PATCH 04/30] add option to debug packets variance --- src/WBTxRx.cpp | 15 ++++++++++++++- src/WBTxRx.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/WBTxRx.cpp b/src/WBTxRx.cpp index f68fc315..f9f713d0 100644 --- a/src/WBTxRx.cpp +++ b/src/WBTxRx.cpp @@ -180,6 +180,8 @@ void WBTxRx::loop_receive_packets() { if(m_options.receive_thread_max_realtime){ SchedulingHelper::setThreadParamsMaxRealtime(); } + std::vector packets_per_card{}; + packets_per_card.resize(m_wifi_cards.size()); while (keep_receiving){ const int timeoutMS = (int) std::chrono::duration_cast(std::chrono::seconds(1)).count(); int rc = poll(m_receive_pollfds.data(), m_receive_pollfds.size(), timeoutMS); @@ -215,10 +217,21 @@ void WBTxRx::loop_receive_packets() { } } if (m_receive_pollfds[i].revents & POLLIN) { - loop_iter(i); + const auto n_packets=loop_iter(i); + packets_per_card[i]=n_packets; rc -= 1; + }else{ + packets_per_card[i]=0; } } + if(m_options.debug_multi_rx_packets_variance){ + std::stringstream ss; + ss<<"Packets"; + for(int i=0;idebug("{}",ss.str()); + } } } diff --git a/src/WBTxRx.h b/src/WBTxRx.h index b1f5b911..60843f57 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -88,6 +88,8 @@ class WBTxRx { bool debug_decrypt_time= false; // Debug packet gaps bool debug_packet_gaps= false; + // Debug multi rx packets variance + bool debug_multi_rx_packets_variance= false; // This is only for debugging / testing, inject packets with a fixed MAC - won't be received as valid packets by another rx instance bool enable_non_openhd_mode= false; }; From 4959ee267d3b3b10eca4b605634a76118114267e Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 22:59:18 +0200 Subject: [PATCH 05/30] keys --- example_keys/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 example_keys/README.md diff --git a/example_keys/README.md b/example_keys/README.md new file mode 100644 index 00000000..199d4ac9 --- /dev/null +++ b/example_keys/README.md @@ -0,0 +1 @@ +Example air / ground keys, used by the unit test From c83385e6f984fb122f6100db70f6ec0730613076 Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 23:00:06 +0200 Subject: [PATCH 06/30] upload keys --- example_keys/drone.key | 1 + example_keys/gs.key | 1 + 2 files changed, 2 insertions(+) create mode 100644 example_keys/drone.key create mode 100644 example_keys/gs.key diff --git a/example_keys/drone.key b/example_keys/drone.key new file mode 100644 index 00000000..21f27a25 --- /dev/null +++ b/example_keys/drone.key @@ -0,0 +1 @@ +΄ޏ 薟˒gTd=Iע9f 58h$tksDxF&!E4Jr \ No newline at end of file diff --git a/example_keys/gs.key b/example_keys/gs.key new file mode 100644 index 00000000..cc56dfe0 --- /dev/null +++ b/example_keys/gs.key @@ -0,0 +1 @@ + jͫ, ؏-=D,‚ko(|qE9gwL&v 20*,T:tsW \ No newline at end of file From d11bf501114d607662f5f7e1ee881aae04c9f2b0 Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 23:01:39 +0200 Subject: [PATCH 07/30] fix unit tests --- .github/workflows/build_and_unit_test.yml | 3 ++- executables/unit_test.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_unit_test.yml b/.github/workflows/build_and_unit_test.yml index b32c19be..ff641a77 100644 --- a/.github/workflows/build_and_unit_test.yml +++ b/.github/workflows/build_and_unit_test.yml @@ -23,5 +23,6 @@ jobs: ./build/wfb_keygen - name: Unit test run: | - ./build/unit_test + cd build + ./unit_test diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index 7ffcf73a..e97da788 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -110,8 +110,10 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){ // Test encryption+packet validation and packet validation only static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool message_signing_only) { std::cout << "Using generated keypair (default seed otherwise):" << (useGeneratedFiles ? "y" : "n") << "\n"; - const std::string filename_gs="gs.key"; //"../example_keys/gs.key" - const std::string filename_drone="drone.key"; //"../example_keys/drone.key" + //const std::string filename_gs="gs.key"; + //const std::string filename_drone="drone.key"; + const std::string filename_gs="../example_keys/gs.key"; + const std::string filename_drone="../example_keys/drone.key"; std::optional encKey = useGeneratedFiles ? std::optional(filename_gs) : std::nullopt; std::optional decKey = useGeneratedFiles ? std::optional(filename_drone) : std::nullopt; if(message_signing_only){ From ee1527341ad1b42231c739ad01153c0fb0dda5fe Mon Sep 17 00:00:00 2001 From: consti10 Date: Thu, 10 Aug 2023 23:11:45 +0200 Subject: [PATCH 08/30] fix unit tests --- executables/benchmark.cpp | 2 +- executables/unit_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/benchmark.cpp b/executables/benchmark.cpp index 9f803e6a..73898150 100644 --- a/executables/benchmark.cpp +++ b/executables/benchmark.cpp @@ -101,7 +101,7 @@ void benchmark_crypt(const Options &options,const bool packet_validation_only) { Encryptor encryptor{std::nullopt}; encryptor.set_encryption_enabled(!packet_validation_only); Decryptor decryptor{std::nullopt}; - encryptor.set_encryption_enabled(!packet_validation_only); + decryptor.set_encryption_enabled(!packet_validation_only); std::array sessionKeyNonce{}; std::array sessionKeyData{}; encryptor.makeNewSessionKey(sessionKeyNonce, sessionKeyData); diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index e97da788..a8fb024c 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -125,7 +125,7 @@ static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool mess Encryptor encryptor{encKey}; encryptor.set_encryption_enabled(!message_signing_only); Decryptor decryptor{decKey}; - encryptor.set_encryption_enabled(!message_signing_only); + decryptor.set_encryption_enabled(!message_signing_only); struct SessionStuff{ std::array sessionKeyNonce{}; // random data std::array sessionKeyData{}; From 74109e767d8b9ff1a86889ae12797ce8219ea371 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:00:43 +0200 Subject: [PATCH 09/30] encrypton - add bind phrase feature --- executables/benchmark.cpp | 4 +- executables/unit_test.cpp | 20 +++- src/Encryption.hpp | 192 +++++++++++++++++++++----------------- src/WBTxRx.cpp | 14 ++- src/WBTxRx.h | 4 +- 5 files changed, 133 insertions(+), 101 deletions(-) diff --git a/executables/benchmark.cpp b/executables/benchmark.cpp index 73898150..d679afb1 100644 --- a/executables/benchmark.cpp +++ b/executables/benchmark.cpp @@ -98,9 +98,9 @@ void benchmark_fec_encode(const Options &options, bool printBlockTime = false) { void benchmark_crypt(const Options &options,const bool packet_validation_only) { assert(options.benchmarkType == BENCHMARK_ENCRYPT || options.benchmarkType == BENCHMARK_DECRYPT); const bool encrypt=options.benchmarkType==BENCHMARK_ENCRYPT; - Encryptor encryptor{std::nullopt}; + wb::Encryptor encryptor{wb::generate_keypair_deterministic(true)}; encryptor.set_encryption_enabled(!packet_validation_only); - Decryptor decryptor{std::nullopt}; + wb::Decryptor decryptor{wb::generate_keypair_deterministic(true)}; decryptor.set_encryption_enabled(!packet_validation_only); std::array sessionKeyNonce{}; std::array sessionKeyData{}; diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index a8fb024c..e88579fa 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -114,17 +114,27 @@ static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool mess //const std::string filename_drone="drone.key"; const std::string filename_gs="../example_keys/gs.key"; const std::string filename_drone="../example_keys/drone.key"; - std::optional encKey = useGeneratedFiles ? std::optional(filename_gs) : std::nullopt; - std::optional decKey = useGeneratedFiles ? std::optional(filename_drone) : std::nullopt; + wb::Keypair encKey{}; + wb::Keypair decKey{}; + if(useGeneratedFiles){ + encKey=wb::read_keypair_from_file(filename_gs); + decKey=wb::read_keypair_from_file(filename_drone); + }else{ + /*encKey=wb::generate_keypair_deterministic(false); + decKey=wb::generate_keypair_deterministic(false);*/ + auto tmp=wb::generate_keypair_from_bind_phrase("openhd"); + encKey=tmp.drone; + decKey=tmp.drone; + } if(message_signing_only){ std::cout<<"Testing message signing\n"; }else{ std::cout<<"Testing encryption & signing\n"; } - Encryptor encryptor{encKey}; + wb::Encryptor encryptor{encKey}; encryptor.set_encryption_enabled(!message_signing_only); - Decryptor decryptor{decKey}; + wb::Decryptor decryptor{decKey}; decryptor.set_encryption_enabled(!message_signing_only); struct SessionStuff{ std::array sessionKeyNonce{}; // random data @@ -135,7 +145,7 @@ static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool mess encryptor.makeNewSessionKey(sessionKeyPacket.sessionKeyNonce, sessionKeyPacket.sessionKeyData); // and "receive" session key (rx) assert(decryptor.onNewPacketSessionKeyData(sessionKeyPacket.sessionKeyNonce, sessionKeyPacket.sessionKeyData) - == Decryptor::SESSION_VALID_NEW); + == wb::Decryptor::SESSION_VALID_NEW); // now encrypt a couple of packets and decrypt them again afterwards for (uint64_t nonce = 0; nonce < 200; nonce++) { const auto data = GenericHelper::createRandomDataBuffer(FEC_PACKET_MAX_PAYLOAD_SIZE); diff --git a/src/Encryption.hpp b/src/Encryption.hpp index d829cf73..144b69d1 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -27,6 +27,97 @@ static_assert(crypto_onetimeauth_BYTES==crypto_aead_chacha20poly1305_ABYTES); // Encryption (or packet validation) adds this many bytes to the end of the message static constexpr auto ENCRYPTION_ADDITIONAL_VALIDATION_DATA=crypto_aead_chacha20poly1305_ABYTES; +namespace wb{ + +struct Keypair{ + std::array public_key; + std::array secret_key; +}; + +struct KeypairData{ + // NOTE: The key itself for drone exists of drone.secret and ground.public + Keypair drone; + Keypair ground; +}; + +// Generates a new keypair. Non-deterministic, 100% secure. +static KeypairData generate_keypair(){ + KeypairData ret{}; + crypto_box_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data()); + crypto_box_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data()); + return ret; +} +static Keypair generate_keypair_deterministic(bool is_air){ + Keypair ret{}; + std::array seed1{0}; + std::array seed2{1}; + crypto_box_seed_keypair(ret.public_key.data(), ret.secret_key.data(),is_air ? seed1.data(): seed2.data()); + return ret; +} + +/** + * Generates a deterministic keypair from the openhd bind_phrase. Deterministic, + * same bind phrase will always generate the same key-pairs (but reversing is hard) + */ +static KeypairData generate_keypair_from_bind_phrase(const std::string& bind_phrase=""){ + // Simple default seed, different for air and ground + std::array seed_ground{0}; + std::array seed_drone{UINT8_MAX}; + assert(bind_phrase.length()<=seed_ground.size()); + // We just use the bind-phrase as seed + memcpy(seed_ground.data(),bind_phrase.c_str(),bind_phrase.length()); + memcpy(seed_drone.data(),bind_phrase.c_str(),bind_phrase.length()); + KeypairData ret{}; + crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_drone.data()); + crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_ground.data()); + return ret; +} + +static int write_keypair_to_file(const Keypair& keypair,const std::string& filename){ + FILE *fp; + if ((fp = fopen(filename.c_str(), "w")) == nullptr) { + std::cerr<<"Unable to save "< create_onetimeauth_subkey(const uint64_t nonce,const std::array session_key){ @@ -46,26 +137,9 @@ class Encryptor { * @param keypair encryption key, otherwise enable a default deterministic encryption key by using std::nullopt * @param DISABLE_ENCRYPTION_FOR_PERFORMANCE only validate, do not encrypt (less CPU usage) */ - explicit Encryptor(std::optional keypair){ - if (keypair == std::nullopt) { - // use default encryption keys - crypto_box_seed_keypair(rx_publickey.data(), tx_secretkey.data(), DEFAULT_ENCRYPTION_SEED.data()); - wifibroadcast::log::get_default()->debug("Using default keys"); - } else { - FILE *fp; - if ((fp = fopen(keypair->c_str(), "r")) == nullptr) { - throw std::runtime_error(fmt::format("Unable to open {}: {}", keypair->c_str(), strerror(errno))); - } - if (fread(tx_secretkey.data(), crypto_box_SECRETKEYBYTES, 1, fp) != 1) { - fclose(fp); - throw std::runtime_error(fmt::format("Unable to read tx secret key: {}", strerror(errno))); - } - if (fread(rx_publickey.data(), crypto_box_PUBLICKEYBYTES, 1, fp) != 1) { - fclose(fp); - throw std::runtime_error(fmt::format("Unable to read rx public key: {}", strerror(errno))); - } - fclose(fp); - } + explicit Encryptor(wb::Keypair keypair) + : tx_secretkey(keypair.secret_key), + rx_publickey(keypair.public_key){ } /** * Creates a new session key, simply put, the data we can send publicly @@ -95,7 +169,7 @@ class Encryptor { if(!m_encrypt_data){ memcpy(dest,src, src_len); uint8_t* sign=dest+src_len; - const auto sub_key=create_onetimeauth_subkey(nonce,session_key); + const auto sub_key=wb::create_onetimeauth_subkey(nonce,session_key); crypto_onetimeauth(sign,src,src_len,sub_key.data()); return src_len+crypto_onetimeauth_BYTES; } @@ -123,8 +197,8 @@ class Encryptor { } private: // tx->rx keypair - std::array tx_secretkey{}; - std::array rx_publickey{}; + const std::array tx_secretkey{}; + const std::array rx_publickey{}; std::array session_key{}; // use this one if you are worried about CPU usage when using encryption bool m_encrypt_data= true; @@ -134,34 +208,15 @@ class Decryptor { public: // enable a default deterministic encryption key by using std::nullopt // else, pass path to file with encryption keys - explicit Decryptor(std::optional keypair){ - if (keypair == std::nullopt) { - crypto_box_seed_keypair(tx_publickey.data(), rx_secretkey.data(), DEFAULT_ENCRYPTION_SEED.data()); - wifibroadcast::log::get_default()->debug("Using default keys"); - } else { - FILE *fp; - if ((fp = fopen(keypair->c_str(), "r")) == nullptr) { - throw std::runtime_error(fmt::format("Unable to open {}: {}", keypair->c_str(), strerror(errno))); - } - if (fread(rx_secretkey.data(), crypto_box_SECRETKEYBYTES, 1, fp) != 1) { - fclose(fp); - throw std::runtime_error(fmt::format("Unable to read rx secret key: {}", strerror(errno))); - } - if (fread(tx_publickey.data(), crypto_box_PUBLICKEYBYTES, 1, fp) != 1) { - fclose(fp); - throw std::runtime_error(fmt::format("Unable to read tx public key: {}", strerror(errno))); - } - fclose(fp); - } + explicit Decryptor(wb::Keypair keypair) + :rx_secretkey(keypair.secret_key),tx_publickey(keypair.public_key){ memset(session_key.data(), 0, sizeof(session_key)); } private: // use this one if you are worried about CPU usage when using encryption bool m_encrypt_data= true; - public: - std::array rx_secretkey{}; - public: - std::array tx_publickey{}; + const std::array rx_secretkey{}; + const std::array tx_publickey{}; std::array session_key{}; public: static constexpr auto SESSION_VALID_NEW=0; @@ -174,7 +229,7 @@ class Decryptor { * */ int onNewPacketSessionKeyData(const std::array &sessionKeyNonce, - const std::array &sessionKeyData) { + const std::array &sessionKeyData) { std::array new_session_key{}; if (crypto_box_open_easy(new_session_key.data(), sessionKeyData.data(), sessionKeyData.size(), @@ -204,7 +259,7 @@ class Decryptor { assert(payload_size>0); const uint8_t* sign=encrypted+payload_size; //const int res=crypto_auth_hmacsha256_verify(sign,msg,payload_size,session_key.data()); - const auto sub_key=create_onetimeauth_subkey(nonce,session_key); + const auto sub_key=wb::create_onetimeauth_subkey(nonce,session_key); const int res=crypto_onetimeauth_verify(sign,encrypted,payload_size,sub_key.data()); if(res!=-1){ memcpy(dest,encrypted,payload_size); @@ -244,46 +299,7 @@ class Decryptor { } }; -namespace wbencryption{ - -struct KeypairData{ - unsigned char drone_publickey[crypto_box_PUBLICKEYBYTES]; - unsigned char drone_secretkey[crypto_box_SECRETKEYBYTES]; - unsigned char gs_publickey[crypto_box_PUBLICKEYBYTES]; - unsigned char gs_secretkey[crypto_box_SECRETKEYBYTES]; -}; - -static KeypairData generate_keypair(){ - KeypairData ret{}; - crypto_box_keypair(ret.drone_publickey, ret.drone_secretkey); - crypto_box_keypair(ret.gs_publickey, ret.gs_secretkey); - return ret; -} - -static int write_to_file(const KeypairData& data){ - FILE *fp; - if ((fp = fopen("drone.key", "w")) == NULL) { - perror("Unable to save drone.key"); - return 1; - } - fwrite(data.drone_secretkey, crypto_box_SECRETKEYBYTES, 1, fp); - fwrite(data.gs_publickey, crypto_box_PUBLICKEYBYTES, 1, fp); - fclose(fp); - - fprintf(stderr, "Drone keypair (drone sec + gs pub) saved to drone.key\n"); - - if ((fp = fopen("gs.key", "w")) == NULL) { - perror("Unable to save gs.key"); - return 1; - } - - fwrite(data.gs_secretkey, crypto_box_SECRETKEYBYTES, 1, fp); - fwrite(data.drone_publickey, crypto_box_PUBLICKEYBYTES, 1, fp); - fclose(fp); - fprintf(stderr, "GS keypair (gs sec + drone pub) saved to gs.key\n"); - return 0; -} +} // namespace wb end -} #endif //ENCRYPTION_HPP \ No newline at end of file diff --git a/src/WBTxRx.cpp b/src/WBTxRx.cpp index f9f713d0..9645729f 100644 --- a/src/WBTxRx.cpp +++ b/src/WBTxRx.cpp @@ -54,8 +54,14 @@ WBTxRx::WBTxRx(std::vector wifi_cards1,Options options1) m_receive_pollfds[i].fd = fd; m_receive_pollfds[i].events = POLLIN; } - m_encryptor=std::make_unique(m_options.encryption_key); - m_decryptor=std::make_unique(m_options.encryption_key); + wb::Keypair keypair{}; + if(m_options.encryption_key.has_value()){ + keypair= wb::read_keypair_from_file(m_options.encryption_key.value()); + }else{ + keypair=wb::generate_keypair_deterministic(true); + } + //m_encryptor=std::make_unique(m_options.encryption_key); + //m_decryptor=std::make_unique(m_options.encryption_key); m_encryptor->makeNewSessionKey(m_tx_sess_key_packet.sessionKeyNonce,m_tx_sess_key_packet.sessionKeyData); // next session key in delta ms if packets are being fed m_session_key_next_announce_ts = std::chrono::steady_clock::now(); @@ -376,11 +382,11 @@ void WBTxRx::on_new_packet(const uint8_t wlan_idx, const pcap_pkthdr &hdr, }*/ SessionKeyPacket &sessionKeyPacket = *((SessionKeyPacket*) parsedPacket->payload); const auto decrypt_res=m_decryptor->onNewPacketSessionKeyData(sessionKeyPacket.sessionKeyNonce, sessionKeyPacket.sessionKeyData); - if(wlan_idx==0 && (decrypt_res==Decryptor::SESSION_VALID_NEW || decrypt_res==Decryptor::SESSION_VALID_NOT_NEW)){ + if(wlan_idx==0 && (decrypt_res==wb::Decryptor::SESSION_VALID_NEW || decrypt_res==wb::Decryptor::SESSION_VALID_NOT_NEW)){ m_pollution_openhd_rx_packets++; recalculate_pollution_perc(); } - if (decrypt_res==Decryptor::SESSION_VALID_NEW) { + if (decrypt_res==wb::Decryptor::SESSION_VALID_NEW) { m_console->debug("Initializing new session."); m_rx_stats.n_received_valid_session_key_packets++; for(auto& handler:m_rx_handlers){ diff --git a/src/WBTxRx.h b/src/WBTxRx.h index 60843f57..499e4faa 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -283,8 +283,8 @@ class WBTxRx { // For multiple RX cards the card with the highest rx rssi is used to inject packets on std::atomic m_curr_tx_card=0; SessionKeyPacket m_tx_sess_key_packet; - std::unique_ptr m_encryptor; - std::unique_ptr m_decryptor; + std::unique_ptr m_encryptor; + std::unique_ptr m_decryptor; struct PcapTxRx{ pcap_t *tx= nullptr; pcap_t *rx= nullptr; From 79222d306866b59b6b04c1a0640b660dad887c53 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:06:21 +0200 Subject: [PATCH 10/30] encrypton - add bind phrase feature --- executables/wfb_keygen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/wfb_keygen.cpp b/executables/wfb_keygen.cpp index 87b816ad..967469b1 100644 --- a/executables/wfb_keygen.cpp +++ b/executables/wfb_keygen.cpp @@ -23,6 +23,6 @@ * Generates a new keypair and saves it to file for later use. */ int main(void) { - auto keypair=wbencryption::generate_keypair(); - return wbencryption::write_to_file(keypair); + auto keypair=wb::generate_keypair(); + return wb::write_to_file(keypair); } From 05dad443b95da0af92747ac1677eff1e6e6330d2 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:11:38 +0200 Subject: [PATCH 11/30] encrypton - add bind phrase feature --- example_keys/drone.key | 2 +- example_keys/gs.key | 2 +- executables/unit_test.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example_keys/drone.key b/example_keys/drone.key index 21f27a25..5ebfaefd 100644 --- a/example_keys/drone.key +++ b/example_keys/drone.key @@ -1 +1 @@ -΄ޏ 薟˒gTd=Iע9f 58h$tksDxF&!E4Jr \ No newline at end of file +ѵV$/ &QCVS4@Nw *Ф|뺷F|bvrRܝ .l & \ No newline at end of file diff --git a/example_keys/gs.key b/example_keys/gs.key index cc56dfe0..33e90a8c 100644 --- a/example_keys/gs.key +++ b/example_keys/gs.key @@ -1 +1 @@ - jͫ, ؏-=D,‚ko(|qE9gwL&v 20*,T:tsW \ No newline at end of file +R[ڭYmwMC4~YO:t;;(Y a0):z&2r \ No newline at end of file diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index e88579fa..6f40c9b6 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -108,15 +108,15 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){ } // Test encryption+packet validation and packet validation only -static void test_encrypt_decrypt_validate(const bool useGeneratedFiles,bool message_signing_only) { - std::cout << "Using generated keypair (default seed otherwise):" << (useGeneratedFiles ? "y" : "n") << "\n"; +static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool message_signing_only) { + std::cout << "Using generated keypair (default seed otherwise):" << (use_key_from_file ? "y" : "n") << "\n"; //const std::string filename_gs="gs.key"; //const std::string filename_drone="drone.key"; const std::string filename_gs="../example_keys/gs.key"; const std::string filename_drone="../example_keys/drone.key"; wb::Keypair encKey{}; wb::Keypair decKey{}; - if(useGeneratedFiles){ + if(use_key_from_file){ encKey=wb::read_keypair_from_file(filename_gs); decKey=wb::read_keypair_from_file(filename_drone); }else{ From bb2ca9b95022af90f0b608bb2d6939851d4dc0a8 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:26:47 +0200 Subject: [PATCH 12/30] encrypton - add bind phrase feature --- src/Encryption.hpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/Encryption.hpp b/src/Encryption.hpp index 144b69d1..fff90f56 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -55,24 +55,32 @@ static Keypair generate_keypair_deterministic(bool is_air){ return ret; } -/** - * Generates a deterministic keypair from the openhd bind_phrase. Deterministic, - * same bind phrase will always generate the same key-pairs (but reversing is hard) - */ +// See https://libsodium.gitbook.io/doc/password_hashing +static std::array create_seed_from_password(const std::string& pw,bool use_salt_air){ + std::array salt_air{0}; + std::array salt_gnd{1}; + const auto salt = use_salt_air ? salt_air : salt_gnd; + std::array key{}; + if (crypto_pwhash(key.data(), sizeof key, pw.c_str(), pw.length(), salt.data(), + crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + std::cerr<<"ERROR: cannot create_seed_from_password"< seed_ground{0}; - std::array seed_drone{UINT8_MAX}; - assert(bind_phrase.length()<=seed_ground.size()); - // We just use the bind-phrase as seed - memcpy(seed_ground.data(),bind_phrase.c_str(),bind_phrase.length()); - memcpy(seed_drone.data(),bind_phrase.c_str(),bind_phrase.length()); + const auto seed_air= create_seed_from_password(bind_phrase, true); + const auto seed_gnd= create_seed_from_password(bind_phrase, false); KeypairData ret{}; - crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_drone.data()); - crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_ground.data()); + crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_air.data()); + crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_gnd.data()); return ret; } + static int write_keypair_to_file(const Keypair& keypair,const std::string& filename){ FILE *fp; if ((fp = fopen(filename.c_str(), "w")) == nullptr) { From 703914988a4a0a1bff54247f95a1fa717b0b2990 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:35:22 +0200 Subject: [PATCH 13/30] encrypton - add bind phrase feature --- src/Encryption.hpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/Encryption.hpp b/src/Encryption.hpp index fff90f56..ddca7258 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -19,10 +19,7 @@ // The Encryption / Decryption name(s) are legacy - // The more difficult part is dealing with the session key stuff, and this class makes it a bit easier to use -// For developing or when encryption is not important, you can use this default seed to -// create deterministic rx and tx keys -static const std::array DEFAULT_ENCRYPTION_SEED = {0}; - +// one time authentication and encryption nicely are really similar static_assert(crypto_onetimeauth_BYTES==crypto_aead_chacha20poly1305_ABYTES); // Encryption (or packet validation) adds this many bytes to the end of the message static constexpr auto ENCRYPTION_ADDITIONAL_VALIDATION_DATA=crypto_aead_chacha20poly1305_ABYTES; @@ -116,12 +113,10 @@ static int write_to_file(const KeypairData& data){ return 1; } fprintf(stderr, "Drone keypair (drone sec + gs pub) saved to drone.key\n"); - if(!write_keypair_to_file(Keypair{data.ground.secret_key,data.drone.public_key},"gs.key")){ return 1; } fprintf(stderr, "GS keypair (gs sec + drone pub) saved to gs.key\n"); - return 0; } @@ -169,18 +164,19 @@ class Encryptor { * (Or if encryption is disabled, only calculate the message sign) * and write the (encrypted) data appended by the validation data into dest * @param nonce: needs to be different for every packet - * @param authenticate_only: if + * @param src @param src_len message to encrypt * @param dest needs to point to a memory region at least @param src_len + 16 bytes big * Returns written data size (msg payload plus sign data) */ - int authenticate_and_encrypt(const uint64_t nonce,const uint8_t *src,std::size_t src_len,uint8_t* dest){ - if(!m_encrypt_data){ + int authenticate_and_encrypt(const uint64_t nonce,const uint8_t *src,int src_len,uint8_t* dest){ + if(!m_encrypt_data){ // Only sign message memcpy(dest,src, src_len); uint8_t* sign=dest+src_len; const auto sub_key=wb::create_onetimeauth_subkey(nonce,session_key); crypto_onetimeauth(sign,src,src_len,sub_key.data()); return src_len+crypto_onetimeauth_BYTES; } + // sign and encrypt all together long long unsigned int ciphertext_len; crypto_aead_chacha20poly1305_encrypt(dest, &ciphertext_len, src, src_len, @@ -220,13 +216,6 @@ class Decryptor { :rx_secretkey(keypair.secret_key),tx_publickey(keypair.public_key){ memset(session_key.data(), 0, sizeof(session_key)); } - private: - // use this one if you are worried about CPU usage when using encryption - bool m_encrypt_data= true; - const std::array rx_secretkey{}; - const std::array tx_publickey{}; - std::array session_key{}; - public: static constexpr auto SESSION_VALID_NEW=0; static constexpr auto SESSION_VALID_NOT_NEW=1; static constexpr auto SESSION_NOT_VALID=-1; @@ -305,6 +294,12 @@ class Decryptor { void set_encryption_enabled(bool encryption_enabled){ m_encrypt_data =encryption_enabled; } + private: + // use this one if you are worried about CPU usage when using encryption + bool m_encrypt_data= true; + const std::array rx_secretkey{}; + const std::array tx_publickey{}; + std::array session_key{}; }; } // namespace wb end From 76bce99b310590af45975e875ffad97bfe980c83 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:45:33 +0200 Subject: [PATCH 14/30] encrypton - add bind phrase feature --- executables/unit_test.cpp | 4 ++-- src/Encryption.hpp | 46 ++++++++++++++++++++++++--------------- src/WBTxRx.cpp | 4 ++-- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index 6f40c9b6..ab8a9c57 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -114,8 +114,8 @@ static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool mess //const std::string filename_drone="drone.key"; const std::string filename_gs="../example_keys/gs.key"; const std::string filename_drone="../example_keys/drone.key"; - wb::Keypair encKey{}; - wb::Keypair decKey{}; + wb::KeyPair encKey{}; + wb::KeyPair decKey{}; if(use_key_from_file){ encKey=wb::read_keypair_from_file(filename_gs); decKey=wb::read_keypair_from_file(filename_drone); diff --git a/src/Encryption.hpp b/src/Encryption.hpp index ddca7258..c7caffa5 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -26,26 +26,34 @@ static constexpr auto ENCRYPTION_ADDITIONAL_VALIDATION_DATA=crypto_aead_chacha20 namespace wb{ -struct Keypair{ +// A wb key consists of a public and private key +struct KeyPair { std::array public_key; std::array secret_key; }; -struct KeypairData{ +struct KeyPairTxRx { // NOTE: The key itself for drone exists of drone.secret and ground.public - Keypair drone; - Keypair ground; + KeyPair drone; + KeyPair ground; + // NOTE the air key consists of key1.sec and key2.pub and vice versa + KeyPair get_keypair_air(){ + return KeyPair{drone.secret_key,ground.public_key}; + } + KeyPair get_keypair_ground(){ + return KeyPair{ground.secret_key,drone.public_key}; + } }; // Generates a new keypair. Non-deterministic, 100% secure. -static KeypairData generate_keypair(){ - KeypairData ret{}; +static KeyPairTxRx generate_keypair(){ + KeyPairTxRx ret{}; crypto_box_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data()); crypto_box_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data()); return ret; } -static Keypair generate_keypair_deterministic(bool is_air){ - Keypair ret{}; +static KeyPair generate_keypair_deterministic(bool is_air){ + KeyPair ret{}; std::array seed1{0}; std::array seed2{1}; crypto_box_seed_keypair(ret.public_key.data(), ret.secret_key.data(),is_air ? seed1.data(): seed2.data()); @@ -68,17 +76,17 @@ static std::array create_seed_from_password(con return key; } -static KeypairData generate_keypair_from_bind_phrase(const std::string& bind_phrase=""){ +static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phrase=""){ const auto seed_air= create_seed_from_password(bind_phrase, true); const auto seed_gnd= create_seed_from_password(bind_phrase, false); - KeypairData ret{}; + KeyPairTxRx ret{}; crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_air.data()); crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_gnd.data()); return ret; } -static int write_keypair_to_file(const Keypair& keypair,const std::string& filename){ +static int write_keypair_to_file(const KeyPair& keypair,const std::string& filename){ FILE *fp; if ((fp = fopen(filename.c_str(), "w")) == nullptr) { std::cerr<<"Unable to save "< wifi_cards1,Options options1) m_receive_pollfds[i].fd = fd; m_receive_pollfds[i].events = POLLIN; } - wb::Keypair keypair{}; + wb::KeyPair keypair{}; if(m_options.encryption_key.has_value()){ keypair= wb::read_keypair_from_file(m_options.encryption_key.value()); }else{ @@ -750,6 +750,6 @@ void WBTxRx::recalculate_pollution_perc() { } std::string WBTxRx::options_to_string(const std::vector& wifi_cards,const WBTxRx::Options& options) { - return fmt::format("Id:{} Cards:{} Keypair:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards), + return fmt::format("Id:{} Cards:{} KeyPair:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards), options.encryption_key.value_or("DEFAULT_SEED")); } From d1759317b931f564a59416b6ae52051212e74ca2 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 01:52:16 +0200 Subject: [PATCH 15/30] encrypton - add bind phrase feature --- executables/unit_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index ab8a9c57..905b0bd1 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -122,7 +122,9 @@ static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool mess }else{ /*encKey=wb::generate_keypair_deterministic(false); decKey=wb::generate_keypair_deterministic(false);*/ + const auto before=std::chrono::steady_clock::now(); auto tmp=wb::generate_keypair_from_bind_phrase("openhd"); + std::cout<<"Generating keypair from bind phrase took:"< Date: Fri, 11 Aug 2023 02:05:30 +0200 Subject: [PATCH 16/30] encrypton - add bind phrase feature --- example_keys/drone.key | 2 +- executables/wfb_keygen.cpp | 1 + src/Encryption.hpp | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example_keys/drone.key b/example_keys/drone.key index 5ebfaefd..c606b61c 100644 --- a/example_keys/drone.key +++ b/example_keys/drone.key @@ -1 +1 @@ -ѵV$/ &QCVS4@Nw *Ф|뺷F|bvrRܝ .l & \ No newline at end of file +n2ņa-GL3/NO=Ȯ:`jc :=Bܒ\sJ7:u \ No newline at end of file diff --git a/executables/wfb_keygen.cpp b/executables/wfb_keygen.cpp index 967469b1..d57ab86b 100644 --- a/executables/wfb_keygen.cpp +++ b/executables/wfb_keygen.cpp @@ -24,5 +24,6 @@ */ int main(void) { auto keypair=wb::generate_keypair(); + //auto keypair=wb::generate_keypair_from_bind_phrase("openhd"); return wb::write_to_file(keypair); } diff --git a/src/Encryption.hpp b/src/Encryption.hpp index c7caffa5..698e90f3 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -85,7 +85,6 @@ static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phr return ret; } - static int write_keypair_to_file(const KeyPair& keypair,const std::string& filename){ FILE *fp; if ((fp = fopen(filename.c_str(), "w")) == nullptr) { From 96a2ed14635320a600f313cf9bf42ea174b1655e Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 02:14:17 +0200 Subject: [PATCH 17/30] encrypton - add bind phrase feature --- src/Encryption.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Encryption.hpp b/src/Encryption.hpp index 698e90f3..5083195b 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -62,11 +62,13 @@ static KeyPair generate_keypair_deterministic(bool is_air){ // See https://libsodium.gitbook.io/doc/password_hashing static std::array create_seed_from_password(const std::string& pw,bool use_salt_air){ - std::array salt_air{0}; - std::array salt_gnd{1}; + // Salts generated once using https://www.random.org/cgi-bin/randbyte?nbytes=16&format=d + // We want deterministic seed from a pw, and are only interested in making it impossible to reverse the process (even though the seed is known) + std::array salt_air{192,189,216,102,56,153,154,92,228,26,49,209,157,7,128,207}; + std::array salt_gnd{179,30,150,20,17,200,225,82,48,64,18,130,89,62,83,234}; const auto salt = use_salt_air ? salt_air : salt_gnd; std::array key{}; - if (crypto_pwhash(key.data(), sizeof key, pw.c_str(), pw.length(), salt.data(), + if (crypto_pwhash(key.data(), key.size(), pw.c_str(), pw.length(), salt.data(), crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_ALG_DEFAULT) != 0) { std::cerr<<"ERROR: cannot create_seed_from_password"< Date: Fri, 11 Aug 2023 02:18:30 +0200 Subject: [PATCH 18/30] encrypton - add bind phrase feature --- executables/unit_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index 905b0bd1..89482f2e 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -118,7 +118,7 @@ static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool mess wb::KeyPair decKey{}; if(use_key_from_file){ encKey=wb::read_keypair_from_file(filename_gs); - decKey=wb::read_keypair_from_file(filename_drone); + decKey=wb::read_keypair_from_file(filename_gs); }else{ /*encKey=wb::generate_keypair_deterministic(false); decKey=wb::generate_keypair_deterministic(false);*/ From 85051fe6aafdfbc6c067e9992b2d2a47aa365628 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 02:21:03 +0200 Subject: [PATCH 19/30] encrypton - add bind phrase feature --- example_keys/drone.key | 3 ++- src/WBTxRx.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/example_keys/drone.key b/example_keys/drone.key index c606b61c..642ce8ff 100644 --- a/example_keys/drone.key +++ b/example_keys/drone.key @@ -1 +1,2 @@ -n2ņa-GL3/NO=Ȯ:`jc :=Bܒ\sJ7:u \ No newline at end of file +;d =go1HF%4Ab׷A " wifi_cards1,Options options1) }else{ keypair=wb::generate_keypair_deterministic(true); } - //m_encryptor=std::make_unique(m_options.encryption_key); - //m_decryptor=std::make_unique(m_options.encryption_key); + m_encryptor=std::make_unique(keypair); + m_decryptor=std::make_unique(keypair); m_encryptor->makeNewSessionKey(m_tx_sess_key_packet.sessionKeyNonce,m_tx_sess_key_packet.sessionKeyData); // next session key in delta ms if packets are being fed m_session_key_next_announce_ts = std::chrono::steady_clock::now(); From 5d4aaef66db2a23a66f9d89ad676d8f2ae38cc70 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 02:58:10 +0200 Subject: [PATCH 20/30] this option is obsolete --- src/WBTxRx.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/WBTxRx.h b/src/WBTxRx.h index 499e4faa..e31c324c 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -56,8 +56,6 @@ class WBTxRx { // file for encryptor // make optional for ease of use - with no keypair given the default "seed" is used std::optional encryption_key = std::nullopt; - // dirty, rssi on rtl8812au is "bugged", this discards the first rssi value reported by the card. - bool rtl8812au_rssi_fixup=false; // on the rx pcap fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271 bool set_direction= true; // thy spam the console, but usefully for debugging From 2616f7c58838e8f3bbc99a13025240c98aece966 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 12:40:12 +0200 Subject: [PATCH 21/30] encryption add bind phrase feature --- .gitignore | 2 +- {example_keys => example_key}/README.md | 0 {example_keys => example_key}/generate.sh | 0 example_key/txrx.key | 1 + example_keys/drone.key | 2 - example_keys/gs.key | 1 - executables/example_hello.cpp | 3 +- executables/example_pollute.cpp | 2 +- executables/example_udp.cpp | 4 +- executables/injection_rate_test.cpp | 2 +- executables/test_txrx.cpp | 4 +- executables/unit_test.cpp | 21 ++-- executables/wfb_keygen.cpp | 4 +- latencyTesting/SimpleTestProgram/.gitignore | 2 +- src/Encryption.hpp | 109 +++++++++----------- src/WBTxRx.cpp | 18 ++-- src/WBTxRx.h | 9 +- 17 files changed, 82 insertions(+), 102 deletions(-) rename {example_keys => example_key}/README.md (100%) rename {example_keys => example_key}/generate.sh (100%) create mode 100644 example_key/txrx.key delete mode 100644 example_keys/drone.key delete mode 100644 example_keys/gs.key diff --git a/.gitignore b/.gitignore index b2be1072..8bec5f8a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ wfb_tx unit_test benchmark gs.key -drone.key +key_1.key wfb_keygen udp_generator_validator socket_helper_test diff --git a/example_keys/README.md b/example_key/README.md similarity index 100% rename from example_keys/README.md rename to example_key/README.md diff --git a/example_keys/generate.sh b/example_key/generate.sh similarity index 100% rename from example_keys/generate.sh rename to example_key/generate.sh diff --git a/example_key/txrx.key b/example_key/txrx.key new file mode 100644 index 00000000..b279cbc5 --- /dev/null +++ b/example_key/txrx.key @@ -0,0 +1 @@ +O8x-%>Kqy?*aoM 0h|p U8B=ά|X3̦';,U;Px:@;oaP6>H؟L-E \ No newline at end of file diff --git a/example_keys/drone.key b/example_keys/drone.key deleted file mode 100644 index 642ce8ff..00000000 --- a/example_keys/drone.key +++ /dev/null @@ -1,2 +0,0 @@ -;d =go1HF%4Ab׷A " txrx=std::make_shared(cards,options_txrx); diff --git a/executables/example_udp.cpp b/executables/example_udp.cpp index a1bb9731..306eac43 100644 --- a/executables/example_udp.cpp +++ b/executables/example_udp.cpp @@ -75,8 +75,8 @@ int main(int argc, char *const *argv) { cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; options_txrx.rtl8812au_rssi_fixup= true; - //options_txrx.set_direction= false; - options_txrx.set_direction= pcap_setdirection; + //options_txrx.pcap_rx_set_direction= false; + options_txrx.pcap_rx_set_direction = pcap_setdirection; options_txrx.log_all_received_validated_packets= false; std::shared_ptr txrx=std::make_shared(cards,options_txrx); diff --git a/executables/injection_rate_test.cpp b/executables/injection_rate_test.cpp index 3ccf1c23..60c60005 100644 --- a/executables/injection_rate_test.cpp +++ b/executables/injection_rate_test.cpp @@ -250,7 +250,7 @@ int main(int argc, char *const *argv) { cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; options_txrx.rtl8812au_rssi_fixup= true; - //options_txrx.set_direction= false; + //options_txrx.pcap_rx_set_direction= false; options_txrx.log_all_received_validated_packets= false; std::shared_ptr txrx=std::make_shared(cards,options_txrx); diff --git a/executables/test_txrx.cpp b/executables/test_txrx.cpp index 9e9211e6..255a0505 100644 --- a/executables/test_txrx.cpp +++ b/executables/test_txrx.cpp @@ -34,8 +34,8 @@ int main(int argc, char *const *argv) { cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; options_txrx.rtl8812au_rssi_fixup= true; - //options_txrx.set_direction= false; - options_txrx.set_direction= pcap_setdirection; + //options_txrx.pcap_rx_set_direction= false; + options_txrx.pcap_rx_set_direction = pcap_setdirection; options_txrx.log_all_received_validated_packets= true; std::shared_ptr txrx=std::make_shared(cards,options_txrx); diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index 89482f2e..cc832df7 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -110,23 +110,14 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){ // Test encryption+packet validation and packet validation only static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool message_signing_only) { std::cout << "Using generated keypair (default seed otherwise):" << (use_key_from_file ? "y" : "n") << "\n"; - //const std::string filename_gs="gs.key"; - //const std::string filename_drone="drone.key"; - const std::string filename_gs="../example_keys/gs.key"; - const std::string filename_drone="../example_keys/drone.key"; - wb::KeyPair encKey{}; - wb::KeyPair decKey{}; + const std::string KEY_FILENAME="../example_key/txrx.key"; + wb::KeyPairTxRx keyPairTxRx{}; if(use_key_from_file){ - encKey=wb::read_keypair_from_file(filename_gs); - decKey=wb::read_keypair_from_file(filename_gs); + keyPairTxRx=wb::read_keypair_from_file(KEY_FILENAME); }else{ - /*encKey=wb::generate_keypair_deterministic(false); - decKey=wb::generate_keypair_deterministic(false);*/ const auto before=std::chrono::steady_clock::now(); - auto tmp=wb::generate_keypair_from_bind_phrase("openhd"); + keyPairTxRx=wb::generate_keypair_from_bind_phrase("openhd"); std::cout<<"Generating keypair from bind phrase took:"< sessionKeyNonce{}; // random data diff --git a/executables/wfb_keygen.cpp b/executables/wfb_keygen.cpp index d57ab86b..e1fc39d1 100644 --- a/executables/wfb_keygen.cpp +++ b/executables/wfb_keygen.cpp @@ -23,7 +23,7 @@ * Generates a new keypair and saves it to file for later use. */ int main(void) { - auto keypair=wb::generate_keypair(); + auto keypair= wb::generate_keypair_random(); //auto keypair=wb::generate_keypair_from_bind_phrase("openhd"); - return wb::write_to_file(keypair); + return wb::write_keypair_to_file(keypair,"txrx.key"); } diff --git a/latencyTesting/SimpleTestProgram/.gitignore b/latencyTesting/SimpleTestProgram/.gitignore index 1bb5e802..91ea6225 100644 --- a/latencyTesting/SimpleTestProgram/.gitignore +++ b/latencyTesting/SimpleTestProgram/.gitignore @@ -8,7 +8,7 @@ env/ _trial_temp/ test gs.key -drone.key +key_1.key wfb_keygen telemetry/conf/site.cfg telemetry/conf/local.cfg diff --git a/src/Encryption.hpp b/src/Encryption.hpp index 5083195b..54089ab9 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -26,47 +26,52 @@ static constexpr auto ENCRYPTION_ADDITIONAL_VALIDATION_DATA=crypto_aead_chacha20 namespace wb{ -// A wb key consists of a public and private key -struct KeyPair { +// A wb key consists of a public and secret key +struct Key { std::array public_key; std::array secret_key; }; +// A wb keypair are 2 keys, one for transmitting, one for receiving +// (Since both ground and air unit talk bidirectional) +// We use a different key for the down-link / uplink, respective struct KeyPairTxRx { - // NOTE: The key itself for drone exists of drone.secret and ground.public - KeyPair drone; - KeyPair ground; - // NOTE the air key consists of key1.sec and key2.pub and vice versa - KeyPair get_keypair_air(){ - return KeyPair{drone.secret_key,ground.public_key}; + Key key_1; + Key key_2; + Key get_tx_key(bool is_air){ + return is_air ? key_1 : key_2; } - KeyPair get_keypair_ground(){ - return KeyPair{ground.secret_key,drone.public_key}; + Key get_rx_key(bool is_air){ + return is_air ? key_2 : key_1; } }; // Generates a new keypair. Non-deterministic, 100% secure. -static KeyPairTxRx generate_keypair(){ +static KeyPairTxRx generate_keypair_random(){ KeyPairTxRx ret{}; - crypto_box_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data()); - crypto_box_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data()); + crypto_box_keypair(ret.key_1.public_key.data(), ret.key_1.secret_key.data()); + crypto_box_keypair(ret.key_2.public_key.data(), ret.key_2.secret_key.data()); return ret; } -static KeyPair generate_keypair_deterministic(bool is_air){ - KeyPair ret{}; + +// Obsolete +static Key generate_keypair_deterministic(bool is_air){ + Key ret{}; std::array seed1{0}; std::array seed2{1}; crypto_box_seed_keypair(ret.public_key.data(), ret.secret_key.data(),is_air ? seed1.data(): seed2.data()); return ret; } +// Salts generated once using https://www.random.org/cgi-bin/randbyte?nbytes=16&format=d +// We want deterministic seed from a pw, and are only interested in making it impossible to reverse the process (even though the salt is plain text) +static constexpr std::array OHD_SALT_AIR{192,189,216,102,56,153,154,92,228,26,49,209,157,7,128,207}; +static constexpr std::array OHD_SALT_GND{179,30,150,20,17,200,225,82,48,64,18,130,89,62,83,234}; +static constexpr auto OHD_DEFAULT_TX_RX_KEY_FILENAME="txrx.key"; + // See https://libsodium.gitbook.io/doc/password_hashing static std::array create_seed_from_password(const std::string& pw,bool use_salt_air){ - // Salts generated once using https://www.random.org/cgi-bin/randbyte?nbytes=16&format=d - // We want deterministic seed from a pw, and are only interested in making it impossible to reverse the process (even though the seed is known) - std::array salt_air{192,189,216,102,56,153,154,92,228,26,49,209,157,7,128,207}; - std::array salt_gnd{179,30,150,20,17,200,225,82,48,64,18,130,89,62,83,234}; - const auto salt = use_salt_air ? salt_air : salt_gnd; + const auto salt = use_salt_air ? OHD_SALT_AIR : OHD_SALT_GND; std::array key{}; if (crypto_pwhash(key.data(), key.size(), pw.c_str(), pw.length(), salt.data(), crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, @@ -78,59 +83,47 @@ static std::array create_seed_from_password(con return key; } -static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phrase=""){ +// We always use the same bind phrase by default +static constexpr auto DEFAULT_BIND_PHRASE="openhd"; +static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phrase=DEFAULT_BIND_PHRASE){ const auto seed_air= create_seed_from_password(bind_phrase, true); const auto seed_gnd= create_seed_from_password(bind_phrase, false); KeyPairTxRx ret{}; - crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_air.data()); - crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_gnd.data()); + crypto_box_seed_keypair(ret.key_1.public_key.data(), ret.key_1.secret_key.data(),seed_air.data()); + crypto_box_seed_keypair(ret.key_2.public_key.data(), ret.key_2.secret_key.data(),seed_gnd.data()); return ret; } -static int write_keypair_to_file(const KeyPair& keypair,const std::string& filename){ +static int write_keypair_to_file(const KeyPairTxRx& keypair_txrx,const std::string& filename){ FILE *fp; if ((fp = fopen(filename.c_str(), "w")) == nullptr) { std::cerr<<"Unable to save "<info("Decryptor-New session detected"); session_key = new_session_key; return SESSION_VALID_NEW; } + // this is NOT an error, the same session key is sent multiple times ! return SESSION_VALID_NOT_NEW; } /** diff --git a/src/WBTxRx.cpp b/src/WBTxRx.cpp index 39c4ca59..ad9a4818 100644 --- a/src/WBTxRx.cpp +++ b/src/WBTxRx.cpp @@ -45,7 +45,7 @@ WBTxRx::WBTxRx(std::vector wifi_cards1,Options options1) pcapTxRx.rx=wifibroadcast::pcap_helper::open_pcap_rx(wifi_card.name); //pcapTxRx.tx=pcapTxRx.rx; pcapTxRx.tx=wifibroadcast::pcap_helper::open_pcap_tx(wifi_card.name); - if(m_options.set_direction){ + if(m_options.pcap_rx_set_direction){ const auto ret=pcap_setdirection(pcapTxRx.rx, PCAP_D_IN); m_console->debug("pcap_setdirection() returned {}",ret); } @@ -54,14 +54,14 @@ WBTxRx::WBTxRx(std::vector wifi_cards1,Options options1) m_receive_pollfds[i].fd = fd; m_receive_pollfds[i].events = POLLIN; } - wb::KeyPair keypair{}; - if(m_options.encryption_key.has_value()){ - keypair= wb::read_keypair_from_file(m_options.encryption_key.value()); + wb::KeyPairTxRx keypair{}; + if(m_options.secure_keypair.has_value()){ + keypair= m_options.secure_keypair.value(); }else{ - keypair=wb::generate_keypair_deterministic(true); + keypair=wb::generate_keypair_from_bind_phrase(); } - m_encryptor=std::make_unique(keypair); - m_decryptor=std::make_unique(keypair); + m_encryptor=std::make_unique(keypair.get_tx_key(!m_options.use_gnd_identifier)); + m_decryptor=std::make_unique(keypair.get_rx_key(!m_options.use_gnd_identifier)); m_encryptor->makeNewSessionKey(m_tx_sess_key_packet.sessionKeyNonce,m_tx_sess_key_packet.sessionKeyData); // next session key in delta ms if packets are being fed m_session_key_next_announce_ts = std::chrono::steady_clock::now(); @@ -750,6 +750,6 @@ void WBTxRx::recalculate_pollution_perc() { } std::string WBTxRx::options_to_string(const std::vector& wifi_cards,const WBTxRx::Options& options) { - return fmt::format("Id:{} Cards:{} KeyPair:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards), - options.encryption_key.value_or("DEFAULT_SEED")); + return fmt::format("Id:{} Cards:{} Key:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards), + options.secure_keypair.has_value() ? "Custom" : "Default(openhd)"); } diff --git a/src/WBTxRx.h b/src/WBTxRx.h index e31c324c..1afa1bee 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -53,11 +53,10 @@ class WBTxRx { public: struct Options{ - // file for encryptor - // make optional for ease of use - with no keypair given the default "seed" is used - std::optional encryption_key = std::nullopt; - // on the rx pcap fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271 - bool set_direction= true; + // Bidirectional, so we need 2 keys + std::optional secure_keypair=std::nullopt; + // on the rx pcap rx fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271 + bool pcap_rx_set_direction = true; // thy spam the console, but usefully for debugging // log all received packets (regardless where they are from) bool log_all_received_packets= false; From f738e66a7158a27dd23722e2ca4e67e6bef522b8 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 12:46:36 +0200 Subject: [PATCH 22/30] encryption add bind phrase feature --- executables/unit_test.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index cc832df7..eb33b1cf 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -109,7 +109,9 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){ // Test encryption+packet validation and packet validation only static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool message_signing_only) { - std::cout << "Using generated keypair (default seed otherwise):" << (use_key_from_file ? "y" : "n") << "\n"; + const std::string TEST_TYPE=message_signing_only ? "Sign" : "Encrypt&Sign"; + const std::string TEST_KEY_TYPE=use_key_from_file ? "key from file" : "default key"; + fmt::print("Testing {} with {}\n",TEST_TYPE,TEST_KEY_TYPE); const std::string KEY_FILENAME="../example_key/txrx.key"; wb::KeyPairTxRx keyPairTxRx{}; if(use_key_from_file){ @@ -119,11 +121,6 @@ static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool mess keyPairTxRx=wb::generate_keypair_from_bind_phrase("openhd"); std::cout<<"Generating keypair from bind phrase took:"<data(), enrypted_wrong_sign->size()); assert(decrypted== nullptr); } - std::cout << "encryption test passed\n"; + fmt::print("Test {} with {} passed\n",TEST_TYPE,TEST_KEY_TYPE); } From dea18a323d41f8c2862b111e3f03d69a4ceddf83 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 12:48:31 +0200 Subject: [PATCH 23/30] encryption add bind phrase feature --- example_key/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_key/README.md b/example_key/README.md index 199d4ac9..486e057b 100644 --- a/example_key/README.md +++ b/example_key/README.md @@ -1 +1 @@ -Example air / ground keys, used by the unit test +Example tx / rx key, generated from the default openhd bind phrase "openhd" From ae52c8bfbcf9a232f09410045656e3fe2617fffb Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 12:54:53 +0200 Subject: [PATCH 24/30] encryption add bind phrase feature --- example_key/generate.sh | 2 +- example_key/txrx.key | 3 ++- executables/wfb_keygen.cpp | 29 ++++++++++++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/example_key/generate.sh b/example_key/generate.sh index d585eb97..caae2b82 100755 --- a/example_key/generate.sh +++ b/example_key/generate.sh @@ -1,3 +1,3 @@ #bin/bash -./../cmake-build-debug/wfb_keygen +./../cmake-build-debug/wfb_keygen -b openhd diff --git a/example_key/txrx.key b/example_key/txrx.key index b279cbc5..5bd1fdfa 100644 --- a/example_key/txrx.key +++ b/example_key/txrx.key @@ -1 +1,2 @@ -O8x-%>Kqy?*aoM 0h|p U8B=ά|X3̦';,U;Px:@;oaP6>H؟L-E \ No newline at end of file +~%Er>>|x;rFKWmnhXY--r{Cm5ʲ +&\ T,Idi1}/E4V)p05LP \ No newline at end of file diff --git a/executables/wfb_keygen.cpp b/executables/wfb_keygen.cpp index e1fc39d1..45b74524 100644 --- a/executables/wfb_keygen.cpp +++ b/executables/wfb_keygen.cpp @@ -22,8 +22,31 @@ /** * Generates a new keypair and saves it to file for later use. */ -int main(void) { - auto keypair= wb::generate_keypair_random(); +int main(int argc, char *const *argv) { + int opt; + std::optional bind_phrase=std::nullopt; + while ((opt = getopt(argc, argv, "b:")) != -1) { + switch (opt) { + case 'b':{ + bind_phrase=std::string(optarg); + } + break; + default: /* '?' */ + show_usage: + fprintf(stderr, + "wfb-keygen [-b bind_phrase], if no bind phrase is specified, random keys are generated (non-deterministic)\n", + argv[0]); + exit(1); + } + } + wb::KeyPairTxRx keyPairTxRx{}; + if(bind_phrase.has_value()){ + std::cout<<"Generating txrx keypair using bind phrase ["< Date: Fri, 11 Aug 2023 12:55:35 +0200 Subject: [PATCH 25/30] encryption add bind phrase feature --- executables/wfb_keygen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/wfb_keygen.cpp b/executables/wfb_keygen.cpp index 45b74524..dbd8eca3 100644 --- a/executables/wfb_keygen.cpp +++ b/executables/wfb_keygen.cpp @@ -20,7 +20,7 @@ #include "../src/Encryption.hpp" /** - * Generates a new keypair and saves it to file for later use. + * Generates a new tx rx keypair and saves it to file for later use. */ int main(int argc, char *const *argv) { int opt; @@ -34,7 +34,7 @@ int main(int argc, char *const *argv) { default: /* '?' */ show_usage: fprintf(stderr, - "wfb-keygen [-b bind_phrase], if no bind phrase is specified, random keys are generated (non-deterministic)\n", + "wfb-keygen [-b bind_phrase,deterministic], if no bind phrase is specified, random keys are generated (non-deterministic)\n", argv[0]); exit(1); } From f923ed61dec7756348829b2d1e70c5c0fae78cb9 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 13:00:41 +0200 Subject: [PATCH 26/30] encryption add bind phrase feature --- src/WBTxRx.cpp | 4 +++- src/WBTxRx.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/WBTxRx.cpp b/src/WBTxRx.cpp index ad9a4818..2eb64fc5 100644 --- a/src/WBTxRx.cpp +++ b/src/WBTxRx.cpp @@ -47,7 +47,9 @@ WBTxRx::WBTxRx(std::vector wifi_cards1,Options options1) pcapTxRx.tx=wifibroadcast::pcap_helper::open_pcap_tx(wifi_card.name); if(m_options.pcap_rx_set_direction){ const auto ret=pcap_setdirection(pcapTxRx.rx, PCAP_D_IN); - m_console->debug("pcap_setdirection() returned {}",ret); + if(ret!=0){ + m_console->debug("pcap_setdirection() returned {}",ret); + } } m_pcap_handles.push_back(pcapTxRx); auto fd = pcap_get_selectable_fd(pcapTxRx.rx); diff --git a/src/WBTxRx.h b/src/WBTxRx.h index 1afa1bee..049e8014 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -53,7 +53,7 @@ class WBTxRx { public: struct Options{ - // Bidirectional, so we need 2 keys + // Bidirectional, so we need 2 keys. If not specified, keys generated from default bind phrase are used std::optional secure_keypair=std::nullopt; // on the rx pcap rx fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271 bool pcap_rx_set_direction = true; From 1a97c5bd8feebdde2bfe2d2ffd448c341d2da1d8 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 13:03:58 +0200 Subject: [PATCH 27/30] encryption add bind phrase feature --- executables/unit_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executables/unit_test.cpp b/executables/unit_test.cpp index eb33b1cf..8d9e138e 100644 --- a/executables/unit_test.cpp +++ b/executables/unit_test.cpp @@ -127,7 +127,7 @@ static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool mess wb::Decryptor decryptor{keyPairTxRx.get_rx_key(false)}; // To the ground unit decryptor.set_encryption_enabled(!message_signing_only); struct SessionStuff{ - std::array sessionKeyNonce{}; // random data + std::array sessionKeyNonce{}; // filled with random data std::array sessionKeyData{}; }; SessionStuff sessionKeyPacket; From 173065d0d186b9cb5a11e16593d1d61a0392529b Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 14:29:00 +0200 Subject: [PATCH 28/30] encryption add bind phrase feature --- executables/example_pollute.cpp | 1 - executables/example_udp.cpp | 1 - executables/injection_rate_test.cpp | 1 - executables/test_txrx.cpp | 1 - 4 files changed, 4 deletions(-) diff --git a/executables/example_pollute.cpp b/executables/example_pollute.cpp index 2530584c..a3c44197 100644 --- a/executables/example_pollute.cpp +++ b/executables/example_pollute.cpp @@ -44,7 +44,6 @@ int main(int argc, char *const *argv) { WBTxRx::WifiCard tmp_card{card,1}; cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; - options_txrx.rtl8812au_rssi_fixup= true; options_txrx.pcap_rx_set_direction = true; options_txrx.enable_non_openhd_mode= true; diff --git a/executables/example_udp.cpp b/executables/example_udp.cpp index 306eac43..a18c0c12 100644 --- a/executables/example_udp.cpp +++ b/executables/example_udp.cpp @@ -74,7 +74,6 @@ int main(int argc, char *const *argv) { WBTxRx::WifiCard tmp_card{card,1}; cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; - options_txrx.rtl8812au_rssi_fixup= true; //options_txrx.pcap_rx_set_direction= false; options_txrx.pcap_rx_set_direction = pcap_setdirection; options_txrx.log_all_received_validated_packets= false; diff --git a/executables/injection_rate_test.cpp b/executables/injection_rate_test.cpp index 60c60005..095feb12 100644 --- a/executables/injection_rate_test.cpp +++ b/executables/injection_rate_test.cpp @@ -249,7 +249,6 @@ int main(int argc, char *const *argv) { WBTxRx::WifiCard tmp_card{card,1}; cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; - options_txrx.rtl8812au_rssi_fixup= true; //options_txrx.pcap_rx_set_direction= false; options_txrx.log_all_received_validated_packets= false; diff --git a/executables/test_txrx.cpp b/executables/test_txrx.cpp index 255a0505..bbce76b4 100644 --- a/executables/test_txrx.cpp +++ b/executables/test_txrx.cpp @@ -33,7 +33,6 @@ int main(int argc, char *const *argv) { WBTxRx::WifiCard tmp_card{card,1}; cards.push_back(tmp_card); WBTxRx::Options options_txrx{}; - options_txrx.rtl8812au_rssi_fixup= true; //options_txrx.pcap_rx_set_direction= false; options_txrx.pcap_rx_set_direction = pcap_setdirection; options_txrx.log_all_received_validated_packets= true; From 5df29b88f0dbce3cc1cd1a2543675505a8ba0212 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 14:33:30 +0200 Subject: [PATCH 29/30] encryption add bind phrase feature --- src/Encryption.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Encryption.hpp b/src/Encryption.hpp index 54089ab9..c6b54e18 100644 --- a/src/Encryption.hpp +++ b/src/Encryption.hpp @@ -243,6 +243,7 @@ class Decryptor { if (memcmp(session_key.data(), new_session_key.data(), sizeof(session_key)) != 0) { wifibroadcast::log::get_default()->info("Decryptor-New session detected"); session_key = new_session_key; + m_has_valid_session= true; return SESSION_VALID_NEW; } // this is NOT an error, the same session key is sent multiple times ! @@ -298,12 +299,17 @@ class Decryptor { void set_encryption_enabled(bool encryption_enabled){ m_encrypt_data =encryption_enabled; } + // Set to true as soon as a valid session has been detected + bool has_valid_session(){ + return m_has_valid_session; + } private: // use this one if you are worried about CPU usage when using encryption bool m_encrypt_data= true; const std::array rx_secretkey{}; const std::array tx_publickey{}; std::array session_key{}; + bool m_has_valid_session= false; }; } // namespace wb end From 82d5a75d21f97876c5df0a457c5684e1d4024b75 Mon Sep 17 00:00:00 2001 From: consti10 Date: Fri, 11 Aug 2023 14:44:28 +0200 Subject: [PATCH 30/30] add likely wrong bind phrase feature --- src/WBTxRx.cpp | 24 +++++++++++++++++++++--- src/WBTxRx.h | 6 ++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/WBTxRx.cpp b/src/WBTxRx.cpp index 2eb64fc5..be9d6ddf 100644 --- a/src/WBTxRx.cpp +++ b/src/WBTxRx.cpp @@ -384,9 +384,27 @@ void WBTxRx::on_new_packet(const uint8_t wlan_idx, const pcap_pkthdr &hdr, }*/ SessionKeyPacket &sessionKeyPacket = *((SessionKeyPacket*) parsedPacket->payload); const auto decrypt_res=m_decryptor->onNewPacketSessionKeyData(sessionKeyPacket.sessionKeyNonce, sessionKeyPacket.sessionKeyData); - if(wlan_idx==0 && (decrypt_res==wb::Decryptor::SESSION_VALID_NEW || decrypt_res==wb::Decryptor::SESSION_VALID_NOT_NEW)){ - m_pollution_openhd_rx_packets++; - recalculate_pollution_perc(); + if(decrypt_res==wb::Decryptor::SESSION_VALID_NEW || decrypt_res==wb::Decryptor::SESSION_VALID_NOT_NEW){ + if(wlan_idx==0){ // Pollution is calculated only on card0 + m_pollution_openhd_rx_packets++; + recalculate_pollution_perc(); + } + m_likely_wrong_encryption_valid_session_keys++; + }else{ + m_likely_wrong_encryption_invalid_session_keys++; + } + // A lot of invalid session keys and no valid session keys hint at a bind phrase mismatch + const auto elapsed_likely_wrong_key=std::chrono::steady_clock::now()-m_likely_wrong_encryption_last_check; + if(elapsed_likely_wrong_key>std::chrono::seconds(5)){ + // No valid session key(s) and at least one invalid session key + if(m_likely_wrong_encryption_valid_session_keys==0 && m_likely_wrong_encryption_invalid_session_keys>=1){ + m_rx_stats.likely_mismatching_encryption_key= true; + }else{ + m_rx_stats.likely_mismatching_encryption_key= false; + } + m_likely_wrong_encryption_last_check=std::chrono::steady_clock::now(); + m_likely_wrong_encryption_valid_session_keys=0; + m_likely_wrong_encryption_invalid_session_keys=0; } if (decrypt_res==wb::Decryptor::SESSION_VALID_NEW) { m_console->debug("Initializing new session."); diff --git a/src/WBTxRx.h b/src/WBTxRx.h index 049e8014..acbabcb2 100644 --- a/src/WBTxRx.h +++ b/src/WBTxRx.h @@ -198,6 +198,8 @@ class WBTxRx { // Usefully for channel scan - n packets that are quite likely coming from an openhd air / ground unit (respective depending on if air/gnd mode) // But not validated - e.g. on a channel scan, session key packet(s) have not been received yet int curr_n_likely_openhd_packets=0; + // Usefully for telling the user that he is probably using incompatible bind phrases / encryption keys on air and ground + bool likely_mismatching_encryption_key= false; }; struct RxStatsPerCard{ int card_index=0; // 0 for first card, 1 for second, ... @@ -361,6 +363,10 @@ class WBTxRx { uint32_t m_pollution_openhd_rx_packets=0; std::chrono::steady_clock::time_point m_last_pollution_calculation=std::chrono::steady_clock::now(); void recalculate_pollution_perc(); + // These are 'extra' for calculating the "likely wrong encryption keys" value + uint32_t m_likely_wrong_encryption_valid_session_keys=0; + std::chrono::steady_clock::time_point m_likely_wrong_encryption_last_check=std::chrono::steady_clock::now(); + uint32_t m_likely_wrong_encryption_invalid_session_keys=0; }; static std::ostream& operator<<(std::ostream& strm, const WBTxRx::TxStats& data){